I6: Der HTTP-Task schreibt die 202 erst nach nl_api_handle(); die
Warteschlangennachricht geht aber schon darin raus, und net_task hat die
hoehere Prioritaet (35 gegen 42, im WM-SDK ist die kleinere Zahl hoeher). Er
verdraengt also sofort und reisst das Netz ab, bevor send_all() laeuft. Beim
Wechsel AUS dem WLAN kam die 202 trotzdem an, weil tls_wifi_disconnect()
asynchron arbeitet - ueber den eigenen AP ist tls_wifi_softap_destroy() der
haertere Abriss, und dieser Fall ist ungemessen.
Deshalb beides: rund 250 ms Pause im MSG_STANDALONE-Zweig vor dem Wechsel als
billige Versicherung, und der Fall als offener Punkt in der Abnahmeliste - die
Messung am Geraet bleibt noetig.
C1 (Merge-Blocker): Schaltet jemand den Standalone-Modus ab, waehrend keine
WLAN-Daten gespeichert sind, geht die Zustandsmaschine in den Onboarding-AP -
nl_wifi_sm_open_access() liefert dann true, obwohl der AP noch mit Name und
Passwort des Nutzers steht. Wer das AP-Passwort kennt, koennte system/settings
und system/command ohne Token benutzen: Token setzen, OTA anstossen,
Werksreset. Der Netz-Task reisst den AP in diesem Fall jetzt ausdruecklich ab
und baut ihn mit den Vorgabedaten neu auf - vor execute(ev) und nicht ueber die
Aktionsstruktur, weil execute() start_ap vor stop_ap ausfuehrt. Damit stimmt
auch die README-Zusage wieder, der AP heisse danach "ninlight-<mac4>".
I1: Der zweite Rueckfall nach drei abgelehnten tls_wifi_softap_create() setzte
ueber reset_ap_defaults() auch das Passwort auf das einkompilierte, das in der
README oeffentlich dokumentiert ist - eine Standalone-Lampe stuende dann mit
einem allgemein bekannten Passwort im Funkfeld, und sACN ist unauthentifiziert.
reset_ap_defaults() ist dafuer in reset_ap_identity() (Name und Kanal) und die
vollstaendige Rueckstellung aufgeteilt; der Rueckfall nimmt nur noch die
Identitaet. Kanal und SSID sind ohnehin die plausiblen Gruende, die
Passwortlaenge prueft die API selbst.
I2: destroy_ap() liess s_ap_live_ssid/-pass/-channel stehen. Nach dem Verlassen
des Standalone-Modus trugen diese Puffer weiter die Daten des Nutzers, und der
erste Rueckfallzweig holte sie Minuten spaeter zurueck - die Lampe pendelte
dann im 15-s-Takt zwischen Nutzerdaten und Vorgaben. Neu: forget_ap_live() in
beiden Abschaltwegen (clear_standalone und enabled:false), nicht in
destroy_ap() selbst, weil der Rueckfall auf zuletzt tragende Daten sonst auch
im Neuaufbau-Fall verlorenginge, fuer den er gedacht ist.
I3: s_ap_create_fails wurde nur bei Erfolg genullt und summierte damit ueber
verschiedene Datensaetze - nach einer Korrektur von Kanal 13 auf 6 loeste schon
ein einziger Fehlschlag den Rueckfall aus. Jetzt auch in destroy_ap() und bei
jedem neuen Wunsch aus MSG_STANDALONE.
Kleinigkeiten: nl_app_clear_standalone() wird auf seinen Rueckgabewert geprueft
und ein Schreibfehler protokolliert (sonst steht die Lampe im WLAN und nach dem
Neustart wieder im eigenen AP, ohne jede Spur). enabled:false auf einer Lampe,
die gar nicht standalone war, erzwingt keine Neuverbindung mehr, sondern tut
nichts und antwortet weiter mit 202.
Abnahmeliste: der Gerätebeleg für C1 als offener Punkt.
Nicht die Ursache: der netif-Ausstieg im SDK-Filter (tls_get_netif liefert das
STA-Interface), fehlender Multicast-Empfang (mDNS kommt an), fehlendes
Multicast-Senden (die mDNS-Ankuendigung der Lampe ist ueber die Luft sichtbar),
die zweite Filterebene tls_filter_mcast_mac (gebaut, aufgespielt, getestet,
zurueckgenommen) und Stromsparen/DTIM. Uebrig bleibt das Indiz, dass die Lampe
keine IGMP-Meldung sendet - beweisbar nur per serieller Konsole oder
Monitor-Mitschnitt.
Vier UniFi-Varianten getestet (Multicast-zu-Unicast, IGMP-Snooping, Querier), in
jeder kam Multicast nicht an und Unicast sofort. Dazu die Einschraenkung, die
beim ersten Freispruch der Firmware unterging: sacn.multicast meldet nur den
Rueckgabewert von IP_ADD_MEMBERSHIP, und die SDK-Funktion fuer den
Hardware-Filter kann ERR_OK liefern, ohne den Filter gesetzt zu haben.
Die Diagnose-Firmware meldet multicast: true, die Pakete kommen trotzdem nicht
an. Damit ist die Firmware raus und die Suche hat eine Richtung: IGMP Snooping
ohne Querier bzw. Multicast-Sperre auf dem IoT-WLAN. Dass mDNS laeuft, ist kein
Gegenbeweis - 224.0.0.0/24 ist von der Filterung per Norm ausgenommen.
Sieben Pruefpunkte an einer E27 RGB, dazu das OTA aus Home Assistant. Zwei
Befunde stehen mit drin, weil sie sonst verlorengehen: Multicast erreicht die
Lampe nicht (Unicast schon), und eine sACN-Quelle aus einem anderen Netz liefert
sichtbar ruckelige Rampen. Beim Multicast ist auch festgehalten, was NICHT
geprueft werden konnte und warum - der Beitritt wird derzeit bewusst ignoriert,
also weiss niemand, ob er scheitert.
Der Absatz stand noch auf "Reparatur laeuft", obwohl 0fe9ca6 den Befund
behoben hat. Das Protokoll haengt am naechsten Geraetetermin - dort darf nichts
Falsches stehen. Der Befund bleibt sichtbar, ergaenzt um die Loesung und die
beiden Testfaelle, die sie festhalten.
Die vier reinen Weiss-Lampen standen flach auf 2500-6500 K, was fuer keine
von ihnen stimmte. Nach Michaels Produktdaten:
- E27 CW/WW, E14 CW/WW, GU10 CW/WW: 2700-6500 K (vorher 2500-5000)
- G95 Vintage: 2000-5000 K (vorher 2500-5000)
Die drei erstgenannten haben damit oben 1500 K verschenkt, die G95 unten
500 K. Die RGB-Varianten und das EVK standen schon richtig auf 2700-6500.
test_board.c prueft die Bereiche jetzt pro Board statt ueber die Faustregel
"RGB oder nicht" - die G95 ist die Ausnahme, und eine Faustregel, die eine
Ausnahme hat, ist keine. Die beiden Clamp-Tests in test_boot_state.c lesen
die Obergrenze jetzt vom Board, statt die Zahl zu wiederholen: sie pruefen
das Begrenzen, nicht die Konstante.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Ein zweiter fw_update waehrend eines laufenden Downloads setzte s_error
auf "busy". Da ota_task() nur bei leerem Fehlerfeld auf "download"
zurueckfaellt, wurde ein spaeter gescheiterter Transfer danach als
"busy" gemeldet statt als "download". Die Abweisung hat kein eigenes
Ergebnis - sie wird der API mit 409 gemeldet, last_ota_error bleibt beim
Ergebnis des laufenden bzw. letzten Updates.
Dazu die Doku auf das am EVK gemessene Verhalten korrigiert: stirbt die
Gegenstelle mitten im Download, haengt der Lesevorgang rund sieben
Minuten in einem TCP-Timeout und bricht ohne Range-Resume ab.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Sieben Punkte bestanden. Der zweite fw_update nach einer Ablehnung ging
erst nach dem SHA256-Kontext-Fix. Die einmalige lwIP-pbuf-Assertion beim
verfälschten Image ist als offene Beobachtung vermerkt.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
sdk/PATCHES.md, README.md und docs/hardware-checklist.md beschrieben teils
einen ueberholten Stand: die Watchdog-Einschaetzung in PATCHES.md Punkt 4
stammte noch von vor dem Drei-Heartbeat-Gate in app_main.c und vor der
Zeitobergrenze in nl_recovery.c; README behauptete eine harte Obergrenze
ueber dem gesamten Download statt nur ueber einem echten Stillstand; der
Boot-Scan ist aktiv (~3 s), nicht passiv wie an einer Stelle der Spec
beschrieben (Spec bleibt unveraendert). PATCHES.md Punkt 1 ergaenzt den
sys/nl_ota.h-Include in wm_fwup.c, Punkt 5 den fls_lock-printf.
hardware-checklist.md: Recovery-Zeile auf "Gegenstelle sendet nichts mehr"
praezisiert; die beiden Werksreset-Haken aus Plan 1 zurueckgesetzt, weil der
vorgelagerte Recovery-Scan das Boot-Timing verschiebt und sie neu geprueft
werden muessen; acht neue Pruefpunkte fuer Plan 3 ergaenzt (Zweitversuch
nach Ablehnung, REST-Erreichbarkeit waehrend/nach Ablehnung, Lichtverhalten
ueber OTA mit pob=off/on, fw_version gegen Trailer, echter Rettungsfall,
Rettungsstation nach Erfolg angelassen, AP-Modus + auth_all) sowie ein
Betriebshinweis zu NINLIGHT_RECOVERY_PASSWORD/NINLIGHT_TOKEN fuer den
Flottenbau.
M9: Hardware-Checkliste um Einträge für C1 (verschachteltes JSON, 400,
Lampe läuft weiter), C2 (Onboarding, 60 s warten, Reboot + Router-Neustart
-> AP darf nicht wiederkommen) und einen Hinweis auf den Build ohne
NINLIGHT_WIFI_SSID für Onboarding-Tests ergänzt. `bri 30`-Eintrag nennt
jetzt explizit den REST-Weg (`{"brightness":30}`) neben der Konsole.
README: klargestellt, dass der Onboarding-Aufruf ohne Authorization-Header
nur im unkonfigurierten AP funktioniert - im Fallback-AP (Zugangsdaten
bereits vorhanden) ist der Token-Header wie bei jedem anderen Endpunkt
erforderlich.
hardware-checklist.md: Watchdog-Zeile beschreibt jetzt den wdtest-Testablauf (Neustart nach ca. 20-40s), bleibt unabgehakt; neuer Punkt unter "Später (Lampen)" zum SM2135EH-Standby-Bit. README.md: tools/flash.sh full als auf Hardware noch ungetestet markiert.