Mesh: én sentral fordeler til flere soner
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>
This commit is contained in:
parent
eb27a162d5
commit
c4a15799dd
17 changed files with 1486 additions and 23 deletions
|
|
@ -56,6 +56,7 @@ class Scheduled:
|
|||
created: float = field(default_factory=time.time)
|
||||
status: str = "pending" # se STATUSES
|
||||
note: str = ""
|
||||
zones: list[str] = field(default_factory=list) # tom = lokalt / alle
|
||||
|
||||
def public(self) -> dict:
|
||||
d = asdict(self)
|
||||
|
|
@ -118,7 +119,8 @@ class Schedule:
|
|||
|
||||
# -- endringer ---------------------------------------------------------
|
||||
def add(self, *, at: float, text: str, voice: str, speed: float, chime: str,
|
||||
user: str = "", subject: str = "", method: str = "none") -> Scheduled:
|
||||
user: str = "", subject: str = "", method: str = "none",
|
||||
zones: list[str] | None = None) -> Scheduled:
|
||||
"""Legger til en melding. Kaster ValueError på et ubrukelig tidspunkt."""
|
||||
at = float(at)
|
||||
now = time.time()
|
||||
|
|
@ -129,6 +131,7 @@ class Schedule:
|
|||
item = Scheduled(
|
||||
id=secrets.token_hex(4), at=at, text=text, voice=voice, speed=speed,
|
||||
chime=chime, user=user, subject=subject, method=method,
|
||||
zones=[str(z) for z in (zones or [])],
|
||||
)
|
||||
with self._lock:
|
||||
self.items.append(item)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue