WebSocket & Conventions

WebSocket

The WebSocket provides real-time bidirectional communication between the server and its clients (the Creature Console, Creature Controller, etc.).

GET /api/v1/websocket — Upgrade to a WebSocket connection.

Client → Server Messages

  • Notice — General notice messages from clients
  • StreamFrame — DMX frame data for streaming playback
  • BoardSensorReport — Board-level sensor data from a Raspberry Pi (temperature, voltage, etc.)
  • MotorSensorReport — Motor sensor data from a Raspberry Pi (current draw, position feedback, etc.)
  • DynamixelSensorReport — Dynamixel servo telemetry from a Raspberry Pi, one entry per servo on the bus (servo ID, temperature, present load, voltage, position)

Server → Client Messages

  • Database — Database change notifications
  • LogMessage — Server log messages
  • ServerCounters — Periodic system metrics
  • VirtualStatusLights — Status light state updates (the virtual version of the physical LEDs from the Pi hat era)
  • UpsertCreature — Creature configuration change notifications
  • CacheInvalidation — Cache invalidation signals. The cache_type field is one of creature, animation, playlist, sound-list, ad-hoc-animation-list, ad-hoc-sound-list, fixture, dialog-script-list, or storyboard-list
  • PlaylistStatus — Playlist state changes
  • JobProgress — Progress updates for async jobs (lip sync generation, ad-hoc animations, dialog renders)
  • JobComplete — Job completion notifications with results
  • IdleStateChanged — Idle loop enable/disable notifications
  • CreatureActivity — Creature activity reports (what each creature is currently doing)

Metrics

GET /api/v1/metric/counters — Get system performance counters — frames processed, events dispatched, WebSocket messages sent, etc.

Debug

Utility endpoints for development and debugging. These trigger cache invalidation messages on connected clients.

GET /api/v1/debug/cache-invalidate/creature — Broadcast a creature cache invalidation to all connected clients.

GET /api/v1/debug/cache-invalidate/animation — Broadcast an animation cache invalidation to all connected clients.

GET /api/v1/debug/cache-invalidate/playlist — Broadcast a playlist cache invalidation to all connected clients.

GET /api/v1/debug/cache-invalidate/sound-list — Broadcast a sound-list cache invalidation to all connected clients.

GET /api/v1/debug/cache-invalidate/ad-hoc-animation-list — Broadcast an ad-hoc-animation-list cache invalidation to all connected clients.

GET /api/v1/debug/cache-invalidate/ad-hoc-sound-list — Broadcast an ad-hoc-sound-list cache invalidation to all connected clients.

GET /api/v1/debug/cache-invalidate/fixture — Broadcast a fixture cache invalidation to all connected clients.

GET /api/v1/debug/cache-invalidate/dialog-script-list — Broadcast a dialog-script-list cache invalidation to all connected clients.

GET /api/v1/debug/cache-invalidate/storyboard-list — Broadcast a storyboard-list cache invalidation to all connected clients.

GET /api/v1/debug/playlist/update — Test playlist update broadcast to connected clients.

System

GET /api/v1/health — Health check endpoint. Returns the canonical envelope: {"status": "ok", "code": 200, "message": "Server is operational", "session_id": null}. See Error Envelope for the shape used by every non-entity JSON response.

Status Codes

The server uses these HTTP status codes consistently:

  • 200 — Success
  • 202 — Accepted (async job started, check WebSocket for progress)
  • 400 — Bad Request (invalid input — client’s fault)
  • 403 — Forbidden (path traversal attempt on file endpoints)
  • 404 — Not Found
  • 409 — Conflict (e.g., creature not registered to a universe)
  • 422 — Unprocessable Entity (missing required fields for processing)
  • 500 — Internal Server Error

Error Envelope

Every JSON response that isn’t a typed entity — every 4xx, every 5xx, and a few 2xx (DELETE confirmations, health) — uses the canonical StatusDto shape:

{
  "status": "ok",       // "ok" for 2xx, "not_found" for 404, "error" otherwise
  "code": 200,           // matches the HTTP status code
  "message": "Storyboard deleted",
  "session_id": null     // only set for playback endpoints that returned a session
}

The status field is one of "ok", "error", or "not_found" (all lowercase). Clients can use it as a cheap discriminator without parsing the numeric code.