# Hardware-Checkliste (EVK) Konsole: `tools/monitor.sh /dev/cu.` (115200 8N1). Flashen: `tools/flash.sh evk `. ## Licht (Plan 1, Task 11) - [x] Nach dem Boot blendet warmweiß 100 % in 0,5 s ein - [x] `rgb 255 0 0` → nur Rot, `rgb 0 255 0` → nur Grün, `rgb 0 0 255` → nur Blau - [x] `ct 2700` → nur Warmweiß, `ct 6500` → nur Kaltweiß, `ct 4000` → Mischung - [x] `bri 1` sichtbar sehr dunkel, `bri 100` hell; `bri 1 3000` → gleichmäßig wirkender Fade - [x] `off 2000` → blendet mit aktueller Farbe aus; `on 2000` → blendet ein - [x] `rgb 255 0 0` dann `ct 3000 2000` → erst dunkel, dann weiß (Moduswechsel) - [x] `blink 3` → 3× Blinken, danach alter Zustand; `pulse on` / `pulse off` - [x] Kein sichtbares Flackern bei konstanten Werten (5 kHz) ## Persistenz und Boot (Plan 1, Task 12) - [x] `pob last`: Farbe setzen, 4 s warten, Strom aus/an → gleicher Zustand, mit Fade - [x] `pob off`: Strom aus/an → bleibt aus; `on` → letzte Farbe - [x] `pob on` bei ausgeschaltetem Licht: Strom aus/an → an - [x] `fade 2000 2000` bleibt nach Reboot erhalten (`state`) - [ ] 5× Strom an/aus mit jeweils < 5 s Laufzeit → 3× Blinken, danach Defaults (`state`) (erneut zu prüfen: der vorgelagerte Recovery-Scan aus Plan 3 verschiebt jeden Boot um bis zu ~3 s, das Timing der 5-Sekunden-Grenze ist damit nicht mehr das von Plan 1) - [ ] Normaler Boot nach > 5 s Laufzeit → kein Werksreset (erneut zu prüfen, gleicher Grund: Recovery-Scan verschiebt die Boot-Zeitrechnung) - [x] Watchdog: `wdtest` → Neustart nach ca. 20–40 s (erste Ablaufzeit löst IRQ aus, Reset beim zweiten Ablauf) — getestet 2026-09-11 mit e19ee98: Neustart nach 40,4 s - [x] Getestet am 2026-09-11 mit Firmware 7502f4f am EVK (MAC 28-6D-CD-5C-68-1F) ## Netzwerk & REST (Plan 2) - [x] Mit Build-Credentials: Boot → `net` zeigt `mode=sta` und eine IP, RSSI plausibel (−30 … −90) — 2026-09-12 - [x] `dns-sd -B _ninlight._tcp` findet `ninlight-`, `dns-sd -L` zeigt TXT type/fw/mac/name — 2026-09-12 - [x] Bruno: alle Device-Requests wirken sichtbar, `Get State` spiegelt den Zustand — 2026-09-12 - [x] Ungültiger Body (`{"brightness":0}`) → 400, `system/settings` ohne Token → 401 — 2026-09-12 - [x] `bri 30` per REST (`{"brightness":30}`) oder Konsole `bri 30`, dann sofort `Reboot` per REST → nach dem Boot 30 % (Flush) — 2026-09-12 - [x] Werksreset → AP `ninlight-` sichtbar, Lampe pulsiert, Beitritt mit `ninlight` — 2026-09-12 - [x] Onboarding mit falschem Passwort → `system/info` zeigt `wifi.error = "auth"`, AP bleibt — 2026-09-12 - [x] Onboarding korrekt → `202`, Lampe verbindet, Pulsieren stoppt, AP nach 60 s weg — 2026-09-12 - [ ] Router aus > 5 min → AP erscheint (`mode=apsta`); Router an → Verbindung, AP nach 10 s weg - [x] Namensänderung per REST → TXT `name=` aktualisiert (`dns-sd -L`) — 2026-09-12 - [x] `auth_all` an → `GET device/state` ohne Token 401, mit Token 200 — 2026-09-12 - [x] Onboarding-Tests: Build ohne `NINLIGHT_WIFI_SSID` in `config.local.cmake` — 2026-09-12 - [x] C1: `curl -d '[[[[[[[[[[[[[[[[[[[[' http://:3333/api/v1/device/state` → 400, Lampe läuft unverändert weiter (kein Absturz/Reboot) — 2026-09-12 - [x] C2: Onboarding ok, 60 s warten, dann Reboot und Router-Neustart → AP `ninlight-` darf nicht wiederkommen (Scan am Mac) — 2026-09-12 (Reboot geprüft, Router-Neustart offen) ## OTA und Recovery (Plan 3) - [x] OTA: Update über `fw_update` läuft durch, danach meldet `system/info` die neue Version — 2026-09-12 (0.3.0 → 0.3.1 → 0.3.2) - [x] OTA: Image eines anderen Gerätetyps wird sofort abgelehnt (`last_ota_error` = `device_mismatch`), kein Reset, Lampe läuft mit der alten Firmware weiter — 2026-09-12 (Ablehnung nach ~4,5 s, Uptime lief durch) - [x] OTA: Image mit verfälschtem Byte wird abgelehnt (`last_ota_error` = `hash` oder `crc`), kein Reset — 2026-09-12 (`crc`, kein Reset) - [x] OTA: HTTP-Server während des Downloads abschalten → Lampe bleibt über REST erreichbar und schaltbar, weist weitere `fw_update` mit `409` ab, und beendet den Versuch mit `last_ota_error = download` — 2026-09-12 (dauerte ~7 min, kein Range-Resume; siehe README) - [ ] OTA: kurzer WLAN-Aussetzer während des Downloads (Verbindung kurz kappen und wiederherstellen) → Download wird fortgesetzt, kein sofortiger `download`-Fehler — *offen, WLAN am Teststandort nicht abschaltbar* - [x] Recovery: Lampe zieht beim Booten das Image von der Station `ninlight-recovery`, Konsole zeigt Scan-, Join- und Fetch-Meldungen — 2026-09-12 (Pi Zero 2W, NetworkManager-AP; Scan → join → fetch → flash → Reboot) - [x] Recovery: ohne Station verlängert sich der Boot um höchstens ~3 s, Konsole loggt das Scan-Ergebnis (gefunden/nichts gefunden/Scan fehlgeschlagen) — 2026-09-12 (`scan done after 1500 ms, 7 AP(s)`, danach normaler WLAN-Start) - [ ] Recovery: Gegenstelle bleibt verbunden, sendet aber keine Daten mehr (nicht: ein langsamer, aber laufender Download) → nach Ablauf der Zeitobergrenze bedient die Firmware den Watchdog nicht mehr, Chip startet neu statt hängen zu bleiben - [x] Einstellungen bleiben über ein OTA hinweg erhalten (WLAN, Name, Fade-Zeiten) — 2026-09-12 (Name, Fade 1200/800, pob, Lichtzustand) - [x] Zweiter `fw_update` mit gültigem Image direkt nach einer Ablehnung, ohne zwischenzeitlichen Reboot → läuft durch, `system/info` meldet danach die neue Version — 2026-09-12 (erst nach dem SHA256-Kontext-Fix) - [x] Lampe bleibt während und nach einer Ablehnung über REST erreichbar: `system/info` und `device/state` antworten beide weiterhin mit 200 — 2026-09-12 (system/info und device/state je 200) - [x] Lichtverhalten über ein OTA hinweg (Spec §8.2, ein Update ist kein Stromausfall): einmal mit `power_on_behaviour = off`, einmal `= on` — die Lampe ist nach dem Update jeweils in demselben Zustand (an/aus, Farbe/Helligkeit), in dem sie vor dem Update war — 2026-09-12 (pob=off + Licht an → blieb an; pob=on + Licht aus → blieb aus) - [x] `system/info.fw_version` nach einem OTA stimmt mit der Version im Trailer des geflashten Images überein (Trailer-Version z.B. mit `tools/mkimage` prüfen) — 2026-09-12 - [ ] Recovery im echten Rettungsfall: Lampe ohne gültige WLAN-Konfiguration bzw. im Onboarding-AP findet die Station, zieht das Image und startet mit der neuen Firmware - [x] Rettungsstation nach erfolgreicher Recovery angelassen lassen, Lampe neu booten lassen → kein erneutes Flashen (Version stimmt bereits überein) und kein Werksreset (Power-Cycle-Zähler wurde vor dem Recovery-Versuch gelöscht) — 2026-09-12 (zweiter Boot: `image already carries the running version, not flashing`, kein Werksreset, beide Boots melden `boot #1`) - [ ] OTA im **AP-/Fallback-Modus** (`mode=apsta`, kein Router erreichbar) → Update läuft durch wie im normalen `sta`-Modus — *offen, braucht einen abschaltbaren Access Point*. Mit `auth_all = true` am 2026-09-12 geprüft: Update läuft durch, `device/*` antwortet ohne Token korrekt mit 401 (`system/info` bleibt laut Spec §7.2 immer offen) Für den echten Flottenbau `NINLIGHT_RECOVERY_PASSWORD` und `NINLIGHT_TOKEN` in `config.local.cmake` setzen — die Defaults sind nur fürs EVK gedacht. ## Später (Lampen) - [ ] SM2135EH: Standby-Bit bei allen Kanälen 0 prüfen (Spec §4; alte Firmware setzte es praktisch nie) - [ ] E27 Color (SM2135EH): RGB und WY getrennt, Ströme plausibel (nicht zu heiß) - [ ] E27 CW: Gegenphase CW sichtbar flackerfrei - [ ] G95: Pinbelegung WW=PB15/CW=PB13 prüfen - [ ] Farbtemperaturbereiche aller Varianten ## Offene Beobachtung aus der EVK-Session vom 2026-09-12 Beim Test mit dem verfälschten Image meldete lwIP einmalig `Assertion "pbuf_free: p->ref > 0" failed at line 747 in pbuf.c` (10:29:23). Die Lampe lief unbeeinträchtigt weiter und meldete korrekt `last_ota_error=crc`. Bei den Läufen mit fremdem Gerätetyp und bei den erfolgreichen Updates trat die Meldung nicht auf. Ursache noch nicht geklärt — in einem Build ohne Assertions wäre das ein doppeltes Freigeben eines Netzwerkpuffers. Vor dem Einsatz auf echten Lampen reproduzieren und aufklären. ## Recovery gegen die installierte Pi-Station (2026-09-13) - [x] Station installiert per `tools/station/setup_pi.sh`, idempotent (zweiter Lauf ließ die Konfiguration in Ruhe) — 2026-09-13 - [x] `ninlight-station on` schaltet Zugangspunkt und Dienst gemeinsam, `status` meldet Dienst, Adresse, Image und Version, Exit 0 — 2026-09-13 - [x] Recovery zieht das Image und flasht: `recovery image version 0.3.7 (running 0.3.6)` → `trailer ok` → Neustart mit der neuen Version — 2026-09-13 - [x] Station angelassen, erneut gebootet → `already carries the running version 0.3.7, not flashing`, `ota: skipped`, kein Werksreset (beide Boots melden `boot #1`), `last_ota_error` bleibt leer — 2026-09-13 - [x] Zustandsdatei der Station protokolliert beide Auslieferungen mit `status: ok`, Gerätetyp und Version — 2026-09-13 - [x] Fehlendes Image für den Gerätetyp → Station antwortet `404`, Eintrag `notfound`, Lampe bootet normal weiter — 2026-09-13 (Lampe meldete `update failed (download)`) - [x] Stillstand: Server hält die Verbindung, sendet nichts mehr → nach Ablauf der Zeitobergrenze startet der Chip neu — 2026-09-13 (Download 00:42:17, ~120 Wiederaufnahmeversuche im 5-s-Takt mit je null Bytes, Obergrenze exakt bei 600000 ms um 00:52:17, Reset um 00:52:56 nach dem 20-s-Watchdog, danach `boot #1` ohne Werksreset) - [x] Wiederaufnahme nach Abriss: Gegenstelle erreichbar, sendet aber nichts mehr → Lampe setzt per `Range` fort — 2026-09-13 (fünf Fortsetzungen 263700 → 198164 → 132628 → 67092 → 1556, Image vollständig; gilt **nicht** für eine tote Gegenstelle, siehe README) - [x] Echter Rettungsfall: Lampe ohne gültige WLAN-Konfiguration findet die Station und wird geflasht — 2026-09-13, zweistufig belegt: (1) Station aus, Build ohne Zugangsdaten seriell aufgespielt → `ninlight 0.3.7-4-gb169fa`, Scan ohne Treffer, Lampe geht in den Onboarding-AP, über Netz nicht erreichbar. (2) Station an, ein Stromzyklus → `station found` → `recovery image version 0.3.7 (running 0.3.7-4-gb169fa)` → `trailer ok` → Neustart → `connecting to ninIOT`. 23 Sekunden vom Einschalten bis zur geretteten Lampe. - [x] `ninlight-station off`, Pi neu starten → Pi kommt im Heim-WLAN hoch, kein Zugangspunkt, Dienst inaktiv — 2026-09-13 **Bekannte Eigenheit:** Die Lampe lädt bei jedem Boot das komplette Image (~256 KB), auch wenn sie es danach wegen gleicher Version verwirft — die Version steht im Trailer am Dateiende. Kein Fehler, aber die Station sieht pro Boot einen vollen Transfer.