Inject _origin=ws:<clientId> into JSON payloads on inbound WS messages and strip it on broadcast while skipping the origin client. Documents behavior in StreamingAPI.md.
2.3 KiB
2.3 KiB
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://<device-ip>/ws
Message Format
- Client → Device
{
"event": "<event-name>",
"payload": "<json-string>" | { /* inline JSON */ }
}
- Device → Client
{
"event": "<event-name>",
"payload": "<json-string>"
}
Notes:
- The device accepts
payloadas 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:<clientId>"
- When re-broadcasting local events to WebSocket clients, the server:
- Strips the
_originfield from the outgoing payload - Skips the originating
clientIdso 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
- Strips the
Event Bus Integration
- The WebSocket registers an
onAnysubscriber toNodeContextso that all local events are mirrored to clients. - Services should subscribe to specific events via
ctx.on("<name>", ...).
Examples
- Set a solid color on NeoPattern:
{
"event": "api/neopattern/color",
"payload": { "color": "#FF0000", "brightness": 128 }
}
- Broadcast a cluster event (delegated to core):
{
"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— centralized UDP broadcasting and CLUSTER_EVENT format