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.
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.