Backend published auf signage/screen/{slug}/playlist-changed nach
Playlist-Mutationen (2s Debounce). Agent subscribed und fetcht
Playlist sofort (3s Debounce). 60s-Polling bleibt als Fallback.
Neue Packages: mqttnotifier (Backend), mqttsubscriber (Agent)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
3.7 KiB
3.7 KiB
Info-Board Neu - MQTT-Vertrag
Vertrag zwischen Backend und Agent für die Echtzeit-Synchronisation von Playlist-Änderungen und Gerätebefehlen.
Überblick
Das Messaging-System nutzt MQTT für:
- Playlist-Mutations-Benachrichtigungen: Backend → Agent
- Device-Commands: Backend → Agent (zukünftig: reload, restart_player, reboot, display_on/off)
- Heartbeat & Status: Agent → Backend (siehe
PLAYER-STATUS-HTTP.md)
Alle Topics folgen dem Naming-Pattern: signage/{component}/{screenSlug}/{event}
Topics
Backend publishes
signage/screen/{screenSlug}/playlist-changed
Publisher: Backend Subscriber: Agent
Wird nach jeder Mutation der Playlist gepublished (Add, Remove, Reorder, Enable/Disable Item).
Payload:
{
"ts": 1711268440000
}
ts: Unix-Zeitstempel in Millisekunden des Änderungsereignisses auf dem Backend
Verhalten:
- Backend debounced Änderungen über 2 Sekunden
- Mehrere schnelle Mutationen werden zu einem Event zusammengefasst
- Garantiert mindestens ein Event pro logischer Änderung
Agent-Reaktion:
- Agent empfängt das Event
- Agent debounced die Verarbeitung über 3 Sekunden
- Agent startet sofortiges Playlist-Fetch via HTTP
GET /api/v1/screens/{screenSlug}/playlist - Agent speichert die Playlist lokal und signalisiert dem Browser einen Reload
Implementierung (Agent):
// Pseudocode
func OnPlaylistChanged(msg PlaylistChangedMessage) {
if debounceTimer.running {
debounceTimer.reset()
} else {
debounceTimer.start(3 * time.Second)
}
}
func onDebounceExpire() {
playlist := fetchPlaylistViaHTTP()
saveToLocalCache(playlist)
signalBrowserReload()
}
Zukünftige Topics
Die folgenden Topics sind geplant für Phase 5 (Prototyping) und später:
signage/screen/{screenSlug}/device-command
Publisher: Backend Subscriber: Agent
Befehl-Queue für Device-Steuerung.
Payload:
{
"cmd_id": "uuid",
"command": "reload|restart_player|reboot|display_on|display_off",
"ts": 1711268440000
}
Agent-Reaktion:
- Befehl ausführen
- ACK via HTTP POST zu
PUT /api/v1/screens/{screenSlug}/command-ack
Beispiel-Flow: Playlist-Update
Admin: Click "Speichern" in Playlist-UI
↓
Backend: Playlist-Mutation in DB schreiben
↓
Backend: `playlist-changed` mit ts=now nach 2s Debounce publifyen
↓
Agent: Event empfangen, 3s Debounce starten
↓
Agent: Nach 3s → HTTP GET /api/v1/screens/{slug}/playlist
↓
Backend: Aktuelle Playlist zurückgeben
↓
Agent: Lokal speichern, Browser signalisieren "reload"
↓
Browser: Neuer Content geladen und abgespielt
MQTT-Verbindungspezifikation
(Siehe PLAYER-KONZEPT.md und Provisioning-Variablen für Broker-URL, Authentifizierung und Retry-Logik)
- Broker-Adresse: Über Provisioning konfigurierbar (Standard:
tcp://backend:1883) - Client-ID:
{tenantSlug}/{screenSlug}(eindeutig pro Screen) - Username/Password: Device-spezifische Credentials (OAuth-ähnlich)
- QoS-Level: 1 (At-Least-Once für Critical-Events)
- Retain: nein (Event-Natur, nicht State)
- Heartbeat: Separat via HTTP (siehe
PLAYER-STATUS-HTTP.md)
Notizen für Implementierer
- Replay bei Reconnect: Topics haben
retain: false, daher entfallen keine Events bei Trennung. Der Agent synchronisiert sich nach Reconnect via regulärem Status-Endpoint. - Ordering: Mehrere Events zu einem Screen sind ordered; Ordering über Screen-Grenzen hinweg ist nicht garantiert.
- Fehlerbehandlung: Fehlgeschlagene Playlisten-Fetches werden vom Agent nach Standard-Retry-Logik wiederholt.
- Version der Spec: v1.0 (März 2026)