151 lines
17 KiB
Markdown
151 lines
17 KiB
Markdown
# Hardware-Checkliste (EVK)
|
||
|
||
Konsole: `tools/monitor.sh /dev/cu.<port>` (115200 8N1). Flashen: `tools/flash.sh evk <port>` — das Skript nutzt `-rs none`, die Lampe braucht also einen **manuellen** Reset in dem Zeitfenster, in dem `wm_tool` auf den Sync wartet; ein automatischer Reset über die Steuerleitungen funktioniert an diesem Board nicht.
|
||
|
||
## 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-<mac4>`, `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-<mac4>` 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://<ip>: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-<mac4>` 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)
|
||
- [x] SM2135EH: Standby-Bit bei allen Kanälen 0 — 2026-09-13 an migrierter GU10 RGB geprüft: **war ein echter Fehler**, die Lampe glomm im Aus weiter. Bit 5 im Kanal-Register wird jetzt gesetzt (Commit zu v0.3.8); danach beide Ausschaltwege (aus Weiß und aus Farbe) vollständig dunkel
|
||
- [ ] E27 Color (SM2135EH): RGB und WY getrennt, Ströme plausibel (nicht zu heiß) — *derselbe Treiber ist am 2026-09-13 an einer GU10 RGB geprüft (rot/grün/blau sauber getrennt, warm- und kaltweiß deutlich unterschieden); für die E27 selbst steht die Prüfung noch aus*
|
||
- [ ] E27 CW: Gegenphase CW sichtbar flackerfrei
|
||
- [x] G95: Pinbelegung WW=PB15/CW=PB13 — 2026-09-13 an einer migrierten G95 geprüft: unteres Bereichsende deutlich warm, oberes deutlich kühler (damals noch 2500–5000 K, inzwischen 2000–5000 K), Dimmen auf 10 % flackerfrei, weiches Ausblenden
|
||
- [ ] Farbtemperaturbereiche aller Varianten — *die Bereiche stammen seit 2026-09-13 von Michael aus den Produktdaten und stehen so in `nl_board.c`: G95 Vintage **2000–5000 K**, alle übrigen **2700–6500 K**. Vorher standen die vier Weiß-Varianten flach auf 2500–5000 K, was für die E27/E14/GU10 CW den oberen Bereich abgeschnitten und für die G95 den unteren verschenkt hat. Am Gerät gegengeprüft ist bisher nur gu10_rgb; die G95 wurde mit den alten Grenzen getestet und gehört an den neuen wiederholt.*
|
||
|
||
## Standalone-AP-Modus (Abnahme am EVK, MAC 28:6d:cd:5c:68:1f)
|
||
|
||
- [x] `type: standalone` per `PUT system/settings` einschalten → 202 `{"status":"standalone"}`, `system/info` meldet `wifi.standalone: true` — 2026-10-02
|
||
- [x] Neustart → Lampe startet direkt im eigenen AP: Konsole `wifi: standalone AP, hostname ninlight-681f`, keine Onboarding-Zeile, kein Onboarding-Pulsen (den gibt es nur im Zustand `AP_ONBOARDING`, aus dem Code ableitbar; der Standalone-Startpuls ist davon getrennt und unten offen) — 2026-10-02
|
||
- [x] Geänderte AP-Daten → `wifi: AP data changed, rebuilding`, danach `wifi: AP ninlight-681f (ch 6) up` — 2026-10-02
|
||
- [x] Standalone mit exakt den Vorgabedaten auf einem bereits stehenden Onboarding-AP (kein Neuaufbau) löst die mDNS-Bekanntmachung ebenfalls aus — 2026-10-02
|
||
- [x] mDNS im eigenen AP: Konsole `mdns: ninlight-681f.local _ninlight._tcp up on en1 192.168.4.1`, `dns-sd -G v4 ninlight-681f.local` löst auf `192.168.4.1` auf, `ping` 0 % Verlust — 2026-10-02
|
||
- [x] REST über den AP antwortet auf `192.168.4.1:3333` — 2026-10-02
|
||
- [ ] Startpuls als Sichtprüfung: läuft beim Start rund 5 s und gibt danach das normale Einschaltverhalten frei; mit `pulse: false` entfällt er ganz — *Logik ist hostgetestet, am Gerät hat noch niemand hingesehen*
|
||
- [ ] REST über den AP verlangt das Token (`GET system/settings` ohne Token → 401)
|
||
- [ ] WLAN eingeben, falsches Passwort → Gerät bleibt im eigenen AP mit eigenen Daten
|
||
- [ ] WLAN eingeben, richtiges Passwort → Gerät im Heimnetz, nach einem Neustart **nicht** wieder im AP
|
||
- [ ] Werksreset über 5× ein/aus → wieder unkonfigurierter Onboarding-AP
|
||
- [ ] sACN über den Standalone-AP, **sichtbar an der Lampe** (nicht nur `active: true`), unicast an die AP-IP und multicast — *Fallen: Ein Sender ohne gesetztes `IP_MULTICAST_IF` misst bei zwei Default-Routen das eigene LAN statt den AP (am 2026-10-01 genau so schiefgegangen). Ein laufender Startpuls übermalt die sACN-Ausgabe, weil `nl_engine_pulse()` eine Überlagerung ist: für die Prüfung `pulse: false` setzen oder den Puls abwarten.*
|
||
|
||
## 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.
|
||
|
||
## Migration echter Lampen (Plan 4b, 2026-09-13)
|
||
|
||
- [x] G95 (Dev-Build, Product-ID `-klyqa.lighting.cw-ww.g95-dev`) mit dem **Entwicklungs**schlüssel signiert → angenommen, geflasht, läuft ninlight als `g95_cw`
|
||
- [x] GU10 (Produktionsbuild, Product-ID `-klyqa.lighting.rgb-cw-ww.gu10`) mit dem **Produktions**schlüssel signiert → angenommen, geflasht, läuft ninlight als `gu10_rgb`
|
||
- [x] Migrierte Lampe lässt sich anschließend über das normale ninlight-OTA aktualisieren (GU10 auf 0.3.8)
|
||
|
||
## Migrationsstation (Plan 4c) — Abnahme 2026-09-14
|
||
|
||
Station: Raspberry Pi Zero W Rev 1.1, Raspberry Pi OS Bookworm 12 (Python 3.11.2, Pillow 9.4.0,
|
||
armv6), Waveshare 2,13" E-Paper **Revision V3** als HAT, ein Taster auf GPIO23 (noch ohne Funktion).
|
||
|
||
- [x] `setup_pi.sh` richtet einen **nackten** Pi vollständig ein — Pakete, SPI, beide
|
||
NetworkManager-Profile, Server, CLI, Anzeigedienst. Zweimal von Grund auf durchgelaufen.
|
||
- [x] SPI wird automatisch eingeschaltet, der Neustart-Hinweis erscheint nur bei echter Änderung.
|
||
- [x] `deploy.sh` liefert 8 OTA-Images und 16 signierte Migrationsimages aus.
|
||
- [x] Panel-Revision am Testbild bestimmt: **V3**.
|
||
- [x] Horchphase: GU10 RGB meldet sich, wird erkannt, bekommt **404** — es floss kein Byte.
|
||
Protokoll: `/qcx_firmware_-klyqa.lighting.rgb-cw-ww.gu10_V1.1.1.103_ota_light.img 404 0B`
|
||
Daraus abgeleitet: Ziel `gu10_rgb`, Variante **prod** (kein `-dev`), Lampenversion V1.1.1.103.
|
||
- [x] Erkennung am Panel sichtbar, vom Bediener bestätigt.
|
||
- [x] Zeitschalter holt die Station selbsttätig ins Heim-WLAN zurück (3 und 15 Minuten geprüft).
|
||
- [x] `arm gu10_rgb` freigegeben, Lampe migriert, startet neu, läuft mit `0.3.8-24-geaaef`,
|
||
per mDNS auffindbar und über REST steuerbar. `last_ota_error: null`.
|
||
- [x] Migrierte Lampe meldet `color: true`, `color_temp: [2700, 6500]`, `transition_default: 300`,
|
||
`wake_on_change: false`.
|
||
- [x] Ausschaltfade ohne Farbrest an der frisch migrierten Lampe — 2026-09-14 bestätigt.
|
||
- [ ] **Nicht geprüft und weiterhin offen: E27 RGB, E14 (RGB und CW), GU10 CW.** Von diesen
|
||
Varianten lag kein Exemplar vor. Ihre Pinbelegung stammt aus der alten Firmware und war
|
||
nie an echter Hardware verifiziert.
|
||
|
||
**Befund während der Abnahme, behoben in `0fe9ca6`:** `ninlight-station off` stoppte den
|
||
Anzeigedienst, aber kein `on`-Pfad startete ihn wieder — nach dem ersten `off` (das auch der
|
||
Zeitschalter auslöst) blieb das Panel bis zum Neustart des Pi dunkel. `off` fasst den
|
||
Anzeigedienst seitdem gar nicht mehr an: er läuft durchgehend und erkennt den ausgeschalteten
|
||
Zustand selbst (`systemctl is-active ninlight-station`), zeichnet also von sich aus
|
||
**Station aus**. Der ausdrückliche Diagnosebefehl `ninlight-station display off` bleibt erhalten.
|
||
Abgesichert durch die Fälle D4 und D4b in `tools/station/tests/test_cli.sh`.
|
||
|
||
**Hardware-Lehre:** Vier Kernel-Paniken an einem Tag, alle mit derselben Fehleradresse und
|
||
unabhängig von Karte und Konfiguration, kamen von einem Mehrfach-Netzteil, das sein Budget
|
||
dynamisch neu verhandelt. Mit einem eigenen Netzteil: `throttled=0x0` auch unter Schreiblast.
|
||
Die zerschossene erste SD-Karte war die Folge, nicht die Ursache.
|