## Streaming API (WebSocket) ### Overview The streaming API exposes an event-driven WebSocket at `/ws`. It bridges between external clients and the internal event bus: - Incoming WebSocket JSON `{ event, payload }` → `ctx.fire(event, payload)` - Local events → broadcasted to all connected WebSocket clients as `{ event, payload }` This allows real-time control and observation of the system without polling. ### URL - `ws:///ws` ### Message Format - Client → Device ```json { "event": "", "payload": "" | { /* inline JSON */ } } ``` - Device → Client ```json { "event": "", "payload": "" } ``` Notes: - The device accepts `payload` as a string or a JSON object/array. Objects are serialized into a string before dispatching to local subscribers to keep a consistent downstream contract. - A minimal ack `{ "ok": true }` is sent after a valid inbound message. #### Echo suppression (origin tagging) - To prevent the sender from receiving an immediate echo of its own message, the server injects a private field into JSON payloads: - `_origin: "ws:"` - When re-broadcasting local events to WebSocket clients, the server: - Strips the `_origin` field from the outgoing payload - Skips the originating `clientId` so only other clients receive the message - If a payload is not valid JSON (plain string), no origin tag is injected and the message may be echoed ### Event Bus Integration - The WebSocket registers an `onAny` subscriber to `NodeContext` so that all local events are mirrored to clients. - Services should subscribe to specific events via `ctx.on("", ...)`. ### Examples 1) Set a solid color on NeoPattern: ```json { "event": "api/neopattern/color", "payload": { "color": "#FF0000", "brightness": 128 } } ``` 2) Broadcast a cluster event (delegated to core): ```json { "event": "cluster/broadcast", "payload": { "event": "api/neopattern/color", "data": { "color": "#00FF00", "brightness": 128 } } } ``` ### Reference Implementation - WebSocket setup and bridging are implemented in `ApiServer`. - Global event subscription uses `NodeContext::onAny`. Related docs: - [`ClusterBroadcast.md`](./ClusterBroadcast.md) — centralized UDP broadcasting and CLUSTER_EVENT format