morz-infoboard/DEVELOPMENT.md
Jesko Anschütz aff12a4d81 Doku-Sync: README, TODO, DEVELOPMENT und API-Docs auf Implementierungsstand nachgezogen
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 <noreply@anthropic.com>
2026-03-23 09:55:36 +01:00

11 KiB
Raw Blame History

Info-Board Neu - Entwicklung

Ziel

Dieses Dokument soll den Einstieg auf einem anderen Entwicklungsrechner moeglichst reibungsfrei machen.

Es beschreibt:

  • minimale Voraussetzungen
  • wichtige Verzeichnisse
  • Build- und Run-Kommandos
  • aktuelle Annahmen fuer den lokalen Entwicklungsbetrieb

Repository

  • Remote: git.az-it.net:az/morz-infoboard.git
  • Standard-Branch: main

Projektwurzel:

  • /srv/docker/info-board-neu

Wichtige Verzeichnisse

  • docs/ fuer Architektur- und Fachkonzepte
  • server/backend/ fuer das zentrale Go-Backend
  • player/agent/ fuer den Go-basierten Player-Agent
  • ansible/ fuer Deployment und Provisionierung
  • compose/ spaeter fuer den zentralen Server-Stack

Aktueller Entwicklungsstand

Bereits vorhanden:

  • fachliche Architektur- und Betriebskonzepte
  • relationaler Schema-Entwurf in docs/SCHEMA.md
  • 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:

  • admin-seitige Benutzerautentifizierung und Zugriffskontrolle
  • Multi-Tenancy-Isolation auf API-Ebene
  • produktives SSL/TLS-Handling fuer Deployment

Voraussetzungen auf dem Entwicklungsrechner

Mindestens empfohlen:

  • git
  • go in Version 1.24.x
  • make

Spaeter zusaetzlich sinnvoll:

  • docker und docker compose
  • postgresql-client
  • mosquitto-clients
  • golangci-lint

Fuer Container-Builds liegen erste Dockerfiles in:

  • server/backend/Dockerfile
  • player/agent/Dockerfile

Schnellstart

Repository klonen:

git clone git.az-it.net:az/morz-infoboard.git
cd morz-infoboard

Dokumentationsbasis lesen:

  1. README.md
  2. PLAN.md
  3. TECH-STACK.md
  4. docs/SCHEMA.md
  5. docs/OFFENE-ARCHITEKTURFRAGEN.md
  6. docs/LAYOUT-JSON.md

Build-Kommandos

Backend bauen

cd server/backend
go build ./...

Agent bauen

cd player/agent
go build ./...

Alternativ ueber Makefile

make build

Aktuell bedeutet das:

  • make build baut Backend und Agent
  • make build-backend baut nur server/backend
  • make build-agent baut nur player/agent
  • make run-backend startet das Backend
  • make run-agent startet den Agenten
  • make fmt formatiert beide Go-Module
  • make lint prueft beide Go-Module mit golangci-lint

Hinweis:

  • auf dem aktuellen System dieser Session sind make und go nicht installiert; die Befehle sind fuer den Entwicklungsrechner vorbereitet

Lokaler Start

Backend lokal starten

cd server/backend
go run ./cmd/api

Standard:

  • HTTP-Adresse: :8080
  • Health-Endpunkt: GET /healthz
  • Basis-Endpunkt: GET /api/v1

Konfigurierbar ueber:

  • MORZ_INFOBOARD_HTTP_ADDR HTTP-Adresse (Standard: :8080)
  • MORZ_INFOBOARD_STATUS_STORE_PATH Pfad zur JSON-Datei fuer persistenten Status-Store; leer lassen fuer reinen In-Memory-Betrieb

Beispiele:

MORZ_INFOBOARD_HTTP_ADDR=:18080 go run ./cmd/api
MORZ_INFOBOARD_HTTP_ADDR=:8080 \
MORZ_INFOBOARD_STATUS_STORE_PATH=/tmp/screen-status.json \
go run ./cmd/api

Agent lokal starten

cd player/agent
go run ./cmd/agent

Standardwerte:

  • MORZ_INFOBOARD_SCREEN_ID=unset-screen
  • MORZ_INFOBOARD_SERVER_URL=http://127.0.0.1:8080
  • MORZ_INFOBOARD_MQTT_BROKER= (leer = MQTT wird uebersprungen)
  • MORZ_INFOBOARD_PLAYER_ADDR=127.0.0.1:8090
  • MORZ_INFOBOARD_PLAYER_CONTENT_URL= (leer = kein Inhalt eingebettet)

Optional:

  • MORZ_INFOBOARD_MQTT_USERNAME MQTT-Benutzername
  • MORZ_INFOBOARD_MQTT_PASSWORD MQTT-Passwort
  • MORZ_INFOBOARD_CONFIG=/etc/signage/config.json dateibasierte Konfiguration

Eine Beispielkonfiguration liegt in player/config/config.example.json.

Der Agent stellt unter http://127.0.0.1:8090/player eine lokale Kiosk-Seite bereit.

Beispiel ohne MQTT:

MORZ_INFOBOARD_SCREEN_ID=info01-dev \
MORZ_INFOBOARD_SERVER_URL=http://127.0.0.1:8080 \
go run ./cmd/agent

Beispiel mit MQTT:

MORZ_INFOBOARD_SCREEN_ID=info01-dev \
MORZ_INFOBOARD_SERVER_URL=http://127.0.0.1:8080 \
MORZ_INFOBOARD_MQTT_BROKER=tcp://127.0.0.1:1883 \
MORZ_INFOBOARD_MQTT_USERNAME=user \
MORZ_INFOBOARD_MQTT_PASSWORD=pass \
go run ./cmd/agent

Ansible-Deployment auf einen Zielrechner

Der ansible/-Ordner enthaelt ein vollstaendiges Playbook fuer das Deployment auf einen Pi oder ein Debian-System.

Voraussetzungen

  • Ansible auf dem Entwicklungsrechner
  • SSH-Key fuer den Zielrechner hinterlegt
  • Ansible Vault fuer MQTT-Zugangsdaten

Inventory und Konfiguration

  • ansible/inventory.yml Hosts und Gruppen
  • ansible/host_vars/<host>/vars.yml host-spezifische Variablen (screen_id, ansible_host, ansible_user)
  • ansible/group_vars/signage_players/vars.yml globale Defaults
  • ansible/group_vars/signage_players/vault.yml verschluesselte Zugangsdaten (gitignored)

Vault-Datei anlegen:

ansible-vault create ansible/group_vars/signage_players/vault.yml

Inhalt:

vault_mqtt_username: "benutzername"
vault_mqtt_password: "passwort"

In vars.yml referenzieren:

morz_mqtt_username: "{{ vault_mqtt_username }}"
morz_mqtt_password: "{{ vault_mqtt_password }}"

Deployment ausfuehren

cd ansible
ansible-playbook site.yml -i inventory.yml --ask-vault-pass

Das Playbook erledigt:

  1. Agent-Binary cross-kompilieren (lokal, GOOS=linux GOARCH=arm64)
  2. Binary und Konfiguration auf den Zielrechner uebertragen
  3. systemd-Unit fuer den Agent anlegen und starten
  4. journald auf RAM-Speicherung konfigurieren (SD-Karte schonen)
  5. X11-Paketstack und Chromium installieren
  6. Kiosk-Startskript und systemd-Unit fuer die Anzeige anlegen

Rollen

  • signage_player Agent, Konfiguration, systemd-Unit, journald
  • signage_display X11, Chromium, Kiosk-Service

Aktuelle Architekturentscheidungen mit direkter Auswirkung auf Entwicklung

  • message_wall wird serverseitig in konkrete Screen-Szenen aufgeloest
  • Kampagnengruppen werden serverseitig in konkrete Screen-Assignments expandiert
  • playlist_items haben im finalen Implementierungsschema keinen direkten screen_id-Fremdschluessel
  • Provisionierung wird worker-/jumphost-faehig geplant
  • API-Fehler sollen einen einheitlichen Fehlerumschlag nutzen

Empfohlene naechste Implementierungsschritte

  1. Backend: einheitliches Fehlerformat und Routing-Grundstruktur anlegen
  2. Backend: Konfigurations- und App-Lifecycle stabilisieren
  3. Agent und Backend: den HTTP-Statuspfad als Grundlage fuer Identitaet, Persistenz und spaetere Admin-Vorschau erweitern
  4. Agent: danach MQTT-spezifische Reachability und feinere Connectivity-Schwellenlogik aufsetzen
  5. Danach die Netzwerk-, Sync- und Kommandopfade schrittweise produktionsnah ausbauen

End-to-End-Entwicklungstest (Backend + Agent)

Backend und Agent koennen lokal gegeneinander laufen. Reihenfolge:

  1. Backend starten (Terminal 1):
cd server/backend
MORZ_INFOBOARD_STATUS_STORE_PATH=/tmp/screen-status.json go run ./cmd/api
  1. Agent starten (Terminal 2):
cd player/agent
MORZ_INFOBOARD_SCREEN_ID=info01-dev \
MORZ_INFOBOARD_SERVER_URL=http://127.0.0.1:8080 \
go run ./cmd/agent
  1. Status pruefen:
# JSON-Uebersicht
curl http://127.0.0.1:8080/api/v1/screens/status

# HTML-Diagnoseseite
open http://127.0.0.1:8080/status

# Einzelner Screen
curl http://127.0.0.1:8080/api/v1/screens/info01-dev/status

# Screen loeschen
curl -X DELETE http://127.0.0.1:8080/api/v1/screens/info01-dev/status

Die Datei /tmp/screen-status.json enthaelt nach dem ersten Heartbeat den persistierten Status-Store.

Ergaenzt seit dem ersten Geruest:

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
  • 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
  • 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 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

Empfohlen:

  • kleine, klar umrissene Commits
  • zuerst Konzepte anpassen, dann Code
  • Schema und API-Vertrag synchron halten
  • neue Fachentscheidungen immer in docs/ dokumentieren

Hinweise fuer einen zweiten Entwicklungsrechner

  • vor Arbeitsbeginn git pull --rebase oder gleichwertig den aktuellen Stand holen
  • bei paralleler Arbeit zuerst in den Dokumenten pruefen, ob neue Architekturentscheidungen getroffen wurden
  • falls lokale Tools abweichen, mindestens go version und make --version pruefen