Architecture - wagnerks1990/RoomGoblin GitHub Wiki
Architecture
See Host Networking for the current Linux container topology, loopback-only maintenance API, explicit add-on migration, listener ports and recovery rules.
RoomGoblin separates the classroom application, browser display clients, persistence, maintenance functions, host-level administration, and external integrations.
Operator Browser
|
v
RoomGoblin API / Controller
|
+---- Display WebSocket / browser clients
+---- Scheduler / automation engine
+---- Media and announcement arbitration
+---- Music Assistant integration
+---- AV / lighting / lab integrations
+---- SQLite persistent state
|
+---- Maintenance Agent
|
+---- Host Agent (systemd on host)
Standard production topology
Ubuntu host
├── /opt/classroom-hub
├── classroom-hub-host-agent.service
│ └── /run/classroom-control-hub/host-agent.sock
└── Docker
├── classroom-control-hub
└── classroom-control-hub-maintenance
Main application
The Node.js service provides controller UI/API, scheduler, display orchestration, class/calendar rules, automation execution, media control, announcement handling, integrations, diagnostics, and persistence access.
The main application does not require unrestricted host privileges. Runtime state is mounted into the container rather than baked into the image.
Display clients
Displays are browser/kiosk endpoints with stable IDs. They render classroom slides, text, timers, images, video, web content, and priority announcements.
Display clients tolerate disconnect/reconnect and converge to current server state. Backend/controller/display version identifiers remain synchronized across releases.
Scheduler and calendar engine
The scheduler evaluates normal weekdays, linked classes, cycle-day rules, no-school dates, remote days, half days, delayed starts, transition periods, explicit continuation rules, and manual execution requests.
Calendar exceptions are resolved before ordinary scheduling. Deployment-specific calendars belong in persistent configuration, not public source constants.
Priority model
Morning / priority live announcement
>
Priority automation audio/video
>
Normal visual automation
>
Background Music
Morning Announcements use a hard priority lock. While active, announcement displays are reserved, Background Music remains paused, and conflicting display actions are deferred. Priority is checked at each delivery so delayed or already-running automations cannot overwrite the takeover. Non-display actions such as lighting continue normally.
Manual and automatic announcement starts use the same runtime priority state.
HLS Morning Announcements
For Ant Media player URLs, HLS is the primary live-state/playback transport when derivable.
- 200 + valid
#EXTM3Uplaylist = LIVE - 404 = OFFLINE
- network/timeout/5xx = UNKNOWN/error
- blocked REST diagnostics do not override HLS
Two confirmed OFFLINE checks are required before automatic release. Playback uses a local media element so announcement volume/mute controls act on the actual player.
Post-announcement failsafe resync
When announcements end:
- clear announcement content;
- release the priority lock;
- mark announcement runtime inactive;
- consume deferred trigger bookkeeping;
- re-evaluate current date/class/time;
- choose the newest currently applicable display automation independently per target;
- re-run the winning current automations;
- reconcile/resume Background Music afterward; if display reconciliation fails, retain the audio hold and retry.
The system deliberately does not restore stale pre-announcement snapshots.
Background Music
Background Music is an independent scheduler backed by Music Assistant. Silent/visual automation does not disturb it. Priority audio pauses it temporarily. Recovery reconciles against the actual Music Assistant player/group state. Runtime state retains the player that actually started playback, so later pause/stop operations cannot accidentally target a newly configured player while leaving the original playing.
Integration health and responsiveness
Each integration reports independently. A Pluto failure must not make MQTT/Govee appear offline. Slow optional hardware probes must not block the initial Overview render.
Maintenance Agent
Maintenance-specific operations are separate from the main application so they do not broaden the primary service's privileges unnecessarily.
Host Agent
The Host Agent runs as a controlled systemd service and listens only on /run/classroom-control-hub/host-agent.sock. The maintenance container receives the socket through a bind mount.
Persistence
Production persistent state remains outside replaceable containers/source:
/opt/classroom-hub/
├── docker-compose.yml
├── .env
├── data/
│ └── classroom-control-hub.db
├── uploads/
├── backups/
└── secrets/
Configuration boundary
Public source must not contain production passwords, tokens, private keys, internal topology, student/user data, or deployment-specific secrets. Site branding, stream endpoints, Music Assistant details, classroom calendars, device configuration, and credentials are supplied at runtime.
Release/version convergence
All embedded version identifiers change together across backend, display renderer, controller, maintenance agent, and host agent. A stale renderer can otherwise cause reconnect/reload loops.
AI context
AGENTS.md is the authoritative AI/contributor operating contract and docs/AI-CONTEXT.md is the compact technical handoff. Architecture changes that affect future reasoning should update those files and this Wiki mirror.
ESPHome native worker
The main, unprivileged Hub image contains the pinned native client and supervises a private-pipe Python worker. It has no listener, Docker/USB privilege or firmware executor. See ESPHome devices for identity, authorization, command/reconnect, encrypted storage and recovery boundaries.