FR-015: - publishHeartbeat() nach Display-Toggle, Session-Reset und Reboot-CMD - publishHeartbeat() von private nach public (mqtt_client.h) - Heartbeat-Intervall 60s -> 10s (config.h) - HA Discovery Switch: state_on/state_off ergaenzt (mqtt_client.cpp) FR-016: - Neuer WebSocket-Endpunkt /status-ws (AsyncWebSocket) - sendStatusWs() am Ende von publishHeartbeat() -> alle Ausloeser abgedeckt - Statusseite: DOM-Updates via WebSocket, kein location.reload() mehr - Config-Seite: Reboot-Button live deaktiviert wenn Laser aktiv - Alle Action-Buttons auf fetch() umgestellt (Reboot, WLAN-Reset, Laufzeit-Reset) - Display-Button: blau+gelb wenn an, grau+grau wenn aus
160 lines
6.6 KiB
C
160 lines
6.6 KiB
C
#pragma once
|
||
|
||
// =============================================================================
|
||
// config.h – Zentrale Pin-Definitionen und Projekt-Konstanten
|
||
// Projekt: MQTT-Display LaserCutter
|
||
// Board: AZ-Delivery ESP32 DevKit V4
|
||
// =============================================================================
|
||
|
||
// -----------------------------------------------------------------------------
|
||
// Firmware-Version
|
||
// Wird durch -DFIRMWARE_VERSION='"x.y.z"' in platformio.ini [env] gesetzt.
|
||
// Fallback für Arduino IDE (ohne build_flags):
|
||
// -----------------------------------------------------------------------------
|
||
#ifndef FIRMWARE_VERSION
|
||
#define FIRMWARE_VERSION "0.0.0"
|
||
#endif
|
||
|
||
// MD_MAX72XX wird hier für den Hardware-Typ-Enum benötigt
|
||
#include <MD_MAX72xx.h>
|
||
|
||
// -----------------------------------------------------------------------------
|
||
// MAX7219 / GYMAX7219 SPI-Pinbelegung (VSPI)
|
||
// -----------------------------------------------------------------------------
|
||
#define DISPLAY_MOSI_PIN 23 // SPI Data
|
||
#define DISPLAY_CLK_PIN 18 // SPI Clock
|
||
#define DISPLAY_CS_PIN 5 // SPI Chip Select
|
||
|
||
// Anzahl der MAX7219-Module in der Kette (4 Spalten × 2 Reihen)
|
||
#define DISPLAY_MODULE_COUNT 8
|
||
|
||
// Hardware-Typ: GENERIC_HW für GYMAX7219 Module (verifiziert durch Hardware-Test)
|
||
// FC16_HW und PAROLA_HW erzeugen kopfstehende Ziffern
|
||
#define DISPLAY_HW_TYPE MD_MAX72XX::GENERIC_HW
|
||
|
||
// Zonenaufteilung (MD_Parola zones, Zone 0 = obere Reihe, Zone 1 = untere Reihe)
|
||
#define DISPLAY_ZONE_TOP 0 // Module 0–3: Laserzeit in Minuten
|
||
#define DISPLAY_ZONE_BOTTOM 1 // Module 4–7: Countdown / Status
|
||
#define DISPLAY_ZONE_COUNT 2
|
||
|
||
// Module je Zone
|
||
#define DISPLAY_MODULES_PER_ZONE (DISPLAY_MODULE_COUNT / DISPLAY_ZONE_COUNT) // 4
|
||
|
||
// Helligkeit (0–15)
|
||
#define DISPLAY_BRIGHTNESS 7
|
||
|
||
// -----------------------------------------------------------------------------
|
||
// Laser-Signal GPIO
|
||
// -----------------------------------------------------------------------------
|
||
#define LASER_SIGNAL_PIN 4 // Digitaler Eingang, potentialfreier Schalter
|
||
|
||
// Debounce-Zeit in Millisekunden
|
||
#define LASER_DEBOUNCE_MS 50
|
||
|
||
// -----------------------------------------------------------------------------
|
||
// Gratiszeit (Default, überschreibbar aus NVS)
|
||
// -----------------------------------------------------------------------------
|
||
#define DEFAULT_GRATIS_SECONDS 20 // Sekunden
|
||
#define MIN_GRATIS_SECONDS 0
|
||
#define MAX_GRATIS_SECONDS 120
|
||
|
||
// -----------------------------------------------------------------------------
|
||
// MQTT – Default-Konfiguration (überschreibbar aus NVS)
|
||
// -----------------------------------------------------------------------------
|
||
#define DEFAULT_MQTT_BROKER "broker.hivemq.com" // Oeffentlicher Testbroker
|
||
#define DEFAULT_MQTT_PORT 1883
|
||
#define DEFAULT_MQTT_USER ""
|
||
#define DEFAULT_MQTT_PASSWORD ""
|
||
#define MQTT_CLIENT_ID "lasercutter-display"
|
||
#define MQTT_RECONNECT_MS 10000 // Reconnect-Intervall in ms
|
||
#define MQTT_HEARTBEAT_MS 10000 // Heartbeat-Intervall in ms
|
||
|
||
// MQTT Topics
|
||
#define MQTT_TOPIC_SESSION "lasercutter/session" // Publish beim Session-Ende
|
||
#define MQTT_TOPIC_STATUS "lasercutter/status" // Publish Heartbeat
|
||
#define MQTT_TOPIC_CMD "lasercutter/cmd" // Subscribe Steuerkommandos
|
||
#define MQTT_TOPIC_AVAILABILITY "lasercutter/availability" // LWT + online/offline (HA Discovery)
|
||
#define MQTT_DISCOVERY_PREFIX "homeassistant" // HA MQTT Discovery Prefix
|
||
|
||
// -----------------------------------------------------------------------------
|
||
// WiFiManager
|
||
// -----------------------------------------------------------------------------
|
||
#define WIFI_AP_NAME "LaserCutter-Setup"
|
||
#define WIFI_AP_TIMEOUT_S 120 // Sekunden bis AP-Timeout und Neustart
|
||
|
||
// -----------------------------------------------------------------------------
|
||
// NVS Namespace
|
||
// -----------------------------------------------------------------------------
|
||
#define NVS_NAMESPACE "lasercutter"
|
||
|
||
// NVS Keys
|
||
#define NVS_KEY_MQTT_BROKER "mqtt_broker"
|
||
#define NVS_KEY_MQTT_PORT "mqtt_port"
|
||
#define NVS_KEY_MQTT_USER "mqtt_user"
|
||
#define NVS_KEY_MQTT_PASSWORD "mqtt_pass"
|
||
#define NVS_KEY_GRATIS_SEC "gratis_sec"
|
||
#define NVS_KEY_SIGNAL_POL "signal_pol" // 0 = LOW_ACTIVE, 1 = HIGH_ACTIVE
|
||
#define NVS_KEY_TOTAL_MINUTES "total_min"
|
||
#define NVS_KEY_WEB_USER "web_user"
|
||
#define NVS_KEY_WEB_PASSWORD "web_pass"
|
||
|
||
// Signal-Polarität Werte
|
||
#define SIGNAL_POL_LOW_ACTIVE 0 // LOW = Laser aktiv (INPUT_PULLUP Default)
|
||
#define SIGNAL_POL_HIGH_ACTIVE 1 // HIGH = Laser aktiv
|
||
|
||
// Webinterface-Authentifizierung
|
||
#define DEFAULT_WEB_USER "admin"
|
||
#define DEFAULT_WEB_PASSWORD "" // leer = kein Passwortschutz
|
||
|
||
// -----------------------------------------------------------------------------
|
||
// Serielles Debugging
|
||
// -----------------------------------------------------------------------------
|
||
#define SERIAL_BAUD_RATE 115200
|
||
|
||
// webLogForward(): Implementierung in web_server.cpp.
|
||
// Kein zirkulaerer Include – extern-Deklaration reicht.
|
||
extern void webLogForward(const char* msg);
|
||
|
||
// Timestamp fuer Log-Makros: Lokalzeit (nach NTP) oder +Xs seit Boot.
|
||
static inline const char* _logTs() {
|
||
static char _ts[12];
|
||
time_t now = time(nullptr);
|
||
if (now > 1600000000UL) { // valide wenn nach 2020
|
||
struct tm* t = localtime(&now);
|
||
strftime(_ts, sizeof(_ts), "%H:%M:%S", t);
|
||
} else {
|
||
uint32_t s = millis() / 1000;
|
||
snprintf(_ts, sizeof(_ts), "+%lus", s);
|
||
}
|
||
return _ts;
|
||
}
|
||
|
||
// Log-Makros: Nachricht formatieren, auf Serial ausgeben und in Web-Log-Puffer schreiben.
|
||
#define LOG_I(tag, fmt, ...) do { \
|
||
char _lb[320]; \
|
||
snprintf(_lb, sizeof(_lb), "[%s][I][%s] " fmt, _logTs(), tag, ##__VA_ARGS__); \
|
||
Serial.println(_lb); \
|
||
webLogForward(_lb); \
|
||
} while(0)
|
||
#define LOG_E(tag, fmt, ...) do { \
|
||
char _lb[320]; \
|
||
snprintf(_lb, sizeof(_lb), "[%s][E][%s] " fmt, _logTs(), tag, ##__VA_ARGS__); \
|
||
Serial.println(_lb); \
|
||
webLogForward(_lb); \
|
||
} while(0)
|
||
#if CORE_DEBUG_LEVEL >= 3
|
||
#define LOG_D(tag, fmt, ...) do { \
|
||
char _lb[320]; \
|
||
snprintf(_lb, sizeof(_lb), "[%s][D][%s] " fmt, _logTs(), tag, ##__VA_ARGS__); \
|
||
Serial.println(_lb); \
|
||
webLogForward(_lb); \
|
||
} while(0)
|
||
#else
|
||
#define LOG_D(tag, fmt, ...) do {} while(0)
|
||
#endif
|
||
|
||
// -----------------------------------------------------------------------------
|
||
// Watchdog
|
||
// -----------------------------------------------------------------------------
|
||
#define WDT_TIMEOUT_S 30 // Watchdog-Timeout in Sekunden
|