diff --git a/README.md b/README.md index 34e2f07..e3557c4 100644 --- a/README.md +++ b/README.md @@ -44,7 +44,7 @@ Firmware flashen (Standard: App-Image): tools/flash.sh -Das Skript druckt `Bitte bei "please manually reset the device" die Reset-Taste drücken.` — wenn wm_tool diese Nachricht zeigt, musst du die Reset-Taste am EVK drücken (Baud 460800). Für blank/erased Chips: `tools/flash.sh full` (flasht stattdessen das Vollbild mit secboot, auf Hardware noch ungetestet). +Das Skript druckt `Bitte bei "please manually reset the device" die Reset-Taste drücken.` — wenn wm_tool diese Nachricht zeigt, musst du die Reset-Taste am EVK drücken (Baud 460800). Das Skript ruft `wm_tool` mit `-rs none` auf, es löst also **keinen** Reset aus: Der Reset muss von Hand in dem Zeitfenster kommen, in dem `wm_tool` auf den Sync wartet. Ein automatischer Reset über die Steuerleitungen (`-rs rts` o. ä.) funktioniert an diesem Board nicht. Wer zu spät drückt, sieht `wm_tool` einfach weiter warten und startet den Aufruf neu. Für blank/erased Chips: `tools/flash.sh full` (flasht stattdessen das Vollbild mit secboot, auf Hardware noch ungetestet). Serielle Konsole (115200 8N1, lokales Echo): @@ -65,7 +65,7 @@ Verfügbare Befehle in der Konsole: `help`. gespeicherten Zugangsdaten). Im Fallback-AP (Router war > 5 min weg, Lampe hat aber bereits Zugangsdaten) ist der Token-Header wie bei jedem anderen Endpunkt erforderlich. Nach Erfolg schließt der AP nach 60 s. Ohne Verbindung für 5 min öffnet die Lampe den AP zusätzlich (Fallback). -- REST auf Port 3333, Präfix `/api/v1`: `GET|POST device/state`, `GET system/info`, `GET|PUT system/settings` (kennt u.a. den Typ `sacn`, siehe unten) und `PUT system/command` (beide mit Header `Authorization: `, Default-Token `aabbccddeeff0011223344`). +- REST auf Port 3333, Präfix `/api/v1`: `GET|POST device/state`, `GET system/info`, `GET|PUT system/settings` (kennt u.a. die Typen `sacn` und `standalone`, siehe unten) und `PUT system/command` (beide mit Header `Authorization: `, Default-Token `aabbccddeeff0011223344`). - Beispiel: `curl -X POST http://ninlight-681f.local:3333/api/v1/device/state -d '{"on":true,"brightness":40,"color_temp":2700}'` - Suchen: `dns-sd -B _ninlight._tcp` (macOS), Details `dns-sd -L ninlight-681f _ninlight._tcp`. - Bruno: `bruno/ninlight.yml` importieren, Environment „EVK (mDNS)" bzw. „Onboarding-AP" wählen. @@ -107,6 +107,42 @@ speichern. Zum Abschalten: `{"type":"sacn","enabled":false}`. Zum Ausprobieren liegt ein Sender bei: `tools/sacn_send.py --values 255,255,0,0,0,0 --seconds 5`. +### Standalone-AP + +Statt sich in ein WLAN einzuwählen, kann die Lampe dauerhaft einen eigenen Zugangspunkt aufspannen +(z. B. für Bühne oder Gartenhaus ohne Router). Der Modus überlebt Neustarts: die Lampe startet +direkt im eigenen AP, ohne Onboarding und ohne Onboarding-Pulsen. Die Lampe ist dann unter +`192.168.4.1` erreichbar, per mDNS als `.local`. + +Einschalten: + + curl -X PUT http://:3333/api/v1/system/settings \ + -H 'Authorization: ' \ + -d '{"type":"standalone","enabled":true,"ssid":"Buehne","password":"geheim123","channel":6}' + +Antwort `202 {"status":"standalone"}`. Felder: + +| Feld | Pflicht | Bedeutung | +|---|---|---| +| `enabled` | ja | `true` schaltet den Modus ein, `false` aus | +| `password` | beim Einschalten, solange noch keines gespeichert ist | AP-Passwort, 8..63 Zeichen | +| `ssid` | nein | AP-Name, 1..32 Zeichen; leer bzw. weggelassen heißt `ninlight-` | +| `channel` | nein | Funkkanal 1..13, Vorgabe 6 | +| `pulse` | nein | Startpuls beim Hochfahren der Lampe an/aus (läuft rund 5 s, danach gilt das normale Einschaltverhalten) | + +Ausschalten braucht kein Passwort: `{"type":"standalone","enabled":false}`. Hat die Lampe gespeicherte +WLAN-Daten, wählt sie sich damit wieder ins WLAN ein; ohne solche öffnet sie den offenen +Onboarding-AP `ninlight-`. + +`GET system/settings` zeigt einen `standalone`-Block mit `enabled`, dem **wirksamen** AP-Namen +(`ssid`), `channel` und `pulse` — das Passwort steht nie darin. `GET system/info` meldet +`wifi.standalone`. + +Der Startpuls übermalt als Überlagerung die sACN-Ausgabe: solange er läuft, ist von sACN nichts +zu sehen. Beim Ausprobieren von sACN über den eigenen AP den Puls mit `pulse: false` abschalten oder +abwarten. Außerdem muss der Sender bei zwei Default-Routen (LAN und AP) das Interface für Multicast +festlegen (`IP_MULTICAST_IF`), sonst sendet er ins eigene LAN statt in den AP. + ## Firmware-Update Der Build erzeugt pro Gerät zwei Images: diff --git a/docs/hardware-checklist.md b/docs/hardware-checklist.md index d905123..e17ed59 100644 --- a/docs/hardware-checklist.md +++ b/docs/hardware-checklist.md @@ -1,6 +1,6 @@ # Hardware-Checkliste (EVK) -Konsole: `tools/monitor.sh /dev/cu.` (115200 8N1). Flashen: `tools/flash.sh evk `. +Konsole: `tools/monitor.sh /dev/cu.` (115200 8N1). Flashen: `tools/flash.sh evk ` — 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 @@ -65,6 +65,21 @@ Für den echten Flottenbau `NINLIGHT_RECOVERY_PASSWORD` und `NINLIGHT_TOKEN` in - [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 — 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 offener 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