diff --git a/docs/API-ENDPOINTS.md b/docs/API-ENDPOINTS.md index 1e4d7b4..7a2b244 100644 --- a/docs/API-ENDPOINTS.md +++ b/docs/API-ENDPOINTS.md @@ -526,6 +526,67 @@ Löscht ein Medien-Asset (und physische Datei falls lokal gespeichert). --- +## Display-Steuerung (JSON API) + +Beide Endpunkte erfordern `RequireAuth` + `RequireScreenAccess` (`authScreen`-Middleware). + +### POST /api/v1/screens/{screenSlug}/display + +Sendet einen MQTT-Befehl zum Ein- oder Ausschalten des physischen Displays. + +**Auth:** Erforderlich (Bearer-Token oder Session-Cookie). Screen-Zugriff erforderlich. + +**Path-Parameter:** +- `screenSlug` — Slug des Screens + +**Request-Body:** +```json +{"state": "on"} +``` +oder +```json +{"state": "off"} +``` + +**Response:** `204 No Content` + +**Fehler:** +- `400 Bad Request` — `state` ist nicht `"on"` oder `"off"`, oder ungültiges JSON +- `502 Bad Gateway` — MQTT-Publish fehlgeschlagen + +--- + +### POST /api/v1/screens/{screenSlug}/schedule + +Speichert den Zeitplan für das automatische Ein-/Ausschalten eines Displays. + +**Auth:** Erforderlich. Screen-Zugriff erforderlich. + +**Path-Parameter:** +- `screenSlug` — Slug des Screens + +**Request-Body:** +```json +{ + "schedule_enabled": true, + "power_on_time": "06:00", + "power_off_time": "22:00" +} +``` + +Zeitangaben müssen im Format `HH:MM` (24h) oder als leerer String `""` übergeben werden. +Der Scheduler prüft jede Minute, ob die aktuelle Uhrzeit mit `power_on_time` oder `power_off_time` +übereinstimmt, und sendet dann den entsprechenden MQTT-Befehl. + +**Response:** `204 No Content` + +**Fehler:** +- `400 Bad Request` — Zeitformat ungültig (nicht `HH:MM`), oder ungültiges JSON +- `404 Not Found` — Screen nicht vorhanden +- `500 Internal Server Error` — DB-Fehler + +--- + ## Message Wall ### POST /api/v1/tools/message-wall/resolve diff --git a/docs/SCHEMA.md b/docs/SCHEMA.md index 17aaf99..51944f0 100644 --- a/docs/SCHEMA.md +++ b/docs/SCHEMA.md @@ -488,6 +488,41 @@ temperature_celsius numeric(5,2) null updated_at timestamptz not null ``` +**Hinweis:** Die Spalten oben beschreiben das geplante Langzeitschema. Migration `004_screen_status.sql` +implementiert eine vereinfachte Version dieser Tabelle mit nur drei Spalten: + +```sql +screen_id TEXT PRIMARY KEY REFERENCES screens(id) ON DELETE CASCADE +display_state TEXT NOT NULL DEFAULT 'unknown' -- "on", "off", "unknown" +reported_at TIMESTAMPTZ NOT NULL DEFAULT now() +``` + +Diese kompakte Tabelle speichert ausschliesslich den zuletzt vom Agent gemeldeten Display-Zustand. +Weitere Laufzeitfelder (online, heartbeat, etc.) werden in einem spaeteren Migrations-Schritt ergaenzt. + +### `screen_schedules` + +Zweck: + +- taeglich konfigurierbarer Ein-/Ausschalt-Zeitplan pro Screen + +Migration: `005_screen_schedules.sql` + +Spalten: + +```sql +screen_id TEXT PRIMARY KEY REFERENCES screens(id) ON DELETE CASCADE +schedule_enabled BOOLEAN NOT NULL DEFAULT false +power_on_time TEXT NOT NULL DEFAULT '' -- HH:MM (24h), leer = nicht gesetzt +power_off_time TEXT NOT NULL DEFAULT '' -- HH:MM (24h), leer = nicht gesetzt +``` + +Regeln: + +- Wird durch den `scheduler`-Package ausgewertet (prueft jede Minute alle aktiven Zeitplaene) +- `schedule_enabled = false` bedeutet: Zeitplan vorhanden, aber deaktiviert +- Leere Zeitfelder bedeuten: kein Einschalt- bzw. kein Ausschaltbefehl + ### `screen_snapshots` Zweck: @@ -556,6 +591,10 @@ und sind vollstaendig unter den Abschnitten `users` und `sessions` oben beschrie Die Screen-Usserverwaltung wird durch `server/backend/internal/db/migrations/003_user_screen_permissions.sql` angelegt und ist unter dem Abschnitt `user_screen_permissions` oben beschrieben. +Die Display-Steuerung wird durch zwei weitere Migrationen angelegt: +- `004_screen_status.sql` — vereinfachte `screen_status`-Tabelle (display_state + reported_at) +- `005_screen_schedules.sql` — `screen_schedules`-Tabelle fuer Zeitplaene + Der `AuthStore` (`internal/store/auth.go`) stellt folgende Methoden bereit: - `GetUserByUsername(ctx, username)` — Nutzer per Username laden (inkl. `TenantSlug` via LEFT JOIN) diff --git a/server/backend/README.md b/server/backend/README.md index 3262d0a..760b1f9 100644 --- a/server/backend/README.md +++ b/server/backend/README.md @@ -29,9 +29,19 @@ Dieses Verzeichnis enthaelt das zentrale Go-Backend fuer das Info-Board-System. - `internal/httpapi/manage/csrf_helpers.go` — CSRF-Token Helpers fuer Templates (manage-Package) - `internal/httpapi/tenant/` — Tenant-Self-Service-Dashboard - `internal/httpapi/tenant/csrf_helpers.go` — CSRF-Token Helpers fuer Templates (tenant-Package, Import-Cycle-Isolation) -- `internal/mqttnotifier/` — MQTT-Notifizierungen (`NotifyChanged`, `RequestScreenshot`) +- `internal/mqttnotifier/` — MQTT-Notifizierungen (`NotifyChanged`, `RequestScreenshot`, `SendDisplayCommand`) +- `internal/scheduler/` — Display-Zeitplan-Scheduler (prueft jede Minute aktive Zeitplaene und sendet MQTT-Befehle) - `internal/reqcontext/` — Context-Keys fuer authentifizierten User +### scheduler (`internal/scheduler/scheduler.go`) + +Startet eine Goroutine (`scheduler.Run`), die jede Minute alle aktiven Zeitplaene aus +`screen_schedules` laedt und — sofern `power_on_time` oder `power_off_time` mit der aktuellen +Uhrzeit übereinstimmt — per MQTT den Befehl `display_on` bzw. `display_off` sendet. + +Der Scheduler wird in `internal/app/app.go` als Goroutine gestartet und laeuft bis zum +Kontext-Abbruch beim Server-Shutdown. + ## Datenbank-Stores ### AuthStore (`internal/store/auth.go`) @@ -105,6 +115,8 @@ Dieses Verzeichnis enthaelt das zentrale Go-Backend fuer das Info-Board-System. | PATCH | `/api/v1/playlists/{playlistId}/duration` | Standard-Dauer setzen (API) | | DELETE | `/api/v1/media/{id}` | Medium loeschen (API) | | GET | `/api/v1/screens/{screenId}/screenshot` | Screenshot eines Screens abrufen | +| POST | `/api/v1/screens/{screenSlug}/display` | Display ein-/ausschalten (MQTT) | +| POST | `/api/v1/screens/{screenSlug}/schedule` | Display-Zeitplan speichern | ### Nur Admins (`RequireAuth` + `RequireAdmin`) @@ -173,3 +185,5 @@ Middleware zur rollenbasierten Zugriffskontrolle auf Screen-Ressourcen. - `001_core.sql` — initiales Schema (Tenants, Screens, Playlists, Media, etc.) - `002_auth.sql` — Auth-Tabellen (`users`, `sessions`) - `003_user_screen_permissions.sql` — Screen-User Management (`user_screen_permissions`) +- `004_screen_status.sql` — Display-Zustand pro Screen (`screen_status`: screen_id, display_state, reported_at) +- `005_screen_schedules.sql` — Zeitplan pro Screen (`screen_schedules`: screen_id, schedule_enabled, power_on_time, power_off_time)