State model
Core Entities
DeviceState (server-side)
Stored in deviceStates map keyed by device ID:
{ id, name, type, ip, port, state: 'play' | 'rec' | 'stop' | 'offline', timecode: string, // HH:MM:SS:FF filename: string, framerate: number, updated: number, // performance.timeOrigin + performance.now() connected: boolean}Initial state is offline, connected=false, timecode='00:00:00:00', filename=''.
Protocol Status
getProtocolStatus() derives:
- emberPlus:
{ enabled, running, port } - tslUmd:
{ enabled, running, destinations, deviceCount }
WebSocket Clients
A Set<WebSocket> tracks connected dashboard clients for broadcast.
State Transitions
High-Level Device State Machine
┌───────────────┐ state/connected event ┌─────────────────────┐│ OFFLINE │ ───────────────────────────────────▶ │ CONNECTED + STATE ││ connected=F │ │ (play/rec/stop) │└───────┬───────┘ ◀─────────────────────────────────── └──────────┬──────────┘ │ disconnect/stale/transport loss │ └─────────────────────────────────────────────────────────┘- Connected + state update:
client.on('state')setsconnected=true, updates state/timecode/filename. - Disconnected:
client.on('disconnected')setsstate='offline',connected=false(timecode/filename retained).
Device-Type Specific Inputs
- HyperDeck: TCP client emits
stateon transport/slot updates; reconnection with exponential backoff. - vMix: HTTP polling every
pollIntervalMs; emits cached last good state on transient failures; marks disconnected after 3 failures. - CasparCG: OSC listener updates internal cache; a stale timer marks disconnected after
staleTimeoutMswithout updates.
Broadcast Cycle
- Device client emits
state→ server updatesdeviceStates. - Ember+ and TSL UMD are updated immediately on state changes.
broadcastState()sends current snapshot to all WebSocket clients on a drift-free schedule (updateIntervalMs).
Timing Model
- Monotonic timestamps are used for device updates (
performance.timeOrigin + performance.now()). - WebSocket clients detect stale device data via
updatedtimestamp on the UI.
Attestation
# Identityagent_id: audit-mapperagent_version: "1.0"protocol_version: "2.0"
# Timingtimestamp: 2026-01-31T13:13:28Zduration_seconds: 720
# Contextgit_ref: e4bb0098264f90d3afc7b5d0f3b5e425d1825761git_branch: mainworking_directory: /Users/david/Documents/GitHub/superdash
# Artefact metadataartefact: STATE_MODEL.mdphase: 1status: COMPLETE
# Confidence assessmentconfidence: HIGHconfidence_notes: "State transitions and data model derived from server.js and protocol client implementations."
# Inputs consumed (with integrity hashes)inputs_consumed: - path: server/server.js hash: sha256:4d09f4acde1032a407f67943d0cd93be1fe10b79a9c07aa3b430cf6dd27b31bb - path: server/hyperdeck-client.js hash: sha256:825d1a4c5e0f3089fb824f6b0d2adef0d7f85342dd46585d6b8007996d1d3ba9 - path: server/vmix-client.js hash: sha256:50a668d504066f9bedfc576890529b2b28e898479ac33e7c7325f7a950f58416 - path: server/osc-casparcg.js hash: sha256:7a22ec8e254ca6d55c5026ebd62068c866ce13f26d62760bfe73b56f116c5a9e
# Commands executedcommands_executed: - seq: 1 cmd: "sed -n '1,240p' server/server.js" exit_code: 0 purpose: "Read config load and device state initialization" output_summary: "DeviceState fields and initialization" - seq: 2 cmd: "sed -n '240,480p' server/server.js" exit_code: 0 purpose: "Read state update handlers and /health response" output_summary: "Connected/disconnected/state event handling" - seq: 3 cmd: "sed -n '1,240p' server/hyperdeck-client.js" exit_code: 0 purpose: "Review HyperDeck state emission" output_summary: "Transport/slot parsing and emit('state')" - seq: 4 cmd: "sed -n '1,240p' server/vmix-client.js" exit_code: 0 purpose: "Review vMix polling model" output_summary: "Polling + cached state" - seq: 5 cmd: "sed -n '240,720p' server/osc-casparcg.js" exit_code: 0 purpose: "Review CasparCG OSC cache and stale detection" output_summary: "OSC bundle handling and stale timer"
# Findings summaryfindings: critical: 0 high: 0 medium: 0 low: 0 info: 0
# Blocking issuesblocking_issues: []
# Handoffhandoff: ready: true next_agents: - reliability-analyst - concurrency-analyst - performance-analyst dependencies_satisfied: STATE_MODEL.md: COMPLETE context_for_next: | DeviceState tracks playback state + connection status. Updates flow from protocol clients to server and then to WebSocket/Ember+/TSL UMD. Stale detection exists for CasparCG; VMix uses failure threshold.