do_POST (und PUT/DELETE/HEAD) riefen reject() auf, ohne eine Logzeile zu schreiben, und das ueberschriebene log_message() legte damit unbeabsichtigt auch log_error() lahm (BaseHTTPRequestHandler ruft es standardmaessig auf, z.B. bei einer kaputten Request-Zeile oder einem Timeout, bevor ueberhaupt ein Handler wie do_GET erreicht wird). Fuer das einzige Diagnosewerkzeug im Rettungsfall darf keine Anfrage stumm bleiben. do_POST loggt jetzt wie do_GET explizit, und log_error() ist separat ueberschrieben statt implizit mit log_message() stillgelegt zu werden. Die neuen Tests fuer den 405-Fall lesen den rohen Datei-Deskriptor des Server-Prozesses statt ueber TextIOWrapper.readline() zu gehen - Letzteres kann mehr Zeilen aus der Pipe in den eigenen Puffer lesen, als es zurueckgibt, was select() auf dem naechsten Datei-Deskriptor faelschlich "nichts da" melden liess. Der Test fuer die kaputte Request-Zeile ruft log_error() direkt auf: ein echter kaputter Rohsocket wird in dieser Sandbox von einer Netzwerkschicht abgefangen, bevor er den Server erreicht (sichtbar an einem untergeschobenen "Server: aiohttp"-Header). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
ninlight-Recovery-Station
Ein Raspberry Pi spannt den Zugangspunkt ninlight-recovery auf und liefert unter
http://192.168.8.1/ninlight_<target>_ota.img Firmware-Images aus.
Jede ninlight-Lampe sucht beim Booten bis zu drei Sekunden nach dieser Station. Findet sie sie, lädt sie das Image für ihren Gerätetyp und flasht es — ohne dass die Lampe im WLAN erreichbar sein muss. Das ist der Rettungsweg für Lampen, an die man sonst nur noch mit dem Lötkolben käme.
Trägt das angebotene Image dieselbe Version, die bereits läuft, lehnt die Lampe es ab und bootet normal weiter. Eine angelassene Station flasht also nicht in einer Endlosschleife.
Bedienung
tools/station/setup_pi.sh <pi-host> einmalig einrichten
tools/station/deploy.sh <pi-host> [target] Images ausliefern
ssh <pi-host> ninlight-station on einschalten
ssh <pi-host> ninlight-station status Zustand und letzte Auslieferungen
ssh <pi-host> ninlight-station off ausschalten
SSID und Passwort stehen in /etc/ninlight-station.conf auf dem Pi und müssen zu den
Build-Parametern NINLIGHT_RECOVERY_SSID und NINLIGHT_RECOVERY_PASSWORD aus
config.local.cmake passen. Weicht eines ab, findet die Lampe die Station nicht.
Vertrauensgrenze
Der Trailer eines Images prüft Gerätetyp und SHA256. Er ist keine kryptografische
Signatur, und der Download läuft über http:// ohne TLS. Die Station schützt allein ein
WPA2-Passwort, dessen Default im Repo steht. Wer in Funkreichweite ist und es kennt, kann
jeder Lampe beim nächsten Boot beliebige Firmware unterschieben.
Das ist gewollt: Die Signaturprüfung der alten Firmware auszuhebeln ist der Zweck dieses Projekts. Daraus folgen zwei Regeln.
Setz ein eigenes Passwort. In config.local.cmake und in
/etc/ninlight-station.conf — an beiden Stellen denselben Wert.
Lass die Station nur an, solange du sie brauchst. Nicht nur wegen des Fremdzugriffs: Die Firmware löscht den Power-Cycle-Zähler, bevor sie einen Recovery-Versuch startet. Solange eine Station in Reichweite ist, funktioniert der Werksreset per fünf Stromzyklen bei keiner Lampe in Reichweite mehr.