diff --git a/API-MQTT-VERTRAG.md b/API-MQTT-VERTRAG.md index 6f01e7d..e79175f 100644 --- a/API-MQTT-VERTRAG.md +++ b/API-MQTT-VERTRAG.md @@ -76,6 +76,21 @@ Beispiel-Endpunkte: - `GET /api/v1/screens/:screenId/status` - `GET /api/v1/screens/:screenId/snapshots/latest` +### 3a. Provisionierung + +Zweck: + +- neue Screens im Admin-Backend anlegen und technisch ausrollen +- Provisionierungslaeufe starten, beobachten und auswerten + +Beispiel-Endpunkte: + +- `POST /api/v1/screens/provision` +- `GET /api/v1/provisioning-jobs` +- `GET /api/v1/provisioning-jobs/:jobId` +- `POST /api/v1/provisioning-jobs/:jobId/retry` +- `POST /api/v1/provisioning-jobs/:jobId/cancel` + ### 4. Medien Zweck: @@ -108,6 +123,28 @@ Beispiel-Endpunkte: - `PATCH /api/v1/screens/:screenId/playlist/items/:itemId` - `DELETE /api/v1/screens/:screenId/playlist/items/:itemId` +### 5a. Globale Templates und Kampagnen + +Zweck: + +- globale monitoruebergreifende Templates verwalten +- Kampagnen konfigurieren, aktivieren und deaktivieren +- Screens gezielt global uebersteuern + +Beispiel-Endpunkte: + +- `GET /api/v1/templates` +- `POST /api/v1/templates` +- `GET /api/v1/templates/:templateId` +- `PATCH /api/v1/templates/:templateId` +- `POST /api/v1/templates/:templateId/scenes` +- `PATCH /api/v1/templates/:templateId/scenes/:sceneId` +- `POST /api/v1/campaigns` +- `PATCH /api/v1/campaigns/:campaignId` +- `POST /api/v1/campaigns/:campaignId/activate` +- `POST /api/v1/campaigns/:campaignId/deactivate` +- `PUT /api/v1/campaigns/:campaignId/assignments` + ### 6. Player-Sync Zweck: @@ -120,6 +157,7 @@ Beispiel-Endpunkte: - `POST /api/v1/player/register` - `GET /api/v1/player/config` - `GET /api/v1/player/playlist` +- `GET /api/v1/player/campaign` - `GET /api/v1/player/media-manifest` - `GET /api/v1/player/media/:mediaId/download` - `POST /api/v1/player/status` @@ -139,6 +177,48 @@ Beispiel-Endpunkte: - `POST /api/v1/screens/:screenId/commands/display-on` - `POST /api/v1/screens/:screenId/commands/display-off` +## Provisionierungs-API + +### `POST /api/v1/screens/provision` + +Legt einen neuen Screen an und startet einen Provisionierungsjob. + +Erwartete Eingaben mindestens: + +- `screen_slug` oder `display_id` +- `screen_name` +- `tenant_id` optional, falls direkt zugeordnet werden soll +- `target_ip` +- `target_port` optional, Default 22 +- `remote_user`, Default `root` +- `auth_mode` +- `password` oder `private_key_ref` fuer die Erstverbindung +- optionale technische Parameter wie `rotation`, `resolution`, `fallback_dir` + +Serverseitiger Ablauf: + +1. Screen-Datensatz anlegen +2. Provisionierungsjob anlegen +3. Secret nur kurzlebig oder referenziert speichern +4. Worker/Jobrunner startet Ansible- oder SSH-gestuetzten Rollout +5. nach Erfolg meldet sich der Screen kuenftig regulaer ueber seinen Agenten + +Antwort mindestens: + +- `screen_id` +- `provisioning_job_id` +- `status` + +### `GET /api/v1/provisioning-jobs/:jobId` + +Liefert: + +- Jobstatus +- aktuelle Stage +- Zeitstempel +- letzte Meldungen +- Fehlerursache bei Fehlschlag + ## API-Antworten fuer den Player ### `GET /api/v1/player/config` @@ -178,6 +258,37 @@ Jedes Item enthaelt mindestens: - `valid_until` - `enabled` +### `GET /api/v1/player/campaign` + +Liefert die fuer den Screen aktuell relevante globale Uebersteuerung. + +Liefert: + +- `campaign_revision` +- `active_campaign` nullable + +Wenn `active_campaign` gesetzt ist, enthaelt es mindestens: + +- `campaign_id` +- `template_id` +- `name` +- `priority` +- `valid_from` +- `valid_until` +- `override_mode` +- `scenes[]` + +Jede Scene enthaelt mindestens: + +- `id` +- `type` +- `src` +- `duration_seconds` +- `load_timeout_seconds` +- `cache_policy` +- `on_error` +- `layout_json` + ### `GET /api/v1/player/media-manifest` Liefert: @@ -256,6 +367,7 @@ Payload-Beispiel: Typische Events: - `playlist_changed` +- `campaign_changed` - `sync_completed` - `sync_failed` - `item_failed` @@ -327,6 +439,8 @@ Der Server signalisiert aktiv: - es gibt neue Playlist-Daten - fuehre einen Befehl aus +Die eigentliche Erstprovisionierung laeuft nicht ueber MQTT, sondern ueber einen serverseitigen Job mit SSH/Ansible. + Beispielablauf bei Playlist-Aenderung: 1. Benutzer speichert Playlist in der Web-UI @@ -336,6 +450,16 @@ Beispielablauf bei Playlist-Aenderung: 5. Player synchronisiert fehlende Medien 6. Player bestaetigt erfolgreichen Reload +Beispielablauf bei Aktivierung einer globalen Kampagne: + +1. Admin aktiviert eine Kampagne +2. Server erhoeht `campaign_revision` +3. Server sendet Event oder Command `reload` +4. Player ruft `GET /api/v1/player/campaign` ab +5. Player synchronisiert kampagnenbezogene Medien +6. Player setzt den Inhaltsmodus auf `campaign` +7. Nach Deaktivierung oder Ablauf faellt der Player wieder auf `tenant_playlist` oder `fallback` zurueck + ## Offline-Verhalten ### Wenn HTTPS ausfaellt diff --git a/DATENMODELL.md b/DATENMODELL.md index 4d09c96..540dd60 100644 --- a/DATENMODELL.md +++ b/DATENMODELL.md @@ -111,6 +111,64 @@ Zweck: - sichere Kommunikation mit API und Broker - technische Inventarisierung +### `provisioning_job` + +Repraesentiert einen Provisionierungslauf fuer einen neuen oder neu aufzubauenden Screen. + +Felder: + +- `id` +- `screen_id` +- `requested_by_user_id` +- `target_ip` +- `target_port` +- `remote_user` +- `auth_mode` (`password`, `key`) +- `provided_secret_ref` +- `ssh_key_fingerprint` nullable +- `status` (`queued`, `running`, `succeeded`, `failed`, `cancelled`) +- `stage` (`connect`, `bootstrap`, `key_install`, `package_install`, `deploy`, `verify`, `done`) +- `log_excerpt` nullable +- `error_message` nullable +- `started_at` nullable +- `finished_at` nullable +- `created_at` +- `updated_at` + +Regeln: + +- das eigentliche Passwort wird nicht im Klartext in der Datenbank gespeichert +- `provided_secret_ref` verweist auf einen kurzlebigen oder extern geschuetzten Secret-Eintrag +- pro Job soll klar erkennbar sein, in welchem Schritt ein Fehler aufgetreten ist + +### `screen_group` + +Optionale logische Gruppierung von Screens. + +Felder: + +- `id` +- `slug` +- `name` +- `description` +- `created_at` +- `updated_at` + +### `screen_group_member` + +Zuordnung eines Screens zu einer Gruppe. + +Felder: + +- `id` +- `screen_group_id` +- `screen_id` +- `created_at` + +Zweck: + +- praktische Zielauswahl fuer Kampagnen und Provisionierungsaktionen + ### `media_asset` Repraesentiert ein verwaltetes Medium. @@ -163,6 +221,95 @@ Regeln: - pro Screen gibt es in v1 genau eine aktive Playlist - spaeter koennen mehrere Playlists mit Umschaltung moeglich werden +### `display_template` + +Repraesentiert ein globales Admin-Template zur monitoruebergreifenden Orchestrierung. + +Beispiele: + +- Schriftzug ueber mehrere Monitore +- saisonales Motiv auf allen Monitoren +- Veranstaltungslayout fuer einen befristeten Zeitraum + +Felder: + +- `id` +- `slug` +- `name` +- `description` +- `template_type` (`message_wall`, `full_screen_media`, `screen_specific_scene`) +- `enabled` +- `created_by_user_id` +- `created_at` +- `updated_at` + +### `template_scene` + +Repraesentiert die konkrete Auspraegung eines Templates fuer einen oder mehrere Screens. + +Felder: + +- `id` +- `display_template_id` +- `screen_id` nullable +- `screen_slot` nullable +- `type` (`image`, `video`, `pdf`, `web`, `html`) +- `src` +- `duration_seconds` +- `load_timeout_seconds` +- `cache_policy` +- `on_error` +- `layout_json` +- `created_at` +- `updated_at` + +Hinweise: + +- `screen_id` erlaubt die direkte Zuweisung zu einem konkreten Monitor +- `screen_slot` erlaubt spaeter abstrakte Wand-Slots wie `row1-col2` +- `layout_json` kann z. B. Textpositionen, Farben oder Teilbereiche des Gesamtmotivs beschreiben + +### `campaign` + +Repraesentiert eine aktivierbare globale Kampagne auf Basis eines Templates. + +Felder: + +- `id` +- `display_template_id` +- `name` +- `description` +- `priority` +- `active` +- `valid_from` nullable +- `valid_until` nullable +- `override_mode` (`replace_tenant_content`, `replace_all`, `merge_reserved_slots`) +- `created_by_user_id` +- `created_at` +- `updated_at` + +Regeln: + +- Kampagnen ueberschreiben in v1 standardmaessig den Firmencontent +- nach Ende oder Deaktivierung greift automatisch wieder der tenantbezogene Normalbetrieb + +### `template_assignment` + +Repraesentiert die Zuordnung einer Kampagne oder eines Templates zu einem oder mehreren Screens. + +Felder: + +- `id` +- `campaign_id` +- `screen_id` +- `enabled` +- `created_at` +- `updated_at` + +Zweck: + +- Auswahl einzelner Monitore, Gruppen oder aller Monitore + ### `playlist_item` Repraesentiert einen einzelnen Eintrag in einer Playlist. @@ -226,6 +373,8 @@ Felder: - `last_sync_at` - `current_playlist_id` - `current_playlist_item_id` nullable +- `current_content_source` (`campaign`, `tenant_playlist`, `fallback`) +- `current_campaign_id` nullable - `current_item_type` nullable - `current_item_label` nullable - `current_item_started_at` nullable @@ -312,6 +461,11 @@ Zweck: - ein `tenant` hat viele `media_assets` - ein `screen` hat genau eine aktive `playlist` in v1 - eine `playlist` hat viele `playlist_items` +- ein `display_template` hat viele `template_scenes` +- ein `display_template` hat viele `campaigns` +- eine `campaign` hat viele `template_assignments` +- ein `screen` hat viele `provisioning_jobs` +- eine `screen_group` hat viele `screen_group_members` - ein `screen` hat genau einen aktuellen `screen_status` - ein `screen` hat viele `screen_snapshots` - ein `screen` hat viele `device_commands` @@ -353,12 +507,31 @@ Sinnvoll sind mindestens: - `playlist_revision` - `media_revision` - `config_revision` +- `campaign_revision` Der Player kann damit erkennen: - ob neue Konfiguration vorliegt - ob Medien nachgeladen werden muessen - ob die lokale Kopie noch gueltig ist +- ob sich globale Uebersteuerungen geaendert haben + +## Prioritaetsmodell der Inhaltsauswahl + +Der Player wertet Inhalte in dieser Reihenfolge aus: + +1. aktive Kampagne mit gueltigem Zeitfenster und Assignment fuer den Screen +2. aktive tenantbezogene Playlist des Screens +3. Fallback-Verzeichnis + +Eine Kampagne ist aktiv, wenn: + +- `active = true` +- `valid_from` leer oder erreicht ist +- `valid_until` leer oder noch nicht abgelaufen ist +- eine `template_assignment` fuer den Screen aktiv ist + +Dadurch ist die globale Uebersteuerung ein Kernbestandteil und kein nachtraeglicher Sonderfall. ## Beispiel fuer aktive Playlist-Auswertung diff --git a/PLAN.md b/PLAN.md index cb5abbd..8364a7e 100644 --- a/PLAN.md +++ b/PLAN.md @@ -12,6 +12,7 @@ Ziele: - 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 @@ -36,6 +37,14 @@ Ziele: - 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: @@ -89,6 +98,49 @@ Funktionen: - 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 @@ -100,6 +152,10 @@ Funktionen: - `media_asset` - `playlist` - `playlist_item` +- `display_template` +- `template_scene` +- `template_assignment` +- `campaign` - `screen_status` - `screen_snapshot` - `device_command` @@ -193,6 +249,23 @@ Eigenschaften: - 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. @@ -244,6 +317,12 @@ Empfohlene Umsetzung: - 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 @@ -309,6 +388,11 @@ Aufgaben: - Screenshot-Erzeugung - Ueberwachung lokaler Dienste +Technische Vorgabe: + +- Implementierung bevorzugt in `Go` +- Auslieferung moeglichst als einzelnes Binary + ### `player-ui` Aufgaben: @@ -330,6 +414,18 @@ Aufgaben: - 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 @@ -344,7 +440,7 @@ Bevorzugt: - Raspberry Pi OS Lite - Xorg-Minimalstack - Chromium -- ein eigenes Player-Binary oder eine sehr schlanke Laufzeit +- ein eigenes Player-Binary in `Go` oder eine gleichwertig schlanke Laufzeit - systemd Vermeiden: @@ -361,6 +457,21 @@ Vermeiden: - `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 @@ -383,6 +494,10 @@ Vermeiden: 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: diff --git a/README.md b/README.md index ef6a042..0c7ad1b 100644 --- a/README.md +++ b/README.md @@ -14,11 +14,23 @@ Die Trennung von `/srv/docker/infoboard-netboot` ist sinnvoll, damit: - Umsetzungs-Todo: `TODO.md` - Datenmodell: `DATENMODELL.md` - API- und MQTT-Vertrag: `API-MQTT-VERTRAG.md` +- Technologieentscheidungen: `TECH-STACK.md` +- Template-/Kampagnenkonzept: `docs/TEMPLATE-KONZEPT.md` +- Provisionierungskonzept: `docs/PROVISIONIERUNGSKONZEPT.md` -## Empfohlene spaetere Struktur +## Projektstruktur - `docs/` fuer weitere Architektur- und Betriebsdokumente - `server/` fuer Backend, Frontends und Compose-Dateien - `player/` fuer Agent, UI und lokale Startlogik - `ansible/` fuer Rollen, Inventories und Deployments +- `compose/` fuer Container-Definitionen und Stack-Bausteine - `scripts/` fuer Hilfsskripte + +## Naechste sinnvolle Inhalte in der Struktur + +- `docs/` fuer weitere technische Detaildokumente +- `server/` fuer API, Admin-UI und Tenant-UI +- `player/` fuer `player-agent`, `player-ui` und lokale Startlogik +- `ansible/` fuer Rollen und Inventories +- `compose/` fuer den zentralen Server-Stack diff --git a/TECH-STACK.md b/TECH-STACK.md new file mode 100644 index 0000000..ed08680 --- /dev/null +++ b/TECH-STACK.md @@ -0,0 +1,147 @@ +# Info-Board Neu - Tech Stack + +## Ziel + +Dieses Dokument zieht die Technologieentscheidungen verbindlich zusammen, damit sie nicht nur verteilt in Plan und Todo-Liste stehen. + +Leitlinien: + +- moeglichst wenige Laufzeitabhaengigkeiten +- gute Portabilitaet zwischen Raspberry Pi OS und Debian +- einfache Verteilung per Ansible +- robuste Offline-Faehigkeit +- moeglichst wenig Ballast auf den Playern + +## Verbindliche Entscheidungen + +### Betriebssysteme + +- Player: aktuelles Raspberry Pi OS Lite auf Debian-13-Basis +- Server: Debian-artiges System, bevorzugt mit Docker Compose betrieben + +### Display-Stack auf dem Player + +- Version 1 basiert auf X11 +- keine volle Desktop-Umgebung +- kein LXDE, kein LightDM als Pflichtbestandteil +- Chromium laeuft im Kiosk-Modus gegen eine lokale Player-Oberflaeche + +Begruendung: + +- X11 ist fuer Chromium-Kiosk auf Raspberry Pi aktuell konservativer und besser vorhersehbar als Wayland +- weniger Ueberraschungen bei Screenshot-Erzeugung, Display-Steuerung und Watchdog-Verhalten + +### Programmiersprachen + +- `Go` ist die bevorzugte Sprache fuer systemnahe Komponenten +- `Go` ist die Standardwahl fuer den `player-agent` +- `Go` ist die bevorzugte Sprache fuer das Server-Backend, solange keine zwingenden Gruende dagegensprechen +- Browser-Oberflaechen werden mit einem normalen Web-Frontend-Stack umgesetzt + +Begruendung: + +- statische oder weitgehend selbstgenuegsame Binaries +- geringe Laufzeitabhaengigkeiten +- gute Cross-Compile- und Deploy-Eigenschaften +- passend fuer Debian- und Raspberry-Pi-Umgebungen + +### Frontend-Stack + +- Admin-UI: Web-Anwendung +- Tenant-/Monitor-UI: Web-Anwendung +- Player-UI: lokale Web-Anwendung fuer den Renderer + +Noch offen, aber bewusst klein zu halten: + +- Framework-Auswahl fuer Server-UIs, bevorzugt leichtgewichtig +- keine unnötig schwere Fullstack-Plattform nur aus Gewohnheit + +### Server-Betrieb + +- zentrale Komponenten bevorzugt in Docker Compose +- getrennte Services fuer Backend, Datenbank, MQTT und Reverse Proxy +- persistente Daten ausserhalb fluechtiger Container-Dateisysteme +- Provisionierungsjobs laufen serverseitig ueber einen dedizierten Worker oder Jobrunner + +### Player-Betrieb + +- keine Voll-Containerisierung des Grafikpfads in Version 1 +- native systemd-Dienste fuer `player-agent` und Browser-Startlogik +- lokale Verzeichnisse fuer Cache, Medien, Status und Logs + +### Provisionierung und Deployment + +- die technische Erstinstallation neuer Screens wird ueber SSH + Ansible umgesetzt +- das Admin-Backend ist die steuernde Oberflaeche, aber nicht der Ort fuer eigentliche Shell-Logik +- Root-Passwoerter dienen nur als Bootstrap-Mittel und sollen nicht dauerhaft gespeichert werden +- nach der Erstinstallation erfolgt die weitere Verwaltung schluesselbasiert + +## Zielkomponenten + +### Player + +- `player-agent` in `Go` +- `player-ui` als lokale Web-Oberflaeche +- Chromium als Renderer +- Xorg-Minimalstack +- systemd fuer Start, Neustart und Watchdog-Integration + +### Server + +- Backend-API in `Go` +- Admin-UI als Web-Frontend +- Tenant-UI als Web-Frontend +- PostgreSQL +- MQTT-Broker, bevorzugt Mosquitto +- Reverse Proxy +- Dateispeicher fuer Uploads, Caches und Screenshots + +## Kommunikationsstack + +- HTTPS fuer API, Upload, Download, Authentifizierung und Screenshots +- MQTT fuer Heartbeat, Status, Kommandos und Acknowledgements + +Nicht vorgesehen: + +- Medienuebertragung ueber MQTT +- permanente Spezial-Streams fuer den Regelbetrieb + +## Laufzeit-Minimum auf dem Player + +Anzustreben sind nur diese grossen Bausteine: + +- Raspberry Pi OS Lite +- Xorg-Minimalstack +- Chromium +- eigenes `Go`-Binary fuer den Agenten +- systemd + +Moeglichst zu vermeiden: + +- komplette Desktop-Umgebungen +- mehrere externe Viewer wie `feh`, `vlc`, `wmctrl`, `xdg-open` +- umfangreiche Python- oder Node-Laufzeitstapel direkt auf dem Player + +## Build- und Deployment-Richtung + +- `Go`-Binaries sollen zentral gebaut und per Ansible verteilt werden koennen +- Konfiguration soll dateibasiert und gut templatisierbar sein +- Frontend-Artefakte sollen versioniert und reproduzierbar baubar sein + +## Architekturfolgen aus diesen Entscheidungen + +- der Player bleibt moeglichst nah an einem Appliance-Modell +- Browserfehler duerfen nicht direkt die eigentliche Logik bestimmen +- Renderer und Systemlogik bleiben getrennt +- Serverlogik ist zentralisiert, Playerlogik minimal und robust + +## Bewusst vertagte Entscheidungen + +- moeglicher spaeterer Wechsel auf Wayland +- exakte Frontend-Framework-Wahl +- genaue Auspraegung des Build-Systems fuer Frontend-Artefakte +- eventuelle Objekt-Storage-Einfuehrung statt einfachem Dateispeicher + +## Aktueller technischer Grundsatz + +Wenn zwei Varianten funktional gleichwertig sind, wird die Variante mit weniger Laufzeitabhaengigkeiten, einfacherem Deployment und besserem Offline-Verhalten bevorzugt. diff --git a/TODO.md b/TODO.md index a6b4ca0..037d583 100644 --- a/TODO.md +++ b/TODO.md @@ -7,6 +7,7 @@ - [ ] Dokumentationsstruktur fuer Architektur, Betrieb und Deployment anlegen - [ ] Entscheidung fuer Server-Tech-Stack dokumentieren - [ ] Entscheidung fuer Player-Implementierung dokumentieren +- [ ] Sprachentscheidung dokumentieren: `Go` als bevorzugte Sprache fuer Agent und moeglichst viele Backend-Komponenten ## Phase 1 - Fachliches Fundament @@ -16,6 +17,8 @@ - [ ] Fallback-Regel fuer ungeplante oder leere Inhalte verbindlich definieren - [ ] Statusmodell fuer Online/Offline/Degraded/Error definieren - [ ] Kommandokatalog fuer Admin-Aktionen finalisieren +- [ ] Template- und Kampagnenmodell fuer globale monitoruebergreifende Uebersteuerung finalisieren +- [ ] Prioritaetsregel `campaign > tenant_playlist > fallback` verbindlich festschreiben ## Phase 2 - Technische Zielarchitektur @@ -26,6 +29,9 @@ - [ ] Screenshot-/Vorschaustrategie spezifizieren - [ ] Offline- und Cache-Strategie bis auf Dateiebene festlegen - [ ] Sicherheitsmodell fuer Uploads, Login und Rechte pruefen +- [ ] API fuer Templates, Kampagnen, Aktivierung und Deaktivierung ausarbeiten +- [ ] Provisionierungs-Workflow fuer neue Screens technisch durchplanen +- [ ] Secret-Handling fuer initiale Root-Passwoerter oder Bootstrap-Zugaenge definieren ## Phase 3 - Player-Design @@ -49,6 +55,11 @@ - [ ] Authentifizierungskonzept festlegen - [ ] Mandantentrennung im Datenmodell und in den APIs absichern - [ ] Logging- und Monitoring-Konzept definieren +- [ ] Template-Editor fuer globale Kampagnen fachlich schneiden +- [ ] Aktivierungsoberflaeche fuer saisonale oder temporäre Kampagnen planen +- [ ] Gruppierung oder Slot-Modell fuer monitoruebergreifende Layouts planen +- [ ] Provisionierungs-UI fuer neue Screens fachlich und technisch schneiden +- [ ] Jobrunner-Konzept fuer Ansible-gestuetzte Erstinstallation planen ## Phase 5 - Prototyping @@ -60,6 +71,8 @@ - [ ] `valid_from`/`valid_until` im Prototyp pruefen - [ ] Offline-Sync mit lokalem Cache pruefen - [ ] MQTT-Kommandos `reload`, `restart_player`, `reboot`, `display_on`, `display_off` testweise durchspielen +- [ ] globale Kampagne testen, die tenantbezogenen Content temporär ueberschreibt +- [ ] Rueckfall auf Normalbetrieb nach manueller Deaktivierung pruefen ## Phase 6 - Betriebsfaehigkeit @@ -76,10 +89,12 @@ - [ ] Rolle `signage_player` erstellen - [ ] Rolle `signage_display` erstellen - [ ] Rolle `signage_server` erstellen +- [ ] Rolle `signage_provision` erstellen - [ ] Inventar-/Variablenmodell fuer mehrere Monitore entwerfen - [ ] Screen-spezifische Variablen wie `screen_id`, Rotation und Aufloesung abbilden - [ ] Erstinstallation eines neuen Players automatisieren - [ ] Update-Rollout eines bestehenden Players automatisieren +- [ ] Bootstrap ueber Root-Passwort auf SSH-Key und dauerhafte Verwaltung umstellen ## Phase 8 - Pilotbetrieb @@ -88,8 +103,10 @@ - [ ] Verbindung zum Zentralserver herstellen - [ ] Upload- und Playlist-Pflege mit einem Testmandanten pruefen - [ ] Admin-Funktionen am Pilotmonitor pruefen +- [ ] globale Template-Aktivierung fuer einen oder mehrere Monitore im Pilot testen - [ ] Offline-Betrieb real testen - [ ] Browser-/Renderer-Stabilitaet ueber laengeren Zeitraum beobachten +- [ ] komplette Neu-Provisionierung eines frischen Test-Screens aus dem Admin-Backend pruefen ## Phase 9 - Migration der Bestandsmonitore diff --git a/docs/PROVISIONIERUNGSKONZEPT.md b/docs/PROVISIONIERUNGSKONZEPT.md new file mode 100644 index 0000000..fd6a00d --- /dev/null +++ b/docs/PROVISIONIERUNGSKONZEPT.md @@ -0,0 +1,294 @@ +# Info-Board Neu - Provisionierungskonzept + +## Ziel + +Neue Displays sollen aus dem Admin-Backend heraus technisch in Betrieb genommen werden koennen. + +Der Workflow soll mindestens leisten: + +- neuen Screen fachlich anlegen +- initiale Verbindung per IP und Bootstrap-Zugang herstellen +- SSH-Key fuer dauerhafte Verwaltung hinterlegen +- noetige Komponenten installieren +- Screen-spezifische Konfiguration ausrollen +- Display in lauffaehigen Zustand versetzen + +Das Konzept ist ausdruecklich nicht auf 9 Monitore begrenzt. Es muss auch kuenftige Einzelanzeigen wie Vertretungsplan-Displays sauber abbilden. + +## Grundprinzip + +Die Admin-Oberflaeche ist der Einstiegspunkt, aber die eigentliche Ausbringung erfolgt reproduzierbar ueber einen serverseitigen Provisionierungsjob. + +Technische Leitlinie: + +- GUI sammelt Eingaben und zeigt Fortschritt +- Backend erzeugt Provisionierungsjob +- Jobrunner fuehrt SSH-/Ansible-Schritte aus +- Ergebnis wird protokolliert und in der UI sichtbar gemacht + +## Eingaben fuer einen neuen Screen + +Mindestens erforderlich: + +- `display_id` bzw. `screen_slug` +- Anzeigename +- Ziel-IP-Adresse +- Bootstrap-Benutzer, Default `root` +- Bootstrap-Passwort oder alternativer Initial-Key +- gewuenschte Orientierung +- optionale Rotation +- Screen-Klasse oder Geraetetyp +- Tenant-Zuordnung, falls direkt bekannt + +Optional sinnvoll: + +- Aufloesung +- Fallback-Verzeichnis +- Snapshot-Intervall +- Zugehoerigkeit zu Gruppen +- Standortbeschreibung + +## Orientierung und Rotationsmodell + +Die Ausrichtung ist von Anfang an ein Pflichtfeld. + +### Fachliche Orientierung + +- `portrait` +- `landscape` + +### Technische Rotation + +- `0` +- `90` +- `180` +- `270` + +Grundregel: + +- die Orientierung ist die fachliche Voreinstellung fuer Templates und Layouts +- die Rotation ist die technische Ableitung fuer den Display-Stack auf dem Geraet + +Beispiele: + +- Infowand-Displays: typischerweise `portrait` +- Vertretungsplan-Displays: typischerweise `landscape` + +Diese Werte muessen in Provisionierung, Player-Konfiguration und Kampagnenlogik gleichermassen sichtbar sein. + +## Screen-Klassen + +Um skalierbar zu bleiben, sollte die Provisionierung mit Klassen oder Profilen arbeiten. + +Empfohlene Startklassen: + +- `info_wall_display` +- `single_info_display` +- `vertretungsplan_display` + +Diese Klassen koennen Defaults liefern fuer: + +- Orientierung +- Rotation +- Aufloesung +- Gruppenmitgliedschaften +- Fallback-Verzeichnis +- spezielle UI- oder Template-Voreinstellungen + +## Provisionierungsablauf + +### 1. Fachliches Anlegen + +Im Admin-Backend wird der Screen angelegt mit: + +- Name +- ID +- Klasse +- Orientierung +- Tenant-Zuordnung +- Standort + +### 2. Start des Provisionierungsjobs + +Der Admin gibt die technischen Zugangsdaten fuer die Erstverbindung an. + +Wichtig: + +- Passwort nur fuer den aktuellen Job verwenden +- keine dauerhafte Klartextspeicherung + +### 3. Verbindungsaufbau + +Der Jobrunner versucht per SSH die Verbindung herzustellen. + +Pruefpunkte: + +- Erreichbarkeit +- SSH-Port +- gueltige Zugangsdaten +- Architektur und Betriebssystem grob erkennen + +### 4. Bootstrap + +Auf dem Zielsystem werden vorbereitet: + +- Verwaltungsschluessel installieren +- optional dedizierten Verwaltungsbenutzer anlegen +- Basisverzeichnisse anlegen +- Systemvoraussetzungen pruefen + +### 5. Basisinstallation + +Installiert werden mindestens: + +- noetige Systempakete +- X11-Minimalstack +- Chromium +- Player-Agent +- Player-UI oder deren Artefakte +- systemd-Units + +### 6. Screen-Konfiguration + +Ausgerollt werden mindestens: + +- `screen_id` +- Server-URL +- MQTT-Parameter +- Orientierung und Rotation +- Snapshot-Intervall +- Fallback-Verzeichnis +- Gruppen oder Zielprofile + +### 7. Verifikation + +Der Job prueft mindestens: + +- Dienste laufen +- lokaler Player-Endpunkt ist erreichbar +- Agent registriert sich am Server +- Heartbeat kommt an +- Screenshot oder Statusmeldung funktioniert + +### 8. Abschluss + +Der Provisionierungsjob wird als erfolgreich markiert und der Screen ist regulär verwaltbar. + +## Sicherheitsmodell + +### Bootstrap-Geheimnisse + +Regeln: + +- Root-Passwoerter nicht dauerhaft im Klartext speichern +- wenn Speicherung noetig ist, nur kurzlebig und stark geschuetzt +- besser: nur Referenz auf temporären Secret-Speicher + +### Verwaltung nach Erstinstallation + +Nach erfolgreicher Provisionierung gilt: + +- weitere Verwaltung nur noch per SSH-Key +- der Screen besitzt eine technische Geraeteidentitaet +- API- und MQTT-Zugangsdaten sind geraetebezogen + +### Protokollierung + +Jeder Provisionierungslauf muss auditierbar sein. + +Mindestens sichtbar: + +- wer den Job gestartet hat +- wann er gestartet wurde +- fuer welchen Screen +- gegen welche Ziel-IP +- welche Stage aktiv war +- ob Fehler auftraten + +## Skalierung ueber die bestehende Wand hinaus + +Das Modell muss von Anfang an mit mehreren Geraetetypen umgehen koennen. + +### Heute + +- 9 Displays in der Infowand, Hochformat + +### Perspektivisch + +- mindestens 4 zusaetzliche Vertretungsplan-Anzeigen, Querformat +- eventuell weitere Einzelanzeigen + +Konsequenz: + +- Provisionierung darf nicht implizit von einer 3x3-Wand ausgehen +- Gruppen, Klassen, Orientierung und technische Defaults muessen explizit modelliert werden + +## Ansible-Rolle `signage_provision` + +Die Provisionierung sollte auf einer eigenen Rolle oder einem eigenen Playbook aufbauen. + +Sinnvolle Teilbereiche: + +- `bootstrap` +- `base` +- `display` +- `player` +- `verify` + +Damit bleibt die Erstinstallation klar getrennt von spaeteren Updates. + +## Fehlerfaelle + +Der Jobrunner soll Fehler moeglichst frueh und verstaendlich melden. + +Typische Fehlerfaelle: + +- Host nicht erreichbar +- falsches Passwort +- SSH blockiert +- unpassendes Betriebssystem +- Paketinstallation fehlgeschlagen +- Chromium oder X11 startet nicht +- Player-Agent registriert sich nicht + +Zu jedem Fehler soll sichtbar sein: + +- Stage +- kurzer Fehlertext +- ob Retry sinnvoll ist + +## Zielbild im Admin-Backend + +Die UI fuer neue Screens sollte mindestens enthalten: + +- Screen anlegen +- Klasse waehlen +- Orientierung waehlen +- Rotation festlegen oder automatisch vorbelegen +- Tenant zuordnen +- IP und Bootstrap-Zugang angeben +- Provisionierungsjob starten +- Fortschritt live oder halb-live sehen +- Erfolg/Fehler mit Details sehen + +## Spaetere Erweiterungen + +Moegliche Ausbaustufen: + +- Provisionierung ohne Passwort nur mit Bootstrap-Key +- Zero-touch-Registrierung ueber vorbereitete Images +- automatische Gruppenzuordnung nach Klasse +- Massenprovisionierung mehrerer Screens +- Neu-Provisionierung oder Rebuild eines bestehenden Screens + +## Fazit + +Provisionierung ist nicht nur Deployment, sondern ein eigener fachlicher Workflow. + +Wesentliche Grundpfeiler sind: + +- Admin-gesteuerter Start +- Ansible-/SSH-basierte reproduzierbare Ausbringung +- explizite Orientierung und Rotation pro Screen +- Unterstuetzung fuer Wand-Screens und Einzelanzeigen +- sichere Umstellung von Bootstrap-Zugang auf dauerhafte schluesselbasierte Verwaltung diff --git a/docs/TEMPLATE-KONZEPT.md b/docs/TEMPLATE-KONZEPT.md new file mode 100644 index 0000000..d0212e5 --- /dev/null +++ b/docs/TEMPLATE-KONZEPT.md @@ -0,0 +1,277 @@ +# Info-Board Neu - Template- und Kampagnenkonzept + +## Ziel + +Dieses Dokument konkretisiert die globale Orchestrierung im Admin-Backend. + +Es geht um drei Kernpunkte: + +1. Template-Typen und ihr fachlicher Zweck +2. Konfiguration und Bearbeitung dieser Templates +3. Zielmodell fuer Monitorwand, Einzelanzeigen und Aktivierung als Kampagne + +Das Ziel ist, dass globale Inhalte von Anfang an sauber in das Systemmodell integriert sind und nicht spaeter als Sonderfall angebaut werden muessen. + +## 1. Template-Typen + +### `message_wall` + +Dieser Typ dient fuer grosse monitoruebergreifende Botschaften. + +Typische Beispiele: + +- `SCHOENE FERIEN` +- `MORZ-INFO` +- `WEIHNACHTSFEIER` + +Eigenschaften: + +- ein Gesamtmotiv oder Gesamttext wird auf mehrere Displays verteilt +- jedes Display zeigt nur einen Ausschnitt oder einen zugewiesenen Teil des Gesamtlayouts +- sinnvoll vor allem fuer die bestehende Infowand mit hochkant montierten Bildschirmen + +Technische Anforderungen: + +- logisches Slot-Modell fuer die Wand +- definierte Zielgruppe von Screens +- klare Zuordnung `welcher Ausschnitt auf welchem Screen` + +### `full_screen_media` + +Dieser Typ dient fuer ein identisches oder pro Zielgeraet passend skaliertes Vollbildmotiv. + +Typische Beispiele: + +- Weihnachtsmotiv auf allen Screens +- Sommerferiengrafik +- Veranstaltungslogo +- identisches Informationsvideo auf mehreren Displays + +Eigenschaften: + +- alle ausgewaehlten Monitore zeigen denselben fachlichen Inhalt +- die technische Darstellung kann je nach Ausrichtung variieren +- ideal fuer schnelle globale Uebersteuerungen + +Technische Anforderungen: + +- medientypgerechte Darstellung fuer Hoch- und Querformat +- optionale getrennte Assets pro Orientierungsgruppe +- einfache Aktivierung/Deaktivierung im Admin-Backend + +### `screen_specific_scene` + +Dieser Typ dient fuer kampagnenweite, aber monitorindividuelle Szenen. + +Typische Beispiele: + +- auf der Infowand ein Schriftzug +- auf zusaetzlichen Vertretungsplan-Anzeigen parallel ein passendes Seitenlayout +- auf bestimmten Screens ein Veranstaltungsprogramm, auf anderen ein Wegweiser + +Eigenschaften: + +- ein Template besteht aus mehreren gezielten Szenen +- jede Szene ist bestimmten Screens, Gruppen oder Slots zugeordnet +- hoechste Flexibilitaet fuer spaetere Ausbaustufen + +Technische Anforderungen: + +- Zuordnung zu konkreten Screens oder Gruppen +- getrennte Assets je Zielgeraet moeglich +- definierte Prioritaet gegenueber tenantbezogenem Content + +## 2. Template-Konfiguration im Admin-Backend + +### Grundaufbau eines Templates + +Ein Template besteht mindestens aus: + +- technischem Namen (`slug`) +- Anzeigenamen +- Template-Typ +- Beschreibung +- Zieldefinition +- einem oder mehreren Szenen-/Medieneintraegen +- optionalen Standardwerten fuer Dauer, Timeouts und Fehlerverhalten + +### Konfigurierbare Felder + +Pro Template sollen mindestens pflegbar sein: + +- `name` +- `slug` +- `description` +- `template_type` +- Standarddauer +- Standard-Timeout +- Standard-Fehlerstrategie +- Zielmenge (`alle Screens`, `Screen-Gruppe`, `einzelne Screens`, `Wall-Slots`) + +### Szenen-/Asset-Konfiguration + +Pro Szene oder Teilbereich sollen mindestens konfigurierbar sein: + +- Medientyp (`image`, `video`, `pdf`, `web`, `html`) +- Quelle oder Asset +- Dauer +- `valid_from` +- `valid_until` +- Fehlerverhalten +- Zielscreen oder Zielslot +- Layout-Metadaten + +### Aktivierung als Kampagne + +Templates werden nicht direkt abgespielt, sondern als Kampagnen aktiviert. + +Eine Kampagne ist die operative Auspraegung eines Templates und enthaelt: + +- Name der Kampagne +- referenziertes Template +- Prioritaet +- Aktiv-Status +- `valid_from` +- `valid_until` +- Zielmenge +- Override-Modus + +### Wichtige Admin-Funktionen + +Im Admin-Backend soll es dafuer geben: + +- Template-Liste +- Template-Editor +- Kampagnenliste +- Aktivieren/Deaktivieren auf Knopfdruck +- Zeitgesteuerte Aktivierung +- Vorschau, welche Screens betroffen sind +- Anzeige, welche Screens aktuell von einer Kampagne uebersteuert werden + +## 3. Zielmodell fuer Monitorwand und Einzelanzeigen + +## Ausgangslage + +Das System darf nicht auf die aktuelle 9er-Infowand beschraenkt bleiben. + +Perspektivisch sind mindestens zwei Klassen von Displays zu erwarten: + +- Infowand-Screens im Hochformat +- zusaetzliche Einzelanzeigen wie Vertretungsplan-Displays im Querformat + +Deshalb wird von Anfang an zwischen logischem Ziel und physischer Darstellung unterschieden. + +### Screen-Klassen + +Sinnvolle fachliche Klassen: + +- `info_wall` +- `single_info_display` +- `vertretungsplan_display` + +Diese Klassen koennen spaeter fuer Voreinstellungen, Templates und Provisionierung genutzt werden. + +### Orientierung als Kernattribut + +Jeder Screen braucht von Anfang an eine fest definierte Orientierung. + +Mindestens: + +- `portrait` +- `landscape` + +Optional spaeter: + +- exakte Rotation `0`, `90`, `180`, `270` + +Warum das wichtig ist: + +- Assets muessen passend skaliert oder getrennt gepflegt werden +- globale Kampagnen koennen fuer Hoch- und Querformat unterschiedliche Szenen brauchen +- Provisionierung und Display-Setup muessen die Orientierung kennen + +### Gruppen- und Slot-Modell + +Es werden zwei Zielmodelle parallel unterstuetzt. + +#### Gruppenmodell + +Gruppen fassen Screens logisch zusammen, z. B.: + +- `all` +- `wall-all` +- `wall-row-1` +- `vertretungsplan-all` + +Dieses Modell ist ideal fuer: + +- globale Motive +- saisonale Kampagnen +- Massenaktionen im Admin-Bereich + +#### Slot-Modell + +Slots beschreiben feste Positionen innerhalb einer Monitorwand. + +Beispiele: + +- `wall-r1-c1` +- `wall-r1-c2` +- `wall-r1-c3` +- `wall-r2-c1` + +Dieses Modell ist ideal fuer: + +- verteilte Schriftzuege +- zusammengesetzte Grossmotive +- geordnete Layouts ueber mehrere Screens + +### Empfohlene Grundregel fuer Kampagnen + +Jede Kampagne definiert ihren Zielraum explizit: + +- `all_screens` +- `screen_group` +- `specific_screens` +- `wall_slots` + +Die Inhaltsprioritaet bleibt dabei immer: + +1. aktive Kampagne +2. tenantbezogene Playlist +3. Fallback + +### Beispiel 1 - Schriftzug ueber die Infowand + +- Template-Typ: `message_wall` +- Ziel: Gruppe `wall-all` +- Layout: Text wird in neun Segmente geteilt +- jeder Slot bekommt seinen Ausschnitt +- die 4 kuenftigen Vertretungsplan-Screens bleiben unberuehrt + +### Beispiel 2 - Weihnachtsmotiv auf allen Screens + +- Template-Typ: `full_screen_media` +- Ziel: Gruppe `all` +- fuer Portrait-Screens wird Portrait-Asset verwendet +- fuer Landscape-Screens wird Landscape-Asset verwendet + +### Beispiel 3 - Veranstaltungstag mit gemischten Anzeigen + +- Template-Typ: `screen_specific_scene` +- Infowand zeigt Event-Motto +- Vertretungsplan-Screens zeigen Programm oder Wegweiser +- alles als eine Kampagne administrierbar + +## Auswirkung auf Datenmodell und Implementierung + +Von Beginn an mitzudenken sind: + +- Template-Typen +- Kampagnen als aktivierbare Instanzen +- Gruppenmodell +- Slot-Modell fuer die Wand +- Orientierung pro Screen +- moegliche getrennte Assets fuer Portrait und Landscape + +Damit ist die globale Orchestrierung ein tragender Bestandteil des Systems und kein nachtraeglicher Sonderbau.