Private
Public Access
160 lines
8.3 KiB
Markdown
160 lines
8.3 KiB
Markdown
# Versionierte Updates auf dem Raspberry Pi
|
||
|
||
`tools/upload_to_pi.sh` überträgt per SSH/rsync eine neue Version und richtet
|
||
bei jedem angewendeten Update den systemd-Autostart der WebUI ein. Ohne
|
||
`--apply` zeigt es nur eine lokale Vorschau und verbindet sich nicht zum Pi.
|
||
|
||
## Auf dem Laptop im Projektordner ausführen
|
||
|
||
Das folgende Beispiel verwendet den vom Nutzer bestätigten SSH-Benutzer,
|
||
Hostnamen und Projektordner. Der absolute Home-Pfad muss auf dem Pi stimmen:
|
||
|
||
```bash
|
||
bash tools/upload_to_pi.sh --user marcinator_2 --host raspi5wlan.local \
|
||
--remote-dir /home/marcinator_2/halloween --web-host 0.0.0.0
|
||
```
|
||
|
||
Zum tatsächlichen Update denselben Befehl mit `--apply` ausführen:
|
||
|
||
```bash
|
||
bash tools/upload_to_pi.sh --user marcinator_2 --host raspi5wlan.local \
|
||
--remote-dir /home/marcinator_2/halloween --web-host 0.0.0.0 --apply
|
||
```
|
||
|
||
`--web-host 0.0.0.0` ermöglicht den gewünschten Heimnetzzugriff auf
|
||
`http://raspi5wlan.local:8000`. Die WebUI hat noch keinen Login; keine
|
||
Router-Portfreigabe einrichten. Mit `--web-host 127.0.0.1` stattdessen den
|
||
SSH-Tunnel aus `SOFTWARE.md` verwenden. Ohne Angabe bleibt die gespeicherte
|
||
Wahl erhalten; beim ersten Update gilt Loopback. `--install-service` wird
|
||
weiterhin akzeptiert, ist aber nicht mehr erforderlich.
|
||
|
||
Autostart heißt: Der Webdienst startet beim Hochfahren des Pi. Ein Browser
|
||
auf dem Laptop wird dadurch nicht automatisch geöffnet.
|
||
|
||
## Voraussetzungen
|
||
|
||
- Laptop: `bash`, `python3`, `ssh`, `rsync`.
|
||
- Pi: `bash`, `rsync`, `flock`, `runuser` (util-linux), `python3-venv`,
|
||
`python3-picamera2`, systemd
|
||
und nutzbares `sudo` für den normalen SSH-Benutzer.
|
||
- Der Pi muss die Python-Pakete aus `requirements.txt` herunterladen können.
|
||
Pro Version wird eine eigene `.venv` mit Systempaketzugriff angelegt;
|
||
pip verwendet ausschließlich Wheels, keinen impliziten Quellbuild.
|
||
- Genug Speicher für neue Version, Python-Umgebung und vollständige Sicherung
|
||
von `data/`. Alte Versionen und Sicherungen werden nicht automatisch gelöscht.
|
||
- SSH-Hostschlüssel am eigenen Gerät prüfen; die Prüfung bleibt eingeschaltet.
|
||
- Eine mit Uvicorn manuell gestartete WebUI vor dem ersten Update mit `Strg+C`
|
||
beenden. Ein bestehender, vom Projekt verwalteter Dienst wird selbst gestoppt.
|
||
Eine fremde gleichnamige systemd-Unit wird abgelehnt.
|
||
|
||
## Passwortabfragen beim Update
|
||
|
||
Alle Upload-Schritte nutzen nun **eine gemeinsame SSH-Verbindung**. Mit korrekter
|
||
Passwortanmeldung ohne SSH-Schlüssel sind normalerweise insgesamt zwei Abfragen
|
||
nötig: einmal das SSH-Passwort für die Verbindung, einmal das sudo-Passwort für
|
||
den privilegierten Updateaufruf. Bei Schlüssel-/Agent-Anmeldung entfällt die
|
||
SSH-Passwortabfrage; bei gültigem sudo-Zeitstempel kann auch diese entfallen.
|
||
Ein erster Hostschlüssel-Dialog ist keine Passwortabfrage.
|
||
|
||
Der Verbindungssocket liegt in einem privaten temporären Ordner (0700) unter
|
||
`/tmp` auf dem Laptop. Ordneranlage, rsync und Aktivierung verwenden denselben
|
||
Socket. Am Ende oder bei Fehlern wird die Master-Verbindung geschlossen und der
|
||
Socketordner entfernt. Bei Verbindungsverlust fragen spätere Schritte nicht
|
||
erneut nach einem Passwort (`BatchMode=yes`), sondern brechen bei fehlender
|
||
Anmeldemöglichkeit ab. SSH-Konfiguration, Schlüssel und Passwörter werden nicht
|
||
neu gespeichert oder geändert. Die Vorschau öffnet keine Verbindung.
|
||
|
||
Das Uploadskript bereitet die neue Python-Umgebung als normaler Pi-Benutzer vor.
|
||
Danach läuft die Umschaltung mit **einem einzigen sudo-Aufruf**: Unitprüfung,
|
||
Dienststopp, Sicherung, Versionswechsel, Dienstneustart und gegebenenfalls Rückfall.
|
||
Bei gültiger sudo-Anmeldung entfällt die Frage; sonst ist für diesen Aufruf eine
|
||
Anmeldung nötig. Keine weitere Abfrage während Neustart oder Rückfall, auch bei
|
||
kurzem oder deaktiviertem sudo-Zeitstempel. SSH-Anmeldung ist davon getrennt.
|
||
|
||
Passwörter werden vom Skript weder gelesen noch gespeichert. Keine sudoers-
|
||
Ausnahme, kein Passwort per Kommandozeile/Pipe und keine Änderung der sudo-Frist.
|
||
Abhängigkeiten und Python-Prüfungen bleiben unprivilegiert; der privilegierte
|
||
Teil startet Python und den Unit-Renderer mit `runuser` als ursprünglichem
|
||
Pi-Benutzer. Auch der Webdienst behält diesen Benutzer. Die Updatesperre bleibt
|
||
im wartenden unprivilegierten Elternprozess über den ganzen sudo-Aufruf gehalten.
|
||
Eine abgelehnte sudo-Anmeldung lässt den aktiven Dienst und Datenbestand bestehen.
|
||
|
||
## Ablauf und Verzeichnisstruktur
|
||
|
||
1. Neue Dateien unter `releases/ZEITSTEMPEL-ZUFALL/` übertragen.
|
||
2. Mit einer Updatesperre parallele Aktivierung verhindern; neue Python-Umgebung
|
||
vorbereiten und Importe/Syntax prüfen, während die alte Version weiterläuft.
|
||
3. Dienst stoppen; Daten einschließlich SQLite-Dateien und Einstellungen unter
|
||
`backups/VERSION/data/` sichern. Keine laufende Datenbank kopieren.
|
||
4. `current` atomar auf die neue Version umschalten und die Unit aktualisieren.
|
||
`HALLOWEEN_STATE_DIR` verweist immer auf den gemeinsamen Basisordner `data/`.
|
||
5. Autostart aktivieren, Dienst neu starten, `/api/status` bis zu 30 Versuche
|
||
mit je einer Sekunde Pause abfragen und aktiven Dienststatus prüfen.
|
||
6. Bei einem Fehler während der Umschaltung Dienst stoppen, vorherige Version,
|
||
Daten und Unit wiederherstellen und den alten Dienst samt HTTP-Antwort prüfen.
|
||
Änderungen des fehlgeschlagenen Starts bleiben in `backups/VERSION/failed-data/`.
|
||
|
||
Die bisherige flache Installation mit `run.py` und `.venv` im Basisordner
|
||
bleibt beim ersten Update als Rückfallziel bestehen. Ohne vorherige Installation
|
||
kann ein fehlgeschlagener Erststart nur die Daten und den Zustand ohne neuen
|
||
Dienst wiederherstellen. Ein Fehlschlag liefert einen Fehlerstatus, auch wenn
|
||
der Rückfall gelungen ist. Ein unvollständiger Rückfall wird ausdrücklich gemeldet.
|
||
Abrupter Stromverlust/SIGKILL während des Updates ist nicht automatisch abgedeckt.
|
||
|
||
`data/` wird niemals vom Laptop übertragen: Datenbank, Bilder, Modelle,
|
||
Modus und Erkennungseinstellungen sowie `follow.json` mit Farbe, Richtungen,
|
||
Nachführ- und Einrichtgrenzen bleiben auf dem Pi. `.git`, `.venv`,
|
||
Vorschauen, Referenzen, `.env`, Schlüssel, Versionsordner und Sicherungen werden
|
||
ebenfalls ausgeschlossen. Eigene Dateien außerhalb von `data/` bleiben im
|
||
Basisordner, werden aber nicht automatisch in die neue Version übernommen.
|
||
Das Skript löscht keine alten Pi-Dateien. Systempakete werden nicht geändert.
|
||
Nach Start gelten die bisherigen Freigabe-/Resetbedingungen der Effektsteuerung.
|
||
|
||
|
||
## Nach einem WebUI-Update
|
||
|
||
Vor dem Update die Kameraservos stoppen und ihre separate Versorgung abziehen.
|
||
Nach erfolgreichem Upload die Browserseite mit **Strg+F5** neu laden. Auf der
|
||
Kameraseite `/kamera` stehen die Bewegungs- und Einrichtgrenzen unter dem Bild.
|
||
`halloween/camera.html` wird zusammen mit dem übrigen Projekt übertragen;
|
||
es ist kein zusätzlicher Einzeldatei-Upload nötig.
|
||
|
||
Beim Laden alter `follow.json`-Dateien bleiben die Nachführgrenzen erhalten;
|
||
fehlende Einrichtgrenzen werden mit dem bisherigen Bereich 1100–1900 µs ergänzt.
|
||
Ein Update erweitert keinen Bewegungsbereich und startet keine Kamerasitzung.
|
||
Vor einem neuen Bewegungstest die gespeicherten Werte im WebUI prüfen.
|
||
|
||
## Auf dem Pi prüfen
|
||
|
||
```bash
|
||
systemctl status halloween-grab.service
|
||
systemctl is-enabled halloween-grab.service
|
||
readlink -f ~/halloween/current
|
||
sudo journalctl -u halloween-grab.service -n 80 --no-pager
|
||
```
|
||
|
||
Erkennung nach dem ersten Update bei Bedarf im aktiven Versionsordner einrichten:
|
||
|
||
```bash
|
||
cd ~/halloween/current
|
||
sudo apt update
|
||
sudo apt install python3-opencv python3-numpy
|
||
HALLOWEEN_STATE_DIR=/home/marcinator_2/halloween/data \
|
||
.venv/bin/python tools/install_detection_model.py
|
||
sudo systemctl restart halloween-grab.service
|
||
```
|
||
|
||
OpenCV mindestens 4.10 und das echte Kamera-/Erkennungsverhalten gemäß
|
||
`SOFTWARE.md` prüfen. Nachfolgende Versionsumgebungen nutzen dieselben Pi-Systempakete.
|
||
|
||
## Verifizierter Stand
|
||
|
||
Lokale Tests simulieren Python-Installation, systemd und HTTP-Prüfung und prüfen
|
||
Versionswechsel, Autostart-Unit, Datenbestand, Start-/HTTP-Fehler, Rückfall,
|
||
Erstinstallation, Altinstallation und Ablehnung fremder Units/manueller Server.
|
||
Sie bestätigen keine echte Pi-Installation, Kamera oder Neustartfestigkeit.
|
||
Der Nutzer hat das echte Livebild und anschließend den erfolgreichen
|
||
Updateaufruf bestätigt. Autostart nach einem tatsächlichen Pi-Neustart und
|
||
automatischer Rückfall bei einem Fehler sind noch am Gerät zu prüfen.
|
||
Die HTTP-Prüfung bestätigt die Status-API, nicht Bildqualität oder Aktoren.
|