Fixrunde 2 zu Task 6b.
- Die Vorbedingung "display.py liegt in der Ablage" steht jetzt VOR dem
ersten sudo install. Vorher stand sie dahinter, und die Meldung "Nichts
installiert" war schlicht unwahr: server.py, products.py, das CLI und
die Stations-Unit lagen dann schon auf dem Pi. Ausgerechnet an dem
Werkbank-Moment, fuer den die Pruefung gedacht ist, log das Skript den
Bediener an. Die Ablage raeumt ein EXIT-Trap jetzt auf beiden Wegen aus
dem Block ab, nicht nur im Erfolgsfall.
- "apt-get update" ist keine Voraussetzung mehr fuer "apt-get install":
update meldet schon dann einen Fehler, wenn eine einzige Quelle nicht
erreichbar ist, und ein Pi, auf dem das Paket aus dem Cache gekommen
waere, bekam so still kein Pillow.
- Die Signalhandler beenden jetzt selbst (130/143/129). Ein Handler ohne
exit laesst bash weiterlaufen - ein Strg-C konnte in "fertig, Exit 0"
muenden. Die Begruendung im Kommentar war falsch und ist korrigiert:
zum Aufraeumen haette der EXIT-Trap allein genuegt.
- test_host.sh ruft die Shell-Suiten aus einer Liste auf, und der
Coverage-Test prueft diese Liste gegen das Dateisystem statt im
Skripttext nach Dateinamen zu suchen - ein nachgestellter Kommentar
hebelte die alte Regel aus. Er deckt jetzt ganz tools/ ab, nicht nur
station/tests.
- Neue Szenarien: Wahrheitsgehalt der Abbruchmeldung, apt-update-Fall,
und ein Strg-C, das aus den Trap-Zeilen des Skripts selbst geprueft
wird.
Fixrunde 1 zu Task 6b.
- setup_pi.sh raeumt die Ablage vor dem scp ab und bricht ab, wenn
display.py dort fehlt. Ein Reststand aus einem abgebrochenen Lauf liess
"scp -r" ins vorhandene Ziel hineinkopieren; die Installationsschleife
ueberspringt Verzeichnisse und fand nichts - der Lauf meldete Erfolg,
aktivierte den Anzeigedienst und hinterliess ein leeres display/:
203/EXEC im 5-Sekunden-Takt bei schwarzem Panel.
- Der Paketschritt steht jetzt hinter der Installation und warnt nur.
Eine Migrationsstation steht typischerweise nicht am Netz; unter set -e
davor hiess ein gescheitertes apt: gar keine Station statt einer Station
ohne Panel. "apt-get update" kommt vor dem install, der Anzeigedienst
startet nach dem Paketschritt.
- setup_pi.sh raeumt display/ auf dem Pi wie deploy.sh auf (im Repo
geloeschte Dateien verschwinden), der Trap haengt auch an INT/TERM/HUP,
und mktemp bekommt eine Vorlage: ohne sie beachtet BSD-mktemp TMPDIR
nicht, und die Temp-Datei landete je nach Plattform woanders.
- test_host.sh ruft test_deploy.sh auf - 95 Zusagen liefen nur bei
Handaufruf, darunter die Deploy-Haelfte der Anzeige-Auslieferung. Der
Coverage-Test deckt jetzt auch die Shell-Suiten ab und zaehlt dabei nur
nicht auskommentierte Zeilen.
- Neue Szenarien fuer alle vier Punkte, darunter die Zusage, dass beim
gescheiterten Schreiben eines Profils keine Datei mit dem WLAN-Passwort
liegenbleibt.
Schritt 8 des Plans: die fertige E-Paper-Anzeige wird endlich ausgeliefert
und verdrahtet, dazu zwei liegengebliebene Dinge.
- deploy.sh/setup_pi.sh uebertragen display/ (mit Panel-Treibern und
HERKUNFT.md) und ninlight-display.service; setup_pi.sh installiert und
aktiviert die Unit und zieht python3-pil nach - ohne Pillow beendet sich
der Anzeigedienst still mit 0, das faellt sonst nirgends auf.
- setup_pi.sh legt auch das Profil fuer den Migrations-Zugangspunkt an
(qconnex-firmware, von der alten Klyqa-Firmware fest vorgegeben, gleiche
Adresse wie das Rettungsprofil). Ohne das scheiterte "migrate on" auf
einem frisch eingerichteten Pi an need_profile. Bestehende Profile
bleiben unangetastet.
- "ninlight-station display test|clear|off"; der Hilfetext erklaert die
Revisionsbestimmung, denn EPD_REVISION laesst sich nur am Testbild
bestimmen.
- "off" nimmt die Anzeige mit: erst Dienst stoppen, dann Panel leeren
(sonst schreibt der Daemon binnen 5 s sein altes Bild zurueck) und beides
vor ap_switch, das bei haengendem NetworkManager abbricht. Ein
stehengebliebenes "MIGRATION" wuerde einen Betriebszustand behaupten, den
es nicht mehr gibt.
- test_host.sh sammelt tools/mkimage als Ganzes ein: die 19 Tests in
test_nl_mkimage.py liefen in keiner Suite mehr mit, darunter die Wache
fuer die Python-3.8-Randbedingung des Build-Containers. Ein neuer Test
haelt die Regel fest, dass keine Testdatei mehr herausfallen kann.
- Nebenbei: die Temp-Datei mit dem WLAN-Passwort wird wieder zuverlaessig
aufgeraeumt, und leere Konfigurationswerte legen kein kaputtes Profil an.
Fixrunde 1 zu Task 4:
- C1 (kritisch): die Unit leerte /run/ninlight-station bei jedem
systemctl restart, weil RuntimeDirectoryPreserve fehlte - genau der
Neustart, mit dem migrate/recovery on den Dienst hochfahren, wischte
die eben geschriebene Modus-/Steuerdatei wieder weg, und der Server
fiel still auf den Recovery-Default zurueck. Unit bekommt
RuntimeDirectoryPreserve=restart, und start_and_verify() prueft nach
dem Neustart zusaetzlich ausdruecklich nach, dass Modus und Phase noch
stimmen.
- I1: status las die Phase aus status.json, die arm/listen (die den
Dienst bewusst nicht neu starten) nie aktualisieren - jetzt kommt sie
aus control.json.
- I2: off pruefte nach dem Herunterfahren nichts nach und konnte
"Station aus" melden, waehrend ein Profil wegen haengendem
NetworkManager weiterhin aktiv war - ap_switch() verifiziert das jetzt
auch im Aus-Fall.
- I3: der Fehlerzweig von ap_switch (Mismatch nach dem Umschalten) war
im bisherigen Test nie erreichbar; der nmcli-Stub kann das jetzt
erzwingen.
- I4: neue Pflichtschluessel blockierten jeden Unterbefehl auf einem
bereits eingerichteten Pi. setup_pi.sh ergaenzt fehlende Schluessel in
einer bestehenden Konfiguration jetzt einzeln, statt sie unangetastet
zu lassen; dafuer musste das Skript per bash-s-Heredocs und
ueberschreibbaren Pfadvariablen erst testbar gemacht werden (neuer
test_setup_pi.sh).
Dazu vier kleinere Punkte aus derselben Review: grep -Fqx statt grep -qx
fuer Profilnamen, install-Stub durch tee+chmod ersetzt (POSIX, kein
Sonderfall mehr fuer macOS), Rechtepruefung auf control.json in den
arm/listen-Testfaellen, stderr sauber von stdout getrennt in den
Warnungs-/Fehlerfaellen.
ninlight-station bekommt recovery/migrate/arm/listen als Unterbefehle statt nur
on/off/status; "on" bleibt Kurzform fuer "recovery on". Eine gemeinsame
ap_switch()-Funktion faehrt vor jedem Wechsel erst jedes andere Stationsprofil
herunter und prueft per nmcli nach, dass auf wlan0 wirklich nur eines aktiv
ist - die beiden Zugangspunkte (Rettung/Migration) schliessen sich damit
gegenseitig aus. Der Modus wandert per /run/ninlight-station/mode an den
(ohnehin neu gestarteten) Dienst statt ueber die Konfigurationsdatei; arm/listen
schreiben die Steuerdatei aus Task 3 mit demselben atomaren 0644-Muster wie
server.py selbst. station.conf.example und die Pflichtschluesselpruefung
bekommen die neuen Migrations- und Anzeige-Schluessel dazu.
nl_sign.py signiert/prueft W600-Images im RSA-4096-PKCS#1-v1.5-Format der
alten Klyqa-Firmware (Check_OTA_Image() in qc_ssl_layer.c): SHA256 ueber die
gesamte Datei, angehaengt als exakt 512 Byte - derselbe Block wie der
ninlight-Trailer, daher die Ablehnung bereits getrailerter Eingaben.
Unterstuetzt sowohl cryptography als auch pycryptodome/pycryptodomex als
Backend. Gegen das echte Klyqa-Schluesselpaar aus ~/workspace/fw-sign
bitgleich verifiziert.
tools/test_host.sh haengt jetzt die Python-Tests aus tools/mkimage/tests
und tools/station/tests an ctest an.