416 lines
8.8 KiB
Markdown
416 lines
8.8 KiB
Markdown
# Info-Board Neu - Architekturplan
|
|
|
|
## Zielbild
|
|
|
|
Das neue System ersetzt die bestehende `pictur`-/LXDE-basierte Loesung durch eine schlanke, zentral verwaltete Signage-Plattform.
|
|
|
|
Ziele:
|
|
|
|
- moeglichst wenig Ballast auf den Player-Clients
|
|
- Anzeige von Bildern, Videos, PDFs und Webseiten
|
|
- flexible Playlist pro Monitor
|
|
- Fallback auf sequentielle Anzeige aller Medien aus einem konfigurierten Verzeichnis
|
|
- mandantenfaehige Pflegeoberflaeche pro Monitor/Firma
|
|
- Admin-Oberflaeche fuer Gesamtsteuerung aller Monitore
|
|
- autonomer Offline-Betrieb bei Serverausfall
|
|
- einfache Verteilung per Ansible
|
|
- moeglichst geringe Abhaengigkeit vom Unterbau innerhalb Debian-/Raspberry-Pi-OS-Welt
|
|
|
|
## Basisentscheidungen
|
|
|
|
### Betriebssystem
|
|
|
|
- Player-Basis: aktuelles Raspberry Pi OS Lite auf Debian-13-Basis
|
|
- Server-Basis: Debian-artiges System, bevorzugt containerisiert
|
|
- keine volle Desktop-Umgebung auf den Playern
|
|
|
|
### Display-Stack
|
|
|
|
- fuer Version 1 X11 statt Wayland
|
|
- Grund: konservativer, besser vorhersehbar fuer Chromium-Kiosk, Screenshot-Erzeugung, Watchdogs und Raspberry-spezifische Display-Steuerung
|
|
- kein LXDE, kein LightDM als Komfortschicht, nur ein minimaler X11-Kiosk-Stack
|
|
|
|
### Container-Strategie
|
|
|
|
- Server: Docker Compose ist sinnvoll und empfohlen
|
|
- Player: kein Voll-Docker-Ansatz fuer den Grafikpfad in Version 1
|
|
- Player besser als native Dienste mit systemd + Chromium-Kiosk
|
|
|
|
## Gesamtarchitektur
|
|
|
|
Das System besteht aus zwei Hauptteilen:
|
|
|
|
1. zentraler Server fuer Verwaltung, API, Medien, Rechte und Steuerung
|
|
2. schlanke Player-Clients auf den Monitoren
|
|
|
|
### Server-Komponenten
|
|
|
|
- Reverse Proxy
|
|
- Backend API
|
|
- Admin-Oberflaeche
|
|
- mandantenbezogene Management-Oberflaeche
|
|
- PostgreSQL
|
|
- MQTT-Broker
|
|
- Dateispeicher fuer Uploads, Vorschaubilder und Screenshots
|
|
|
|
### Player-Komponenten
|
|
|
|
- `player-agent` als nativer systemd-Dienst
|
|
- `player-ui` als lokale Web-Anwendung
|
|
- Chromium im Kiosk-Modus, der nur die lokale `player-ui` rendert
|
|
- lokaler Cache fuer Playlist, Medien und Status
|
|
|
|
## Rollenmodell
|
|
|
|
### Monitor-/Firmen-Oberflaeche
|
|
|
|
Jede Firma sieht nur den ihr zugeordneten Monitor bzw. Kanal.
|
|
|
|
Funktionen:
|
|
|
|
- Medien hochladen
|
|
- Medien loeschen und ordnen
|
|
- Playlist pflegen
|
|
- Anzeigedauer je Eintrag festlegen
|
|
- `valid_from` und `valid_until` setzen
|
|
- lokale Vorschau des eigenen Monitors sehen
|
|
|
|
### Admin-Oberflaeche
|
|
|
|
Die Administration der Schule sieht und steuert die gesamte Anlage.
|
|
|
|
Funktionen:
|
|
|
|
- Inhalte aller Monitore verwalten
|
|
- Monitore global uebersichtlich sehen
|
|
- Vorschau/Screenshots aller Monitore sehen
|
|
- Reload des Players ausloesen
|
|
- Seite neu laden
|
|
- Dienste neu starten
|
|
- Monitore rebooten
|
|
- Monitore an- und ausschalten
|
|
|
|
## Datenmodell
|
|
|
|
### Zentrale Entitaeten
|
|
|
|
- `tenant`
|
|
- `screen`
|
|
- `user`
|
|
- `media_asset`
|
|
- `playlist`
|
|
- `playlist_item`
|
|
- `screen_status`
|
|
- `screen_snapshot`
|
|
- `device_command`
|
|
- `sync_state`
|
|
|
|
### Wichtige Felder
|
|
|
|
#### `screen`
|
|
|
|
- `id`
|
|
- `name`
|
|
- `tenant_id`
|
|
- `location`
|
|
- `rotation`
|
|
- `resolution`
|
|
- `enabled`
|
|
|
|
#### `media_asset`
|
|
|
|
- `id`
|
|
- `tenant_id`
|
|
- `type` (`image`, `video`, `pdf`, `web`)
|
|
- `source_kind` (`upload`, `remote_url`)
|
|
- `storage_path`
|
|
- `original_url`
|
|
- `checksum`
|
|
- `mime_type`
|
|
- `created_at`
|
|
|
|
#### `playlist_item`
|
|
|
|
- `id`
|
|
- `playlist_id`
|
|
- `screen_id`
|
|
- `order_index`
|
|
- `type`
|
|
- `src`
|
|
- `duration`
|
|
- `valid_from`
|
|
- `valid_until`
|
|
- `load_timeout`
|
|
- `cache_policy`
|
|
- `on_error`
|
|
- `enabled`
|
|
|
|
#### `screen_status`
|
|
|
|
- `screen_id`
|
|
- `online`
|
|
- `last_heartbeat`
|
|
- `current_item`
|
|
- `current_type`
|
|
- `current_since`
|
|
- `last_sync_at`
|
|
- `server_connected`
|
|
- `cache_state`
|
|
- `error_state`
|
|
|
|
#### `screen_snapshot`
|
|
|
|
- `screen_id`
|
|
- `captured_at`
|
|
- `image_path`
|
|
|
|
## Playlist-Konzept
|
|
|
|
### Unterstuetzte Typen
|
|
|
|
- Bild
|
|
- Video
|
|
- PDF
|
|
- Webseite
|
|
- Verzeichnisreferenz als Fallback-/Sammelquelle
|
|
|
|
### Pro Eintrag steuerbar
|
|
|
|
- Dauer
|
|
- Gueltigkeit ueber `valid_from` und `valid_until`
|
|
- Reihenfolge
|
|
- Timeout fuer das Laden
|
|
- Cache-Strategie
|
|
- Fehlerverhalten (`skip`, `retry`, `fallback`)
|
|
|
|
### Fallback-Regel
|
|
|
|
Wenn keine aktive Playlist vorhanden ist oder kein gueltiges Item aktiv ist, zeigt der Player alle Medien aus einem konfigurierten Fallback-Verzeichnis nacheinander an.
|
|
|
|
Eigenschaften:
|
|
|
|
- deterministische Reihenfolge, standardmaessig alphabetisch
|
|
- medientypgerechte Anzeigezeiten
|
|
- funktioniert komplett lokal aus dem Cache oder Dateisystem
|
|
|
|
## Offline- und Cache-Strategie
|
|
|
|
Offline-Betrieb ist Pflicht.
|
|
|
|
Der Player speichert lokal:
|
|
|
|
- die letzte gueltige Playlist
|
|
- alle noetigen Medien
|
|
- letzten bekannten Status
|
|
- letzte Server-/Sync-Metadaten
|
|
|
|
Bei Serverausfall:
|
|
|
|
- Wiedergabe laeuft lokal weiter
|
|
- ein kleines Overlay-Symbol zeigt den Offline-Zustand an
|
|
- Heartbeat wird lokal gepuffert oder beim Wiederverbinden aktualisiert
|
|
|
|
### Overlay-Zustaende
|
|
|
|
- gruen: online
|
|
- gelb: Verbindung instabil oder Daten veraltet
|
|
- rot: keine Verbindung zum Server
|
|
|
|
## Vermeidung von Chromium-Haengern
|
|
|
|
Chromium rendert niemals direkt externe Medien- oder Playlist-URLs.
|
|
|
|
Stattdessen:
|
|
|
|
- Chromium zeigt nur `http://127.0.0.1:<port>/player`
|
|
- die lokale `player-ui` kapselt alle Medien und Fehlerzustande
|
|
- externe Medien werden vorher geladen oder lokal gespiegelt, wo immer moeglich
|
|
|
|
Konsequenzen:
|
|
|
|
- keine haengenden 404-Fehlerseiten als Hauptansicht
|
|
- Timeouts pro Inhalt moeglich
|
|
- bei Fehlern: Skip oder Fallback statt Stehenbleiben
|
|
- lokaler Watchdog kann Anzeige und Browser neu initialisieren
|
|
|
|
## Vorschaukonzept
|
|
|
|
Eine Vorschau ist sinnvoll, aber nicht als permanenter Livestream.
|
|
|
|
Empfohlene Umsetzung:
|
|
|
|
- Screenshot bei Item-Wechsel
|
|
- zusaetzlicher Screenshot in Intervallen, z. B. alle 30 bis 60 Sekunden
|
|
- Anzeige des letzten Screenshots in Admin- und Firmen-Oberflaeche
|
|
- ergaenzt durch strukturierte Statusdaten
|
|
|
|
Statusdaten:
|
|
|
|
- aktuelles Item
|
|
- Typ
|
|
- Startzeit
|
|
- Restlaufzeit
|
|
- letzter Heartbeat
|
|
- letzter Sync
|
|
- Fehlerstatus
|
|
|
|
## Kommunikation
|
|
|
|
### HTTPS
|
|
|
|
Fuer:
|
|
|
|
- Login
|
|
- Uploads
|
|
- API-Aufrufe
|
|
- Playlist-Bearbeitung
|
|
- Download von Medien und Konfiguration
|
|
- Abruf von Screenshots und Status
|
|
|
|
### MQTT
|
|
|
|
Fuer:
|
|
|
|
- Heartbeat
|
|
- Statusmeldungen
|
|
- Kommandos
|
|
- Acknowledgements
|
|
- Hinweis auf Playlist-Aenderungen
|
|
|
|
### MQTT-Topics
|
|
|
|
- `signage/screen/<screen-id>/heartbeat`
|
|
- `signage/screen/<screen-id>/status`
|
|
- `signage/screen/<screen-id>/event`
|
|
- `signage/screen/<screen-id>/command`
|
|
- `signage/screen/<screen-id>/ack`
|
|
|
|
### Befehle
|
|
|
|
- `reload`
|
|
- `restart_player`
|
|
- `reboot`
|
|
- `display_on`
|
|
- `display_off`
|
|
- `refresh_snapshot`
|
|
- `clear_cache`
|
|
|
|
## Player-Aufbau
|
|
|
|
### `player-agent`
|
|
|
|
Aufgaben:
|
|
|
|
- Registrierung des Geraets
|
|
- HTTPS-Sync
|
|
- MQTT-Kommunikation
|
|
- Cache-Verwaltung
|
|
- Befehlsausfuehrung
|
|
- Screenshot-Erzeugung
|
|
- Ueberwachung lokaler Dienste
|
|
|
|
### `player-ui`
|
|
|
|
Aufgaben:
|
|
|
|
- lokale Wiedergabeoberflaeche
|
|
- Darstellung von Bild, Video, PDF und Web
|
|
- Auswertung von Zeitfenstern
|
|
- Umschalten zwischen Playlist und Fallback
|
|
- Offline-/Fehler-Overlay
|
|
|
|
## Server-Aufbau
|
|
|
|
### Kernkomponenten
|
|
|
|
- API-Backend
|
|
- Admin-Frontend
|
|
- Tenant-Frontend
|
|
- MQTT-Broker
|
|
- Datenbank
|
|
- Media-Storage
|
|
|
|
### Betriebsform
|
|
|
|
- bevorzugt per Docker Compose
|
|
- klare Trennung von persistenten Daten, Konfiguration und Deploy-Code
|
|
|
|
## Minimale Abhaengigkeiten auf dem Player
|
|
|
|
Das Ziel ist ein moeglichst kleiner Satz an Laufzeitabhaengigkeiten.
|
|
|
|
Bevorzugt:
|
|
|
|
- Raspberry Pi OS Lite
|
|
- Xorg-Minimalstack
|
|
- Chromium
|
|
- ein eigenes Player-Binary oder eine sehr schlanke Laufzeit
|
|
- systemd
|
|
|
|
Vermeiden:
|
|
|
|
- voller Desktop
|
|
- mehrere externe Viewer wie `feh`, `vlc`, `wmctrl`, `xdg-open`
|
|
- Python-/Node-Laufzeiten mit grossem Paketbaum direkt auf dem Client, wenn vermeidbar
|
|
|
|
## Ansible-Zielstruktur
|
|
|
|
### Rollen
|
|
|
|
- `signage_base`
|
|
- `signage_player`
|
|
- `signage_display`
|
|
- `signage_server`
|
|
|
|
### Konfigurationspfade auf dem Client
|
|
|
|
- `/etc/signage/config.yml`
|
|
- `/var/lib/signage/cache/`
|
|
- `/var/lib/signage/media/`
|
|
- `/var/lib/signage/state/`
|
|
- `/var/log/signage/`
|
|
|
|
## Migrationsstrategie
|
|
|
|
1. Architektur finalisieren
|
|
2. Datenmodell finalisieren
|
|
3. Minimalen Player-Prototyp bauen
|
|
4. Server-Minimalversion bauen
|
|
5. Referenz-Raspi aufsetzen
|
|
6. Offline-/Netzfehler-/Timeout-Szenarien testen
|
|
7. Management-Oberflaechen ausbauen
|
|
8. Ansible-Rollen erstellen
|
|
9. Einen Pilotmonitor migrieren
|
|
10. Restliche Monitore sukzessive migrieren
|
|
|
|
## Teststrategie
|
|
|
|
Zu testen sind mindestens:
|
|
|
|
- kurzer Netzverlust
|
|
- kompletter Serverausfall
|
|
- MQTT-Ausfall bei funktionierendem HTTPS
|
|
- HTTPS-Ausfall bei funktionierendem MQTT
|
|
- kaputte URL in Playlist
|
|
- defekte PDF-Datei
|
|
- grosses Video
|
|
- Wechsel von `valid_from`/`valid_until` waehrend des laufenden Betriebs
|
|
- Reload aus der Admin-Oberflaeche
|
|
- Dienstneustart aus der Admin-Oberflaeche
|
|
- Reboot aus der Admin-Oberflaeche
|
|
- Display an/aus
|
|
- Screenshot-Erzeugung unter Last
|
|
|
|
## Projektstruktur-Empfehlung
|
|
|
|
Ein separates Projektverzeichnis ist sinnvoll, um die neue Architektur sauber von der bestehenden Netboot-Struktur zu trennen.
|
|
|
|
Empfohlener Pfad:
|
|
|
|
- `/srv/docker/info-board-neu`
|
|
|
|
Dieses Verzeichnis sollte mindestens enthalten:
|
|
|
|
- `PLAN.md`
|
|
- `TODO.md`
|
|
- spaeter `compose/`, `ansible/`, `server/`, `player/`, `docs/`
|