Building a Server in Any Language (Raw Protocol)

The wire format is small JSON over WebSocket, so you can integrate from Node, Go, Rust, C#, browser JavaScript, or anything with a WebSocket client — no special library required. This page is the implementer's recipe; the authoritative verb list is Message Reference, and the concepts are in The MeshSocket Protocol and Data Flow — sync & actions.

The frame

Send and receive JSON objects of this shape:

{ "id": "uuid", "type": "string", "payload": <any>, "reply_to": "uuid | null" }
  • Generate a fresh id (UUID) per outbound frame.
  • type is the verb. payload is your data. reply_to is set only when you are answering a request (echo the request's id).

The handshake

  1. Open a WebSocket to the relay URL (ws:// LAN, wss:// gateway).
  2. Send an identify frame:

json { "id": "<uuid>", "type": "identify", "payload": { "name": "My Server", "channel": "home", "role": "hub", "can_broadcast": true, "can_route": true, "auth_token": "" } }

(On the gateway, set auth_token to a valid token, or you'll be parked.) 3. Read frames until you receive {"type":"welcome", ...}. You're now on the channel.

Sending data (server → device)

Broadcast a telemetry frame; the relay fans it out as type:"broadcast" to the channel:

{ "id":"<uuid>", "type":"broadcast_request",
  "payload": { "msg_type":"metrics", "cpu": 73, "mem": 41 } }

Controls listening on event:"broadcast" with filter:{"msg_type":"metrics"} and a valuePath will update. (See Data Flow — sync & actions for the matching layout side.)

Receiving inputs (device → server)

Read incoming frames. Control actions sent via broadcast_request arrive to you as:

{ "type":"broadcast", "payload": { "msg_type":"command", "command":"reboot" } }

Demux on payload.msg_type and react. Pseudocode:

ws.onmessage = (raw) => {
  const frame = JSON.parse(raw.data);
  if (frame.type === "broadcast") {
    const p = frame.payload || {};
    if (p.msg_type === "command") handleCommand(p);
    if (p.msg_type === "set")     applySetting(p);
  }
  if (frame.type === "welcome")   onReady();
  if (isRoutedRequest(frame))     answer(frame);   // see below
};

Answering routed requests

When a control uses mode:"request" over route_msg, the relay delivers the inner request to you as a frame of that type carrying a reply_to you must echo:

function answer(frame) {
  if (frame.type === "get_doc") {
    const reply = { title: frame.payload.path, content: loadMarkdown(frame.payload.path) };
    ws.send(JSON.stringify({ id: uuid(), type: "get_doc", payload: reply, reply_to: frame.id }));
  }
}

The key detail: set reply_to to the incoming frame's id so the relay can route your answer back to the original caller.

Minimal Node.js example

import WebSocket from "ws";
import { randomUUID } from "crypto";

const ws = new WebSocket("ws://192.168.1.50:8765");
const send = (type, payload, reply_to = null) =>
  ws.send(JSON.stringify({ id: randomUUID(), type, payload, reply_to }));

ws.on("open", () => {
  send("identify", { name: "Node Server", channel: "home", role: "hub",
                     can_broadcast: true, can_route: true, auth_token: "" });
});

ws.on("message", (data) => {
  const f = JSON.parse(data);
  if (f.type === "welcome") {
    console.log("connected");
    setInterval(() => send("broadcast_request",
      { msg_type: "metrics", cpu: Math.floor(Math.random() * 100) }), 1000);
  }
  if (f.type === "broadcast" && f.payload?.msg_type === "command") {
    console.log("command:", f.payload.command);
  }
});

Issuing your own requests (optional)

To call another member (rarely needed for a data server), send route_msg and match the reply by id:

{ "id":"<uuid>", "type":"route_msg",
  "payload": { "target_id":"<peer-uuid>", "type":"get_state", "payload": {} } }

The relay returns the peer's reply as a frame whose reply_to equals your <uuid>. To discover peers, send { "type":"get_nodes" } (requires can_monitor: true) and read { clients: [...] }.

Checklist

  • [ ] UUID per frame; JSON encode/decode.
  • [ ] identify with channel, sending-capable role, can_broadcast: true.
  • [ ] Wait for welcome before sending.
  • [ ] Producer broadcasts broadcast_request with a msg_type.
  • [ ] Consumer reads broadcast, demuxes on msg_type.
  • [ ] (If using mode:"request" controls) echo reply_to on answers.
  • [ ] wss:// + valid auth_token for the Connect+ gateway.

Reference: Message Reference. Recipes: Recipe: Telemetry Dashboard, Recipe: Interactive Controls.