Files
ninlight-w600/docs/hardware-checklist.md
T

18 KiB
Raw Blame History

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)

  • Nach dem Boot blendet warmweiß 100 % in 0,5 s ein
  • rgb 255 0 0 → nur Rot, rgb 0 255 0 → nur Grün, rgb 0 0 255 → nur Blau
  • ct 2700 → nur Warmweiß, ct 6500 → nur Kaltweiß, ct 4000 → Mischung
  • bri 1 sichtbar sehr dunkel, bri 100 hell; bri 1 3000 → gleichmäßig wirkender Fade
  • off 2000 → blendet mit aktueller Farbe aus; on 2000 → blendet ein
  • rgb 255 0 0 dann ct 3000 2000 → erst dunkel, dann weiß (Moduswechsel)
  • blink 3 → 3× Blinken, danach alter Zustand; pulse on / pulse off
  • Kein sichtbares Flackern bei konstanten Werten (5 kHz)

Persistenz und Boot (Plan 1, Task 12)

  • pob last: Farbe setzen, 4 s warten, Strom aus/an → gleicher Zustand, mit Fade
  • pob off: Strom aus/an → bleibt aus; on → letzte Farbe
  • pob on bei ausgeschaltetem Licht: Strom aus/an → an
  • 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)
  • 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
  • Getestet am 2026-09-11 mit Firmware 7502f4f am EVK (MAC 28-6D-CD-5C-68-1F)

Netzwerk & REST (Plan 2)

  • Mit Build-Credentials: Boot → net zeigt mode=sta und eine IP, RSSI plausibel (−30 … −90) — 2026-09-12
  • dns-sd -B _ninlight._tcp findet ninlight-<mac4>, dns-sd -L zeigt TXT type/fw/mac/name — 2026-09-12
  • Bruno: alle Device-Requests wirken sichtbar, Get State spiegelt den Zustand — 2026-09-12
  • Ungültiger Body ({"brightness":0}) → 400, system/settings ohne Token → 401 — 2026-09-12
  • bri 30 per REST ({"brightness":30}) oder Konsole bri 30, dann sofort Reboot per REST → nach dem Boot 30 % (Flush) — 2026-09-12
  • Werksreset → AP ninlight-<mac4> sichtbar, Lampe pulsiert, Beitritt mit ninlight — 2026-09-12
  • Onboarding mit falschem Passwort → system/info zeigt wifi.error = "auth", AP bleibt — 2026-09-12
  • 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
  • Namensänderung per REST → TXT name= aktualisiert (dns-sd -L) — 2026-09-12
  • auth_all an → GET device/state ohne Token 401, mit Token 200 — 2026-09-12
  • Onboarding-Tests: Build ohne NINLIGHT_WIFI_SSID in config.local.cmake — 2026-09-12
  • C1: curl -d '[[[[[[[[[[[[[[[[[[[[' http://<ip>:3333/api/v1/device/state → 400, Lampe läuft unverändert weiter (kein Absturz/Reboot) — 2026-09-12
  • 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)

  • 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)
  • 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)
  • OTA: Image mit verfälschtem Byte wird abgelehnt (last_ota_error = hash oder crc), kein Reset — 2026-09-12 (crc, kein Reset)
  • 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
  • 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)
  • 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
  • Einstellungen bleiben über ein OTA hinweg erhalten (WLAN, Name, Fade-Zeiten) — 2026-09-12 (Name, Fade 1200/800, pob, Lichtzustand)
  • 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)
  • 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)
  • 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)
  • 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
  • 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 — 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
  • 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)

  • type: standalone per PUT system/settings einschalten → 202 {"status":"standalone"}, system/info meldet wifi.standalone: true — 2026-10-02
  • 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
  • Geänderte AP-Daten → wifi: AP data changed, rebuilding, danach wifi: AP ninlight-681f (ch 6) up — 2026-10-02
  • Standalone mit exakt den Vorgabedaten auf einem bereits stehenden Onboarding-AP (kein Neuaufbau) löst die mDNS-Bekanntmachung ebenfalls aus — 2026-10-02
  • 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
  • REST über den AP antwortet auf 192.168.4.1:3333 — 2026-10-02
  • Startpuls als Sichtprüfung: Michael hat zugesehen — der Puls lief nach dem Start, hörte nach rund 5 s auf, danach stand die voreingestellte Farbe wieder. Das Einschaltverhalten greift vor dem Netz-Task (app_main.c:224 vs. :250), die Lampe zeigt deshalb erst ihre Farbe und der Puls legt sich darüber — 2026-10-02
  • REST über den AP verlangt das Token: im Standalone-AP GET system/settings ohne Token → 401 unauthorized, mit Werkstoken → 200; GET system/info ohne Token → 200. Gegenprobe nach dem Werksreset im unkonfigurierten Onboarding-AP: derselbe Aufruf ohne Token → 200 — 2026-10-02
  • {"enabled":false} ohne gespeicherte WLAN-Daten: 202, danach heißt der AP wieder ninlight-681f (Beitritt mit dem Vorgabepasswort gelang, Name und Passwort sind also umgestellt), system/info meldet wifi.ssid: ninlight-681f und standalone: false, GET system/settings ohne Token → 200. Der gespeicherte Wunschname bleibt in system/settings als standalone.ssid: Buehne stehen — 2026-10-02
  • Standalone-Daten ändern, während der Aufrufer über den AP verbunden ist: die 202 kommt an. Direkter Vorher/Nachher-Beleg — derselbe Aufruf lieferte auf dem Stand vor der I6-Pause HTTP 000 (Verbindung riss ab, bevor die Antwort raus war), mit der Pause {"status":"standalone"} HTTP 202 — 2026-10-02
  • WLAN eingeben, falsches Passwort → Gerät bleibt im eigenen AP mit eigenen Daten: 202 connecting, nach dem Fehlschlag wifi.error: auth, standalone: true, AP weiterhin Buehne mit dem Nutzerpasswort, GET system/settings ohne Token weiterhin 401 — 2026-10-02
  • WLAN eingeben, richtiges Passwort → Gerät im Heimnetz (192.168.2.58, standalone: false), nach einem Neustart mode: sta und nicht wieder im AP — 2026-10-02
  • Im Standalone-Betrieb meldet GET system/info unter wifi.ssid den AP-Namen: an einer Lampe mit gespeichertem Heimnetz (settings.wifi.ssid: ninIOT, source: stored) meldete die tokenfreie Antwort wifi.ssid: Buehne, nicht ninIOT. Vor dem Wechsel in den Standalone-Modus stand dort korrekt die Stations-SSID — 2026-10-02
  • Werksreset über 5× ein/aus → wieder unkonfigurierter Onboarding-AP: alte Heimnetz-IP antwortet nicht mehr, AP ninlight-681f mit Vorgabepasswort, settings ohne Token → 200, alle Werte auf Vorgabe (name: '', standalone.enabled: false) — 2026-10-02
  • sACN über den Standalone-AP, sichtbar an der Lampe: Michael hat grün (unicast an 192.168.4.1) und blau (multicast 239.255.0.1, Sender mit IP_MULTICAST_IF auf 192.168.4.2) gesehen, sacn.active jeweils true — 2026-10-02

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)

  • Station installiert per tools/station/setup_pi.sh, idempotent (zweiter Lauf ließ die Konfiguration in Ruhe) — 2026-09-13
  • ninlight-station on schaltet Zugangspunkt und Dienst gemeinsam, status meldet Dienst, Adresse, Image und Version, Exit 0 — 2026-09-13
  • 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
  • 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
  • Zustandsdatei der Station protokolliert beide Auslieferungen mit status: ok, Gerätetyp und Version — 2026-09-13
  • Fehlendes Image für den Gerätetyp → Station antwortet 404, Eintrag notfound, Lampe bootet normal weiter — 2026-09-13 (Lampe meldete update failed (download))
  • 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)
  • 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)
  • 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.
  • 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)

  • G95 (Dev-Build, Product-ID -klyqa.lighting.cw-ww.g95-dev) mit dem Entwicklungsschlüssel signiert → angenommen, geflasht, läuft ninlight als g95_cw
  • GU10 (Produktionsbuild, Product-ID -klyqa.lighting.rgb-cw-ww.gu10) mit dem Produktionsschlüssel signiert → angenommen, geflasht, läuft ninlight als gu10_rgb
  • 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).

  • setup_pi.sh richtet einen nackten Pi vollständig ein — Pakete, SPI, beide NetworkManager-Profile, Server, CLI, Anzeigedienst. Zweimal von Grund auf durchgelaufen.
  • SPI wird automatisch eingeschaltet, der Neustart-Hinweis erscheint nur bei echter Änderung.
  • deploy.sh liefert 8 OTA-Images und 16 signierte Migrationsimages aus.
  • Panel-Revision am Testbild bestimmt: V3.
  • 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.
  • Erkennung am Panel sichtbar, vom Bediener bestätigt.
  • Zeitschalter holt die Station selbsttätig ins Heim-WLAN zurück (3 und 15 Minuten geprüft).
  • 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.
  • Migrierte Lampe meldet color: true, color_temp: [2700, 6500], transition_default: 300, wake_on_change: false.
  • 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.