Flere anlegg – hovedscene, resepsjon, crew – og ett sted å sende fra, med avkryssing for hvilke soner meldingen skal til. Sentralen er en vanlig announcer med [zones] i config. En sone er en vanlig announcer med ANNOUNCER_MESH_SECRET. Samme image, ingen mode, og en sone kan brukes alene hvis sentralen faller ut. Hver avhengighet med C-kode har aarch64-wheel i uv.lock, så det samme bildet går på en Raspberry Pi uten å kompilere noe. Sentralen syntetiserer én gang og sender ferdig WAV (POST /api/play, multipart). Sonen trenger da verken nett, edge-tts eller Pipers 670 MB for det den får – Item.wav er hele endringen i avspillingen. Køene forblir per sone: dispatcheren har egen tråd og egen kø, leverer til hver sone i hver sin tråd med timeout, og går videre. En opptatt hovedscene holder ikke igjen resepsjonen, og en sone som er nede feiler alene – synlig per sone i UI og revisjonslogg. Auth gjenbrukes: ny leverandør mesh på header X-Mesh-Key (ikke Bearer – den leses av JWT-leverandøren, som avviser alt som ikke er et JWT før neste får prøve), med én handling, play. To regler som fulgte med: - play følger aldri med «alt åpent». Uten det kunne hvem som helst POSTe en WAV til en åpen sone og få den spilt. Testen for åpen modus fanget det. - En legitimasjon som vises fram og er feil gir 401 også der gjester ellers har lov. Før slapp en feil PIN i åpen modus stille gjennom som gjest. mesh teller ikke som innlogging for folk: en sone med bare nøkkelen har fortsatt åpen side lokalt. Planlagte sendinger husker sonene sine og fordeles gjennom dispatcheren; planen ender som sent hvis minst én sone tok imot, med «hovedscene: kø #3, crew: nede» som note. Hodeløs Pi: install.sh kjører loginctl enable-linger, ellers finnes ikke lydsocketen når ingen logger inn. docs/mesh.md tar også raspi-config for jack framfor HDMI. 38 nye tester, 148 totalt. Fordelingen testes uten nett med stubbet transport; selve HTTP-en testes mot en levende werkzeug-server, så den håndrullede multiparten møter Flask sin parser. Verifisert i compose med sentral og to soner: til alle, bare til én, og én sone stoppet. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
81 lines
2.9 KiB
YAML
81 lines
2.9 KiB
YAML
# Testoppsett, ikke drift:
|
||
#
|
||
# docker compose -f compose.test.yaml up --build
|
||
#
|
||
# http://localhost:8091 sentralen: PIN, JWT og OIDC slått på, soner «her», «a», «b»
|
||
# http://localhost:9000 dummy-IdP som står for crew-panelet
|
||
# http://localhost:8093 sone-a (uten lyd – bare kø, så fordeling kan ses)
|
||
# http://localhost:8094 sone-b (samme)
|
||
#
|
||
# Stopp sone-b og send til alle, så ser du «nede» på den og «kø» på resten:
|
||
# docker compose -f compose.test.yaml stop sone-b
|
||
#
|
||
# Egen fil og eget prosjektnavn, så den ikke kan forveksles med eller
|
||
# forstyrre den som kjører i drift. Porten er 8091 av samme grunn.
|
||
# Koden bind-monteres her, så endringer slår inn med en restart.
|
||
name: announcer-test
|
||
|
||
services:
|
||
announcer:
|
||
build: .
|
||
ports: ["127.0.0.1:8091:8090"]
|
||
user: "${PUID:-1000}:${PGID:-1000}"
|
||
environment:
|
||
ANNOUNCER_CONFIG: /app/docker/config.test.toml
|
||
ANNOUNCER_CACHE: /data/cache
|
||
ANNOUNCER_LOG: /data/logs/announcements.jsonl
|
||
ANNOUNCER_STATE: /data/instance
|
||
# Gjenbruker stemmene i repoet (bind-mountet på /app), så testriggen
|
||
# ikke laster ned 670 MB til en gang.
|
||
ANNOUNCER_VOICES: /app/voices
|
||
ANNOUNCER_CHIMES: /data/chimes
|
||
ANNOUNCER_JWT_SECRET: test-hemmelighet-kun-for-docker-ikke-bruk-ekte
|
||
ANNOUNCER_OIDC_CLIENT_SECRET: test-client-secret-kun-for-docker
|
||
ANNOUNCER_PUBLIC_URL: http://localhost:8091
|
||
ANNOUNCER_MESH_SECRET: mesh-test-nokkel-kun-for-docker
|
||
XDG_RUNTIME_DIR: ${XDG_RUNTIME_DIR:-/run/user/1000}
|
||
TZ: ${TZ:-Europe/Oslo}
|
||
volumes:
|
||
- .:/app
|
||
- ./data:/data
|
||
- ${XDG_RUNTIME_DIR:-/run/user/1000}:${XDG_RUNTIME_DIR:-/run/user/1000}
|
||
depends_on: [idp, sone-a, sone-b]
|
||
|
||
# Soner: samme image, bare mesh-nøkkelen satt. Ingen lyd montert inn, så
|
||
# avspilling feiler der – med vilje, det er fordelingen som skal ses.
|
||
# tmpfs på /data, så ingen rot-eide mapper dukker opp på verten.
|
||
sone-a: &sone
|
||
build: .
|
||
ports: ["127.0.0.1:8093:8090"]
|
||
user: "${PUID:-1000}:${PGID:-1000}"
|
||
environment: &sone-env
|
||
ANNOUNCER_CONFIG: /finnes-ikke.toml
|
||
ANNOUNCER_MESH_SECRET: mesh-test-nokkel-kun-for-docker
|
||
ANNOUNCER_VOICES: /app/voices
|
||
ANNOUNCER_TITLE: "Sone A"
|
||
TZ: ${TZ:-Europe/Oslo}
|
||
volumes:
|
||
- .:/app
|
||
tmpfs:
|
||
- /data:mode=1777
|
||
|
||
sone-b:
|
||
<<: *sone
|
||
ports: ["127.0.0.1:8094:8090"]
|
||
environment:
|
||
<<: *sone-env
|
||
ANNOUNCER_TITLE: "Sone B"
|
||
|
||
idp:
|
||
build: .
|
||
ports: ["127.0.0.1:9000:9000"]
|
||
user: "${PUID:-1000}:${PGID:-1000}"
|
||
environment:
|
||
IDP_ISSUER: http://localhost:9000
|
||
IDP_CLIENT_ID: announcer
|
||
IDP_CLIENT_SECRET: test-client-secret-kun-for-docker
|
||
ANNOUNCER_JWT_SECRET: test-hemmelighet-kun-for-docker-ikke-bruk-ekte
|
||
ANNOUNCER_PUBLIC_URL: http://localhost:8091
|
||
volumes:
|
||
- .:/app
|
||
command: ["python", "docker/dummy_idp.py"]
|