# 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 - globale Admin-Templates zur monitoruebergreifenden Orchestrierung - 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 ### Sprach- und Laufzeitstrategie - `Go` ist die bevorzugte Sprache fuer systemnahe und portable Komponenten - insbesondere gilt das fuer den `player-agent` und nach Moeglichkeit auch fuer zentrale Backend-Komponenten - Ziel ist eine geringe Zahl externer Laufzeitabhaengigkeiten und moeglichst einfache Verteilung per Ansible - fuer Browser-Oberflaechen bleibt JavaScript/TypeScript im Frontend natuerlich zulaessig - falls einzelne Server-Bausteine spaeter aus pragmatischen Gruenden anders umgesetzt werden, soll das begruendet und dokumentiert werden ## 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 - globale Templates erstellen, testen und aktivieren - temporaere Kampagnen fuer mehrere oder alle Monitore einschalten und wieder abschalten - neue Monitore initial provisionieren und betriebsbereit ausrollen ### Globale Template-Orchestrierung Die Admin-Seite bekommt zusaetzlich einen globalen Orchestrierungsbereich. Ziele: - grossformatige monitoruebergreifende Botschaften wie `SCHOENE FERIEN` oder `MORZ-INFO` - saisonale oder veranstaltungsbezogene globale Motive, z. B. Weihnachten - schnelles temporäres Ueberstimmen des Firmencontents - Rueckkehr zum normalen Firmencontent auf Knopfdruck Grundprinzip: - globale Templates sind administrative Kampagnen mit hoeherer Prioritaet als tenantbezogene Inhalte - sie koennen auf einzelne Monitore, Monitorgruppen oder alle Monitore angewendet werden - sie sind zeitlich planbar oder manuell aktivierbar - nach Deaktivierung faellt der Bildschirm automatisch auf seine normale tenantbezogene Playlist zurueck ### Automatische Screen-Provisionierung Die Admin-Oberflaeche soll neue Bildschirme nicht nur fachlich anlegen, sondern technisch in Betrieb nehmen koennen. Zielablauf: - Admin gibt `display_id`, Ziel-IP und initiale Root-Zugangsdaten an - das System stellt per SSH eine Erstverbindung her - ein Deploy-Key oder dedizierter Verwaltungsschluessel wird hinterlegt - noetige Pakete und Komponenten werden installiert - Konfiguration fuer den neuen Screen wird ausgerollt - der Player wird gestartet und meldet sich selbststaendig am Server an Der Vorgang soll moeglichst als gefuehrter Provisionierungs-Workflow im Admin-Backend verfuegbar sein. Wichtige Randbedingungen: - Root-Passwoerter duerfen nicht dauerhaft im Klartext gespeichert werden - Provisionierungsdaten sind nur fuer Admins sichtbar - jeder Provisionierungslauf muss nachvollziehbar protokolliert werden - die eigentliche Ausbringung soll auf einem automatisierbaren Ansible- oder SSH-Workflow basieren, nicht auf ad-hoc-Shellmagie im Browser ## Datenmodell ### Zentrale Entitaeten - `tenant` - `screen` - `user` - `media_asset` - `playlist` - `playlist_item` - `display_template` - `template_scene` - `template_assignment` - `campaign` - `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 ### Prioritaetsregel fuer globale Templates Die Inhaltsauswahl pro Screen folgt in v1 einer klaren Prioritaetskette: 1. aktive globale Kampagne bzw. aktives Admin-Template 2. normale tenantbezogene Playlist des Monitors 3. lokaler Fallback aus dem konfigurierten Verzeichnis Das verhindert spaeteres Anflanschen und macht die Uebersteuerung von Beginn an explizit. Wichtige Regeln: - globale Templates sind immer explizit aktiv oder inaktiv - sie koennen `valid_from` und `valid_until` besitzen - sie koennen manuell sofort deaktiviert werden - nach Ablauf oder Deaktivierung setzt der Screen automatisch beim normalen Inhalt fort ## 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:/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 Die Vorschau soll auch sichtbar machen, ob ein Screen gerade: - tenantbezogenen Normalbetrieb zeigt - von einer globalen Kampagne uebersteuert wird - im Fallback-Modus laeuft 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//heartbeat` - `signage/screen//status` - `signage/screen//event` - `signage/screen//command` - `signage/screen//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 Technische Vorgabe: - Implementierung bevorzugt in `Go` - Auslieferung moeglichst als einzelnes Binary ### `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 Zusaetzliche fachliche Server-Faehigkeiten: - Verwaltung globaler Templates - Konfiguration monitoruebergreifender Layouts und Szenen - Aktivierung, Deaktivierung und Zeitplanung globaler Kampagnen - technische Provisionierung neuer Screens ueber einen gefuehrten Admin-Workflow Technische Vorgabe: - Backend bevorzugt in `Go`, sofern die Entwicklungsdynamik nicht klar dagegen spricht - Frontends als Web-Anwendungen mit ueblichem Browser-Stack ### 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 in `Go` oder eine gleichwertig 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` - `signage_provision` ### Provisionierungsmodell Die Erstinstallation eines neuen Screens soll auf Ansible aufsetzen. Vorgesehener Ablauf: 1. Screen im Admin-Backend anlegen 2. einmalige technische Zugangsdaten fuer die Erstverbindung angeben 3. Backend startet einen Provisionierungsjob 4. der Job nutzt SSH/Ansible fuer Basis-Setup, Key-Deployment, Paketinstallation und Konfiguration 5. nach erfolgreicher Provisionierung verwendet der Screen nur noch den hinterlegten Verwaltungsschluessel und seine technische Geraeteidentitaet Damit wird die GUI zur komfortablen Steuerschicht ueber einem reproduzierbaren Automatisierungsprozess. ### 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 Parallel von Anfang an mitdenken: - globale Template-Orchestrierung darf kein Nachbau sein, sondern muss im Inhalts- und Prioritaetsmodell direkt vorgesehen werden ## 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/`