morz-infoboard/DATENMODELL.md
2026-03-22 12:46:34 +01:00

8.5 KiB

Info-Board Neu - Datenmodell

Ziel

Das Datenmodell trennt klar zwischen:

  • Mandanten und Benutzern
  • Bildschirmen und ihrer technischen Laufzeitinformation
  • Medien und Playlists
  • Steuerbefehlen und Rueckmeldungen

Das Modell ist so ausgelegt, dass:

  • jede Firma nur ihren eigenen Monitor bzw. Kanal pflegt
  • die Administration alle Monitore zentral sehen und steuern kann
  • Offline-Betrieb der Player moeglich bleibt
  • Zeitsteuerung mit valid_from und valid_until sauber abbildbar ist

Kernentitaeten

tenant

Repraesentiert eine Firma bzw. einen abgeschotteten Inhaltsbereich.

Felder:

  • id
  • slug
  • name
  • active
  • created_at
  • updated_at

Hinweise:

  • ein Tenant kann spaeter mehrere Screens haben, auch wenn zunaechst meist 1:1 gearbeitet wird
  • alle Medien und Playlists sind einem Tenant zugeordnet

user

Repraesentiert einen Benutzer der Firmen- oder Admin-Oberflaeche.

Felder:

  • id
  • tenant_id nullable fuer globale Admins
  • username
  • email
  • password_hash
  • role (admin, tenant_user)
  • active
  • last_login_at
  • created_at
  • updated_at

Regeln:

  • tenant_user darf nur Daten des eigenen Tenants sehen und bearbeiten
  • admin darf alle Tenants und alle Screens verwalten

screen

Repraesentiert einen physischen Monitor bzw. einen Player-Client.

Felder:

  • id
  • tenant_id
  • slug
  • name
  • description
  • location
  • hardware_name
  • enabled
  • rotation (0, 90, 180, 270)
  • resolution_width
  • resolution_height
  • fallback_dir
  • snapshot_interval_seconds
  • offline_overlay_enabled
  • created_at
  • updated_at

Hinweise:

  • der slug dient als technische Kennung fuer Konfiguration, API und MQTT
  • fallback_dir beschreibt die lokale oder synchronisierte Fallback-Quelle auf dem Client

screen_registration

Optionale Trennung zwischen fachlichem Screen und technischer Registrierung.

Felder:

  • id
  • screen_id
  • device_uuid
  • hostname
  • api_token_hash
  • mqtt_client_id
  • last_seen_at
  • last_ip
  • player_version
  • os_version
  • created_at
  • updated_at

Zweck:

  • Wiedererkennung eines konkreten Geraets
  • sichere Kommunikation mit API und Broker
  • technische Inventarisierung

media_asset

Repraesentiert ein verwaltetes Medium.

Felder:

  • id
  • tenant_id
  • screen_id nullable
  • title
  • description
  • type (image, video, pdf, web)
  • source_kind (upload, remote_url)
  • storage_path nullable bei reinen Web-URLs
  • original_url nullable
  • mime_type
  • checksum
  • size_bytes
  • enabled
  • created_by_user_id
  • created_at
  • updated_at

Regeln:

  • upload bedeutet: Datei liegt im Medien-Storage
  • remote_url bedeutet: Quelle ist extern und wird vom Player oder Server gecacht
  • screen_id kann optional gesetzt werden, wenn ein Medium nur fuer einen Monitor gedacht ist

playlist

Repraesentiert eine logische Playlist eines Screens.

Felder:

  • id
  • tenant_id
  • screen_id
  • name
  • is_active
  • default_duration_seconds
  • fallback_enabled
  • fallback_dir
  • shuffle_enabled
  • created_at
  • updated_at

Regeln:

  • pro Screen gibt es in v1 genau eine aktive Playlist
  • spaeter koennen mehrere Playlists mit Umschaltung moeglich werden

playlist_item

Repraesentiert einen einzelnen Eintrag in einer Playlist.

Felder:

  • id
  • playlist_id
  • screen_id
  • order_index
  • media_asset_id nullable
  • type (image, video, pdf, web, dir)
  • src
  • title
  • duration_seconds
  • load_timeout_seconds
  • cache_policy (required, prefer_cache, no_cache)
  • on_error (skip, retry, fallback)
  • retry_count
  • valid_from nullable
  • valid_until nullable
  • enabled
  • created_at
  • updated_at

Regeln:

  • media_asset_id wird bei verwalteten Medien gesetzt
  • src enthaelt den effektiven Pfad oder die URL, damit der Player auch ohne Join-Struktur arbeiten kann
  • type=dir erlaubt definierte Verzeichnisreferenzen innerhalb der Playlist

playlist_item_dir_rule

Optionale Zusatzregel fuer type=dir.

Felder:

  • id
  • playlist_item_id
  • directory_path
  • sort_mode (name_asc, name_desc, mtime_asc, mtime_desc, shuffle)
  • per_item_duration_seconds
  • recursive
  • file_filter nullable

Zweck:

  • sauberere Modellierung fuer Verzeichnisbasierte Fallbacks oder Einschuebe

screen_status

Repraesentiert den letzten bekannten Laufzeitstatus eines Players.

Felder:

  • screen_id
  • online
  • server_connected
  • mqtt_connected
  • last_heartbeat_at
  • last_sync_at
  • current_playlist_id
  • current_playlist_item_id nullable
  • current_item_type nullable
  • current_item_label nullable
  • current_item_started_at nullable
  • current_item_duration_seconds nullable
  • cache_state (ok, stale, missing, error)
  • overlay_state (online, degraded, offline)
  • error_code nullable
  • error_message nullable
  • player_version
  • uptime_seconds
  • free_disk_bytes nullable
  • temperature_celsius nullable
  • updated_at

Hinweise:

  • screen_status ist eine verdichtete Sicht fuer Dashboard und Ueberwachung
  • historische Verlaeufe koennen spaeter separat gespeichert werden

screen_snapshot

Repraesentiert eine Vorschauaufnahme des aktuellen Bildschirminhalts.

Felder:

  • id
  • screen_id
  • captured_at
  • storage_path
  • width
  • height
  • mime_type
  • source (scheduled, item_change, manual)

Regeln:

  • in der UI wird typischerweise nur der letzte Snapshot angezeigt
  • aeltere Snapshots koennen nach Zeit oder Anzahl aufgeraeumt werden

device_command

Repraesentiert einen an einen Screen gesendeten Befehl.

Felder:

  • id
  • screen_id
  • command_type (reload, restart_player, reboot, display_on, display_off, refresh_snapshot, clear_cache)
  • payload_json
  • requested_by_user_id
  • requested_at
  • delivery_state (queued, sent, acknowledged, failed, expired)
  • delivered_at nullable
  • acknowledged_at nullable
  • result_code nullable
  • result_message nullable

Zweck:

  • nachvollziehbare Fernsteuerung mit Audit-Trail

sync_state

Repraesentiert den Synchronisationsstand eines Screens.

Felder:

  • screen_id
  • config_revision
  • playlist_revision
  • media_revision
  • last_successful_sync_at
  • last_failed_sync_at nullable
  • last_error_message nullable

Zweck:

  • Erkennung, ob ein Player auf dem aktuellen Stand ist

Beziehungen

  • ein tenant hat viele users
  • ein tenant hat viele screens
  • ein tenant hat viele media_assets
  • ein screen hat genau eine aktive playlist in v1
  • eine playlist hat viele playlist_items
  • ein screen hat genau einen aktuellen screen_status
  • ein screen hat viele screen_snapshots
  • ein screen hat viele device_commands
  • ein screen hat genau einen aktuellen sync_state

Zugriffsregeln

Tenant-User

Ein tenant_user darf:

  • nur den eigenen tenant sehen
  • nur den eigenen screen bzw. die dem Tenant zugeordneten Screens sehen
  • nur eigene Medien hochladen und pflegen
  • nur eigene Playlists bearbeiten
  • nur die Vorschau des eigenen Screens sehen

Ein tenant_user darf nicht:

  • andere Tenants sehen
  • globale Steuerkommandos senden
  • andere Screens administrieren

Admin

Ein admin darf:

  • alle Tenants, Screens, Medien und Playlists sehen
  • globale Steuerbefehle senden
  • Vorschau und Status aller Screens sehen
  • neue Screens und Benutzer anlegen

Revisions- und Caching-Modell

Damit Offline-Betrieb einfach bleibt, arbeitet der Player nicht gegen beliebige Einzelobjekte, sondern gegen Revisionen.

Sinnvoll sind mindestens:

  • playlist_revision
  • media_revision
  • config_revision

Der Player kann damit erkennen:

  • ob neue Konfiguration vorliegt
  • ob Medien nachgeladen werden muessen
  • ob die lokale Kopie noch gueltig ist

Beispiel fuer aktive Playlist-Auswertung

Ein playlist_item ist aktiv, wenn:

  • enabled = true
  • valid_from leer oder in der Vergangenheit liegt
  • valid_until leer oder in der Zukunft liegt

Wenn kein aktives Item existiert:

  • greift die globale Fallback-Regel des Screens oder der Playlist

Beispiel fuer Admin-Steuerung

Wenn ein Admin reload ausloest:

  1. Ein device_command wird gespeichert
  2. der Befehl wird per MQTT an den Screen signalisiert
  3. der Player fuehrt den Reload aus
  4. der Player sendet ein ACK
  5. device_command.delivery_state wird aktualisiert

Offene spaetere Erweiterungen

  • mehrere Screens pro Tenant in der Firmenoberflaeche
  • Vorlagen und globale Playlists
  • Historie der Statusdaten als Zeitreihe
  • Geplante Kampagnen mit Prioritaeten
  • serverseitige Konvertierung oder Transkodierung von Medien