MQTT-Display-LaserCutter/Feature-Requests.md
2026-03-01 10:11:28 +01:00

122 lines
7.3 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Feature Requests & Bug Fixes
> Dieses Dokument verfolgt laufende Bug Fixes und kleinere Feature Requests nach Abschluss der Hauptentwicklungsphasen (Implementation-Plan.md Phase 19).
> Größere Änderungen (neue Module, neue Architektur) werden weiterhin im `Implementation-Plan.md` dokumentiert.
> 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
*(keine offenen Punkte)*
---
## Erledigt
### Version 1.2.0
- [x] **FR-009** Bug: `session_start_time` bei nachgelieferten Sessions (Queue) falsch ✅
- Bei Offline-Puffer (Queue) wird `session_start_time` erst beim Publish aus `laserTracker.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 um `time_t startTime` erweitert; Startzeit schon in `publishSession()` via `laserTracker.getSessionStartTime()` in den Payload geschrieben
- Betroffene Dateien: `include/mqtt_client.h` (`SessionPayload`), `src/mqtt_client.cpp` (`publishSession`, `_doPublishSession`)
- Commit: `aae34fe`
- [x] **FR-007** Feature: Laufende Session-ID in MQTT Session-Payload ✅
- Jede Session erhält eine aufsteigende Ganzzahl (`session_id`), die im MQTT-Payload `MQTT_TOPIC_SESSION` mitgesendet wird
- Empfänger (z. B. Home Assistant, Node-RED) kann fehlende Sessions sofort erkennen: Lücke zwischen `session_id` 47 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`
### Version 1.1.1
- [x] **FR-006** Bug: MQTT Session-Publish nicht zuverlässig bei Verbindungsausfall ✅
- **Bug A Race Condition**: `_pendingSession = false` vor `_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_t` mit 128 Slots; `xQueuePeek` + Dequeue erst nach erfolgreichem Publish → kein Datenverlust
- Betroffene Dateien: `src/mqtt_client.cpp`, `include/mqtt_client.h`
- Commit: `9650891`
### Version 1.1.0
- [x] **FR-008** Bug: Reset-Befehle setzen Maschinenlaufzeit (NVS) ungewollt zurück ✅
- **Bug A MQTT `{"reset":true}`** ruft `resetTotal()` 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}`)
- **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: `_totalMinutesBase` beim `resetSessionSum()` um den bereits akkumulierten `_sessionNetSec`-Anteil erhöhen, bevor `_sessionNetSec` auf 0 gesetzt wird → Kontinuität der Gesamtzeit sicherstellen
- Betroffene Dateien: `src/laser_tracker.cpp` (`resetSessionSum`, `resetTotal`), `src/mqtt_client.cpp` (MQTT-Reset-Handler)
- Commit: `c636add`
### Version 1.?.?
- [x] **FR-005** Bug: WDT-Crash + Display-/Browser-Freeze durch blockierenden TLS-Handshake ✅
- MQTT `reconnect()` mit TLS (Port 8883) blockiert `loop()` 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: `MqttClient` komplett auf FreeRTOS-Task (Core 0) ausgelagert
- `begin()` startet nur Task (`xTaskCreatePinnedToCore`, Stack 16 KB), kein Netzwerk-Zugriff auf Core 1
- `WiFiClientSecure`/mbedtls wird **ausschließlich auf Core 0** initialisiert und verwendet (Cross-Core-Heap-Korruption vermieden)
- `mqttClient.loop()` in `main.cpp` ist No-Op alle MQTT-Arbeit im Task
- `publishSession()` von Core 1 safe: setzt nur `volatile`-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)
### Version 1.?.?
- [x] **FR-002** Web Console serieller Monitor über Browser (WebSocket) ✅
- Route `/log` liefert HTML-Seite mit automatisch scrollendem Terminal (dunkles Theme)
- WebSocket-Endpunkt `/log-ws` via `AsyncWebSocket` im bestehenden ESPAsyncWebServer
- `LOG_I`/`LOG_E`/`LOG_D` in `config.h` formatieren in lokalen Puffer und rufen `webLogForward()` auf
- `webLogForward()` sendet per `ws.textAll()` läuft nativ in AsyncTCP, kein Konflikt
- "Log Console"-Button auf Statusseite / automatischer WebSocket-Reconnect nach Trennung
- Commit: `4dd4ce0`
### Version 1.?.?
- [x] **FR-004** Bug: `session_sum` im 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, kein `serialized()` nötig
- `machine_running_time_min` war korrekt: `String(float, 2)` = 2 Dezimalstellen anderer Overload
- Version: 1.0.1 → 1.0.2
- Commit: `83537e3`
### Version 1.?.?
- [x] **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 Sommerzeit
- `mqtt_client.cpp`: `gmtime()``localtime()`, `Z`-Suffix entfernt Payload zeigt Lokalzeit
- Version: 1.0.0 → 1.0.1
- Commit: `3a31082`
### Version 1.?.?
- [x] **FR-001** Firmware-Version auf Webseite und im MQTT-Status-Payload
- Definition: `FIRMWARE_VERSION` als `build_flags` in `platformio.ini` `[env]`-Basisblock (Single Source of Truth)
- Fallback `#define FIRMWARE_VERSION "0.0.0"` in `config.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)"` im `lasercutter/status`-Payload
- Commit: `46a8c59`
---
*Erstellt: 26. Februar 2026*
*Zuletzt aktualisiert: 28. Februar 2026*