MQTT-Display-LaserCutter/test_sketches
2026-02-28 22:38:59 +01:00
..
mqtt_test_secrets.h.example feat(FR-002): Web Console via HTTP-Polling (/log + /log-data) -- v1.1.0 2026-02-28 17:24:56 +01:00
README.md feat(web): HTTP-Basic-Auth fuer alle Routen; webUser/webPassword in NVS; ElegantOTA.setAuth() 2026-02-23 21:32:47 +01:00
test_button.cpp feat(phase1): complete hardware setup, display and button test sketches 2026-02-22 13:20:52 +01:00
test_display_manager.cpp fix(display): showSessionRing 1-basiert (1..60), kein Flash bei Session-Start 2026-02-28 22:38:59 +01:00
test_display.cpp feat(phase1): complete hardware setup, display and button test sketches 2026-02-22 13:20:52 +01:00
test_laser_tracker.cpp feat(display): showSessionRing - Sekunden-Kreisanzeige auf Modulen 5-7, 12-Uhr-Start (Phase 5b / 5.7 abgeschlossen) 2026-02-23 20:19:33 +01:00
test_mqtt_client.cpp feat(display): showSessionRing - Sekunden-Kreisanzeige auf Modulen 5-7, 12-Uhr-Start (Phase 5b / 5.7 abgeschlossen) 2026-02-23 20:19:33 +01:00
test_nvs.cpp feat(settings): implement NVS persistence via Preferences 2026-02-22 13:35:44 +01:00
test_telnet.cpp feat(FR-002): Web Console via HTTP-Polling (/log + /log-data) -- v1.1.0 2026-02-28 17:24:56 +01:00
test_web_server.cpp feat(display): showSessionRing - Sekunden-Kreisanzeige auf Modulen 5-7, 12-Uhr-Start (Phase 5b / 5.7 abgeschlossen) 2026-02-23 20:19:33 +01:00
test_wifi.cpp feat(wifi): implement WiFiManager connection handling 2026-02-22 13:50:07 +01:00

Test Sketches - Hardware-Verifikationstests

Eigenstaendige Test-Sketches zur Verifikation der Hardware und einzelner Subkomponenten. Jeder Sketch laeuft als separates PlatformIO-Environment und beruehrt src/main.cpp nicht.

Übersicht

Nr. Environment Datei Testet
1.4 test-display test_display.cpp GYMAX7219 Verkabelung, Modul-Nummerierung, Rotation
1.5 test-button test_button.cpp Potentialfreier Schalter / Debounce an GPIO 4
2.2 test-nvs test_nvs.cpp NVS Lesen/Schreiben/Reset (SettingsManager)
3.3 test-wifi test_wifi.cpp WiFiManager Captive Portal, WLAN-Verbindung
4.3 test-display-mgr test_display_manager.cpp DisplayManager API (alle show*-Methoden)
5.6 test-laser-tracker test_laser_tracker.cpp LaserTracker Session-Logik, Gratiszeit, Summe Session/NVS
6.5 test-mqtt test_mqtt_client.cpp MqttClient TLS, Heartbeat, Session-Publish, JSON-Reset, LWT
7.7 test-web test_web_server.cpp WebServer Routen, Config-Formular, Reset, ElegantOTA OTA

Physisches Display-Layout (GYMAX7219, 4x2)

DIN <- ESP32 GPIO 23
        |
+----------+----------+----------+----------+
| Modul 1  | Modul 2  | Modul 3  | Modul 4  |  <- Obere Reihe  (0-idx: 0-3)
|  links   |          |          |  rechts  |
+----------+----------+----------+----------+
| Modul 5  | Modul 6  | Modul 7  | Modul 8  |  <- Untere Reihe (0-idx: 4-7)
|  links   |          |          |  rechts  |
+----------+----------+----------+----------+
  DOUT Modul 4 -> DIN Modul 5 (Reihen verbinden)

SPI-Datenfluss: ESP32 -> Modul 1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8

Hardware-Typ: GENERIC_HW (verifiziert; 90 Grad CCW Software-Rotation aktiv per rotateCCW())

Modul-Belegung im Betrieb

Modul(e) 0-Index Funktion
Modul 1 0 WiFi-Fehler-Indikator (E = kein WLAN, leer = OK)
Modul 2-4 1-3 Summe Session-Minuten ganzzahlig (0 bei Neustart, RAM-only)
Modul 5 4 MQTT-Fehler-Indikator (E = kein Broker, leer = OK)
Modul 6-8 5-7 Countdown (Gratiszeit) oder -- (Idle/Netto)

Test 1.4 - Dot-Matrix-Display (test_display.cpp)

Zweck

Verdrahtung und Ausrichtung aller 8 GYMAX7219-Module pruefen.

Flash & Monitor

pio run -e test-display --target upload
pio device monitor -e test-display

Verdrahtung

ESP32 GPIO Modul-Pin Beschreibung
GPIO 23 DIN SPI Data (VSPI MOSI)
GPIO 18 CLK SPI Clock
GPIO 5 CS / LOAD SPI Chip Select
GND GND Masse (gemeinsam mit ESP32 GND)
5V extern VCC Externes Netzteil >= 1 A (USB-Port reicht nicht aus)

Erwartetes Verhalten

  1. Alle LEDs EIN (2 s) - alle 8 Module leuchten
  2. Jedes Modul zeigt seine Nummer einzeln
  3. Realistische Anzeige: Minuten oben, Countdown unten Text erscheint lesbar (nicht gespiegelt oder kopfstehend).

Ergebnis

  • GYMAX7219 mit GENERIC_HW + 90 Grad CCW Software-Rotation
  • Modul 1 oben-links, Modul 8 unten-rechts
  • Externes 5 V-Netzteil notwendig

Test 1.5 - Potentialfreier Schalter (test_button.cpp)

Zweck

GPIO-Eingang (INPUT_PULLUP) testen, Pegel und Entprellzeit verifizieren.

Flash & Monitor

pio run -e test-button --target upload
pio device monitor -e test-button

Verdrahtung

ESP32 GPIO 4  ----| Button |----- GND   (kein externer Widerstand noetig)

Erwartetes Verhalten

Zustand GPIO-Pegel Serial-Ausgabe
Schalter offen HIGH HIGH (inaktiv)
Schalter geschl. LOW LOW -> LASER AKTIV

Ergebnis

  • LOW_ACTIVE-Polaritaet bestaetigt
  • Debounce 50 ms funktioniert

Test 2.2 - NVS Persistenz (test_nvs.cpp)

Zweck

Schreiben, Lesen und Reset aller NVS-Werte ueber den SettingsManager pruefen.

Flash & Monitor

pio run -e test-nvs --target upload
pio device monitor -e test-nvs

Testablauf

  1. Testwerte in NVS schreiben (MQTT-Config, gratisSeconds, totalMinutes, Polaritaet)
  2. NVS-Werte zuruecklesen und pruefen
  3. ESP32 neu starten -> Werte muessen erhalten bleiben
  4. settings.reset() aufrufen -> alle Werte auf Default zurueck

Erwartetes Verhalten

Alle Pruefungen als PASS im Serial Monitor. Nach Neustart bleiben geschriebene Werte erhalten.

Ergebnis

  • NVS Roundtrip fuer alle Felder bestanden
  • reset() setzt auf Defaults zurueck
  • Persistenz ueber Neustart bestaetigt

Test 3.3 - WiFiManager (test_wifi.cpp)

Zweck

WiFiManager Captive Portal und WLAN-Verbindungsaufbau testen.

Flash & Monitor

pio run -e test-wifi --target upload
pio device monitor -e test-wifi

Testablauf

  1. Erstes Flash: ESP32 oeffnet AP LaserCutter-Setup
  2. Mit Handy/PC mit AP verbinden - Captive Portal oeffnet sich automatisch
  3. WLAN-Credentials eingeben und speichern
  4. ESP32 verbindet sich mit dem WLAN und gibt IP-Adresse aus
  5. BOOT-Taste (GPIO 0) beim Start 3 s halten -> gespeicherte Credentials loeschen, AP neu oeffnen

Erwartetes Verhalten

Nach erfolgreicher Verbindung im Serial Monitor:

[WiFi] Verbunden: 192.168.x.x

Ergebnis

  • Captive Portal startet korrekt
  • Credentials werden in NVS gespeichert
  • Reconnect nach Neustart ohne Portal

Test 4.3 - DisplayManager (test_display_manager.cpp)

Zweck

Alle show*-Methoden des DisplayManager auf korrektes Modul-Mapping und Darstellung pruefen.

Flash & Monitor

pio run -e test-display-mgr --target upload
pio device monitor -e test-display-mgr

Testablauf (automatisch, kein Eingriff noetig)

Der Sketch durchlaeuft nacheinander:

Schritt Methode Modul(e) Erwartete Anzeige
1 showWifiError(true) 0 E
2 showWifiError(false) 0 leer
3 showLaserTime(0) 1-3 0
4 showLaserTime(42) 1-3 42
5 showLaserTime(999) 1-3 999
6 showMqttError(true) 4 E
7 showMqttError(false) 4 leer
8 showCountdown(20) 5-7 20
9 showCountdown(1) 5-7 1
10 showIdle() 5-7 --

Ergebnis

  • Alle Module reagieren auf die korrekten Methoden
  • showLaserTime() zeigt ganze Zahlen rechtbuendig
  • Fehler-Indikatoren auf Modul 0 und 4 unabhaengig voneinander

Test 5.6 - LaserTracker (test_laser_tracker.cpp)

Zweck

Session-Zustandsmaschine, Gratiszeit-Countdown, Summe Session-Minuten und NVS-Gesamtzeit pruefen.

Flash & Monitor

pio run -e test-laser-tracker --target upload
pio device monitor -e test-laser-tracker

Verdrahtung

GPIO 4: Push-Button gegen GND (simuliert Laser-AN/AUS, LOW_ACTIVE)

Testablauf

A) Gratis-Session (Laser < 20 s):

  1. Schalter schliessen -> Countdown startet auf Modul 6-8
  2. Schalter vor Ablauf der 20 s oeffnen
  3. Erwartung: Summe Session-Minuten unveraendert (0), NVS erhoehte sich um Session-Dauer

B) Netto-Session (Laser > 20 s):

  1. Schalter schliessen -> Countdown startet
  2. Nach 20 s -> Countdown erlischt, Module 6-8 zeigen --
  3. Schalter nach z.B. 80 Netto-Sekunden oeffnen
  4. Erwartung: keine Minutenaenderung (80 s < 60 s ist falsch; 80 s >= 60 s -> +1 Minute auf Modul 2-4)

C) Neustart-Test:

  1. ESP32 neu starten
  2. Erwartung: Summe Session-Minuten = 0 auf Modul 2-4
  3. NVS-Gesamtzeit aus vorherigen Sessions bleibt erhalten (im Serial Monitor sichtbar)

D) Komplett-Reset:

  1. BOOT-Taste (GPIO 0) 3 Sekunden halten
  2. Erwartung: settings.reset() + resetTotal() -> gratisSeconds = 20, totalMinutes = 0

Erwartetes Display-Verhalten

Zustand Module 1-3 (Session) Module 5-7 (Status)
Idle 0 --
Laser an (0-20 s) 0 20 -> 1 Countdown
Laser an (> 20 s) 0 --
Laser aus nach 80 Netto-s 1 --
Neustart 0 --

Ergebnis

  • GRATIS -> NET_COUNTING Uebergang nach 20 s
  • Session-Minuten incrementieren hart bei 60 Netto-Sekunden
  • Gratis-Sessions addieren keine Session-Zeit
  • Gratis-Sessions senden kein MQTT-Publish
  • NVS zaehlt gesamte Laser-AN-Zeit (inkl. Gratiszeit)
  • resetTotal() loescht NVS + Session

Test 6.5 - MqttClient (test_mqtt_client.cpp)

Zweck

MQTT-Verbindung, Session-Publish, Heartbeat und Reset-Subscribe ueber broker.hivemq.com pruefen.

Flash & Monitor

pio run -e test-mqtt --target upload
pio device monitor -e test-mqtt

Vorbereitung: MQTT Explorer

  1. MQTT Explorer herunterladen: https://mqtt-explorer.com (kostenlos, Windows/Mac/Linux)
  2. Neue Verbindung anlegen:
    • Host: broker.hivemq.com
    • Port: 1883
    • Kein Username / Passwort
  3. Verbinden -> lasercutter/# wird automatisch angezeigt

Testablauf

A) Verbindung & Heartbeat:

  1. ESP32 flashen und starten
  2. Serial Monitor: [MQTT] Verbunden! und sofortiger Heartbeat erwartet
  3. Im MQTT Explorer: lasercutter/status erscheint mit {"online":true,...} (retained)
  4. Nach 60 s: erneuter Heartbeat sichtbar

B) Session-Publish nach Session-Ende:

  1. GPIO 4 Taste druecken (Laser AN) -> Countdown auf Modul 6-8
  2. Taste loslassen (Laser AUS) nach Ablauf der Gratiszeit
  3. Serial: SessionEnd -> publishSession
  4. MQTT Explorer: lasercutter/session erscheint mit JSON:
    {"session_minutes": 1, "session_seconds": 5, "freetime_s": 20, "ip": "192.168.x.x"}
    

C) Gratis-Session (< 20 s):

  1. Taste < 20 s druecken und loslassen
  2. Kein Publish auf lasercutter/session (Netto-Zeit = 0s)
  3. machine_running_time_min im naechsten Heartbeat erhoehte sich trotzdem (Gratiszeit zaehlt in NVS)

D) Reset-Kommando via MQTT:

  1. Im MQTT Explorer auf Topic lasercutter/reset publishen
    • JSON-Payload (empfohlen): {"reset":true}
    • Alternativ Plain: 1
  2. Serial: [MQTT] RESET-Kommando empfangen -> laserTracker.resetTotal()
  3. Naechster Heartbeat zeigt "total_min": "0.00"

E) LWT (Last Will und Testament):

  1. USB-Kabel ziehen (oder Strom aus)
  2. Nach ca. 60 s (Broker Keep-Alive-Timeout) erscheint im MQTT Explorer:
    • lasercutter/status -> {"online":false} (retained, vom Broker versendet)

F) Reconnect-Test:

  1. WiFi-Router kurz ausschalten oder ESP32 in WLAN-toten Bereich bringen
  2. Serial: alle 10 s [MQTT] Verbindung fehlgeschlagen, rc=-2
  3. Modul 5 zeigt E (MQTT-Fehler-Indikator)
  4. WiFi wieder einschalten -> automatischer Reconnect, E erlischt

G) BOOT-Taste lokaler Reset:

  1. BOOT-Taste (GPIO 0) 3 s halten
  2. Serial: BOOT 3s: Gesamtzeit loeschen
  3. total_min springt auf 0

Erwartetes Serial-Verhalten (Auszug)

[I][TEST-MQTT] === Phase 6 MQTT Test gestartet ===
[I][TEST-MQTT] Broker Default: broker.hivemq.com:1883
[MQTT] Broker: broker.hivemq.com:1883
[MQTT] Client-ID: lasercutter-display
[MQTT] Verbinde als 'lasercutter-display'...
[MQTT] Verbunden!
[MQTT] Abonniert: lasercutter/reset
[MQTT] Heartbeat: {"online":true,...} -> OK
...
[LaserTracker] SessionEnd: gesamt=35s  netto=15s  sessionNetSec=15  total=0.58min
[I][TEST-MQTT] SessionEnd -> publishSession (lastSession=15s)
[MQTT] publishSession: {"session_minutes":1,"session_seconds":15,"freetime_s":20,"ip":"192.168.x.x"} -> OK

Checkliste

Pruefpunkt Erwartung Ergebnis
Verbindung zu mqtt.majufilo.eu [MQTT] Verbunden! im Serial [x]
Heartbeat beim Connect lasercutter/status retained im MQTT Explorer [x]
Heartbeat alle 60 s Topic aktualisiert sich periodisch [x]
Session-Publish nach Session-Ende lasercutter/session mit session_minutes, session_seconds [x]
Gratis-Session publiziert NICHT kein Topic-Update bei lastSession=0 [ ]
Reset via MQTT (lasercutter/reset = {"reset":true}) total_min springt auf 0 [x]
LWT {"online":false} nach Verbindungsabbruch Nach 60 s im MQTT Explorer sichtbar [x]
MQTT-Error Modul 5 bei Verbindungsverlust E auf Display Modul 5 - ungetestet -
Reconnect nach WiFi-Ausfall Automatisch nach <= 10 s - ungetestet -

Test 7.7 - WebServer (test_web_server.cpp)

Zweck

Alle HTTP-Routen des WebServerManager im Browser pruefen: Statusseite, Konfigurationsformular (NVS), Session-Reset und ElegantOTA.

Flash & Monitor

pio run -e test-web --target upload
pio device monitor -e test-web

Vorbereitung

IP-Adresse aus dem Serial Monitor ablesen (erscheint nach WiFi-Connect):

[I][TEST-WEB] Browser: http://192.168.x.x/

Testablauf

A) Statusseite GET /:

  1. Browser oeffnen: http://<IP>/
  2. Folgende Felder pruefen:
    • Summe Session-Minuten, Maschinenlaufzeit (gesamt), letzte Laserzeit
    • IP-Adresse und MQTT-Status (verbunden/getrennt)
    • Broker-Hostname und Gratiszeit
  3. Seite aktualisiert sich automatisch alle 10 s
  4. GPIO 4 Taste betaetigen -> Session-Minuten aendern sich

B) Konfigurationsformular GET /config + POST /config:

  1. Browser: http://<IP>/config
  2. Felder pruefen: Broker, Port, User, Passwort, Gratiszeit-Slider, Polaritaet-Radio
  3. Gratiszeit auf z.B. 30 s aendern und "Speichern" klicken
  4. Serial: [WebServer] Konfiguration gespeichert
  5. ESP32 neu starten -> Serial zeigt gratisSeconds: 30 -> NVS-Persistenz bestaetigt
  6. Config-Seite: Wert auf 20 s zuruecksetzen

C) Session-Reset POST /reset:

  1. Auf Statusseite: Button "Session zuruecksetzen" klicken
  2. Browser-Bestaetigung (confirm-Dialog) bestaetigen
  3. Statusseite zeigt Session: 0 min
  4. Gesamtzeit (NVS) bleibt unveraendert
  5. Serial: [WebServer] Session zurueckgesetzt

D) ElegantOTA GET /update:

  1. Browser: http://<IP>/update
  2. ElegantOTA-Seite erscheint
  3. (Optional) Test-Firmware hochladen und Neustart beobachten

E) HTTP-Basic-Auth:

  1. In /config Abschnitt "Web-Zugang": Passwort setzen (z.B. geheim) und speichern
  2. ESP32 neu starten
  3. Browser: http://<IP>/ → Browser-Login-Dialog erscheint
  4. Benutzername admin, Passwort geheim eingeben → Zugang gewährt
  5. Falsches Passwort eingeben → Browser zeigt 401 / erneuten Dialog
  6. In /config Passwort wieder leeren → nach Neustart kein Schutz mehr

Checkliste

Pruefpunkt Erwartung Ergebnis
Statusseite erreichbar HTML mit Session, Gesamtzeit, IP [ ]
MQTT-Status korrekt "verbunden" oder "getrennt" [ ]
Auto-Reload alle 10 s Seite aktualisiert sich [ ]
Config-Formular laden Aktuelle NVS-Werte vorbelegt [ ]
Gratiszeit aendern + speichern NVS-Wert nach Neustart korrekt [ ]
Polaritaet aendern + speichern NVS-Wert nach Neustart korrekt [ ]
Session-Reset per Browser Session = 0 min, Gesamtzeit (NVS) unveraendert [ ]
/update erreichbar ElegantOTA-Seite erscheint [ ]
Passwort setzen + Neustart Browser-Login-Dialog erscheint [ ]
Korrektes Passwort Zugang gewaehrt [ ]
Falsches Passwort 401 / erneuter Dialog [ ]
Passwort leeren + Neustart Kein Login-Dialog [ ]

Gesamt-Testergebnisse

Test Environment Status Anmerkung
1.4 test-display OK GENERIC_HW, 90 Grad CCW Rotation, externes 5V-Netzteil
1.5 test-button OK LOW_ACTIVE, Debounce 50 ms
2.2 test-nvs OK Alle NVS-Felder, Roundtrip, Persistenz, Reset
3.3 test-wifi OK Captive Portal, Credentials-Persistenz, Reconnect
4.3 test-display-mgr OK Alle show*-Methoden, Modul-Mapping, Fehler-Indikatoren
5.6 test-laser-tracker OK Session-Logik, Gratiszeit, Summe Session/NVS-Trennung, Reset
6.5 test-mqtt OK mqtt.majufilo.eu TLS:8883, publishSession, Heartbeat, Reset-Subscribe