# Info-Board Neu - Erster HTTP-Statuspfad fuer den Player-Agent ## Ziel Dieses Dokument beschreibt den ersten bewusst kleinen Statuspfad zwischen `player/agent` und `server/backend`. Er ist fuer die aktuelle Entwicklungsstufe gedacht und noch kein finales Authentifizierungs- oder MQTT-Modell. ## V1-Dev-Entscheidung - der Agent sendet zunaechst Statusdaten per HTTP an das Backend - das Backend validiert und bestaetigt den Request und haelt den letzten bekannten Status pro Screen vor - der Pfad dient als erste echte Backend-Agent-Integration vor Registration, Sync und MQTT ## Endpoints im Ueberblick | Methode | Pfad | Beschreibung | |----------|---------------------------------------|-------------------------------------| | POST | /api/v1/player/status | Statusingest vom Player-Agent | | GET | /api/v1/screens/status | JSON-Uebersicht aller Screens | | GET | /api/v1/screens/{screenId}/status | JSON-Detail fuer einen Screen | | DELETE | /api/v1/screens/{screenId}/status | Screen-Eintrag loeschen | | GET | /status | HTML-Diagnoseseite (Uebersicht) | | GET | /status/{screenId} | HTML-Diagnoseseite (Einzelscreen) | ## POST /api/v1/player/status ### Request-Felder Pflichtfelder: - `screen_id` - `ts` (RFC3339-Zeitstempel) - `status`: `starting`, `running`, `stopped` - `heartbeat_every_seconds` (positive Ganzzahl) Optionale Felder: - `server_connectivity`: `unknown`, `online`, `degraded`, `offline` - `server_url` - `mqtt_broker` - `started_at` (RFC3339-Zeitstempel) - `last_heartbeat_at` (RFC3339-Zeitstempel) ### Beispiel ```json { "screen_id": "info01-dev", "ts": "2026-03-22T16:00:00Z", "status": "running", "server_connectivity": "online", "server_url": "http://127.0.0.1:8080", "mqtt_broker": "tcp://127.0.0.1:1883", "heartbeat_every_seconds": 30, "started_at": "2026-03-22T15:59:30Z", "last_heartbeat_at": "2026-03-22T16:00:00Z" } ``` ### Antwort ```json { "status": "accepted" } ``` Bei ungueltigen Requests wird der gemeinsame Fehlerumschlag verwendet. ## GET /api/v1/screens/status Liefert eine Uebersicht aller bisher berichtenden Screens mit ihrem jeweils letzten bekannten Datensatz. Die Antwort enthaelt: - `summary` mit kompakten Counts fuer `total`, `online`, `degraded`, `offline`, `stale` - `screens` sortiert nach Prioritaet: zuerst `offline`, dann `degraded`, dann `online`; innerhalb derselben Gruppe nach `screen_id` Die `summary` beschreibt immer den gesamten bekannten Statusbestand, unabhaengig von aktiven Filtern. Die `screens`-Liste wird durch die Query-Parameter eingeschraenkt. ### Query-Parameter | Parameter | Erlaubte Werte | Fehlercode bei Verstoß | |---------------------|-----------------------------------------|-------------------------------------| | `q` | beliebig (Substring-Suche, case-insen.) | – | | `derived_state` | `online`, `degraded`, `offline` | `invalid_derived_state` | | `server_connectivity` | `online`, `degraded`, `offline`, `unknown` | `invalid_server_connectivity` | | `stale` | `true`, `false` | `invalid_stale` | | `updated_since` | RFC3339-Zeitstempel | `invalid_updated_since` | | `limit` | positive Ganzzahl | `invalid_limit` | `q` filtert nach Screen-ID-Substring (Gross-/Kleinschreibung wird ignoriert). Dieselben Parameter koennen sowohl an `GET /api/v1/screens/status` als auch an `GET /status` uebergeben werden, damit Browser-Ansicht und JSON-Uebersicht dieselbe Diagnosesicht teilen. ## GET /api/v1/screens/{screenId}/status Liefert den zuletzt akzeptierten Status fuer einen einzelnen Screen. Wenn fuer den Screen noch kein Status vorliegt, liefert das Backend `404` mit dem gemeinsamen Fehlerumschlag. Der Datensatz enthaelt neben den gespeicherten Feldern: - `received_at` – serverseitiger Annahmezeitpunkt des letzten gueltigen Reports - `stale` – ob der letzte Report bereits veraltet wirkt (mehr als zwei Heartbeat-Intervalle ohne neuen Report) - `derived_state` – zusammengefasste Diagnoseeinschaetzung (s.u.) ## DELETE /api/v1/screens/{screenId}/status Loescht den gespeicherten Statuseintrag fuer einen Screen endgueltig. Wenn kein Eintrag vorhanden ist, liefert das Backend `404`. ### Antwort ```json { "status": "deleted" } ``` ## GET /status Serverseitig gerenderte HTML-Diagnoseseite fuer den Browser. Nutzt dieselbe Statusuebersicht wie der JSON-Endpunkt. - automatisches Refresh alle 15 Sekunden - Shortcut-Links fuer Connectivity- und Freshness-Filter - kleines Filterformular fuer dieselben Parameter wie beim JSON-Read-Pfad - direkte JSON-Detail-Links pro Screen Bei ungueltigen Query-Parametern liefert `/status` eine HTML-Fehlerseite (kein JSON), damit Browser-Aufrufe direkt lesbare Hinweise erhalten. ## GET /status/{screenId} HTML-Detailseite fuer einen einzelnen Screen. Zeigt denselben Datensatz wie `GET /api/v1/screens/{screenId}/status` (Derived State, Player-Status, Connectivity, Frische, Timestamps, Endpoints). Bei unbekanntem Screen: 404 mit HTML-Fehlermeldung und Rueck-Link auf `/status`. ## Serverseitig abgeleitete Felder ### stale Die Schwelle wird aus dem gemeldeten `heartbeat_every_seconds` abgeleitet: mehr als zwei Intervalle ohne neuen Report gelten als veraltet. `stale` ist aktuell eine Diagnosehilfe fuer die Entwicklungsstufe und noch kein vollstaendiges Online-/Offline-Modell fuer Admin-Oberflaechen. ### derived_state - `offline` bei `stale = true` oder `server_connectivity = offline` - `degraded` bei `server_connectivity = degraded|unknown` oder wenn `status` nicht `running` ist - `online` in den verbleibenden Faellen ## Persistenz Der Status-Store kann dateibasiert betrieben werden. Konfiguration ueber die Umgebungsvariable: - `MORZ_INFOBOARD_STATUS_STORE_PATH` – Pfad zur JSON-Datei; leer lassen fuer reinen In-Memory-Betrieb Beim Datei-Store gilt: - beim Start wird die Datei eingelesen, falls sie vorhanden ist (fehlende Datei ist kein Fehler) - bei jedem `Save` und `Delete` wird der Inhalt atomar in die Datei geschrieben (write + rename) - nach einem Neustart des Backends bleibt der letzte bekannte Statusbestand erhalten ## Agentseitige Connectivity-Ableitung Agent-seitig wird die Server-Erreichbarkeit lokal als `unknown`, `online`, `degraded` oder `offline` aus dem Erfolg der HTTP-Reports abgeleitet. Fuer den transportierten Wert im erfolgreichen HTTP-Report gilt: - wenn ein Report vom Backend akzeptiert wurde, wird dieser Report selbst als `server_connectivity = online` gespeichert - anhaltende Ausfaelle werden primaer ueber lokale Agent-Zustaende und serverseitige `stale`-Ableitung sichtbar ## Abgrenzung Noch nicht Teil dieser Stufe: - Screen-Authentifizierung - MQTT-Heartbeat oder MQTT-Status - Admin-UI-Anzeige des letzten Status - Retry-Queue oder lokale Zwischenspeicherung im Agent ## Verwandte Endpoints Siehe auch die vollständige API-Dokumentation in `API-ENDPOINTS.md`: - Screen-Registrierung: `POST /api/v1/screens/register` - Playlist-Abruf: `GET /api/v1/screens/{screenId}/playlist` - Medien-Verwaltung: `GET /api/v1/tenants/{tenantSlug}/media`, `POST /api/v1/tenants/{tenantSlug}/media` ## Folgeschritte Auf diesem Pfad bauen spaeter auf: - Screen-Identitaet und Authentifizierung - Trennung zwischen HTTP-Snapshot und MQTT-Heartbeat - Admin-Vorschau fuer Online-/Offline- und Degraded-Zustaende