# Info-Board Neu - Player-Konzept

## Ziel

Der Player ist eine moeglichst schlanke Display-Appliance fuer Raspberry Pi OS Lite.

Er soll:

- Bilder, Videos, PDFs und Webseiten anzeigen
- globale Kampagnen, tenantbezogene Playlists und Fallback sauber priorisieren
- bei Serverausfall autonom weiterlaufen
- per MQTT steuerbar sein
- per Ansible einfach ausrollbar sein
- moeglichst wenige Laufzeitabhaengigkeiten haben

## Leitprinzip

Chromium ist nur Renderer, nicht Steuerzentrale.

Das bedeutet:

- Chromium zeigt nur die lokale `player-ui`
- die `player-ui` entscheidet, was angezeigt wird
- der `player-agent` verwaltet Sync, Cache, Kommandos und Status
- externe URLs werden nie unkontrolliert direkt als Hauptbrowserziel verwendet

## Komponenten

### `player-agent`

Implementierung:

- bevorzugt in `Go`
- als einzelnes Binary auslieferbar

Aufgaben:

- Registrierung beim Server
- Abruf von Konfiguration, Playlist, Kampagne und Medienmanifest
- lokaler Mediencache
- MQTT-Kommunikation
- Heartbeat und Statusmeldungen
- Screenshot-Erzeugung
- Ausfuehrung von Admin-Kommandos
- Ueberwachung von Chromium und `player-ui`

### `player-ui`

Implementierung:

- lokale Web-Anwendung
- von Chromium im Kiosk dargestellt

Aufgaben:

- Playlist-Logik lokal darstellen
- Prioritaet `campaign > tenant_playlist > fallback` umsetzen
- Bilder, Videos, PDFs und Webseiten anzeigen
- Lade-Timeouts und Fehlerpfade umsetzen
- Offline-/Degraded-Overlay anzeigen
- Renderer-seitige Healthchecks liefern

### Chromium

Aufgabe:

- reine Darstellung der lokalen `player-ui`

Vorgaben:

- Kiosk-Modus
- Vollbild
- moeglichst ohne weitere Browser-Interaktion
- Neustart durch systemd/Watchdog erlaubt

## Laufzeitmodell

## Startreihenfolge

1. Basis-System bootet
2. X11-Minimalstack startet
3. `player-agent` startet
4. `player-ui` ist lokal erreichbar
5. Chromium startet auf lokaler URL
6. Agent fuehrt ersten Sync und Registrierungsablauf aus

## Lokaler Zustand

Der Player haelt lokal vor:

- aktuelle Konfiguration
- letzte gueltige Playlist
- letzte gueltige Kampagne
- lokales Medienmanifest
- heruntergeladene Medien
- Status-/Snapshot-Metadaten

Empfohlene Pfade:

- `/etc/signage/config.yml`
- `/var/lib/signage/cache/`
- `/var/lib/signage/media/`
- `/var/lib/signage/state/`
- `/var/log/signage/`

## Inhaltsprioritaet

Die Anzeigeentscheidung erfolgt immer in dieser Reihenfolge:

1. aktive globale Kampagne fuer diesen Screen
2. normale tenantbezogene Playlist
3. lokaler Fallback aus dem konfigurierten Verzeichnis

### Kampagnenmodus

Wenn eine gueltige Kampagne fuer den Screen aktiv ist:

- zeigt der Player nur den Kampagneninhalt
- der Firmencontent wird temporär uebersteuert
- nach Ablauf oder Deaktivierung springt der Player automatisch zurueck

### Tenant-Playlist-Modus

Wenn keine Kampagne aktiv ist:

- wird die tenantbezogene Playlist ausgewertet
- nur aktive und zeitlich gueltige Elemente werden angezeigt

### Fallback-Modus

Wenn weder Kampagne noch gueltige Playlist-Inhalte verfuegbar sind:

- werden alle Dateien aus dem Fallback-Verzeichnis nacheinander angezeigt

## Medientypen

### Bild

- lokal oder aus Cache
- Anzeige fuer definierte Dauer

### Video

- lokal oder aus Cache
- entweder feste Dauer oder bis Medienende

### PDF

- lokal oder aus Cache
- Anzeige ueber Browser/PDF-Renderer
- Sidebar und Toolbar im Chromium PDF-Viewer ausblenden (URL-Parameter: `navpanes=0&toolbar=0`)
- Folgeschritt geplant: PDF.js-Integration fuer automatisches Seitendurchblaettern

### Webseite

- live geladen oder kontrolliert zwischengespeichert
- immer mit `load_timeout`
- nie rohe Browser-Fehlerseite dauerhaft stehen lassen

## Fehlerverhalten

### Grundregeln

- Fehler eines einzelnen Items duerfen den Player nicht blockieren
- jeder Fehler fuehrt zu `retry`, `skip` oder `fallback`
- haengende Browserfehlerseiten muessen aktiv verhindert werden

### Typische Fehlerfaelle

- Medium fehlt lokal
- externe URL nicht erreichbar
- PDF fehlerhaft
- Video unlesbar
- Webseite liefert 404/500 oder timeout

### Reaktion

- Fehler loggen
- Status aktualisieren
- ggf. Overlay auf `degraded`
- zum naechsten Element wechseln oder definierte Retry-Logik ausfuehren

## Offline-Verhalten

Offline-Betrieb ist Standardfall, nicht Sonderfall.

Wenn der Server nicht erreichbar ist:

- laeuft die Wiedergabe lokal weiter
- letzte gueltige Daten bleiben aktiv
- Overlay zeigt den Verbindungszustand an
- Heartbeats und Status koennen lokal zwischengespeichert oder spaeter aktualisiert werden

## Overlay-Konzept

Das Overlay soll klein und unaufdringlich sein.

Zustaende:

- `online`
- `degraded`
- `offline`

Moegliche Anzeige:

- kleines Symbol in Ecke
- optional Text wie `offline - letzter Sync vor 2h`

## Orientierung und Display-Konfiguration

Jeder Screen hat:

- fachliche Orientierung: `portrait` oder `landscape`
- technische Rotation: `0`, `90`, `180`, `270`

Diese Werte beeinflussen:

- Chromium-Startkonfiguration
- X11-/Display-Setup
- Asset-Auswahl bei Kampagnen
- Darstellung in der `player-ui`

## Watchdogs

### Agent-Watchdog

- systemd Restart-Strategie
- eigener Healthcheck fuer Sync und Broker-Verbindung

### Renderer-Watchdog

- Ueberwachung von Chromium
- Erkennung haengender Darstellungen
- geordneter Neustart bei Freeze oder Crash

## Screenshots und Status

Der Player erzeugt Screenshots:

- bei Item-Wechsel
- zyklisch
- auf Admin-Anforderung

Der Player meldet Status:

- aktuelles Item
- Quelle (`campaign`, `tenant_playlist`, `fallback`)
- Fehlerstatus
- letzter Sync
- Heartbeat

## MQTT-Kommandos auf dem Player

Mindestens zu unterstuetzen:

- `reload`
- `restart_player`
- `reboot`
- `display_on`
- `display_off`
- `refresh_snapshot`
- `clear_cache`

## Minimaler Paketbedarf

Auf dem Player anzustreben:

- Raspberry Pi OS Lite
- Xorg-Minimalstack
- Chromium
- eigenes Go-Binary
- systemd

Vermeiden:

- LXDE/LXQt
- LightDM, wenn nicht zwingend noetig
- mehrere externe Viewer
- schwergewichtige Laufzeitstapel auf dem Geraet

## Zielstruktur im Repo

Empfohlene Unterstruktur fuer den Player:

- `player/agent/`
- `player/ui/`
- `player/systemd/`
- `player/config/`
- `player/scripts/`

## Testfaelle fuer den Player

- lokaler Start ohne Server
- späterer Verbindungsaufbau zum Server
- Wechsel zwischen Kampagne, Playlist und Fallback
- kurzer Netzverlust
- kaputte Web-URL
- defektes PDF
- Neustart von Chromium
- Screenshot-Erzeugung
- Rotation/Portrait/Landscape
