docs: OTA und Recovery dokumentieren
This commit is contained in:
@@ -71,6 +71,66 @@ Verfügbare Befehle in der Konsole: `help`.
|
||||
- Bruno: `bruno/ninlight.yml` importieren, Environment „EVK (mDNS)" bzw. „Onboarding-AP" wählen.
|
||||
- Konsole: `net` zeigt Modus, SSID, IP, RSSI und den letzten Onboarding-Fehler.
|
||||
|
||||
## Firmware-Update
|
||||
|
||||
Der Build erzeugt pro Gerät zwei Images:
|
||||
|
||||
- **`_gz.img`** — komprimiertes App-Image für das serielle Flashen mit `tools/flash.sh` (siehe oben).
|
||||
- **`_ota.img`** — dasselbe `_gz.img`, um einen 512-Byte-Trailer ergänzt (`tools/mkimage/nl_mkimage.py`,
|
||||
automatisch bei jedem Build via `cmake/run_mkimage.cmake`). Der Trailer enthält Gerätetyp, Firmware-Version
|
||||
und den SHA256 über das komplette `_gz.img` — das ist genau der Hash, den die Firmware beim Schreiben ins
|
||||
Flash prüft.
|
||||
|
||||
Netz-Update über die REST-API:
|
||||
|
||||
curl -X PUT http://ninlight-681f.local:3333/api/v1/system/command \
|
||||
-H 'Authorization: aabbccddeeff0011223344' \
|
||||
-d '{"command":{"type":"fw_update","url":"http://<host-ip>:8000/pfad/zur/ninlight_evk_ota.img"}}'
|
||||
|
||||
Antwort `202 {"status":"updating"}` startet den Download im Hintergrund; ein per HTTP-Server bereitgestelltes
|
||||
`_ota.img` reicht (z.B. `python3 -m http.server 8000`). Läuft der Trailer- bzw. Hash-Check durch, resettet die
|
||||
Lampe und bootet mit der neuen Version. Wird das Image abgelehnt, gibt es **keinen** Reset — die Lampe läuft
|
||||
mit der alten Firmware weiter und trägt den Grund in `last_ota_error` (`GET system/info`) ein. Ein
|
||||
Verbindungsabbruch mitten im Download löst dagegen einen Wiederaufnahmeversuch per HTTP-Range aus (begrenzte
|
||||
Anzahl Runden); erst wenn auch das ausgeht, landet der Versuch bei `last_ota_error = download`.
|
||||
|
||||
Werte von `last_ota_error` (`null`, solange nichts fehlgeschlagen ist):
|
||||
|
||||
| Wert | Bedeutung |
|
||||
|---|---|
|
||||
| `download` | Verbindung/Transfer gescheitert (auch nach ausgeschöpftem Wiederaufnahmeversuch) |
|
||||
| `crc` | Prüfsumme des SDK-eigenen Update-Mechanismus stimmt nicht |
|
||||
| `trailer` | Trailer fehlt, ist zu kurz oder hat eine falsche Magic/Version |
|
||||
| `device_mismatch` | Trailer nennt einen anderen Gerätetyp |
|
||||
| `hash` | SHA256 im Trailer stimmt nicht mit dem übertragenen Image überein |
|
||||
| `busy` | es läuft bereits ein Update, oder die übergebene URL war ungültig |
|
||||
|
||||
Ein erneuter `fw_update`-Aufruf mit einem gültigen Image funktioniert nach einer Ablehnung sofort, ohne
|
||||
manuellen Reboot.
|
||||
|
||||
## Recovery
|
||||
|
||||
Findet die Firmware beim Booten keinen Weg, sich selbst zu aktualisieren (z.B. weil das reguläre WLAN nicht
|
||||
erreichbar ist), sucht sie kurz nach einem Rettungs-Zugangspunkt: SSID/Passwort sind Build-Parameter
|
||||
(`NINLIGHT_RECOVERY_SSID`/`NINLIGHT_RECOVERY_PASSWORD` in `config.local.cmake`, Default für beide
|
||||
`ninlight-recovery`). Wird die Station gefunden, verbindet sich die Lampe und lädt
|
||||
`http://192.168.8.1/ninlight_<device>_ota.img` (z.B. `ninlight_evk_ota.img`) — der Dateiname enthält den
|
||||
Gerätetyp, `<device>` ist der Wert von `NINLIGHT_DEVICE` aus dem Build.
|
||||
|
||||
Bei jedem Boot scannt die Firmware dafür bis zu ~3 Sekunden nach der Station und loggt das Ergebnis
|
||||
(gefunden, nichts gefunden, oder Scan fehlgeschlagen). Ist keine Station in Reichweite, verlängert sich der
|
||||
Boot nur um diese Scan-Zeit; danach startet der normale WLAN-Aufbau wie gewohnt. Über dem Download selbst
|
||||
liegt eine harte Zeitobergrenze — läuft sie ab, wird der Watchdog nicht mehr bedient und der Chip startet neu,
|
||||
statt unbeobachtet hängen zu bleiben; der nächste Boot versucht Recovery erneut.
|
||||
|
||||
**Vertrauensgrenze:** Der Trailer prüft Gerätetyp und SHA256 — das ist kein kryptografisches Signaturverfahren.
|
||||
Der Download läuft über `http://` ohne TLS, und der Recovery-Kanal ist ausschließlich durch das oben genannte
|
||||
WLAN-Passwort geschützt, das mit einem öffentlichen Default im Repo steht. Wer im selben WLAN ist und das
|
||||
API-Token kennt (bzw. beim Recovery in Funkreichweite ist und das Passwort kennt), kann der Lampe beliebige
|
||||
Firmware unterschieben. Das ist eine bewusste Entscheidung dieses Projekts: Ziel ist, die Signaturprüfung der
|
||||
alten, abgekündigten Original-Firmware zu umgehen, damit die Lampen überhaupt weiter nutzbar bleiben — nicht,
|
||||
ein neues, gehärtetes Sicherheitsmodell zu bauen.
|
||||
|
||||
## Werksreset
|
||||
|
||||
Gerät 5× hintereinander einschalten, jeweils kürzer als 5 Sekunden.
|
||||
|
||||
Reference in New Issue
Block a user