424 lines
8.3 KiB
Markdown
424 lines
8.3 KiB
Markdown
# 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
|