Lege Planungsgrundlage fuer neues Info-Board an
This commit is contained in:
commit
de15ee2e63
5 changed files with 1387 additions and 0 deletions
424
API-MQTT-VERTRAG.md
Normal file
424
API-MQTT-VERTRAG.md
Normal file
|
|
@ -0,0 +1,424 @@
|
|||
# Info-Board Neu - API- und MQTT-Vertrag
|
||||
|
||||
## Ziel
|
||||
|
||||
Dieses Dokument beschreibt die technische Arbeitsteilung zwischen HTTPS-API und MQTT.
|
||||
|
||||
Grundregel:
|
||||
|
||||
- HTTPS fuer Daten, Uploads, Konfiguration und Authentifizierung
|
||||
- MQTT fuer Ereignisse, Heartbeats, Status und Fernsteuerung
|
||||
|
||||
## Architekturprinzip
|
||||
|
||||
Der Player arbeitet autonom aus lokalem Zustand.
|
||||
|
||||
Das bedeutet:
|
||||
|
||||
- die API liefert Konfiguration, Playlist und Medieninformationen
|
||||
- der Player cached diese Daten lokal
|
||||
- MQTT informiert ueber Aenderungen und traegt leichte Steuerkommandos
|
||||
- bei Ausfall der Verbindung laeuft der Player mit dem letzten gueltigen Stand weiter
|
||||
|
||||
## HTTPS-API
|
||||
|
||||
### Authentifizierung
|
||||
|
||||
Die Web-Oberflaechen nutzen benutzerbezogene Sessions oder Tokens.
|
||||
|
||||
Die Player nutzen ein geraetebezogenes Token.
|
||||
|
||||
Empfohlene Aufteilung:
|
||||
|
||||
- Browser-UI: Cookie-Session oder JWT
|
||||
- Player: statischer oder rotierbarer API-Token je Screen
|
||||
|
||||
## API-Bereiche
|
||||
|
||||
### 1. Auth
|
||||
|
||||
Zweck:
|
||||
|
||||
- Login
|
||||
- Logout
|
||||
- Session-Pruefung
|
||||
|
||||
Beispiel-Endpunkte:
|
||||
|
||||
- `POST /api/v1/auth/login`
|
||||
- `POST /api/v1/auth/logout`
|
||||
- `GET /api/v1/auth/me`
|
||||
|
||||
### 2. Tenants und Benutzer
|
||||
|
||||
Zweck:
|
||||
|
||||
- Verwaltung von Firmen und Benutzern
|
||||
|
||||
Beispiel-Endpunkte:
|
||||
|
||||
- `GET /api/v1/tenants`
|
||||
- `POST /api/v1/tenants`
|
||||
- `GET /api/v1/tenants/:tenantId/users`
|
||||
- `POST /api/v1/tenants/:tenantId/users`
|
||||
|
||||
### 3. Screens
|
||||
|
||||
Zweck:
|
||||
|
||||
- technische und fachliche Verwaltung der Monitore
|
||||
|
||||
Beispiel-Endpunkte:
|
||||
|
||||
- `GET /api/v1/screens`
|
||||
- `GET /api/v1/screens/:screenId`
|
||||
- `PATCH /api/v1/screens/:screenId`
|
||||
- `GET /api/v1/screens/:screenId/status`
|
||||
- `GET /api/v1/screens/:screenId/snapshots/latest`
|
||||
|
||||
### 4. Medien
|
||||
|
||||
Zweck:
|
||||
|
||||
- Uploads
|
||||
- Listenansicht
|
||||
- Loeschen
|
||||
- Metadatenbearbeitung
|
||||
|
||||
Beispiel-Endpunkte:
|
||||
|
||||
- `GET /api/v1/media`
|
||||
- `POST /api/v1/media/upload`
|
||||
- `POST /api/v1/media/import-url`
|
||||
- `PATCH /api/v1/media/:mediaId`
|
||||
- `DELETE /api/v1/media/:mediaId`
|
||||
|
||||
### 5. Playlists
|
||||
|
||||
Zweck:
|
||||
|
||||
- Playlist lesen und bearbeiten
|
||||
- Reihenfolge und Zeitfenster verwalten
|
||||
|
||||
Beispiel-Endpunkte:
|
||||
|
||||
- `GET /api/v1/screens/:screenId/playlist`
|
||||
- `PUT /api/v1/screens/:screenId/playlist`
|
||||
- `POST /api/v1/screens/:screenId/playlist/items`
|
||||
- `PATCH /api/v1/screens/:screenId/playlist/items/:itemId`
|
||||
- `DELETE /api/v1/screens/:screenId/playlist/items/:itemId`
|
||||
|
||||
### 6. Player-Sync
|
||||
|
||||
Zweck:
|
||||
|
||||
- geraeteseitiger Abruf von Konfiguration und Daten
|
||||
- differenzieller Sync ueber Revisionen
|
||||
|
||||
Beispiel-Endpunkte:
|
||||
|
||||
- `POST /api/v1/player/register`
|
||||
- `GET /api/v1/player/config`
|
||||
- `GET /api/v1/player/playlist`
|
||||
- `GET /api/v1/player/media-manifest`
|
||||
- `GET /api/v1/player/media/:mediaId/download`
|
||||
- `POST /api/v1/player/status`
|
||||
- `POST /api/v1/player/snapshot`
|
||||
|
||||
### 7. Admin-Kommandos
|
||||
|
||||
Zweck:
|
||||
|
||||
- Ausloesen von Fernaktionen
|
||||
|
||||
Beispiel-Endpunkte:
|
||||
|
||||
- `POST /api/v1/screens/:screenId/commands/reload`
|
||||
- `POST /api/v1/screens/:screenId/commands/restart-player`
|
||||
- `POST /api/v1/screens/:screenId/commands/reboot`
|
||||
- `POST /api/v1/screens/:screenId/commands/display-on`
|
||||
- `POST /api/v1/screens/:screenId/commands/display-off`
|
||||
|
||||
## API-Antworten fuer den Player
|
||||
|
||||
### `GET /api/v1/player/config`
|
||||
|
||||
Liefert:
|
||||
|
||||
- `screen_id`
|
||||
- `screen_slug`
|
||||
- `config_revision`
|
||||
- `player_settings`
|
||||
- `fallback_dir`
|
||||
- `snapshot_interval_seconds`
|
||||
- `offline_overlay_enabled`
|
||||
- `rotation`
|
||||
|
||||
### `GET /api/v1/player/playlist`
|
||||
|
||||
Liefert:
|
||||
|
||||
- `playlist_id`
|
||||
- `playlist_revision`
|
||||
- `default_duration_seconds`
|
||||
- `fallback_enabled`
|
||||
- `items[]`
|
||||
|
||||
Jedes Item enthaelt mindestens:
|
||||
|
||||
- `id`
|
||||
- `type`
|
||||
- `src`
|
||||
- `duration_seconds`
|
||||
- `load_timeout_seconds`
|
||||
- `cache_policy`
|
||||
- `on_error`
|
||||
- `retry_count`
|
||||
- `valid_from`
|
||||
- `valid_until`
|
||||
- `enabled`
|
||||
|
||||
### `GET /api/v1/player/media-manifest`
|
||||
|
||||
Liefert:
|
||||
|
||||
- `media_revision`
|
||||
- `assets[]`
|
||||
|
||||
Jeder Asset-Eintrag enthaelt mindestens:
|
||||
|
||||
- `id`
|
||||
- `type`
|
||||
- `source_kind`
|
||||
- `download_url` nullable
|
||||
- `original_url` nullable
|
||||
- `checksum`
|
||||
- `size_bytes`
|
||||
- `mime_type`
|
||||
- `cache_required`
|
||||
|
||||
## MQTT-Verwendung
|
||||
|
||||
MQTT dient nur der schnellen, leichten Signal- und Statuskommunikation.
|
||||
|
||||
Nicht ueber MQTT transportieren:
|
||||
|
||||
- Datei-Uploads
|
||||
- grosse JSON-Payloads fuer komplette Medienlisten
|
||||
- eigentliche Mediendateien
|
||||
|
||||
## MQTT-Topics
|
||||
|
||||
### Heartbeat
|
||||
|
||||
- `signage/screen/<screen-id>/heartbeat`
|
||||
|
||||
Payload-Beispiel:
|
||||
|
||||
```json
|
||||
{
|
||||
"screen_id": "info01",
|
||||
"ts": "2026-03-22T12:00:00Z",
|
||||
"online": true,
|
||||
"server_connected": true,
|
||||
"mqtt_connected": true,
|
||||
"player_version": "0.1.0",
|
||||
"uptime_seconds": 86400
|
||||
}
|
||||
```
|
||||
|
||||
### Status
|
||||
|
||||
- `signage/screen/<screen-id>/status`
|
||||
|
||||
Payload-Beispiel:
|
||||
|
||||
```json
|
||||
{
|
||||
"screen_id": "info01",
|
||||
"ts": "2026-03-22T12:00:00Z",
|
||||
"current_item_id": "pli_123",
|
||||
"current_item_type": "image",
|
||||
"current_item_label": "Begruessung",
|
||||
"current_item_started_at": "2026-03-22T11:59:45Z",
|
||||
"current_item_duration_seconds": 20,
|
||||
"overlay_state": "online",
|
||||
"cache_state": "ok",
|
||||
"error_code": null,
|
||||
"error_message": null
|
||||
}
|
||||
```
|
||||
|
||||
### Events
|
||||
|
||||
- `signage/screen/<screen-id>/event`
|
||||
|
||||
Typische Events:
|
||||
|
||||
- `playlist_changed`
|
||||
- `sync_completed`
|
||||
- `sync_failed`
|
||||
- `item_failed`
|
||||
- `browser_restarted`
|
||||
- `snapshot_uploaded`
|
||||
|
||||
### Commands
|
||||
|
||||
- `signage/screen/<screen-id>/command`
|
||||
|
||||
Payload-Beispiel:
|
||||
|
||||
```json
|
||||
{
|
||||
"command_id": "cmd_456",
|
||||
"type": "reload",
|
||||
"payload": {},
|
||||
"requested_at": "2026-03-22T12:00:00Z"
|
||||
}
|
||||
```
|
||||
|
||||
### ACK
|
||||
|
||||
- `signage/screen/<screen-id>/ack`
|
||||
|
||||
Payload-Beispiel:
|
||||
|
||||
```json
|
||||
{
|
||||
"command_id": "cmd_456",
|
||||
"screen_id": "info01",
|
||||
"ts": "2026-03-22T12:00:02Z",
|
||||
"result": "ok",
|
||||
"message": "playlist reloaded"
|
||||
}
|
||||
```
|
||||
|
||||
## QoS- und Broker-Hinweise
|
||||
|
||||
Empfehlung:
|
||||
|
||||
- Heartbeat: QoS 0 oder 1
|
||||
- Status: QoS 0 oder 1
|
||||
- Commands: QoS 1
|
||||
- ACK: QoS 1
|
||||
|
||||
Zusatzempfehlungen:
|
||||
|
||||
- Last-Will fuer Offline-Erkennung nutzen
|
||||
- retained Messages nur sparsam und gezielt einsetzen
|
||||
- kein Missbrauch von retained Commands
|
||||
|
||||
## Trennung von Pull und Push
|
||||
|
||||
### Pull ueber HTTPS
|
||||
|
||||
Der Player holt aktiv:
|
||||
|
||||
- Konfiguration
|
||||
- Playlist
|
||||
- Medienmanifest
|
||||
- eigentliche Medien
|
||||
|
||||
### Push ueber MQTT
|
||||
|
||||
Der Server signalisiert aktiv:
|
||||
|
||||
- es gibt neue Konfiguration
|
||||
- es gibt neue Playlist-Daten
|
||||
- fuehre einen Befehl aus
|
||||
|
||||
Beispielablauf bei Playlist-Aenderung:
|
||||
|
||||
1. Benutzer speichert Playlist in der Web-UI
|
||||
2. Server erhoeht `playlist_revision`
|
||||
3. Server sendet Event oder Command `reload`
|
||||
4. Player ruft `GET /api/v1/player/playlist` ab
|
||||
5. Player synchronisiert fehlende Medien
|
||||
6. Player bestaetigt erfolgreichen Reload
|
||||
|
||||
## Offline-Verhalten
|
||||
|
||||
### Wenn HTTPS ausfaellt
|
||||
|
||||
- Player nutzt letzte lokale Konfiguration
|
||||
- Player nutzt letzte lokale Playlist
|
||||
- Player nutzt lokalen Mediencache
|
||||
- Overlay signalisiert Offline-Zustand
|
||||
|
||||
### Wenn MQTT ausfaellt
|
||||
|
||||
- Player laeuft normal weiter
|
||||
- periodischer HTTPS-Sync erkennt spaetere Aenderungen trotzdem
|
||||
- Admin-Kommandos werden ggf. verzoegert, aber nicht die Anzeige selbst
|
||||
|
||||
### Wenn beides ausfaellt
|
||||
|
||||
- Player bleibt autonom betriebsfaehig
|
||||
- keine frischen Inhalte oder Befehle mehr
|
||||
- bestehende Playlist/Fallback laufen weiter
|
||||
|
||||
## Web-Inhalte und Fehlerstrategie
|
||||
|
||||
Webseiten sind der stoeranfaelligste Medientyp.
|
||||
|
||||
Regeln:
|
||||
|
||||
- Chromium zeigt immer nur die lokale `player-ui`
|
||||
- `player-ui` bettet Web-Inhalte kontrolliert ein
|
||||
- jedes Web-Item hat einen `load_timeout_seconds`
|
||||
- bei Fehler gilt `on_error`
|
||||
|
||||
Typische Fehlerpfade:
|
||||
|
||||
- 404 oder DNS-Problem -> `skip` oder `fallback`
|
||||
- langsamer Ladevorgang -> Timeout -> `retry` oder `skip`
|
||||
- Renderer-Fehler -> lokaler Watchdog startet den Renderer neu
|
||||
|
||||
## Screenshot-Upload
|
||||
|
||||
Der Player erstellt Screenshots:
|
||||
|
||||
- bei Item-Wechsel
|
||||
- zyklisch
|
||||
- auf Admin-Anforderung
|
||||
|
||||
Ablauf:
|
||||
|
||||
1. Player erzeugt Bild lokal
|
||||
2. Player sendet es per HTTPS an `POST /api/v1/player/snapshot`
|
||||
3. Server speichert das Bild und aktualisiert die letzte Vorschau des Screens
|
||||
|
||||
## Sicherheitsgrundsaetze
|
||||
|
||||
- jeder Player hat eine eigene technische Identitaet
|
||||
- API und MQTT werden authentifiziert
|
||||
- Tenant-Benutzer sehen nur tenantbezogene Objekte
|
||||
- Admin-Kommandos werden serverseitig protokolliert
|
||||
- Screenshots und Statusdaten sind nur fuer berechtigte Nutzer sichtbar
|
||||
|
||||
## Minimale API-Frequenzen
|
||||
|
||||
Sinnvolle Startwerte:
|
||||
|
||||
- Heartbeat alle 30 Sekunden
|
||||
- Status-Update bei Item-Wechsel und zusaetzlich alle 60 Sekunden
|
||||
- Konfigurations-/Playlist-Poll als Fallback alle 5 Minuten
|
||||
- Snapshot alle 60 Sekunden oder bei Item-Wechsel
|
||||
|
||||
## V1-Abgrenzung
|
||||
|
||||
Fuer Version 1 bewusst nicht zwingend enthalten:
|
||||
|
||||
- Live-Video-Stream der Monitore
|
||||
- komplexe Kampagnenlogik mit Prioritaeten
|
||||
- Multi-Screen-Synchronisation auf Frame-Ebene
|
||||
- serverseitiges Video-Transcoding
|
||||
|
||||
## Empfohlene naechste Dokumente
|
||||
|
||||
Als direkte Folge sollten entstehen:
|
||||
|
||||
- technisches Player-Konzept
|
||||
- Server-Komponentenplan
|
||||
- Ansible-Deploymentplan
|
||||
- Rechte- und Authentifizierungskonzept
|
||||
391
DATENMODELL.md
Normal file
391
DATENMODELL.md
Normal file
|
|
@ -0,0 +1,391 @@
|
|||
# Info-Board Neu - Datenmodell
|
||||
|
||||
## Ziel
|
||||
|
||||
Das Datenmodell trennt klar zwischen:
|
||||
|
||||
- Mandanten und Benutzern
|
||||
- Bildschirmen und ihrer technischen Laufzeitinformation
|
||||
- Medien und Playlists
|
||||
- Steuerbefehlen und Rueckmeldungen
|
||||
|
||||
Das Modell ist so ausgelegt, dass:
|
||||
|
||||
- jede Firma nur ihren eigenen Monitor bzw. Kanal pflegt
|
||||
- die Administration alle Monitore zentral sehen und steuern kann
|
||||
- Offline-Betrieb der Player moeglich bleibt
|
||||
- Zeitsteuerung mit `valid_from` und `valid_until` sauber abbildbar ist
|
||||
|
||||
## Kernentitaeten
|
||||
|
||||
### `tenant`
|
||||
|
||||
Repraesentiert eine Firma bzw. einen abgeschotteten Inhaltsbereich.
|
||||
|
||||
Felder:
|
||||
|
||||
- `id`
|
||||
- `slug`
|
||||
- `name`
|
||||
- `active`
|
||||
- `created_at`
|
||||
- `updated_at`
|
||||
|
||||
Hinweise:
|
||||
|
||||
- ein Tenant kann spaeter mehrere Screens haben, auch wenn zunaechst meist 1:1 gearbeitet wird
|
||||
- alle Medien und Playlists sind einem Tenant zugeordnet
|
||||
|
||||
### `user`
|
||||
|
||||
Repraesentiert einen Benutzer der Firmen- oder Admin-Oberflaeche.
|
||||
|
||||
Felder:
|
||||
|
||||
- `id`
|
||||
- `tenant_id` nullable fuer globale Admins
|
||||
- `username`
|
||||
- `email`
|
||||
- `password_hash`
|
||||
- `role` (`admin`, `tenant_user`)
|
||||
- `active`
|
||||
- `last_login_at`
|
||||
- `created_at`
|
||||
- `updated_at`
|
||||
|
||||
Regeln:
|
||||
|
||||
- `tenant_user` darf nur Daten des eigenen Tenants sehen und bearbeiten
|
||||
- `admin` darf alle Tenants und alle Screens verwalten
|
||||
|
||||
### `screen`
|
||||
|
||||
Repraesentiert einen physischen Monitor bzw. einen Player-Client.
|
||||
|
||||
Felder:
|
||||
|
||||
- `id`
|
||||
- `tenant_id`
|
||||
- `slug`
|
||||
- `name`
|
||||
- `description`
|
||||
- `location`
|
||||
- `hardware_name`
|
||||
- `enabled`
|
||||
- `rotation` (`0`, `90`, `180`, `270`)
|
||||
- `resolution_width`
|
||||
- `resolution_height`
|
||||
- `fallback_dir`
|
||||
- `snapshot_interval_seconds`
|
||||
- `offline_overlay_enabled`
|
||||
- `created_at`
|
||||
- `updated_at`
|
||||
|
||||
Hinweise:
|
||||
|
||||
- der `slug` dient als technische Kennung fuer Konfiguration, API und MQTT
|
||||
- `fallback_dir` beschreibt die lokale oder synchronisierte Fallback-Quelle auf dem Client
|
||||
|
||||
### `screen_registration`
|
||||
|
||||
Optionale Trennung zwischen fachlichem Screen und technischer Registrierung.
|
||||
|
||||
Felder:
|
||||
|
||||
- `id`
|
||||
- `screen_id`
|
||||
- `device_uuid`
|
||||
- `hostname`
|
||||
- `api_token_hash`
|
||||
- `mqtt_client_id`
|
||||
- `last_seen_at`
|
||||
- `last_ip`
|
||||
- `player_version`
|
||||
- `os_version`
|
||||
- `created_at`
|
||||
- `updated_at`
|
||||
|
||||
Zweck:
|
||||
|
||||
- Wiedererkennung eines konkreten Geraets
|
||||
- sichere Kommunikation mit API und Broker
|
||||
- technische Inventarisierung
|
||||
|
||||
### `media_asset`
|
||||
|
||||
Repraesentiert ein verwaltetes Medium.
|
||||
|
||||
Felder:
|
||||
|
||||
- `id`
|
||||
- `tenant_id`
|
||||
- `screen_id` nullable
|
||||
- `title`
|
||||
- `description`
|
||||
- `type` (`image`, `video`, `pdf`, `web`)
|
||||
- `source_kind` (`upload`, `remote_url`)
|
||||
- `storage_path` nullable bei reinen Web-URLs
|
||||
- `original_url` nullable
|
||||
- `mime_type`
|
||||
- `checksum`
|
||||
- `size_bytes`
|
||||
- `enabled`
|
||||
- `created_by_user_id`
|
||||
- `created_at`
|
||||
- `updated_at`
|
||||
|
||||
Regeln:
|
||||
|
||||
- `upload` bedeutet: Datei liegt im Medien-Storage
|
||||
- `remote_url` bedeutet: Quelle ist extern und wird vom Player oder Server gecacht
|
||||
- `screen_id` kann optional gesetzt werden, wenn ein Medium nur fuer einen Monitor gedacht ist
|
||||
|
||||
### `playlist`
|
||||
|
||||
Repraesentiert eine logische Playlist eines Screens.
|
||||
|
||||
Felder:
|
||||
|
||||
- `id`
|
||||
- `tenant_id`
|
||||
- `screen_id`
|
||||
- `name`
|
||||
- `is_active`
|
||||
- `default_duration_seconds`
|
||||
- `fallback_enabled`
|
||||
- `fallback_dir`
|
||||
- `shuffle_enabled`
|
||||
- `created_at`
|
||||
- `updated_at`
|
||||
|
||||
Regeln:
|
||||
|
||||
- pro Screen gibt es in v1 genau eine aktive Playlist
|
||||
- spaeter koennen mehrere Playlists mit Umschaltung moeglich werden
|
||||
|
||||
### `playlist_item`
|
||||
|
||||
Repraesentiert einen einzelnen Eintrag in einer Playlist.
|
||||
|
||||
Felder:
|
||||
|
||||
- `id`
|
||||
- `playlist_id`
|
||||
- `screen_id`
|
||||
- `order_index`
|
||||
- `media_asset_id` nullable
|
||||
- `type` (`image`, `video`, `pdf`, `web`, `dir`)
|
||||
- `src`
|
||||
- `title`
|
||||
- `duration_seconds`
|
||||
- `load_timeout_seconds`
|
||||
- `cache_policy` (`required`, `prefer_cache`, `no_cache`)
|
||||
- `on_error` (`skip`, `retry`, `fallback`)
|
||||
- `retry_count`
|
||||
- `valid_from` nullable
|
||||
- `valid_until` nullable
|
||||
- `enabled`
|
||||
- `created_at`
|
||||
- `updated_at`
|
||||
|
||||
Regeln:
|
||||
|
||||
- `media_asset_id` wird bei verwalteten Medien gesetzt
|
||||
- `src` enthaelt den effektiven Pfad oder die URL, damit der Player auch ohne Join-Struktur arbeiten kann
|
||||
- `type=dir` erlaubt definierte Verzeichnisreferenzen innerhalb der Playlist
|
||||
|
||||
### `playlist_item_dir_rule`
|
||||
|
||||
Optionale Zusatzregel fuer `type=dir`.
|
||||
|
||||
Felder:
|
||||
|
||||
- `id`
|
||||
- `playlist_item_id`
|
||||
- `directory_path`
|
||||
- `sort_mode` (`name_asc`, `name_desc`, `mtime_asc`, `mtime_desc`, `shuffle`)
|
||||
- `per_item_duration_seconds`
|
||||
- `recursive`
|
||||
- `file_filter` nullable
|
||||
|
||||
Zweck:
|
||||
|
||||
- sauberere Modellierung fuer Verzeichnisbasierte Fallbacks oder Einschuebe
|
||||
|
||||
### `screen_status`
|
||||
|
||||
Repraesentiert den letzten bekannten Laufzeitstatus eines Players.
|
||||
|
||||
Felder:
|
||||
|
||||
- `screen_id`
|
||||
- `online`
|
||||
- `server_connected`
|
||||
- `mqtt_connected`
|
||||
- `last_heartbeat_at`
|
||||
- `last_sync_at`
|
||||
- `current_playlist_id`
|
||||
- `current_playlist_item_id` nullable
|
||||
- `current_item_type` nullable
|
||||
- `current_item_label` nullable
|
||||
- `current_item_started_at` nullable
|
||||
- `current_item_duration_seconds` nullable
|
||||
- `cache_state` (`ok`, `stale`, `missing`, `error`)
|
||||
- `overlay_state` (`online`, `degraded`, `offline`)
|
||||
- `error_code` nullable
|
||||
- `error_message` nullable
|
||||
- `player_version`
|
||||
- `uptime_seconds`
|
||||
- `free_disk_bytes` nullable
|
||||
- `temperature_celsius` nullable
|
||||
- `updated_at`
|
||||
|
||||
Hinweise:
|
||||
|
||||
- `screen_status` ist eine verdichtete Sicht fuer Dashboard und Ueberwachung
|
||||
- historische Verlaeufe koennen spaeter separat gespeichert werden
|
||||
|
||||
### `screen_snapshot`
|
||||
|
||||
Repraesentiert eine Vorschauaufnahme des aktuellen Bildschirminhalts.
|
||||
|
||||
Felder:
|
||||
|
||||
- `id`
|
||||
- `screen_id`
|
||||
- `captured_at`
|
||||
- `storage_path`
|
||||
- `width`
|
||||
- `height`
|
||||
- `mime_type`
|
||||
- `source` (`scheduled`, `item_change`, `manual`)
|
||||
|
||||
Regeln:
|
||||
|
||||
- in der UI wird typischerweise nur der letzte Snapshot angezeigt
|
||||
- aeltere Snapshots koennen nach Zeit oder Anzahl aufgeraeumt werden
|
||||
|
||||
### `device_command`
|
||||
|
||||
Repraesentiert einen an einen Screen gesendeten Befehl.
|
||||
|
||||
Felder:
|
||||
|
||||
- `id`
|
||||
- `screen_id`
|
||||
- `command_type` (`reload`, `restart_player`, `reboot`, `display_on`, `display_off`, `refresh_snapshot`, `clear_cache`)
|
||||
- `payload_json`
|
||||
- `requested_by_user_id`
|
||||
- `requested_at`
|
||||
- `delivery_state` (`queued`, `sent`, `acknowledged`, `failed`, `expired`)
|
||||
- `delivered_at` nullable
|
||||
- `acknowledged_at` nullable
|
||||
- `result_code` nullable
|
||||
- `result_message` nullable
|
||||
|
||||
Zweck:
|
||||
|
||||
- nachvollziehbare Fernsteuerung mit Audit-Trail
|
||||
|
||||
### `sync_state`
|
||||
|
||||
Repraesentiert den Synchronisationsstand eines Screens.
|
||||
|
||||
Felder:
|
||||
|
||||
- `screen_id`
|
||||
- `config_revision`
|
||||
- `playlist_revision`
|
||||
- `media_revision`
|
||||
- `last_successful_sync_at`
|
||||
- `last_failed_sync_at` nullable
|
||||
- `last_error_message` nullable
|
||||
|
||||
Zweck:
|
||||
|
||||
- Erkennung, ob ein Player auf dem aktuellen Stand ist
|
||||
|
||||
## Beziehungen
|
||||
|
||||
- ein `tenant` hat viele `users`
|
||||
- ein `tenant` hat viele `screens`
|
||||
- ein `tenant` hat viele `media_assets`
|
||||
- ein `screen` hat genau eine aktive `playlist` in v1
|
||||
- eine `playlist` hat viele `playlist_items`
|
||||
- ein `screen` hat genau einen aktuellen `screen_status`
|
||||
- ein `screen` hat viele `screen_snapshots`
|
||||
- ein `screen` hat viele `device_commands`
|
||||
- ein `screen` hat genau einen aktuellen `sync_state`
|
||||
|
||||
## Zugriffsregeln
|
||||
|
||||
### Tenant-User
|
||||
|
||||
Ein `tenant_user` darf:
|
||||
|
||||
- nur den eigenen `tenant` sehen
|
||||
- nur den eigenen `screen` bzw. die dem Tenant zugeordneten Screens sehen
|
||||
- nur eigene Medien hochladen und pflegen
|
||||
- nur eigene Playlists bearbeiten
|
||||
- nur die Vorschau des eigenen Screens sehen
|
||||
|
||||
Ein `tenant_user` darf nicht:
|
||||
|
||||
- andere Tenants sehen
|
||||
- globale Steuerkommandos senden
|
||||
- andere Screens administrieren
|
||||
|
||||
### Admin
|
||||
|
||||
Ein `admin` darf:
|
||||
|
||||
- alle Tenants, Screens, Medien und Playlists sehen
|
||||
- globale Steuerbefehle senden
|
||||
- Vorschau und Status aller Screens sehen
|
||||
- neue Screens und Benutzer anlegen
|
||||
|
||||
## Revisions- und Caching-Modell
|
||||
|
||||
Damit Offline-Betrieb einfach bleibt, arbeitet der Player nicht gegen beliebige Einzelobjekte, sondern gegen Revisionen.
|
||||
|
||||
Sinnvoll sind mindestens:
|
||||
|
||||
- `playlist_revision`
|
||||
- `media_revision`
|
||||
- `config_revision`
|
||||
|
||||
Der Player kann damit erkennen:
|
||||
|
||||
- ob neue Konfiguration vorliegt
|
||||
- ob Medien nachgeladen werden muessen
|
||||
- ob die lokale Kopie noch gueltig ist
|
||||
|
||||
## Beispiel fuer aktive Playlist-Auswertung
|
||||
|
||||
Ein `playlist_item` ist aktiv, wenn:
|
||||
|
||||
- `enabled = true`
|
||||
- `valid_from` leer oder in der Vergangenheit liegt
|
||||
- `valid_until` leer oder in der Zukunft liegt
|
||||
|
||||
Wenn kein aktives Item existiert:
|
||||
|
||||
- greift die globale Fallback-Regel des Screens oder der Playlist
|
||||
|
||||
## Beispiel fuer Admin-Steuerung
|
||||
|
||||
Wenn ein Admin `reload` ausloest:
|
||||
|
||||
1. Ein `device_command` wird gespeichert
|
||||
2. der Befehl wird per MQTT an den Screen signalisiert
|
||||
3. der Player fuehrt den Reload aus
|
||||
4. der Player sendet ein ACK
|
||||
5. `device_command.delivery_state` wird aktualisiert
|
||||
|
||||
## Offene spaetere Erweiterungen
|
||||
|
||||
- mehrere Screens pro Tenant in der Firmenoberflaeche
|
||||
- Vorlagen und globale Playlists
|
||||
- Historie der Statusdaten als Zeitreihe
|
||||
- Geplante Kampagnen mit Prioritaeten
|
||||
- serverseitige Konvertierung oder Transkodierung von Medien
|
||||
416
PLAN.md
Normal file
416
PLAN.md
Normal file
|
|
@ -0,0 +1,416 @@
|
|||
# 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/`
|
||||
24
README.md
Normal file
24
README.md
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
# Info-Board Neu
|
||||
|
||||
Dieses Verzeichnis enthaelt die Planung und spaetere Umsetzung der neuen Info-Board-Plattform.
|
||||
|
||||
Die Trennung von `/srv/docker/infoboard-netboot` ist sinnvoll, damit:
|
||||
|
||||
- die bestehende produktive Netboot-Struktur unangetastet bleibt
|
||||
- Planung, Prototypen und neue Deployments sauber getrennt sind
|
||||
- Server-, Player- und Ansible-Artefakte nicht mit Altbestand vermischt werden
|
||||
|
||||
## Aktueller Stand
|
||||
|
||||
- Architekturplan: `PLAN.md`
|
||||
- Umsetzungs-Todo: `TODO.md`
|
||||
- Datenmodell: `DATENMODELL.md`
|
||||
- API- und MQTT-Vertrag: `API-MQTT-VERTRAG.md`
|
||||
|
||||
## Empfohlene spaetere Struktur
|
||||
|
||||
- `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
|
||||
- `scripts/` fuer Hilfsskripte
|
||||
132
TODO.md
Normal file
132
TODO.md
Normal file
|
|
@ -0,0 +1,132 @@
|
|||
# Info-Board Neu - Umsetzungs-Todo
|
||||
|
||||
## Phase 0 - Projektbasis
|
||||
|
||||
- [ ] Projektverzeichnisstruktur unter `/srv/docker/info-board-neu` festlegen
|
||||
- [ ] Namenskonventionen fuer Server, Player, Rollen und Pakete definieren
|
||||
- [ ] Dokumentationsstruktur fuer Architektur, Betrieb und Deployment anlegen
|
||||
- [ ] Entscheidung fuer Server-Tech-Stack dokumentieren
|
||||
- [ ] Entscheidung fuer Player-Implementierung dokumentieren
|
||||
|
||||
## Phase 1 - Fachliches Fundament
|
||||
|
||||
- [ ] Rollenmodell fuer `admin` und monitorgebundene Nutzer final festschreiben
|
||||
- [ ] Datenmodell fuer `tenant`, `screen`, `user`, `media_asset`, `playlist`, `playlist_item`, `screen_status`, `screen_snapshot` definieren
|
||||
- [ ] Playlist-Semantik mit `duration`, `valid_from`, `valid_until`, `load_timeout`, `cache_policy`, `on_error` spezifizieren
|
||||
- [ ] Fallback-Regel fuer ungeplante oder leere Inhalte verbindlich definieren
|
||||
- [ ] Statusmodell fuer Online/Offline/Degraded/Error definieren
|
||||
- [ ] Kommandokatalog fuer Admin-Aktionen finalisieren
|
||||
|
||||
## Phase 2 - Technische Zielarchitektur
|
||||
|
||||
- [ ] Server-Komponentenliste finalisieren
|
||||
- [ ] API-Schnittstellen grob definieren
|
||||
- [ ] MQTT-Topic-Struktur finalisieren
|
||||
- [ ] HTTPS- und MQTT-Aufgabentrennung dokumentieren
|
||||
- [ ] Screenshot-/Vorschaustrategie spezifizieren
|
||||
- [ ] Offline- und Cache-Strategie bis auf Dateiebene festlegen
|
||||
- [ ] Sicherheitsmodell fuer Uploads, Login und Rechte pruefen
|
||||
|
||||
## Phase 3 - Player-Design
|
||||
|
||||
- [ ] Minimalen Paketbedarf fuer den Player auf Raspberry Pi OS Debian 13 ermitteln
|
||||
- [ ] X11-Minimalkonzept fuer Chromium-Kiosk dokumentieren
|
||||
- [ ] Startmechanismus fuer Chromium ohne Desktop-Umgebung definieren
|
||||
- [ ] Verzeichnislayout auf dem Player festlegen
|
||||
- [ ] `player-agent` fachlich zuschneiden
|
||||
- [ ] `player-ui` fachlich zuschneiden
|
||||
- [ ] Watchdog-Konzept fuer Browser und Agent definieren
|
||||
- [ ] Offline-Overlay-Verhalten spezifizieren
|
||||
- [ ] Fehlerbehandlung fuer Web-Inhalte und Timeouts ausarbeiten
|
||||
- [ ] Display-Steuerung fuer An/Aus, Rotation und Neustart planen
|
||||
|
||||
## Phase 4 - Server-Design
|
||||
|
||||
- [ ] API-Backend fachlich schneiden
|
||||
- [ ] Admin-Oberflaeche in Hauptbereiche aufteilen
|
||||
- [ ] Firmen-/Monitor-Oberflaeche in Hauptbereiche aufteilen
|
||||
- [ ] Storage-Konzept fuer Uploads, Cache-Dateien und Screenshots festlegen
|
||||
- [ ] Authentifizierungskonzept festlegen
|
||||
- [ ] Mandantentrennung im Datenmodell und in den APIs absichern
|
||||
- [ ] Logging- und Monitoring-Konzept definieren
|
||||
|
||||
## Phase 5 - Prototyping
|
||||
|
||||
- [ ] Minimalen Server-Prototyp bauen
|
||||
- [ ] Minimalen Player-Agent-Prototyp bauen
|
||||
- [ ] Minimale Player-UI bauen
|
||||
- [ ] Lokale Test-Playlist mit Bild, Video, PDF und Webseite anlegen
|
||||
- [ ] Fallback-Verzeichnisbetrieb demonstrieren
|
||||
- [ ] `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
|
||||
|
||||
## Phase 6 - Betriebsfaehigkeit
|
||||
|
||||
- [ ] Docker-Compose-Setup fuer den Server anlegen
|
||||
- [ ] systemd-Units fuer den Player erstellen
|
||||
- [ ] Chromium-Kiosk-Startskript erstellen
|
||||
- [ ] Screenshot-Erzeugung auf dem Player integrieren
|
||||
- [ ] Heartbeat- und Statusmeldungen integrieren
|
||||
- [ ] Fehler- und Wiederanlaufverhalten verifizieren
|
||||
|
||||
## Phase 7 - Ansible-Automatisierung
|
||||
|
||||
- [ ] Rolle `signage_base` erstellen
|
||||
- [ ] Rolle `signage_player` erstellen
|
||||
- [ ] Rolle `signage_display` erstellen
|
||||
- [ ] Rolle `signage_server` 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
|
||||
|
||||
## Phase 8 - Pilotbetrieb
|
||||
|
||||
- [ ] Einen Referenzmonitor fuer den Pilotbetrieb auswaehlen
|
||||
- [ ] Pilotmonitor neu aufsetzen
|
||||
- [ ] Verbindung zum Zentralserver herstellen
|
||||
- [ ] Upload- und Playlist-Pflege mit einem Testmandanten pruefen
|
||||
- [ ] Admin-Funktionen am Pilotmonitor pruefen
|
||||
- [ ] Offline-Betrieb real testen
|
||||
- [ ] Browser-/Renderer-Stabilitaet ueber laengeren Zeitraum beobachten
|
||||
|
||||
## Phase 9 - Migration der Bestandsmonitore
|
||||
|
||||
- [ ] Migrationsreihenfolge fuer `info01` bis `info09` festlegen
|
||||
- [ ] Rueckfallstrategie pro Monitor definieren
|
||||
- [ ] Altinhalte in das neue Medienmodell ueberfuehren
|
||||
- [ ] Playlists uebernehmen oder neu modellieren
|
||||
- [ ] Monitore nacheinander umstellen
|
||||
- [ ] Nach jeder Umstellung Stabilitaet und Fernsteuerung pruefen
|
||||
|
||||
## Phase 10 - Nacharbeiten
|
||||
|
||||
- [ ] Betriebsdokumentation schreiben
|
||||
- [ ] Admin-Handbuch schreiben
|
||||
- [ ] Kurzhandbuch fuer Firmen-Nutzer schreiben
|
||||
- [ ] Backup- und Restore-Konzept dokumentieren
|
||||
- [ ] Update- und Release-Prozess festlegen
|
||||
- [ ] Langfristige Wayland-Neubewertung fuer spaetere Version vormerken
|
||||
|
||||
## Querschnittsthemen
|
||||
|
||||
- [ ] Datensicherung fuer Datenbank und Medien einplanen
|
||||
- [ ] TLS-/Reverse-Proxy-Konzept festlegen
|
||||
- [ ] Ressourcenverbrauch auf Raspberry Pi beobachten
|
||||
- [ ] Verhalten bei grossen Videos optimieren
|
||||
- [ ] Verhalten bei defekten externen Webseiten absichern
|
||||
- [ ] Datenschutz- und Rechtefragen fuer Screenshots/Vorschauen pruefen
|
||||
|
||||
## Erste konkrete Abarbeitungsreihenfolge
|
||||
|
||||
- [ ] 1. Projektstruktur im neuen Verzeichnis vervollstaendigen
|
||||
- [ ] 2. Datenmodell in eigener Datei ausformulieren
|
||||
- [ ] 3. API- und MQTT-Vertrag definieren
|
||||
- [ ] 4. Player-Minimalkonzept fuer Raspberry Pi OS Debian 13 festzurren
|
||||
- [ ] 5. Server-Compose-Grundgeruest erstellen
|
||||
- [ ] 6. Player-Prototyp mit lokalem Browser-Renderer bauen
|
||||
- [ ] 7. Offline-Cache und Fallback robust machen
|
||||
- [ ] 8. UIs fuer Admin und Firmen schrittweise aufbauen
|
||||
- [ ] 9. Ansible-Rollen erstellen
|
||||
- [ ] 10. Pilotmonitor migrieren
|
||||
Loading…
Add table
Reference in a new issue