fix(station): SPI in setup_pi.sh automatisch einschalten

Auf frischem Raspberry Pi OS ist SPI aus, das E-Paper bleibt schwarz mit
irrefuehrender "nicht verfuegbar"-Meldung. setup_pi.sh erkennt jetzt beide
config.txt-Pfade, normalisiert dtparam=spi=on (fehlend/auskommentiert/off),
sichert vorher nach config.txt.bak-ninlight und weist nur bei echter
Aenderung auf den noetigen Neustart hin.
This commit is contained in:
Michael Sauer
2026-09-14 14:13:56 +02:00
parent 03d6328dd5
commit e77d3da292
2 changed files with 290 additions and 3 deletions
+168 -1
View File
@@ -169,7 +169,12 @@ setup_state() {
local state=$1
rm -rf "$state"
mkdir -p "$state/etc" "$state/opt" "$state/usr/local/bin" "$state/etc/systemd/system" \
"$state/etc/NetworkManager/system-connections" "$state/tmp"
"$state/etc/NetworkManager/system-connections" "$state/tmp" \
"$state/boot/firmware" "$state/dev"
# $state/boot/firmware/config.txt und $state/boot/config.txt existieren absichtlich
# NICHT von selbst (ein Szenario legt sie an, wenn es sie braucht) - so deckt der
# Standardzustand genau den Fall "kein Boot-Verfahren gefunden" ab, ohne dass jedes
# Szenario das extra anfordern muesste.
}
# Fuehrt setup_pi.sh mit gestubbtem PATH und auf die Sandbox umgebogenen
@@ -198,6 +203,9 @@ run_setup() {
NINLIGHT_STATION_UNIT="$state/etc/systemd/system/ninlight-station.service" \
NINLIGHT_DISPLAY_UNIT="$state/etc/systemd/system/ninlight-display.service" \
NINLIGHT_NM_DIR="$state/etc/NetworkManager/system-connections" \
NINLIGHT_BOOT_CONFIG_NEW="$state/boot/firmware/config.txt" \
NINLIGHT_BOOT_CONFIG_OLD="$state/boot/config.txt" \
NINLIGHT_SPIDEV_PATH="$state/dev/spidev0.0" \
"$STATION_DIR/setup_pi.sh" pi-test
}
@@ -638,6 +646,10 @@ echo "=== Szenario 17 (Task 6b F2, N2): ein gescheitertes 'apt-get update' verhi
STATE="$TMPROOT/s17-state"; STUBBIN="$TMPROOT/bin17"; LOG="$TMPROOT/s17.log"
setup_state "$STATE"
setup_stubbin "$STUBBIN" "$LOG"
# SPI schon aktiv: dieses Szenario prueft ausschliesslich den Paketschritt, eine
# fehlende Boot-Konfiguration wuerde eine zweite, hier voellig unbeteiligte Warnung
# erzeugen (Szenario 26 deckt genau die ab).
printf 'dtparam=spi=on\n' >"$STATE/boot/firmware/config.txt"
: >"$LOG"
set +e
OUT=$(FAKE_PIL_MISSING=1 FAKE_APT_UPDATE_EXIT=100 run_setup "$STATE" "$STUBBIN" 2>"$TMPROOT/s17.err")
@@ -739,6 +751,161 @@ else
fail "ninlight-display.service wurde nicht installiert - Szenario 20 kann nichts pruefen"
fi
echo
echo "=== Szenario 21 (Hardware-Abnahme, SPI): fehlende dtparam=spi-Zeile wird ergaenzt ==="
# Auf einem frischen Pi ist SPI aus, es gibt aber schon eine config.txt (mit anderem
# Inhalt) ohne jede dtparam=spi-Zeile - der haeufigste Fall auf einem frisch
# geflashten Image.
STATE="$TMPROOT/s21-state"; STUBBIN="$TMPROOT/bin21"; LOG="$TMPROOT/s21.log"
setup_state "$STATE"
setup_stubbin "$STUBBIN" "$LOG"
CONFIG21="$STATE/boot/firmware/config.txt"
cat >"$CONFIG21" <<'CFG'
# For more options and information see
# http://rptl.io/configtxt
dtparam=i2c_arm=on
dtparam=audio=on
CFG
BEFORE21=$(cat "$CONFIG21")
: >"$LOG"
set +e
OUT=$(run_setup "$STATE" "$STUBBIN" 2>&1)
RC=$?
set -e
[ "$RC" -eq 0 ] && pass "Exit-Code 0" || fail "Exit-Code $RC, Ausgabe: $OUT"
grep -Fqx "dtparam=spi=on" "$CONFIG21" && pass "dtparam=spi=on wurde ergaenzt" || fail "dtparam=spi=on fehlt weiterhin: $(cat "$CONFIG21")"
grep -Fq "dtparam=i2c_arm=on" "$CONFIG21" && pass "der Rest der Datei blieb erhalten" || fail "vorhandener Inhalt ging verloren"
[ -f "${CONFIG21}.bak-ninlight" ] && pass "Sicherung angelegt" || fail "keine Sicherung unter ${CONFIG21}.bak-ninlight"
[ "$(cat "${CONFIG21}.bak-ninlight")" = "$BEFORE21" ] && pass "Sicherung entspricht dem Originalzustand" || fail "Sicherung weicht vom Original ab"
echo "$OUT" | grep -q "WICHTIG: SPI wurde soeben erst eingeschaltet" && pass "Neustart-Hinweis erscheint" || fail "kein Neustart-Hinweis in der Ausgabe: $OUT"
echo "$OUT" | grep -q "sudo reboot" && pass "der Hinweis nennt den Neustart-Befehl" || fail "kein 'sudo reboot' im Hinweis"
echo
echo "=== Szenario 22 (Hardware-Abnahme, SPI): eine auskommentierte Zeile wird aktiviert ==="
STATE="$TMPROOT/s22-state"; STUBBIN="$TMPROOT/bin22"; LOG="$TMPROOT/s22.log"
setup_state "$STATE"
setup_stubbin "$STUBBIN" "$LOG"
CONFIG22="$STATE/boot/firmware/config.txt"
cat >"$CONFIG22" <<'CFG'
dtparam=audio=on
#dtparam=spi=on
dtparam=i2c_arm=on
CFG
: >"$LOG"
set +e
OUT=$(run_setup "$STATE" "$STUBBIN" 2>&1)
RC=$?
set -e
[ "$RC" -eq 0 ] && pass "Exit-Code 0" || fail "Exit-Code $RC, Ausgabe: $OUT"
grep -Fqx "dtparam=spi=on" "$CONFIG22" && pass "die Zeile ist jetzt aktiv" || fail "dtparam=spi=on steht nicht aktiv in der Datei: $(cat "$CONFIG22")"
COUNT22=$(grep -c 'dtparam=spi=on' "$CONFIG22")
[ "$COUNT22" -eq 1 ] && pass "die Zeile wurde ersetzt, nicht verdoppelt" || fail "dtparam=spi=on steht $COUNT22 mal in der Datei"
[ -f "${CONFIG22}.bak-ninlight" ] && pass "Sicherung angelegt" || fail "keine Sicherung angelegt"
echo "$OUT" | grep -q "WICHTIG: SPI wurde soeben erst eingeschaltet" && pass "Neustart-Hinweis erscheint" || fail "kein Neustart-Hinweis: $OUT"
echo
echo "=== Szenario 23 (Hardware-Abnahme, SPI): 'dtparam=spi=off' wird umgeschaltet ==="
# An eine explizit deaktivierte Zeile ist genauso zu denken wie an eine
# auskommentierte - beide sind "nicht an", beide muessen normalisiert werden.
STATE="$TMPROOT/s23-state"; STUBBIN="$TMPROOT/bin23"; LOG="$TMPROOT/s23.log"
setup_state "$STATE"
setup_stubbin "$STUBBIN" "$LOG"
CONFIG23="$STATE/boot/firmware/config.txt"
printf 'dtparam=spi=off\n' >"$CONFIG23"
: >"$LOG"
set +e
OUT=$(run_setup "$STATE" "$STUBBIN" 2>&1)
RC=$?
set -e
[ "$RC" -eq 0 ] && pass "Exit-Code 0" || fail "Exit-Code $RC, Ausgabe: $OUT"
grep -Fqx "dtparam=spi=on" "$CONFIG23" && pass "'off' wurde auf 'on' umgeschaltet" || fail "Zeile weiterhin nicht aktiv: $(cat "$CONFIG23")"
echo "$OUT" | grep -q "WICHTIG: SPI wurde soeben erst eingeschaltet" && pass "Neustart-Hinweis erscheint" || fail "kein Neustart-Hinweis: $OUT"
echo
echo "=== Szenario 24 (Hardware-Abnahme, SPI): schon aktiv -> echtes No-Op, kein Neustart-Hinweis ==="
STATE="$TMPROOT/s24-state"; STUBBIN="$TMPROOT/bin24"; LOG="$TMPROOT/s24.log"
setup_state "$STATE"
setup_stubbin "$STUBBIN" "$LOG"
CONFIG24="$STATE/boot/firmware/config.txt"
cat >"$CONFIG24" <<'CFG'
dtparam=audio=on
dtparam=spi=on
CFG
BEFORE24=$(cat "$CONFIG24")
: >"$LOG"
set +e
OUT=$(run_setup "$STATE" "$STUBBIN" 2>&1)
RC=$?
set -e
[ "$RC" -eq 0 ] && pass "Exit-Code 0" || fail "Exit-Code $RC, Ausgabe: $OUT"
[ "$(cat "$CONFIG24")" = "$BEFORE24" ] && pass "die Datei blieb byteweise unveraendert" || fail "die Datei wurde trotz bereits aktivem SPI angefasst"
[ ! -f "${CONFIG24}.bak-ninlight" ] && pass "keine Sicherung angelegt (es gab nichts zu sichern)" || fail "eine Sicherung wurde angelegt, obwohl nichts geaendert wurde"
echo "$OUT" | grep -q "bereits eingeschaltet" && pass "meldet ruhig, dass SPI schon an ist" || fail "keine Bestaetigung in der Ausgabe: $OUT"
echo "$OUT" | grep -q "WICHTIG: SPI wurde soeben erst eingeschaltet" && fail "Neustart-Hinweis erscheint, obwohl nichts geaendert wurde" || pass "kein Neustart-Hinweis"
echo
echo "=== Szenario 25 (Hardware-Abnahme, SPI): /dev/spidev0.0 existiert schon -> SPI gilt als an, egal was in config.txt steht ==="
# Kann per Overlay oder einem anderen Mechanismus aktiviert worden sein - die Datei
# ist dann nicht die Wahrheit.
STATE="$TMPROOT/s25-state"; STUBBIN="$TMPROOT/bin25"; LOG="$TMPROOT/s25.log"
setup_state "$STATE"
setup_stubbin "$STUBBIN" "$LOG"
mkdir -p "$(dirname "$STATE/dev/spidev0.0")"
: >"$STATE/dev/spidev0.0"
CONFIG25="$STATE/boot/firmware/config.txt"
printf '#dtparam=spi=on\n' >"$CONFIG25"
: >"$LOG"
set +e
OUT=$(run_setup "$STATE" "$STUBBIN" 2>&1)
RC=$?
set -e
[ "$RC" -eq 0 ] && pass "Exit-Code 0" || fail "Exit-Code $RC, Ausgabe: $OUT"
grep -Fqx "#dtparam=spi=on" "$CONFIG25" && pass "config.txt blieb unangetastet (spidev0.0 war entscheidend, nicht die Datei)" || fail "config.txt wurde trotz vorhandenem spidev0.0 geaendert: $(cat "$CONFIG25")"
[ ! -f "${CONFIG25}.bak-ninlight" ] && pass "keine Sicherung angelegt" || fail "eine Sicherung wurde angelegt, obwohl spidev0.0 schon da war"
echo "$OUT" | grep -q "SPI ist bereits aktiv" && pass "meldet, dass SPI ueber das Geraet schon aktiv ist" || fail "keine passende Meldung: $OUT"
echo "$OUT" | grep -q "WICHTIG: SPI wurde soeben erst eingeschaltet" && fail "Neustart-Hinweis erscheint, obwohl nichts geaendert wurde" || pass "kein Neustart-Hinweis"
echo
echo "=== Szenario 26 (Hardware-Abnahme, SPI): weder config.txt noch config.txt (alt) vorhanden -> Warnung, kein Abbruch ==="
# Kein Raspberry Pi OS oder ein anderes Boot-Verfahren - die Anzeige ist nirgends
# Voraussetzung fuer eine funktionierende Station, dasselbe Prinzip wie beim
# apt-Schritt.
STATE="$TMPROOT/s26-state"; STUBBIN="$TMPROOT/bin26"; LOG="$TMPROOT/s26.log"
setup_state "$STATE"
setup_stubbin "$STUBBIN" "$LOG"
: >"$LOG"
set +e
OUT=$(run_setup "$STATE" "$STUBBIN" 2>"$TMPROOT/s26.err")
RC=$?
set -e
ERR=$(cat "$TMPROOT/s26.err")
[ "$RC" -eq 0 ] && pass "Exit-Code 0 trotz fehlender Boot-Konfiguration" || fail "Exit-Code $RC: $ERR"
echo "$ERR" | grep -qi "Warnung" && pass "Warnung auf stderr" || fail "keine Warnung: $ERR"
echo "$ERR" | grep -q "weder" && pass "Warnung nennt beide gesuchten Pfade" || fail "Warnung erwaehnt die Pfade nicht: $ERR"
[ -x "$STATE/opt/ninlight-station/server.py" ] && pass "die Station wurde trotzdem vollstaendig eingerichtet" || fail "server.py fehlt - ein fehlendes Boot-Verfahren haette die Einrichtung nicht verhindern duerfen"
echo "$OUT" | grep -q "WICHTIG: SPI wurde soeben erst eingeschaltet" && fail "Neustart-Hinweis erscheint, obwohl SPI gar nicht geprueft werden konnte" || pass "kein Neustart-Hinweis"
echo
echo "=== Szenario 27 (Hardware-Abnahme, SPI): eine bestehende Sicherung wird nicht ueberschrieben ==="
# Ein zweiter Lauf, nachdem SPI zwischendurch von Hand wieder ausgeschaltet wurde -
# ohne diese Absicherung waere der allererste Originalzustand nach dem zweiten Lauf
# weg.
STATE="$TMPROOT/s27-state"; STUBBIN="$TMPROOT/bin27"; LOG="$TMPROOT/s27.log"
setup_state "$STATE"
setup_stubbin "$STUBBIN" "$LOG"
CONFIG27="$STATE/boot/firmware/config.txt"
printf '#dtparam=spi=on\n' >"$CONFIG27"
printf 'urspruenglicher-originalzustand\n' >"${CONFIG27}.bak-ninlight"
: >"$LOG"
set +e
OUT=$(run_setup "$STATE" "$STUBBIN" 2>&1)
RC=$?
set -e
[ "$RC" -eq 0 ] && pass "Exit-Code 0" || fail "Exit-Code $RC, Ausgabe: $OUT"
grep -Fqx "dtparam=spi=on" "$CONFIG27" && pass "die Zeile wurde trotzdem aktiviert" || fail "dtparam=spi=on fehlt: $(cat "$CONFIG27")"
[ "$(cat "${CONFIG27}.bak-ninlight")" = "urspruenglicher-originalzustand" ] && pass "die bestehende Sicherung blieb unangetastet" || fail "die Sicherung wurde ueberschrieben: $(cat "${CONFIG27}.bak-ninlight")"
echo "$OUT" | grep -q "existiert bereits - wird nicht ueberschrieben" && pass "Ausgabe erwaehnt, dass die Sicherung nicht ueberschrieben wurde" || fail "keine entsprechende Meldung: $OUT"
echo
if [ "$FAILED" -eq 0 ]; then
echo "Alle Tests bestanden."