16 KiB
Feature Requests & Bug Fixes
Dieses Dokument verfolgt laufende Bug Fixes und kleinere Feature Requests nach Abschluss der Hauptentwicklungsphasen (Implementation-Plan.md Phase 1–9).
Größere Änderungen (neue Module, neue Architektur) werden weiterhin imImplementation-Plan.mddokumentiert. Wird ein offener Punkt erledigt, wird dieser von ## Offen nach ## Erledigt verschoben, mit Details zum Fix/Feature und Commit-Hash und mit der Version in der Überschrift ### Version X.Y.Z, dokumentiert.
Format
- [ ] **FR-NNN** Kurzbeschreibung
- Details, Kontext, betroffene Dateien
- Commit: `<hash>` (wird nach Erledigung eingetragen)
Status: [ ] = offen · [x] = erledigt
Offen
Erledigt
Version 1.6.1
- FR-017 Bug: Maschinenlaufzeit ist in HA nicht verfügbar (MQTT Discovery Sensor fehlt) ✅
- Symptom: Home Assistant zeigte die Maschinenlaufzeit (Gesamtbetriebszeit) nicht als eigenständigen Sensor an.
- Ursache: In
publishDiscovery()fehlte ein dedizierter numerischer Discovery-Sensor fürtotal_minutes. Der bestehende Sensor #4 "Gesamtzeit" formatiert den Wert als hh:mm-String (kein numerischer HA-Sensor, keine Langzeitstatistik möglich). - Fix: Neuer Discovery-Sensor #6 "Maschinenlaufzeit" hinzugefügt:
value_template: {{ value_json.total_minutes }},unit_of_measurement: min,state_class: total_increasing→ HA kann Statistiken und Diagramme erstellen. Anzahl publizierter Entities von 8 auf 9 erhöht. - Betroffene Dateien:
src/mqtt_client.cpp - Commit:
f6dfdeb
Version 1.6.0
-
FR-015 Feature: Sofortiger MQTT-Status-Publish nach jeder Statusänderung ✅
- Motivation: HA zeigte veraltete Werte bis zum nächsten Heartbeat. Änderungen durch Webinterface, MQTT-CMD oder lokale Buttons sind nun sofort in HA sichtbar.
- Umsetzung:
publishHeartbeat()vonprivatenachpublicverschoben; wird nach Display-Toggle, Session-Reset und Reboot-CMD sofort aufgerufen (zusätzlich zum 10s-Timer). Heartbeat-Intervall von 60s auf 10s reduziert. HA MQTT Discovery Switch:state_on/state_offergänzt damit Display-Zustand korrekt angezeigt wird. - Betroffene Dateien:
include/mqtt_client.h,src/web_server.cpp,src/mqtt_client.cpp,include/config.h - Commit:
fc5e169 - Version: 1.6.0
-
FR-016 Feature: Webinterface Live-Aktualisierung ohne Neuladen ✅
- Motivation: Nach einer Aktion im Webinterface blieb die Statusseite veraltet bis zum manuellen Reload.
- Umsetzung: Neuer WebSocket-Endpunkt
/status-ws(AsyncWebSocket).sendStatusWs()wird am Ende vonpublishHeartbeat()aufgerufen – deckt damit alle Auslöser ab (10s-Timer, Web-Aktionen, Laser-Statuswechsel). Statusseite und Config-Seite nutzen/status-wsfür Live-DOM-Updates ohne Reload. Reboot-Button auf Config-Seite wird automatisch deaktiviert wenn Laser aktiv. Alle Action-Buttons (Reboot, WLAN-Reset, Maschinenlaufzeit-Reset) auffetch()umgestellt. - Betroffene Dateien:
include/web_server.h,src/web_server.cpp,src/mqtt_client.cpp - Commit:
fc5e169 - Version: 1.6.0
Version 1.5.2
- FR-014 Bug: Display Störung bei Relais Umschaltung ✅
- Symptom: Nach Relais-Umschaltung (Laser an/aus) friert das Display ein oder zeigt Störungen (z.B. Modul M2–M4 leer, keine Sekundenanzeige)
- Ursache: EMV-Störung durch Relais → SPI-Leitungen fangen Spike auf → MAX7219-interne Register (Decode-Mode, Scan-Limit) werden korrumpiert
- Fix: Neue Methode
display.reinit()inDisplayManager— setzt nur Kontroll-Register neu (keinclear()), danach wird der zuletzt angezeigte Zustand viaredraw()sofort neu gezeichnet. State-Tracking in allenshow*()-Methoden.LaserTracker::onSessionStart()undonSessionEnd()rufendisplay.reinit()auf. - Betroffene Dateien:
include/display_manager.h,src/display_manager.cpp,src/laser_tracker.cpp - Commit:
6c8be70 - Version: 1.5.2
Version 1.5.1
- FR-013 Bug:
binary_sensorLaser aktiv zeigt "In Betrieb" / "Außer Betrieb" statt "An" / "Aus" ✅- Symptom: HA Tile-Card zeigt unter dem Sensor-Status "Außer Betrieb" statt "Aus"
- Ursache:
device_class: runningin der MQTT Discovery-Config erzeugt HA-spezifische Texte ("In Betrieb" / "Außer Betrieb") - Fix:
device_classaus derpublishDiscovery()-binary_sensor-Config inmqtt_client.cppentfernt → HA zeigt generisch "An" / "Aus" - Betroffene Dateien:
src/mqtt_client.cpp - Commit:
db1fd0b - Version: 1.5.1
Version 1.5.0
- FR-012 Feature: Home Assistant MQTT Discovery (automatische Device-Erkennung ohne configuration.yaml) ✅
- Ziel: Der ESP32 soll in Home Assistant als vollständiges Device mit allen Entities automatisch erkannt werden, ohne manuelle Einträge in
configuration.yaml - Mechanismus: MQTT Discovery – Gerät publiziert beim Connect einmalig JSON-Config-Nachrichten an
homeassistant/<typ>/lasercutter-display/<entity>/config - Implementiert:
MQTT_TOPIC_AVAILABILITY+MQTT_DISCOVERY_PREFIXinconfig.h- LWT auf
lasercutter/availability(offline), nach Connectonline(retained) publishDiscovery(): 8 retained Entities nach jedem (Re-)Connect- Heartbeat: neue Felder
laser_active,session_minutes_sum,session_seconds,total_minutesfür HAvalue_template - PubSubClient Buffer: 512 → 1024 Bytes
- Entities in HA (automatisch gruppiert):
- Steuerelemente: Display (switch)
- Sensoren: Laser aktiv, Laserzeit Aktuell, Laserzeit Summe
- Konfiguration: Neustart, Session zurücksetzen (buttons)
- Diagnose: Firmware
- Betroffene Dateien:
src/mqtt_client.cpp,include/mqtt_client.h,include/config.h,platformio.ini - Commit:
ae3e40f - Version: 1.5.0
- Ziel: Der ESP32 soll in Home Assistant als vollständiges Device mit allen Entities automatisch erkannt werden, ohne manuelle Einträge in
Version 1.4.1
- FR-011 Bug: PANIC/EXCEPTION durch Heap-Korruption bei MQTT-Verbindungsabbruch (TLS) ✅
- Symptom: ESP32 crasht mit
CORRUPT HEAP: Bad tail+assert failed: multi_heap_freewenn der MQTT-Broker nicht erreichbar ist und eine bestehende TLS-Session unerwartet abbricht - Fehlermeldung:
(-76) UNKNOWN ERROR CODE (004C)=MBEDTLS_ERR_NET_CONN_RESET - Crash-Kette:
- Broker bricht TLS-Verbindung ab (Connection reset by peer)
PubSubClient::connected()→WiFiClientSecure::connected()→available()available()erkennt EOF → ruft internstop()→stop_ssl_socket()aufmbedtls_ssl_free()wird auf einem bereits inkonsistenten SSL-Kontext aufgerufen- Heap-Corruption →
multi_heap_freeassert → PANIC
- Backtrace-Frames:
multi_heap_free←heap_caps_free←esp_mbedtls_mem_free←mbedtls_free←mbedtls_ssl_free←stop_ssl_socket←WiFiClientSecure::stop()←WiFiClientSecure::available()←WiFiClientSecure::connected()←PubSubClient::connected()←MqttClient::_taskLoop() - Root Cause:
WiFiClientSecure-Objekt wird nach einem TLS-Verbindungsabbruch nicht neu erstellt — der interne mbedTLS-State ist korrupt, beim nächstenconnected()-Aufruf crashtmbedtls_ssl_free() - Fix:
_rebuildClient()— zerstört und erstelltWiFiClientSecure,WiFiClientundPubSubClientvor jedem Reconnect-Versuch neu auf Core 0. mbedTLS startet damit immer mit sauberem Heap-Kontext. Broker/Port werden in_broker/_portgecacht. - Betroffene Dateien:
src/mqtt_client.cpp,include/mqtt_client.h - Commit:
1ef0464 - Version: 1.4.1
- Symptom: ESP32 crasht mit
Version 1.4.0
- FR-010 Feature: Webinterface-Redesign + MQTT-Steuerung ✅
/– Laser Cutter Status (öffentlich, kein Auth)- Seitentitel
Laser Cutter Status, bereinigte Tabelle: Laserzeit Summe, Laserzeit Aktuell (m:ss), Laserstatus (an/aus), Gratiszeit, Firmware - Button
Summe Laserzeit zurücksetzen(kein Auth, bewusst öffentlich) - Button
💡 Display ausschalten/einschalten– Toggle viafetch()ohne Seitenwechsel, RoutePOST /display-toggleantwortet 204 - Button
🔒 Laser Cutter Setup & Status→/config - Auto-Refresh alle 10 s
- Seitentitel
/config– Laser Cutter Setup & Status (Auth erforderlich)- H2: Laser Cutter Status – Maschinenlaufzeit h:mm:ss, roter Reset-Button (
/reset-total) - H2: MQTT Broker, H2: Webzugang, WLAN-Abschnitt
- H2: Gerät – Reboot-Button
🔄 ESP32 neu starten(grau, bei aktivem Laserdisabled) - H2: Tools – OTA Update, Log Console
- Button
← Laser Cutter Statuszurück auf/
- H2: Laser Cutter Status – Maschinenlaufzeit h:mm:ss, roter Reset-Button (
- MQTT-Steuerung:
lasercutter/resetersetzt durchlasercutter/cmd{"reset_session_nvs":true}– Session-Summe + NVS-Maschinenlaufzeit auf 0{"reset_session_ram":true}– nur RAM-Session-Summe auf 0, NVS bleibt{"display":true/false}– Display ein-/ausschalten{"reboot":true}– ESP32 neu starten
- Heartbeat
lasercutter/status: Feld"display_on": true/falsehinzugefügt DisplayManager:setEnabled()/isEnabled()via MAX7219 SHUTDOWN-Modus- Betroffene Dateien:
src/web_server.cpp,src/mqtt_client.cpp,include/config.h,include/display_manager.h,src/display_manager.cpp - Commit:
c61a67f - Version: 1.4.0
Version 1.2.0
-
FR-009 Bug:
session_start_timebei nachgelieferten Sessions (Queue) falsch ✅- Bei Offline-Puffer (Queue) wird
session_start_timeerst beim Publish auslaserTracker.getSessionStartTime()gelesen → zeigt immer die aktuelle Session-Startzeit, nicht die der gepufferten Session - Beispiel: Session A (22:00) läuft offline, Session B (22:10) beendet, dann Reconnect → beide Sessions wurden mit Startzeit von Session B publiziert
- Fix:
SessionPayload-Struct umtime_t startTimeerweitert; Startzeit schon inpublishSession()vialaserTracker.getSessionStartTime()in den Payload geschrieben - Betroffene Dateien:
include/mqtt_client.h(SessionPayload),src/mqtt_client.cpp(publishSession,_doPublishSession) - Commit:
aae34fe
- Bei Offline-Puffer (Queue) wird
-
FR-007 Feature: Laufende Session-ID in MQTT Session-Payload ✅
- Jede Session erhält eine aufsteigende Ganzzahl (
session_id), die im MQTT-PayloadMQTT_TOPIC_SESSIONmitgesendet wird - Empfänger (z. B. Home Assistant, Node-RED) kann fehlende Sessions sofort erkennen: Lücke zwischen
session_id47 und 49 → Session 48 ging verloren - Zähler wird im RAM gehalten (kein NVS nötig), startet bei 0 nach jedem Reboot — Lücke beim Reboot ist akzeptabel
- Zähler wird auf 0 zurückgesetzt bei
{"reset":true}und{"reset_session":true}via MQTT - Betroffene Dateien:
include/mqtt_client.h(SessionPayload,_sessionCounter,resetSessionCounter()),src/mqtt_client.cpp - Commit:
c40668f
- Jede Session erhält eine aufsteigende Ganzzahl (
Version 1.1.1
- FR-006 Bug: MQTT Session-Publish nicht zuverlässig bei Verbindungsausfall ✅
- Bug A – Race Condition:
_pendingSession = falsevor_client->publish()→ bei Abbruch gehen Session-Daten still verloren - Bug B – Nur 1 Slot: volatile Einzelslot überschreibt ältere Session bei mehreren Offline-Sessions
- Fix:
QueueHandle_tmit 128 Slots;xQueuePeek+ Dequeue erst nach erfolgreichem Publish → kein Datenverlust - Betroffene Dateien:
src/mqtt_client.cpp,include/mqtt_client.h - Commit:
9650891
- Bug A – Race Condition:
Version 1.1.0
- FR-008 Bug: Reset-Befehle setzen Maschinenlaufzeit (NVS) ungewollt zurück ✅
- Bug A – MQTT
{"reset":true}ruftresetTotal()auf →settings.saveTotalMinutes(0.0f)→ Maschinenlaufzeit (Gesamtbetriebszeit) wird unwiderruflich aus dem NVS gelöscht- Gewünscht:
{"reset":true}soll nur die Session-Summe (Tages-/Wochenzähler) zurücksetzen, nicht die Gesamtbetriebszeit resetTotal()sollte gar nicht per MQTT erreichbar sein (oder einen separaten, expliziten Befehl erfordern, z.B.{"reset_total":true})
- Gewünscht:
- Bug B – Web-Button "Summe Laserzeit zurücksetzen" ruft
resetSessionSum()auf → NVS wird nicht angefasst, aber_sessionNetSec = 0→getTotalMinutes()sinkt sofort in der Anzeige (weil_sessionNetSec-Anteil verschwindet), obwohl der NVS-Wert korrekt bleibt. Täuscht einen Gesamt-Reset vor.- Fix:
_totalMinutesBasebeimresetSessionSum()um den bereits akkumulierten_sessionNetSec-Anteil erhöhen, bevor_sessionNetSecauf 0 gesetzt wird → Kontinuität der Gesamtzeit sicherstellen
- Fix:
- Betroffene Dateien:
src/laser_tracker.cpp(resetSessionSum,resetTotal),src/mqtt_client.cpp(MQTT-Reset-Handler) - Commit:
c636add
- Bug A – MQTT
Version 1.?.?
- FR-005 Bug: WDT-Crash + Display-/Browser-Freeze durch blockierenden TLS-Handshake ✅
- MQTT
reconnect()mit TLS (Port 8883) blockiertloop()auf Core 1 bis zu 15 s - Folge: Task-Watchdog (30 s) feuert wenn zwei Reconnect-Versuche in einem 30s-Fenster → Neustart mit
WATCHDOG (Task) - Zusätzlich: Display-Updates, WebServer-Responses und WiFi-Stack auf Core 1 eingefroren während TLS-Handshake
- Fix:
MqttClientkomplett auf FreeRTOS-Task (Core 0) ausgelagertbegin()startet nur Task (xTaskCreatePinnedToCore, Stack 16 KB), kein Netzwerk-Zugriff auf Core 1WiFiClientSecure/mbedtls wird ausschließlich auf Core 0 initialisiert und verwendet (Cross-Core-Heap-Korruption vermieden)mqttClient.loop()inmain.cppist No-Op – alle MQTT-Arbeit im TaskpublishSession()von Core 1 safe: setzt nurvolatile-Flags, Task auf Core 0 führt den Publish aus
- Version: 1.1.0 → 1.1.1
- Commit:
a7c6edb(Task auf Core 0),b91b3ca(Heap-Fix: Objekte per new auf Core 0)
- MQTT
Version 1.?.?
- FR-002 Web Console – serieller Monitor über Browser (WebSocket) ✅
- Route
/logliefert HTML-Seite mit automatisch scrollendem Terminal (dunkles Theme) - WebSocket-Endpunkt
/log-wsviaAsyncWebSocketim bestehenden ESPAsyncWebServer LOG_I/LOG_E/LOG_Dinconfig.hformatieren in lokalen Puffer und rufenwebLogForward()aufwebLogForward()sendet perws.textAll()– läuft nativ in AsyncTCP, kein Konflikt- "Log Console"-Button auf Statusseite / automatischer WebSocket-Reconnect nach Trennung
- Commit:
4dd4ce0
- Route
Version 1.?.?
- FR-004 Bug:
session_sumim MQTT-Heartbeat falsch (Binärzahl statt Dezimal) ✅serialized(String(getAllSessionsSumMinutes(), 2))→String(int, basis)interpretiert 2. Argument als Basis, nicht Dezimalstellen- Beispiel: 18 Min →
"10010"(18 in Binär), 20 Min →"10100" - Fix:
doc["session_sum"] = laserTracker.getAllSessionsSumMinutes()– direkt als JSON-Integer, keinserialized()nötig machine_running_time_minwar korrekt:String(float, 2)= 2 Dezimalstellen – anderer Overload- Version: 1.0.1 → 1.0.2
- Commit:
83537e3
Version 1.?.?
- FR-003 Bug: NTP Zeitzone falsch (UTC statt CET/CEST) ✅
configTime(0, 0, ...)lieferte UTC → Anzeige 1h zu früh (CET) / 2h zu früh (CEST)wifi_connector.cpp:configTzTime("CET-1CEST,M3.5.0,M10.5.0/3", "pool.ntp.org", "time.nist.gov")– automatische Sommerzeitmqtt_client.cpp:gmtime()→localtime(),Z-Suffix entfernt – Payload zeigt Lokalzeit- Version: 1.0.0 → 1.0.1
- Commit:
3a31082
Version 1.?.?
- FR-001 Firmware-Version auf Webseite und im MQTT-Status-Payload
- Definition:
FIRMWARE_VERSIONalsbuild_flagsinplatformio.ini[env]-Basisblock (Single Source of Truth) - Fallback
#define FIRMWARE_VERSION "0.0.0"inconfig.h(Arduino IDE ohne build_flags) - Format:
1.0.0 (Feb 26 2026)– Version + C++-Makro__DATE__(Compile-Zeitpunkt) - Web: Firmware-Zeile in der Statustabelle auf
/+ Footer auf/config - MQTT:
"firmware_version": "1.0.0 (Feb 26 2026)"imlasercutter/status-Payload - Commit:
46a8c59
- Definition:
Erstellt: 26. Februar 2026 Zuletzt aktualisiert: 28. Februar 2026