morz-infoboard/PLAN.md
2026-03-22 13:06:31 +01:00

14 KiB

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:<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

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/<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

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/