Ein Taster auf GPIO23 (active low, 50 ms entprellt) bedient die Station am Geraet: kurz oeffnet das Menue bzw. blaettert, gehalten waehlt (1,5 s), bricht ab (3 s, feuert sofort) und faehrt herunter (10 s, nur ueber die sichtbare Abbruchstufe hinweg). Menue schliesst nach 20 s, Rueckfrage verfaellt nach 10 s als Abbruch; jede veraendernde Auswahl bekommt eine Rueckfrage. Noetig, weil "on"/"migrate on" wlan0 zum Zugangspunkt macht und damit jede SSH-Sitzung abreisst - bisher blieb dort nur warten oder Stecker ziehen. "Migration starten" startet ueber das Menue IMMER mit --listen: der Migrations-AP hat ein oeffentlich bekanntes Passwort, ein Tastendruck im Automatikmodus wuerde jede alte Klyqa-Lampe in Reichweite ungefragt migrieren. Der Tasterdienst fasst den SPI-Bus nicht an (sonst "GPIO busy"), sondern schreibt seinen Bedienzustand atomar mit 0644 nach /run/ninlight-button/ui.json - bewusst nicht ins RuntimeDirectory der Hauptunit, das systemd beim "off" aufraeumt. Der Anzeigedienst liest die Datei jede halbe Sekunde (der teure build_state()-Fork bleibt beim 5-Sekunden-Takt) und zeichnet sie als Teilaufbau, kostet dem Panel also keinen Vollaufbau je Tastendruck. Fehlt gpiozero oder der Taster, gibt es genau eine Protokollzeile und sys.exit(0) - dieselbe Zusage wie bei der Anzeige. Ausliefern/Einrichten folgt in einem eigenen Durchgang.
84 lines
4.5 KiB
Markdown
84 lines
4.5 KiB
Markdown
# 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.
|
|
|
|
## Voraussetzung
|
|
|
|
Der SSH-Benutzer auf dem Pi braucht passwortloses `sudo` — beide Skripte und die CLI
|
|
(`ninlight-station on|off|status`) rufen `sudo` nicht-interaktiv auf; ein Passwort-Prompt
|
|
würde dort nur mit einer Fehlermeldung enden.
|
|
|
|
## 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
|
|
|
|
## Taster am Gerät
|
|
|
|
Sobald die Station läuft, wird `wlan0` zum Zugangspunkt und **jede SSH-Sitzung reißt ab**.
|
|
Für genau diesen Zustand gibt es einen Taster auf **GPIO23**; die Rückmeldung kommt aufs
|
|
E-Paper. Ein Taster, zwei Zusammenhänge:
|
|
|
|
| | kurz (unter 1 s) | gehalten |
|
|
|----------------------|------------------|-------------------------------------------------------|
|
|
| Ruhe (Statusbild) | Menü öffnen | 3 s → Abbruch (Station aus), weiter 10 s → Herunterfahren |
|
|
| Menü offen | nächster Eintrag | 1,5 s → Eintrag auswählen |
|
|
| Rückfrage | abbrechen | 1,5 s → bestätigen |
|
|
|
|
Der Abbruch feuert **bei 3 s**, nicht erst beim Loslassen — danach läuft auf dem Panel ein
|
|
Countdown bis zum Herunterfahren, den Loslassen jederzeit abbricht. Das Menü schließt nach
|
|
20 s ohne Eingabe, eine Rückfrage verfällt nach 10 s als Abbruch. Die Einträge hängen vom
|
|
Zustand ab (Station aus / Rettung läuft / Migration läuft); jede verändernde Auswahl
|
|
bekommt eine Rückfrage.
|
|
|
|
**„Migration starten" startet über das Menü immer in der Horchphase** (`--listen`), nie
|
|
automatisch: der Migrations-Zugangspunkt hat ein öffentlich bekanntes Passwort, und ein
|
|
Tastendruck, der ihn im Automatikmodus hochfährt, würde jede alte Klyqa-Lampe in
|
|
Funkreichweite ungefragt migrieren, auch fremde. Wer den Automatikmodus will, nimmt die
|
|
Kommandozeile.
|
|
|
|
Der Taster ist nirgends Voraussetzung: fehlt `gpiozero` oder der Taster, protokolliert der
|
|
Dienst eine Zeile und beendet sich ohne Fehler. Er fasst den SPI-Bus **nicht** an (zwei
|
|
Prozesse auf denselben Leitungen ergeben `GPIO busy`), sondern schreibt seinen
|
|
Bedienzustand nach `/run/ninlight-button/ui.json`; der Anzeigedienst liest ihn und
|
|
zeichnet. Ausgeführt wird ausschließlich über das CLI.
|
|
|
|
Dienst und Unit liegen in `tools/station/button/` bzw.
|
|
`tools/station/ninlight-button.service` — das Ausliefern und Einrichten (`deploy.sh`,
|
|
`setup_pi.sh`) kommt in einem eigenen Durchgang, bis dahin installiert der Aufsetzweg den
|
|
Tasterdienst noch nicht.
|
|
|
|
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.
|