diff --git a/tools/station/ninlight-station b/tools/station/ninlight-station index 3ad216c..dfce1fe 100755 --- a/tools/station/ninlight-station +++ b/tools/station/ninlight-station @@ -13,6 +13,14 @@ CONF=/etc/ninlight-station.conf # shellcheck disable=SC1090 . "$CONF" +for _key in SSID PSK IMAGE_DIR HOME_CONNECTION AP_CONNECTION; do + eval "test -n \"\${$_key-}\"" || { + echo "Fehler: $CONF: Schluessel $_key fehlt oder ist leer - tools/station/setup_pi.sh ausfuehren" >&2 + exit 1 + } +done +unset _key + need_profile() { nmcli -t -f NAME con show | grep -qx "$AP_CONNECTION" || { echo "Fehler: NetworkManager-Profil '$AP_CONNECTION' fehlt - tools/station/setup_pi.sh ausfuehren" >&2 @@ -31,14 +39,28 @@ on) [ "$n" -gt 0 ] || echo "Warnung: $IMAGE_DIR enthaelt kein Image - die Station antwortet auf alles mit 404" >&2 sudo nmcli con up "$AP_CONNECTION" >/dev/null sudo systemctl start ninlight-station - echo "Station an: SSID $SSID auf 192.168.8.1, $n Image(s)" - echo "Nicht vergessen: 'ninlight-station off', wenn du fertig bist." + # "systemctl start" meldet bei Type=simple schon Erfolg, sobald der Prozess + # gestartet wurde - nicht, sobald er ueberlebt hat. Kurz warten und wirklich + # nachsehen, sonst bleibt ein offener AP ohne Server dahinter stehen. + sleep 1 + if systemctl is-active --quiet ninlight-station; then + echo "Station an: SSID $SSID auf 192.168.8.1, $n Image(s)" + echo "Nicht vergessen: 'ninlight-station off', wenn du fertig bist." + else + sudo nmcli con down "$AP_CONNECTION" >/dev/null 2>&1 || true + echo "Fehler: ninlight-station ist nach dem Start nicht aktiv - Zugangspunkt wieder abgeschaltet. Details: journalctl -u ninlight-station" >&2 + exit 1 + fi ;; off) sudo systemctl stop ninlight-station 2>/dev/null || true sudo nmcli con down "$AP_CONNECTION" >/dev/null 2>&1 || true if nmcli -t -f NAME con show | grep -qx "$HOME_CONNECTION"; then - sudo nmcli con up "$HOME_CONNECTION" >/dev/null && echo "Station aus, wlan0 zurueck im Heim-WLAN ($HOME_CONNECTION)" + if sudo nmcli con up "$HOME_CONNECTION" >/dev/null; then + echo "Station aus, wlan0 zurueck im Heim-WLAN ($HOME_CONNECTION)" + else + echo "Station aus. Zurueckschalten zu '$HOME_CONNECTION' fehlgeschlagen - wlan0-Status pruefen." >&2 + fi else echo "Station aus. Profil '$HOME_CONNECTION' fehlt, wlan0 bleibt ungenutzt - der Zugang ueber Kabel ist davon nicht betroffen." >&2 fi @@ -53,7 +75,7 @@ status) "$(python3 - "$f" <<'PY' import pathlib, sys t = pathlib.Path(sys.argv[1]).read_bytes()[-512:] -print(t[21:37].rstrip(b"\x00").decode() if t[:4] == b"NINL" else "kein Trailer") +print(t[21:37].rstrip(b"\x00").decode("ascii", "replace") if t[:4] == b"NINL" else "kein Trailer") PY )" done diff --git a/tools/station/ninlight-station.service b/tools/station/ninlight-station.service index 274cf95..eefa362 100644 --- a/tools/station/ninlight-station.service +++ b/tools/station/ninlight-station.service @@ -1,14 +1,19 @@ [Unit] Description=ninlight recovery station (HTTP image server) -After=network.target -# Ohne den Zugangspunkt hat der Server keine Adresse zum Binden. -BindsTo=NetworkManager.service +# Ohne den Zugangspunkt hat der Server beim Start keine Adresse zum Binden. +# Bewusst kein BindsTo=NetworkManager.service: ein dadurch ausgeloester Stop +# gilt fuer systemd als sauber und wuerde von KEINER Restart=-Politik erneut +# gestartet - ein NetworkManager-Neustart wuerde den Server dann still und +# dauerhaft mitreissen. Stattdessen nur Start-Reihenfolge vorgeben und den +# Prozess bei jedem Absturz (z.B. Bind-Fehler nach einem NM-Neustart) per +# Restart=always in kurzen Abstaenden neu versuchen lassen. +After=network.target NetworkManager.service [Service] Type=simple EnvironmentFile=/etc/ninlight-station.conf ExecStart=/usr/bin/python3 /opt/ninlight-station/server.py --image-dir ${IMAGE_DIR} -Restart=on-failure +Restart=always RestartSec=2 # Laeuft als root: Port 80 und - fuer 4c - die DHCP-Leases in diff --git a/tools/station/station.conf.example b/tools/station/station.conf.example index f98bb73..15bcaa8 100644 --- a/tools/station/station.conf.example +++ b/tools/station/station.conf.example @@ -2,18 +2,25 @@ # Muss zu den Build-Parametern der Firmware passen (NINLIGHT_RECOVERY_SSID, # NINLIGHT_RECOVERY_PASSWORD in config.local.cmake). Weicht etwas ab, findet # die Lampe die Station nicht. +# +# Werte immer in einfachen Anführungszeichen: ninlight-station liest diese +# Datei per POSIX ". datei" ein, und dabei wertet die Shell auch in doppelten +# Anführungszeichen $ und ` aus - ein Passwort mit "$1" wuerde so lautlos +# durch ein Shell-Argument ersetzt. Einfache Anführungszeichen unterbinden +# das; systemds EnvironmentFile= entfernt sie ebenso wie doppelte und fuehrt +# ohnehin nie eine Shell aus. -SSID="ninlight-recovery" +SSID='ninlight-recovery' # Oeffentlicher Default. Fuer den echten Einsatz hier UND in config.local.cmake # einen eigenen Wert setzen - wer das Passwort kennt und in Funkreichweite ist, # kann jeder Lampe beim naechsten Boot beliebige Firmware unterschieben. -PSK="ninlight-recovery" +PSK='ninlight-recovery' -IMAGE_DIR="/opt/ninlight-station/images" +IMAGE_DIR='/opt/ninlight-station/images' # NetworkManager-Profil, in das "ninlight-station off" zurueckschaltet. -HOME_CONNECTION="preconfigured" +HOME_CONNECTION='preconfigured' # NetworkManager-Profil der Station selbst. -AP_CONNECTION="ninlight-recovery" +AP_CONNECTION='ninlight-recovery'