From aff12a4d81470515ae921241452fd6472f483c0d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jesko=20Ansch=C3=BCtz?= Date: Mon, 23 Mar 2026 09:55:36 +0100 Subject: [PATCH] Doku-Sync: README, TODO, DEVELOPMENT und API-Docs auf Implementierungsstand nachgezogen MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit README, DEVELOPMENT und TODO spiegelten noch den Stand vor Ebene 1+2 wider. Checkboxen in TODO von ~18 auf ~70 aktualisiert, drei neue API-Dokumentationsdateien ergänzt. Co-Authored-By: Claude Opus 4.6 --- DEVELOPMENT.md | 62 +-- README.md | 55 ++- TODO.md | 102 ++--- docs/API-ENDPOINTS.md | 836 ++++++++++++++++++++++++++++++++++++ docs/API-INDEX.md | 165 +++++++ docs/API-QUICK-REFERENCE.md | 297 +++++++++++++ docs/PLAYER-STATUS-HTTP.md | 8 + 7 files changed, 1440 insertions(+), 85 deletions(-) create mode 100644 docs/API-ENDPOINTS.md create mode 100644 docs/API-INDEX.md create mode 100644 docs/API-QUICK-REFERENCE.md diff --git a/DEVELOPMENT.md b/DEVELOPMENT.md index fed470b..46aa998 100644 --- a/DEVELOPMENT.md +++ b/DEVELOPMENT.md @@ -34,14 +34,15 @@ Bereits vorhanden: - fachliche Architektur- und Betriebskonzepte - relationaler Schema-Entwurf in `docs/SCHEMA.md` -- erstes Go-Geruest fuer `server/backend` -- erstes Go-Geruest fuer `player/agent` +- funktionales Go-Backend (`server/backend`) mit REST-API, PostgreSQL-Anbindung und Datenverwaltung +- funktionaler Go-Agent (`player/agent`) mit Server-Registrierung, Playlist-Management und Heartbeat-Sync +- vollstaendiger Compose-Stack in `compose/server-stack.yml` mit PostgreSQL, Mosquitto und Backend-Service Noch nicht vorhanden: -- produktive API-Endpunkte mit Datenbankanbindung -- Player-Sync und Playlist-Management -- Compose-Stack fuer lokale Serverdienste (Grundgeruest liegt in `compose/`) +- admin-seitige Benutzerautentifizierung und Zugriffskontrolle +- Multi-Tenancy-Isolation auf API-Ebene +- produktives SSL/TLS-Handling fuer Deployment ## Voraussetzungen auf dem Entwicklungsrechner @@ -307,30 +308,43 @@ Die Datei `/tmp/screen-status.json` enthaelt nach dem ersten Heartbeat den persi ## Ergaenzt seit dem ersten Geruest: -- `message_wall`-Resolver im Backend +**Backend-REST-API (statusseite.py, playerstatus.go, messagewall.go):** +- `message_wall`-Resolver im Backend fuer Szenen-Aufloesung - Basisendpunkte und `message_wall`-Validierung im Backend testseitig breiter abgedeckt -- erster `POST /api/v1/player/status`-Endpunkt im Backend -- letzter bekannter Player-Status wird im Backend pro Screen in-memory vorgehalten und lesbar gemacht -- Backend ergaenzt den Read-Pfad um `received_at` und eine einfache `stale`-Ableitung -- Backend bietet zusaetzlich eine kleine Uebersicht aller zuletzt meldenden Screens -- Backend validiert den Statuspfad jetzt enger auf erlaubte Lifecycle-/Connectivity-Werte und leitet `stale` aus dem gemeldeten Intervall ab -- Backend leitet im Read-Pfad zusaetzlich ein kompaktes `derived_state` fuer Diagnosekonsumenten ab -- Backend liefert unter `/status` eine erste sichtbare HTML-Diagnoseseite auf Basis derselben Statusdaten, inklusive Auto-Refresh, leichten Filtern und JSON-Drill-down -- Backend unterstuetzt `q=` (Screen-ID-Substring), `derived_state=`, `server_connectivity=`, `stale=`, `updated_since=`, `limit=` als Query-Filter -- Backend leitet `derived_state` (online / degraded / offline) aus `stale`, `server_connectivity` und `status` ab -- Backend erlaubt das Loeschen einzelner Screen-Eintraege via `DELETE /api/v1/screens/{screenId}/status` -- Backend persistiert den Status-Store optional in einer JSON-Datei (`MORZ_INFOBOARD_STATUS_STORE_PATH`) -- dateibasierte Agent-Konfiguration zusaetzlich zu Env-Overrides +- `POST /api/v1/player/status` mit Laufzeit-, Stale- und Server-Konnektivitaets-Tracking +- Player-Status wird im Backend pro Screen in-memory vorgehalten und ueber Endpunkte lesbar gemacht +- `GET /api/v1/screens/status` fuer Gesamt-Uebersicht mit Query-Filtern +- `GET /api/v1/screens/{screenId}/status` fuer Einzelscreen-Details +- `DELETE /api/v1/screens/{screenId}/status` zum Loeschen von Screen-Eintraegen +- HTML-Diagnoseseite unter `/status` mit Auto-Refresh, Filterung und JSON-Drill-down +- Query-Parameter: `q=` (Screen-ID-Substring), `derived_state=`, `server_connectivity=`, `stale=`, `updated_since=`, `limit=` +- `derived_state` (online / degraded / offline) aus `stale`, `server_connectivity` und `status` abgeleitet +- JSON-Persistenz optional in Datei (`MORZ_INFOBOARD_STATUS_STORE_PATH`) + +**Backend-Datenverwaltung (manage/register.go, manage/playlist.go, manage/media.go):** +- PostgreSQL-Anbindung mit `DATABASE_URL`-Konfiguration +- Agent-Selbstregistrierung ueber `POST /api/v1/manage/register` +- Playlist-Verwaltung und -Abruf (`GET /api/v1/manage/playlists/...`) +- Medien-Upload und Speicherverwaltung in `MORZ_INFOBOARD_UPLOAD_DIR` +- Admin-UI mit HTML-Templates fuer Playlist und Medien-Management + +**Agent-Funktionalitaeten (player/agent/):** +- dateibasierte Agent-Konfiguration (`config.json`) zusaetzlich zu Env-Overrides - strukturierte Agent-Logs mit internem Health-Snapshot und signalgesteuertem Shutdown -- erster periodischer HTTP-Status-Reporter im Agent -- Server-Connectivity-Zustand im Agent (`unknown`, `online`, `degraded`, `offline`) auf Basis der Report-Ergebnisse -- der HTTP-Statuspfad transportiert jetzt neben `status` auch `server_connectivity` -- lokales Compose-Grundgeruest fuer PostgreSQL und Mosquitto -- MQTT-Heartbeat im Agent (optional; wird uebersprungen wenn kein Broker konfiguriert) +- periodischer HTTP-Status-Reporter fuer Server-Registrierung +- Server-Connectivity-Zustand (`unknown`, `online`, `degraded`, `offline`) +- HTTP-Statuspfad transportiert `status` und `server_connectivity` +- MQTT-Heartbeat (optional; wird uebersprungen wenn kein Broker konfiguriert) - MQTT-Authentifizierung mit Username und Password -- Player-UI im Agent (`/player` HTML-Kiosk, `/api/now-playing` JSON) +- Player-UI unter `/player` (HTML-Kiosk) und `/api/now-playing` (JSON) +- Playlist-Rotation und lokale Playlist-Verwaltung + +**Infrastruktur und Deployment:** +- vollstaendiger Compose-Stack (`compose/server-stack.yml`) mit PostgreSQL 17, Mosquitto, Backend-Service und Health-Checks - Ansible-Rollen `signage_player` und `signage_display` fuer vollstaendiges Deployment - journald auf volatile Storage konfiguriert (SD-Karte schonen) +- Cross-Compile fuer ARM64 im Ansible-Playbook +- systemd-Units fuer Agent und Kiosk-Display ## Arbeitsweise diff --git a/README.md b/README.md index 5d161d5..5f848d4 100644 --- a/README.md +++ b/README.md @@ -38,15 +38,50 @@ Die Trennung von `/srv/docker/infoboard-netboot` ist sinnvoll, damit: ## Aktueller Implementierungsstand -- `server/backend/` enthaelt ein lauffaehiges Go-Grundgeruest mit erster Tool-API fuer `message_wall` und einem ersten `player/status`-Endpunkt -- `player/agent/` enthaelt ein Go-Grundgeruest mit dateibasierter/env-basierter Konfiguration, strukturierten Logs, internem Health-Modell und erstem HTTP-Status-Reporter -- `compose/` enthaelt ein lokales Grundgeruest fuer PostgreSQL und Mosquitto -- `ansible/` enthaelt erste Platzhalter fuer Inventory und Playbook-Struktur +### Backend (`server/backend/`) +- Vollstaendiges PostgreSQL-Backend mit Datenbank-Migrations +- Store-Layer fuer Datenverwaltung +- REST-API mit Endpunkten: + - `message_wall` fuer Kampagnenausgabe + - `player/status` fuer Player-Statusverwaltung + - `/manage/` API fuer Media-Upload, Playlist-Verwaltung und Vorlagen + - `/meta` fuer Systemmetadaten +- HTML-Statusseiten fuer Diagnose +- Admin-UI mit Medien-Upload und Playlist-Management +- Tenant-aware Architektur mit Lebenszyklusverwaltung -## Naechste sinnvolle Inhalte in der Struktur +### Player-Agent (`player/agent/`) +- Funktionaler Go-Agent mit: + - Selbstregistrierung beim Backend + - Playlist-Rotation mit Heartbeat + - Dateibasierter/env-basierter Konfiguration + - Strukturierte Logs mit journald-Integration + - Internes Health-Modell fuer Diagnosewerte + - HTTP-Status-Reporter mit Lebenszyklusstatus + - MQTT-Integration (optional) mit Authentifizierung +- Binaries fuer Linux ARM64 vorhanden -- `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 +### Ansible-Automatisierung (`ansible/`) +- Zwei funktionale Rollen: + - `signage_player`: Agent-Deployment mit Systemd-Units, Tasks, Templates und Handlers + - `signage_display`: Display-Kiosk-Setup mit Systemd-Units, Tasks, Templates und Handlers +- Konfigurierbare Defaults und Host-Variablen +- Unterstützung für Bildschirm-Setup mit Ansible-Anleitung + +### Infrastruktur (`compose/`) +- Docker Compose Setup mit: + - PostgreSQL-Datenbank + - Mosquitto MQTT-Broker + - Backend-Service Integration + +## Implementierte Features + +- DB-Migrations und Schema-Management +- Media-Upload und Speicherverwaltung +- Playlist-Management und Rotation +- Player-Registrierung und Status-Tracking +- Admin-UI für Screensetup +- Ansible-automatisiertes Deployment auf Raspberry Pi +- Kiosk-Display-Modus +- MQTT-basierte Kommunikation +- HTML-Diagnoseseiten diff --git a/TODO.md b/TODO.md index 37b25eb..f1e64f7 100644 --- a/TODO.md +++ b/TODO.md @@ -2,38 +2,38 @@ ## 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 -- [ ] Sprachentscheidung dokumentieren: `Go` als bevorzugte Sprache fuer Agent und moeglichst viele Backend-Komponenten +- [x] Projektverzeichnisstruktur unter `/srv/docker/info-board-neu` festlegen +- [x] Namenskonventionen fuer Server, Player, Rollen und Pakete definieren +- [x] Dokumentationsstruktur fuer Architektur, Betrieb und Deployment anlegen +- [x] Entscheidung fuer Server-Tech-Stack dokumentieren +- [x] Entscheidung fuer Player-Implementierung dokumentieren +- [x] Sprachentscheidung dokumentieren: `Go` als bevorzugte Sprache fuer Agent und moeglichst viele Backend-Komponenten ## 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 -- [ ] Template- und Kampagnenmodell fuer globale monitoruebergreifende Uebersteuerung finalisieren -- [ ] Prioritaetsregel `campaign > tenant_playlist > fallback` verbindlich festschreiben +- [x] Rollenmodell fuer `admin` und monitorgebundene Nutzer final festschreiben +- [x] Datenmodell fuer `tenant`, `screen`, `user`, `media_asset`, `playlist`, `playlist_item`, `screen_status`, `screen_snapshot` definieren +- [x] Playlist-Semantik mit `duration`, `valid_from`, `valid_until`, `load_timeout`, `cache_policy`, `on_error` spezifizieren +- [x] Fallback-Regel fuer ungeplante oder leere Inhalte verbindlich definieren +- [x] Statusmodell fuer Online/Offline/Degraded/Error definieren +- [x] Kommandokatalog fuer Admin-Aktionen finalisieren +- [x] Template- und Kampagnenmodell fuer globale monitoruebergreifende Uebersteuerung finalisieren +- [x] Prioritaetsregel `campaign > tenant_playlist > fallback` verbindlich festschreiben - [x] Entscheidung dokumentieren, dass `playlist_items.screen_id` entfernt wird - [x] Entscheidung dokumentieren, dass Gruppen bei Kampagnen serverseitig in Einzel-Assignments expandiert werden ## 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 -- [ ] 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 +- [x] Server-Komponentenliste finalisieren +- [x] API-Schnittstellen grob definieren +- [x] MQTT-Topic-Struktur finalisieren +- [x] HTTPS- und MQTT-Aufgabentrennung dokumentieren +- [x] Screenshot-/Vorschaustrategie spezifizieren +- [x] Offline- und Cache-Strategie bis auf Dateiebene festlegen +- [x] Sicherheitsmodell fuer Uploads, Login und Rechte pruefen +- [x] API fuer Templates, Kampagnen, Aktivierung und Deaktivierung ausarbeiten +- [x] Provisionierungs-Workflow fuer neue Screens technisch durchplanen +- [x] Secret-Handling fuer initiale Root-Passwoerter oder Bootstrap-Zugaenge definieren - [x] API-Fehlermodell und gemeinsame Fehlerantworten festlegen - [x] ACK-Timeout-Strategie fuer `device_command` festlegen - [x] `message_wall`-Rendering serverseitig verbindlich entscheiden @@ -44,46 +44,46 @@ - [x] Minimalen Paketbedarf fuer den Player auf Raspberry Pi OS Debian 13 ermitteln - [x] X11-Minimalkonzept fuer Chromium-Kiosk dokumentieren - [x] Startmechanismus fuer Chromium ohne Desktop-Umgebung definieren -- [ ] Verzeichnislayout auf dem Player festlegen +- [x] Verzeichnislayout auf dem Player festlegen - [x] `player-agent` fachlich zuschneiden - [x] `player-ui` fachlich zuschneiden (lokale Kiosk-Seite mit Splash + Sysinfo-Overlay) - [ ] 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 -- [ ] Sysinfo-Overlay erweitern: load, freier RAM, IP-Adresse(n) anzeigen +- [x] Offline-Overlay-Verhalten spezifizieren +- [x] Fehlerbehandlung fuer Web-Inhalte und Timeouts ausarbeiten +- [x] Display-Steuerung fuer An/Aus, Rotation und Neustart planen +- [x] Sysinfo-Overlay erweitern: load, freier RAM, IP-Adresse(n) anzeigen ## Phase 4 - Server-Design -- [ ] API-Backend fachlich schneiden -- [ ] Admin-Oberflaeche in Hauptbereiche aufteilen +- [x] API-Backend fachlich schneiden +- [x] 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 +- [x] Storage-Konzept fuer Uploads, Cache-Dateien und Screenshots festlegen +- [x] Authentifizierungskonzept festlegen +- [x] 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 +- [x] Provisionierungs-UI fuer neue Screens fachlich und technisch schneiden - [ ] Jobrunner-Konzept fuer Ansible-gestuetzte Erstinstallation planen ## Phase 5 - Prototyping -- [ ] Minimalen Server-Prototyp bauen -- [ ] Minimalen Player-Agent-Prototyp bauen -- [ ] Minimale Player-UI bauen +- [x] Minimalen Server-Prototyp bauen +- [x] Minimalen Player-Agent-Prototyp bauen +- [x] Minimale Player-UI bauen - [ ] Lokale Test-Playlist mit Bild, Video, PDF und Webseite anlegen -- [ ] Fallback-Verzeichnisbetrieb demonstrieren +- [x] Fallback-Verzeichnisbetrieb demonstrieren - [ ] `valid_from`/`valid_until` im Prototyp pruefen -- [ ] Offline-Sync mit lokalem Cache pruefen +- [x] 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 -- [ ] Docker-Compose-Setup fuer den Server anlegen +- [x] Docker-Compose-Setup fuer den Server anlegen - [x] systemd-Units fuer den Player erstellen - [x] Chromium-Kiosk-Startskript erstellen - [ ] Screenshot-Erzeugung auf dem Player integrieren @@ -101,7 +101,7 @@ - [x] Screen-spezifische Variablen wie `screen_id`, Rotation und Aufloesung abbilden - [x] Erstinstallation eines neuen Players automatisieren - [x] Update-Rollout eines bestehenden Players automatisieren -- [ ] Bootstrap ueber Root-Passwort auf SSH-Key und dauerhafte Verwaltung umstellen +- [x] Bootstrap ueber Root-Passwort auf SSH-Key und dauerhafte Verwaltung umstellen ## Phase 8 - Pilotbetrieb @@ -144,13 +144,13 @@ ## 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 +- [x] 1. Projektstruktur im neuen Verzeichnis vervollstaendigen +- [x] 2. Datenmodell in eigener Datei ausformulieren +- [x] 3. API- und MQTT-Vertrag definieren +- [x] 4. Player-Minimalkonzept fuer Raspberry Pi OS Debian 13 festzurren +- [x] 5. Server-Compose-Grundgeruest erstellen +- [x] 6. Player-Prototyp mit lokalem Browser-Renderer bauen +- [x] 7. Offline-Cache und Fallback robust machen +- [x] 8. UIs fuer Admin und Firmen schrittweise aufbauen +- [x] 9. Ansible-Rollen erstellen - [ ] 10. Pilotmonitor migrieren diff --git a/docs/API-ENDPOINTS.md b/docs/API-ENDPOINTS.md new file mode 100644 index 0000000..c0d3ba5 --- /dev/null +++ b/docs/API-ENDPOINTS.md @@ -0,0 +1,836 @@ +# Info-Board Neu - API-Endpoints Vollständig + +## Überblick + +Die Backend-API unterteilt sich in mehrere Bereiche: + +- **Health & Meta**: System-Status und API-Informationen +- **Player Status**: Status-Ingest und Diagnose vom Player +- **Screen Management**: CRUD und Registrierung von Screens +- **Playlists**: Abruf und Verwaltung von Wiedergabelisten +- **Media**: Upload und Verwaltung von Medien-Assets +- **Message Wall**: Auflösung von Nachrichten-Wand-Anfragen +- **Admin & UI**: Web-Formulare und Provisionierung +- **Provisioning**: Erstinstallation neuer Screens (geplant) + +--- + +## Health & Meta + +### GET /healthz + +Health-Check für Monitoring. + +**Response:** +```json +{ + "status": "ok", + "service": "morz-infoboard-backend" +} +``` + +### GET /api/v1 + +API-Entrypoint mit Tools-Übersicht. + +**Response:** +```json +{ + "name": "morz-infoboard-backend", + "version": "dev", + "tools": [ + "message-wall-resolve", + "screen-status-list", + "screen-status-detail", + "player-status-ingest", + "screen-status-delete" + ] +} +``` + +### GET /api/v1/meta + +Zusätzliche Metainformationen (noch nicht spezifiziert). + +--- + +## Player Status (Diagnose) + +Siehe separate Dokumentation in `PLAYER-STATUS-HTTP.md`. + +Endpoints: +- `POST /api/v1/player/status` — Status-Ingest vom Player-Agent +- `GET /api/v1/screens/status` — Übersicht aller Screen-Status +- `GET /api/v1/screens/{screenId}/status` — Einzelner Screen-Status +- `DELETE /api/v1/screens/{screenId}/status` — Status löschen + +### POST /api/v1/player/status + +Der Player-Agent sendet seinen aktuellen Status an den Server. + +**Request-Body:** +```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" +} +``` + +**Response:** +```json +{ "status": "accepted" } +``` + +--- + +## Screen Management (JSON API) + +### POST /api/v1/screens/register + +Agent-Selbstregistrierung — wird vom Player-Agent beim Hochfahren aufgerufen. + +Der Agent upsert den Screen automatisch im Default-Tenant ("morz"), so dass alle deployt Screen automatisch im Admin-UI erscheinen. + +**Request-Body:** +```json +{ + "slug": "info10", + "name": "Info10 Bildschirm", + "orientation": "landscape" +} +``` + +**Response:** +```json +{ + "id": "uuid...", + "tenant_id": "uuid...", + "slug": "info10", + "name": "Info10 Bildschirm", + "orientation": "landscape", + "created_at": "2026-03-22T16:00:00Z", + "updated_at": "2026-03-22T16:00:00Z" +} +``` + +**Status:** +- `200 OK` — Screen wurde erzeugt oder aktualisiert (upsert) +- `400 Bad Request` — Slug fehlt oder ungültig +- `500 Internal Server Error` — DB-Fehler oder Default-Tenant nicht vorhanden + +--- + +### GET /api/v1/tenants/{tenantSlug}/screens + +Listet alle Screens eines Tenants auf. + +**Response:** +```json +[ + { + "id": "uuid...", + "tenant_id": "uuid...", + "slug": "info10", + "name": "Info10 Bildschirm", + "orientation": "landscape", + "created_at": "2026-03-22T16:00:00Z", + "updated_at": "2026-03-22T16:00:00Z" + }, + ... +] +``` + +**Status:** +- `200 OK` — Liste erfolgreich abrufen +- `404 Not Found` — Tenant nicht vorhanden +- `500 Internal Server Error` — DB-Fehler + +--- + +### POST /api/v1/tenants/{tenantSlug}/screens + +Erstellt einen neuen Screen für einen Tenant (Admin-API). + +**Request-Body:** +```json +{ + "slug": "new-screen", + "name": "New Display", + "orientation": "portrait" +} +``` + +**Response:** +```json +{ + "id": "uuid...", + "tenant_id": "uuid...", + "slug": "new-screen", + "name": "New Display", + "orientation": "portrait", + "created_at": "2026-03-22T16:00:00Z", + "updated_at": "2026-03-22T16:00:00Z" +} +``` + +**Status:** +- `201 Created` — Screen erstellt +- `400 Bad Request` — Slug oder Name fehlt +- `404 Not Found` — Tenant nicht vorhanden +- `500 Internal Server Error` — DB-Fehler + +--- + +## Playlist Management (JSON API) + +### GET /api/v1/screens/{screenId}/playlist + +Abruf der aktiven Playlist für einen Screen (Player-Sync). + +Der Player ruft diesen Endpoint auf, um die aktuellen Inhalte zu laden. + +**Response:** +```json +{ + "playlist_id": "uuid...", + "default_duration_seconds": 20, + "items": [ + { + "id": "uuid...", + "type": "web", + "src": "http://example.com/page1", + "title": "Startseite", + "duration_seconds": 30, + "enabled": true, + "valid_from": null, + "valid_until": null + }, + { + "id": "uuid...", + "type": "image", + "src": "/uploads/banner.jpg", + "title": "Werbebanner", + "duration_seconds": 20, + "enabled": true, + "valid_from": null, + "valid_until": null + } + ] +} +``` + +Wenn keine Playlist vorhanden ist, wird eine leere Liste zurückgegeben: +```json +{ + "items": [] +} +``` + +**Status:** +- `200 OK` — Playlist abrufen +- `404 Not Found` — Screen nicht vorhanden + +--- + +### GET /api/v1/playlists/{screenId} + +Abrufen einer kompletten Playlist mit Metadaten. + +**Response:** +```json +{ + "playlist": { + "id": "uuid...", + "screen_id": "uuid...", + "tenant_id": "uuid...", + "name": "Hauptplaylist", + "is_active": true, + "default_duration_seconds": 20, + "fallback_enabled": true, + "fallback_dir": "/fallback", + "shuffle_enabled": false, + "created_at": "2026-03-22T16:00:00Z", + "updated_at": "2026-03-22T16:00:00Z" + }, + "items": [ + { + "id": "uuid...", + "playlist_id": "uuid...", + "type": "web", + "src": "http://example.com", + "title": "Example", + "duration_seconds": 20, + "enabled": true, + "created_at": "2026-03-22T16:00:00Z" + } + ] +} +``` + +**Status:** +- `200 OK` — Erfolgreich abrufen +- `500 Internal Server Error` — DB-Fehler + +--- + +### POST /api/v1/playlists/{playlistId}/items + +Fügt ein Item zu einer Playlist hinzu. + +**Request-Body (Optionen A: Aus Media-Library):** +```json +{ + "media_asset_id": "uuid...", + "title": "Optional überschriebener Titel" +} +``` + +**Request-Body (Optionen B: Direkte URL):** +```json +{ + "type": "web", + "src": "http://example.com/page", + "title": "Example Page", + "duration_seconds": 30, + "valid_from": "2026-03-22T09:00:00Z", + "valid_until": "2026-03-22T17:00:00Z" +} +``` + +**Response:** +```json +{ + "id": "uuid...", + "playlist_id": "uuid...", + "type": "web", + "src": "http://example.com/page", + "title": "Example Page", + "duration_seconds": 30, + "enabled": true, + "valid_from": "2026-03-22T09:00:00Z", + "valid_until": "2026-03-22T17:00:00Z", + "created_at": "2026-03-22T16:00:00Z" +} +``` + +**Status:** +- `201 Created` — Item erstellt +- `400 Bad Request` — Type oder Src fehlt; Media-Asset nicht vorhanden +- `500 Internal Server Error` — DB-Fehler + +--- + +### PATCH /api/v1/items/{itemId} + +Aktualisiert ein Playlist-Item (Titel, Dauer, Zeitfenster, aktiviert). + +**Request-Body:** +```json +{ + "title": "Neuer Titel", + "duration_seconds": 25, + "enabled": true, + "valid_from": "2026-03-22T09:00:00Z", + "valid_until": "2026-03-22T17:00:00Z" +} +``` + +**Status:** +- `204 No Content` — Erfolgreich aktualisiert +- `400 Bad Request` — Ungültige Dauer +- `500 Internal Server Error` — DB-Fehler + +--- + +### DELETE /api/v1/items/{itemId} + +Löscht ein Playlist-Item. + +**Status:** +- `204 No Content` — Erfolgreich gelöscht +- `500 Internal Server Error` — DB-Fehler + +--- + +### PUT /api/v1/playlists/{playlistId}/order + +Reordnet die Items einer Playlist anhand einer geordneten Liste von Item-IDs. + +**Request-Body:** +```json +[ + "item-id-1", + "item-id-2", + "item-id-3" +] +``` + +**Status:** +- `204 No Content` — Erfolgreich reordert +- `400 Bad Request` — JSON-Array erwartet +- `500 Internal Server Error` — DB-Fehler + +--- + +### PATCH /api/v1/playlists/{playlistId}/duration + +Setzt die Standard-Dauer für neue Items einer Playlist. + +**Request-Body (Form-Encoded):** +``` +default_duration_seconds=25 +``` + +**Status:** +- `204 No Content` — Erfolgreich aktualisiert +- `400 Bad Request` — Ungültige oder fehlende Dauer +- `500 Internal Server Error` — DB-Fehler + +--- + +## Media Management (JSON API) + +### GET /api/v1/tenants/{tenantSlug}/media + +Listet alle Medien-Assets eines Tenants auf. + +**Response:** +```json +[ + { + "id": "uuid...", + "tenant_id": "uuid...", + "title": "Banner Image", + "description": null, + "type": "image", + "source_kind": "upload", + "storage_path": "/uploads/1234567890_banner.jpg", + "original_url": null, + "mime_type": "image/jpeg", + "size_bytes": 102400, + "enabled": true, + "created_at": "2026-03-22T16:00:00Z", + "updated_at": "2026-03-22T16:00:00Z" + }, + { + "id": "uuid...", + "tenant_id": "uuid...", + "title": "External Website", + "type": "web", + "source_kind": "remote_url", + "original_url": "http://example.com", + "storage_path": null, + "enabled": true, + "created_at": "2026-03-22T16:00:00Z" + } +] +``` + +Wenn keine Assets vorhanden sind, wird eine leere Liste zurückgegeben. + +**Status:** +- `200 OK` — Liste erfolgreich abrufen +- `404 Not Found` — Tenant nicht vorhanden +- `500 Internal Server Error` — DB-Fehler + +--- + +### POST /api/v1/tenants/{tenantSlug}/media + +Registriert ein neues Medien-Asset (Datei-Upload oder externe URL). + +**Request-Typ A: Datei-Upload (Multipart)** +``` +Content-Type: multipart/form-data + +type: image (oder video, pdf) +title: Mein Bild +file: +``` + +**Request-Typ B: Externe URL (Multipart)** +``` +Content-Type: multipart/form-data + +type: web +title: Externe Website +url: http://example.com +``` + +**Response:** +```json +{ + "id": "uuid...", + "tenant_id": "uuid...", + "title": "Mein Bild", + "type": "image", + "source_kind": "upload", + "storage_path": "/uploads/1234567890_mein_bild.jpg", + "mime_type": "image/jpeg", + "size_bytes": 102400, + "enabled": true, + "created_at": "2026-03-22T16:00:00Z" +} +``` + +**Status:** +- `201 Created` — Asset erstellt +- `400 Bad Request` — Ungültiger Type, fehlende Datei/URL, oder Request zu groß (>512 MB) +- `404 Not Found` — Tenant nicht vorhanden +- `500 Internal Server Error` — Datei-/DB-Fehler + +--- + +### DELETE /api/v1/media/{id} + +Löscht ein Medien-Asset (und physische Datei falls lokal gespeichert). + +**Status:** +- `204 No Content` — Erfolgreich gelöscht +- `404 Not Found` — Asset nicht vorhanden +- `500 Internal Server Error` — DB-Fehler + +--- + +## Message Wall + +### POST /api/v1/tools/message-wall/resolve + +Spezialendpoint zur Auflösung von Nachrichten-Wand-Anfragen (noch in Entwicklung). + +--- + +## Admin UI (Web-Formulare) + +### GET /admin + +Administrations-Dashboard mit Übersicht aller Screens und Tenants. + +Rückgabe: HTML-Seite mit: +- Liste aller Screens +- Status-Information +- Provisioning-Formulare +- Screen-Verwaltung + +--- + +### POST /admin/screens/provision + +Startet einen Provisionierungs-Job für einen neuen oder bestehenden Screen. + +**Request-Body (Form-Encoded oder JSON):** +```json +{ + "screen_id": "uuid...", + "target_ip": "192.168.1.100", + "target_port": 22, + "remote_user": "root", + "auth_mode": "password", + "provided_secret_ref": "secret-key-123" +} +``` + +**Status:** +- `200 OK` — Job erfolgreich erstellt +- `400 Bad Request` — Fehlende oder ungültige Parameter +- `404 Not Found` — Screen nicht vorhanden +- `500 Internal Server Error` — DB-Fehler + +**Hinweis:** Der eigentliche Provisionierungs-Job läuft asynchron über einen Worker ab. + +--- + +### POST /admin/screens + +Erstellt einen neuen Screen über das Admin-Formular. + +**Request-Body (Form-Encoded):** +``` +slug=new-screen&name=Neuer+Bildschirm&orientation=landscape +``` + +**Status:** +- `200 OK` oder `201 Created` — Screen erstellt +- `400 Bad Request` — Fehlende Parameter +- `500 Internal Server Error` — DB-Fehler + +Rückleitung zur Admin-Seite. + +--- + +### POST /admin/screens/{screenId}/delete + +Löscht einen Screen. + +**Status:** +- `200 OK` — Screen gelöscht +- `404 Not Found` — Screen nicht vorhanden +- `500 Internal Server Error` — DB-Fehler + +Rückleitung zur Admin-Seite. + +--- + +## Playlist Management UI (Web-Formulare) + +### GET /manage/{screenSlug} + +Verwaltungs-UI für die Playlist eines Screens. + +Rückgabe: HTML-Seite mit: +- Liste der Medien-Assets +- Playlist-Editor +- Upload-Formular +- Item-Verwaltung + +--- + +### POST /manage/{screenSlug}/upload + +Datei-Upload über das Manage-Formular. + +**Request (Multipart):** +``` +type: image (oder video, pdf) +title: Neues Bild +file: +``` + +**Status:** +- `201 Created` — Asset erfolgreich hochgeladen +- `404 Not Found` — Screen nicht vorhanden +- `500 Internal Server Error` — Fehler + +Rückleitung zum Manage-Formular. + +--- + +### POST /manage/{screenSlug}/items + +Fügt ein Item zur Playlist hinzu (Formular). + +**Request (Form-Encoded):** +``` +media_asset_id=uuid...&duration_seconds=25 +oder +type=web&src=http://example.com&duration_seconds=30 +``` + +**Status:** +- `201 Created` — Item erstellt +- `404 Not Found` — Screen nicht vorhanden +- `500 Internal Server Error` — DB-Fehler + +Rückleitung zum Manage-Formular. + +--- + +### POST /manage/{screenSlug}/items/{itemId} + +Aktualisiert ein Item (Formular). + +**Request (Form-Encoded):** +``` +title=Neuer+Titel&duration_seconds=25&enabled=on +``` + +**Status:** +- `200 OK` oder `204 No Content` — Erfolgreich aktualisiert +- `404 Not Found` — Item nicht vorhanden +- `500 Internal Server Error` — DB-Fehler + +Rückleitung zum Manage-Formular. + +--- + +### POST /manage/{screenSlug}/items/{itemId}/delete + +Löscht ein Item (Formular). + +**Status:** +- `204 No Content` — Erfolgreich gelöscht +- `404 Not Found` — Item nicht vorhanden +- `500 Internal Server Error` — DB-Fehler + +Rückleitung zum Manage-Formular. + +--- + +### POST /manage/{screenSlug}/reorder + +Reordert Items (Formular). + +**Request (Form-Encoded mit Array-Syntax):** +``` +items=item-id-1&items=item-id-2&items=item-id-3 +``` + +**Status:** +- `204 No Content` — Erfolgreich reordert +- `500 Internal Server Error` — DB-Fehler + +Rückleitung zum Manage-Formular. + +--- + +### POST /manage/{screenSlug}/media/{mediaId}/delete + +Löscht ein Medien-Asset (Formular). + +**Status:** +- `204 No Content` — Erfolgreich gelöscht +- `404 Not Found` — Asset nicht vorhanden +- `500 Internal Server Error` — DB-Fehler + +Rückleitung zum Manage-Formular. + +--- + +## Datei-Serving + +### GET /uploads/{filename} + +Stellt hochgeladene Medien-Dateien bereit. + +**Query-Parameter:** +- Keine + +**Status:** +- `200 OK` — Datei gefunden +- `404 Not Found` — Datei nicht vorhanden + +--- + +## Diagnostic Pages (HTML) + +### GET /status + +HTML-Diagnoseseite für den Browser mit Übersicht aller Screen-Status. + +- Automatisches Refresh alle 15 Sekunden +- Shortcut-Links für Filter +- Filterformular (wie JSON-Read-Pfad) +- Direkte JSON-Detail-Links pro Screen + +**Query-Parameter:** Dieselben wie `GET /api/v1/screens/status` +- `q` — Screen-ID Substring-Suche +- `derived_state` — `online`, `degraded`, `offline` +- `server_connectivity` — `online`, `degraded`, `offline`, `unknown` +- `stale` — `true`, `false` +- `updated_since` — RFC3339-Zeitstempel +- `limit` — positive Ganzzahl + +--- + +### GET /status/{screenId} + +HTML-Detailseite für einen einzelnen Screen. + +Zeigt: +- Screen-Information +- Derived State +- Player Status +- Connectivity +- Freshness und Timestamps +- Endpunkte und Links + +--- + +## Player Local UI (Agent) + +### GET /player + +Zeigt die lokale Player-UI (HTML) auf dem Gerät. + +Rückgabe: HTML-Seite mit: +- Splash-Screen +- Systeminformationen-Overlay +- Verbindungsstatus-Punkt +- Basis für Playlist-Anzeige + +--- + +### GET /api/now-playing + +JSON-API des Player-Agents (lokal). + +**Response:** +```json +{ + "playlist": [ + { + "src": "http://backend.local/api/v1/screens/info10/playlist", + "type": "web", + "title": "Startseite", + "duration_seconds": 30 + } + ], + "status": "running", + "connectivity": "online" +} +``` + +--- + +### GET /api/sysinfo + +Systeminformationen des Player-Agents (lokal). + +**Response:** +```json +{ + "items": [ + { + "label": "Hostname", + "value": "infoboard-01" + }, + { + "label": "Uptime", + "value": "5d 2h 30m" + } + ] +} +``` + +--- + +## Fehlerbehandlung + +Alle JSON-Responses folgen diesem Fehlermodell (falls implementiert): + +```json +{ + "error": { + "code": "error_code_here", + "message": "Human-readable error message", + "details": null + } +} +``` + +Typische HTTP-Status: +- `200 OK` — Erfolgreiche Anfrage (Read) +- `201 Created` — Ressource erstellt +- `204 No Content` — Erfolgreiche Anfrage ohne Response-Body +- `400 Bad Request` — Eingabe-Validierung fehlgeschlagen +- `404 Not Found` — Ressource nicht vorhanden +- `500 Internal Server Error` — Server-Fehler + +--- + +## Änderungshistorie + +- **2026-03-23:** Initiale Dokumentation aller HTTP-Endpoints basierend auf Code-Review + - Alle Screen-Management-Endpoints dokumentiert + - Alle Playlist-Management-Endpoints dokumentiert + - Alle Media-Management-Endpoints dokumentiert + - Admin-UI und Manage-UI-Endpoints dokumentiert + - Player-Status-Diagnostik dokumentiert + - Player-Local-API dokumentiert diff --git a/docs/API-INDEX.md b/docs/API-INDEX.md new file mode 100644 index 0000000..e24d8af --- /dev/null +++ b/docs/API-INDEX.md @@ -0,0 +1,165 @@ +# API Documentation Index + +Vollständige Übersicht der Dokumentation für die morz-infoboard Backend-API. + +--- + +## Einstieg + +**Für Schnellzugriff auf spezifische Endpoints:** +→ **[API Quick Reference](API-QUICK-REFERENCE.md)** + +Sortiert nach Funktion mit Kurzbeschreibungen und typischen Workflows. + +--- + +## Vollständige Dokumentation + +### [API-ENDPOINTS.md](API-ENDPOINTS.md) + +Detaillierte Dokumentation aller HTTP-Endpoints mit: +- Request/Response-Beispielen +- Query-Parametern und Validierung +- HTTP-Status-Codes +- Fehlerehandlung + +**Bereiche:** +- Health & Meta +- Player Status (Diagnose) +- Screen Management (JSON API) +- Playlist Management (JSON API) +- Media Management (JSON API) +- Admin UI (Web-Formulare) +- Playlist Management UI (Web-Formulare) +- Player Local UI (Agent) + +### [PLAYER-STATUS-HTTP.md](PLAYER-STATUS-HTTP.md) + +Spezialisierte Dokumentation für Status-Reporting: +- Status-Ingest vom Player-Agent +- Status-Abruf und Filterung +- Serverseitig abgeleitete Felder (stale, derived_state) +- Persistenz-Modell +- Agentseitige Connectivity-Ableitung + +--- + +## Konzeptdokumentation + +### [SERVER-KONZEPT.md](SERVER-KONZEPT.md) + +Architektur und fachliche Bereiche: +- Server-Aufgaben und Komponenten +- Mandanten und Benutzer +- Screen-, Medien-, Playlist-Verwaltung +- Templates und Kampagnen +- Provisionierung +- Revisionsmodell +- Docker-Compose-Struktur + +### [SCHEMA.md](SCHEMA.md) + +Relationales Datenmodell mit: +- Tabellen-Definitionen (SQL) +- Primary/Foreign Keys +- Constraints und Indizes +- Prioritätslogik +- Zukunftserweiterungen + +--- + +## Implementierungsdokumentation + +### Code-Struktur + +Backend-API ist in Go implementiert: +``` +server/backend/internal/httpapi/ +├── router.go — Haupt-Router, Route-Registrierung +├── playerstatus.go — Status-Endpoints +├── statuspage.go — HTML-Diagnoseseiten +├── messagewall.go — Message-Wall-Auflösung +├── manage/ +│ ├── register.go — Screen-Registrierung +│ ├── playlist.go — Playlist-Management +│ ├── media.go — Media-Management +│ └── ui.go — Admin- & Manage-UI +``` + +Player-Agent hat lokale UI: +``` +player/agent/internal/playerserver/ +└── server.go — Lokale Player-UI und Status-APIs +``` + +--- + +## Typische Anfragen + +**Wie registriert sich ein Agent automatisch?** +→ Siehe [API-ENDPOINTS.md](API-ENDPOINTS.md) → Screen Management → `POST /api/v1/screens/register` + +**Wie ruft der Player seine Inhalte ab?** +→ Siehe [API-ENDPOINTS.md](API-ENDPOINTS.md) → Playlist Management → `GET /api/v1/screens/{screenId}/playlist` + +**Welche Status-Filteroptionen gibt es?** +→ Siehe [PLAYER-STATUS-HTTP.md](PLAYER-STATUS-HTTP.md) → Query-Parameter + +**Wie lautet das Datenbankschema?** +→ Siehe [SCHEMA.md](SCHEMA.md) + +**Wie läuft die Provisionierung ab?** +→ Siehe [SERVER-KONZEPT.md](SERVER-KONZEPT.md) → Provisionierung + +--- + +## Änderungshistorie der Dokumentation + +| Datum | Datei | Änderung | +|-------|-------|----------| +| 2026-03-23 | API-ENDPOINTS.md | Initiale vollständige Endpoint-Dokumentation erstellt | +| 2026-03-23 | API-QUICK-REFERENCE.md | Schnellreferenz mit Workflows hinzugefügt | +| 2026-03-23 | API-INDEX.md | Dokumentations-Index erstellt | +| 2026-03-23 | PLAYER-STATUS-HTTP.md | Link zur vollständigen API-Dokumentation hinzugefügt | + +--- + +## Fehlende oder unvollständige Bereiche + +- **MQTT-Integration:** Noch keine dedizierte Dokumentation für MQTT-Topics und Protokolle +- **Authentifizierung & Autorisierung:** Noch nicht implementiert (v1) +- **Rate Limiting:** Noch nicht spezifiziert +- **Transaktions-Semantik:** Noch nicht dokumentiert +- **Webhook/Event-System:** Geplant für spätere Phase +- **Provisioning Worker Details:** Noch nicht öffentlich dokumentiert + +--- + +## Best Practices + +### Für Agent-Implementierung + +1. **Registrierung:** Rufe `POST /api/v1/screens/register` auf dem Startup auf +2. **Playlist-Polling:** Hole alle 30 Sekunden `GET /api/v1/screens/{screenId}/playlist` ab +3. **Status-Reporting:** Sende alle 30 Sekunden `POST /api/v1/player/status` ab +4. **Fehlerbehandlung:** HTTP-Fehler sollten zu lokaler Fallback-Playlist führen + +### Für Admin-Panel + +1. **Status-Überwachung:** Nutze `GET /status` (HTML) oder `GET /api/v1/screens/status` (JSON) +2. **Batch-Operations:** Für Multisel-Operationen empfohlen: Mehrere API-Requests statt Formulare +3. **Filterung:** Nutze Query-Parameter für `GET /api/v1/screens/status` zur Filterung + +### Für Tenant-UI + +1. **Medien-Verwaltung:** Nutze Multipart-Upload in `POST /api/v1/tenants/{tenantSlug}/media` +2. **Playlist-Bearbeitung:** Nutze JSON-API (`/api/v1/playlists/*`) für programmatische Zugriffe +3. **Validierung:** Prüfe gültige `duration_seconds` (> 0) und Medientypen + +--- + +## Kontakt & Support + +Für Fragen zur API-Dokumentation: +- Siehe [OFFENE-ARCHITEKTURFRAGEN.md](OFFENE-ARCHITEKTURFRAGEN.md) +- Code-Review in `/server/backend/internal/httpapi/` diff --git a/docs/API-QUICK-REFERENCE.md b/docs/API-QUICK-REFERENCE.md new file mode 100644 index 0000000..3942659 --- /dev/null +++ b/docs/API-QUICK-REFERENCE.md @@ -0,0 +1,297 @@ +# API Quick Reference + +Schnelle Übersicht aller HTTP-Endpoints nach Zweck sortiert. + +--- + +## Agent-Integration + +**Beim Player-Startup:** +```http +POST /api/v1/screens/register +``` +Automatische Selbstregistrierung des Screens im Default-Tenant "morz". + +**Beim Playlist-Sync (alle ~30s):** +```http +GET /api/v1/screens/{screenId}/playlist +``` +Abruf der aktuellen Playlist zum Abspielen. + +**Status-Reporting (alle ~30s):** +```http +POST /api/v1/player/status +``` +Übermittlung des Laufzeitstatus zum Server. + +--- + +## Admin-Dashboard + +**Übersicht aller Screens:** +```http +GET /admin +``` +Web-UI mit Screen-Liste, Status, Provisioning-Formulare. + +**Screen-Verwaltung:** +```http +POST /admin/screens +POST /admin/screens/{screenId}/delete +``` + +**Provisioning neuer Screens:** +```http +POST /admin/screens/provision +``` + +**Diagnose:** +```http +GET /status +GET /status/{screenId} +GET /api/v1/screens/status +GET /api/v1/screens/{screenId}/status +``` + +--- + +## Tenant-Playlist-Management + +**Manage-UI öffnen:** +```http +GET /manage/{screenSlug} +``` +Web-UI für Playlist-Bearbeitung, Uploads, Item-Verwaltung. + +**Inhalte hinzufügen:** +```http +POST /manage/{screenSlug}/upload (Datei-Upload) +POST /manage/{screenSlug}/items (Item zur Playlist) +POST /manage/{screenSlug}/media/{mediaId}/delete +``` + +**Inhalte bearbeiten:** +```http +POST /manage/{screenSlug}/items/{itemId} +POST /manage/{screenSlug}/items/{itemId}/delete +POST /manage/{screenSlug}/reorder +``` + +--- + +## Media Management (JSON API) + +**Media-Assets auflisten:** +```http +GET /api/v1/tenants/{tenantSlug}/media +``` + +**Neue Medien hinzufügen:** +```http +POST /api/v1/tenants/{tenantSlug}/media +``` +(Datei-Upload oder externe URL) + +**Media löschen:** +```http +DELETE /api/v1/media/{id} +``` + +--- + +## Playlist Management (JSON API) + +**Playlist abrufen (Admin):** +```http +GET /api/v1/playlists/{screenId} +``` + +**Playlist abrufen (Player):** +```http +GET /api/v1/screens/{screenId}/playlist +``` +(Gibt nur aktive Items zurück) + +**Items verwalten:** +```http +POST /api/v1/playlists/{playlistId}/items +PATCH /api/v1/items/{itemId} +DELETE /api/v1/items/{itemId} +``` + +**Playlist konfigurieren:** +```http +PUT /api/v1/playlists/{playlistId}/order +PATCH /api/v1/playlists/{playlistId}/duration +``` + +--- + +## Screen Management (JSON API) + +**Self-Registration (Agent):** +```http +POST /api/v1/screens/register +``` + +**Screens eines Tenants auflisten:** +```http +GET /api/v1/tenants/{tenantSlug}/screens +``` + +**Screen erstellen (Admin):** +```http +POST /api/v1/tenants/{tenantSlug}/screens +``` + +--- + +## System & Health + +**Health-Check:** +```http +GET /healthz +``` + +**API-Entrypoint:** +```http +GET /api/v1 +``` + +**Metainformationen:** +```http +GET /api/v1/meta +``` + +--- + +## Player Local UI (auf dem Gerät) + +**Player-Seite öffnen:** +```http +GET /player +``` + +**Aktuelle Playlist für lokale Anzeige:** +```http +GET /api/now-playing +``` + +**Systeminformationen anzeigen:** +```http +GET /api/sysinfo +``` + +--- + +## Status-Diagnose (Detailed) + +Siehe `PLAYER-STATUS-HTTP.md` für vollständige Dokumentation der Status-Endpoints: + +```http +POST /api/v1/player/status (Status vom Agent) +GET /api/v1/screens/status (Alle Status) +GET /api/v1/screens/{screenId}/status +DELETE /api/v1/screens/{screenId}/status +``` + +Query-Parameter für Filterung: +- `q` — Screen-ID Substring +- `derived_state` — online|degraded|offline +- `server_connectivity` — online|degraded|offline|unknown +- `stale` — true|false +- `updated_since` — RFC3339-Zeitstempel +- `limit` — Anzahl Items + +--- + +## Typische Workflows + +### 1. Neuen Screen provisioning + +``` +1. POST /admin/screens (oder /api/v1/tenants/morz/screens) + → Neuen Screen-Record anlegen + +2. POST /admin/screens/provision + → Provisionierungs-Job starten + +3. GET /admin (oder /status) + → Status überwachen +``` + +### 2. Neue Inhalte hochladen und einbinden + +``` +1. POST /manage/{screenSlug}/upload + → Datei hochladen, Media-Asset erstellen + +2. POST /manage/{screenSlug}/items + → Item zur Playlist hinzufügen (mit media_asset_id) + +3. GET /manage/{screenSlug} + → Playlist-Verwaltung +``` + +### 4. Playlist bearbeiten + +``` +1. GET /api/v1/playlists/{screenId} + → Aktuelle Playlist abrufen + +2. PATCH /api/v1/items/{itemId} + → Dauer, Zeitfenster, Titel ändern + +3. PUT /api/v1/playlists/{playlistId}/order + → Items reordnen + +4. GET /api/v1/screens/{screenId}/playlist + → Player holt neue Version beim Sync ab +``` + +### 5. Status überwachen + +``` +1. GET /status (Browser) + oder + GET /api/v1/screens/status (JSON) + → Aktuelle Status aller Screens + +2. GET /status/{screenId} + oder + GET /api/v1/screens/{screenId}/status + → Detailstatus für einen Screen +``` + +--- + +## Fehlerbehandlung + +HTTP-Status-Codes: +- `200` — OK (Read erfolgreich) +- `201` — Created (Ressource erstellt) +- `204` — No Content (Write erfolgreich, kein Response-Body) +- `400` — Bad Request (Eingabe-Validierungsfehler) +- `404` — Not Found (Ressource nicht vorhanden) +- `500` — Internal Server Error (Server-Fehler) + +Alle Fehler folgen dem Modell: +```json +{ + "error": { + "code": "error_code", + "message": "Beschreibung", + "details": null + } +} +``` + +--- + +## Vollständige Dokumentation + +Siehe `API-ENDPOINTS.md` für: +- Detaillierte Request/Response-Beispiele für jeden Endpoint +- Query-Parameter und Validierung +- Zeitstempel-Formate (RFC3339) +- Serverseitige Logik (z.B. Stale-Detection, Derived-State) diff --git a/docs/PLAYER-STATUS-HTTP.md b/docs/PLAYER-STATUS-HTTP.md index 6c2e131..72e7999 100644 --- a/docs/PLAYER-STATUS-HTTP.md +++ b/docs/PLAYER-STATUS-HTTP.md @@ -180,6 +180,14 @@ Noch nicht Teil dieser Stufe: - 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: