# 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` - erstes Go-Geruest fuer `server/backend` - erstes Go-Geruest fuer `player/agent` Noch nicht vorhanden: - produktive API-Endpunkte mit Datenbankanbindung - Player-Sync und Playlist-Management - Compose-Stack fuer lokale Serverdienste (Grundgeruest liegt in `compose/`) ## 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: ```bash 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 ```bash cd server/backend go build ./... ``` ### Agent bauen ```bash cd player/agent go build ./... ``` ### Alternativ ueber Makefile ```bash 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 ```bash 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: ```bash MORZ_INFOBOARD_HTTP_ADDR=:18080 go run ./cmd/api ``` ```bash MORZ_INFOBOARD_HTTP_ADDR=:8080 \ MORZ_INFOBOARD_STATUS_STORE_PATH=/tmp/screen-status.json \ go run ./cmd/api ``` ### Agent lokal starten ```bash 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: ```bash MORZ_INFOBOARD_SCREEN_ID=info01-dev \ MORZ_INFOBOARD_SERVER_URL=http://127.0.0.1:8080 \ go run ./cmd/agent ``` Beispiel mit MQTT: ```bash 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//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: ```bash ansible-vault create ansible/group_vars/signage_players/vault.yml ``` Inhalt: ```yaml vault_mqtt_username: "benutzername" vault_mqtt_password: "passwort" ``` In `vars.yml` referenzieren: ```yaml morz_mqtt_username: "{{ vault_mqtt_username }}" morz_mqtt_password: "{{ vault_mqtt_password }}" ``` ### Deployment ausfuehren ```bash 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): ```bash cd server/backend MORZ_INFOBOARD_STATUS_STORE_PATH=/tmp/screen-status.json go run ./cmd/api ``` 2. Agent starten (Terminal 2): ```bash cd player/agent MORZ_INFOBOARD_SCREEN_ID=info01-dev \ MORZ_INFOBOARD_SERVER_URL=http://127.0.0.1:8080 \ go run ./cmd/agent ``` 3. Status pruefen: ```bash # 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: - `message_wall`-Resolver im Backend - 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 - 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) - MQTT-Authentifizierung mit Username und Password - Player-UI im Agent (`/player` HTML-Kiosk, `/api/now-playing` JSON) - Ansible-Rollen `signage_player` und `signage_display` fuer vollstaendiges Deployment - journald auf volatile Storage konfiguriert (SD-Karte schonen) ## 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