DocsBluetooth LE Open APIProtocol & Commands

Protocol & Commands

One JSON message format for every command, response, and event — plus the full command reference.

Requests

Write a JSON object to CMD_IN. Every request has the same shape:

{
  "method": "get" | "set",   // read or write
  "ns":     "deviceState",   // namespace (see below)
  "prop":   "PLAYER_SHIELD", // property within the namespace
  "value":  100,             // the new value (for "set"); omit for "get"
  "id":     "abc123"         // your correlation id (echoed in the response)
}

Give every request a unique id. Responses arrive on CMD_OUT carrying the same id, so you can match a reply to the request that produced it.

Responses

Responses are delivered as notifications on CMD_OUT:

// success
{ "status": "ok", "ns": "deviceState", "prop": "PLAYER_SHIELD", "value": 100, "id": "abc123" }

// error
{ "status": "error", "key": "invalidValue", "msg": "…", "data": "prop", "id": "abc123" }
Error keyMeaning
unknownValueThe namespace or property is not recognised.
invalidValueThe value was the wrong type or out of range for that property.
missingValueA required field (method / ns / prop) was missing.
missingInputThe written value was empty.
jsonParse…The request was not valid JSON.

Events

Events are unsolicited notifications on EVENTS_OUT. They use the same ns / prop / value fields but carry no status or ( usually) id — treat them as a fire-and-forget stream.

nsShapeWhen
deviceState{ "ns": "deviceState", "prop": "<KEY>", "value": <any> }A state value changed. Fires only while DEVICE_APP_CONNECTED is true. High-frequency values are rate limited (GPS ~2s, battery ~5s).
fsm{ "ns": "fsm", "prop": "state", "value": "<state>" }The device entered a new game / UI state (e.g. IN_GAME → DEAD).
kb{ "ns": "kb", "prop": "state", "value": { "isOpen": true, "msg": "…" } }The device is requesting text input. Reply via the kb namespace.
ota{ "ns": "ota", "prop": "progress", "value": { "phase", "status", "percent", "bytes", "total" } }Firmware update progress during an OTA.

Command reference

Commands are grouped by namespace (ns). Unless noted, the response value mirrors the request.

deviceState

Read, write, and subscribe to the device's live state. prop is any state key (see the Device State Reference). Any value that changes is also pushed as an event.

MethodPropertyValueDescription
get<KEY>Read a value, e.g. PLAYER_SHIELD. GET GAME_TIME returns the live game clock rather than the stored field.
set<KEY>new valueWrite a value, e.g. set PLAYER_NAME to a string, or DEVICE_APP_CONNECTED to true. The value is coerced to the key's type; a type mismatch returns invalidValue.

audio

Play and stop audio, and set the master volume.

MethodPropertyValueDescription
setstartTrackfile path (string)Play an audio file, e.g. "/audio/default/pickup.wav".
setmasterVolume0–30Set the master volume.
setstopTracktrack numberStop a playing track.
getisTrackPlayingReturns whether audio is currently playing.

rgb

Drive the addressable RGB LEDs directly.

MethodPropertyValueDescription
setsetAll[[r,g,b,brightness], …]Set every pixel at once. One [r, g, b, brightness] array per pixel.
setsetOne[index,r,g,b,brightness]Set a single pixel by index.

fsm

The device's state machine — its current game / UI state. State transitions are also pushed as events.

MethodPropertyValueDescription
getstateReturns the current state name, e.g. HOME, IN_GAME, DEAD.
setstatestate nameForce a state transition (advanced — most integrations only read this).

wifi

WiFi used by the device for firmware updates.

MethodPropertyValueDescription
setcredentials{ ssid, password }Store the WiFi network the device should use for OTA updates.
getchannelCurrent radio channel.

provisioning

Fleet grouping and firmware-update triggers.

MethodPropertyValueDescription
setgroupgroup name (string)Assign this device to a named update group. Group update triggers only affect devices in the same group.
setcheckUpdateCheck this device for a firmware update AND broadcast the trigger to every device in the same group over the mesh.
setcheckUpdateSelfCheck only this device for a firmware update (no mesh broadcast).

kb

On-screen keyboard. When the device needs text it emits a kb event; reply with the text.

MethodPropertyValueDescription
setvaluestringSupply the text the device requested via a kb event.

Advanced

Lower-level namespaces used internally by the official app. Included for completeness.

MethodPropertyValueDescription
getscreenController · currentScreenNameThe name of the UI screen currently shown.
setesp-bridge · enabledbooleanRelay ESP-NOW mesh traffic over the BLE event channel.
setirSender · 1 / 2Fire IR emitter 1 or 2.

Worked example

Read the player's current ammo, then halve it:

// request  -> CMD_IN
{ "method": "get", "ns": "deviceState", "prop": "WEAPON_AMMO", "id": "1" }

// response <- CMD_OUT
{ "status": "ok", "ns": "deviceState", "prop": "WEAPON_AMMO", "value": 48, "id": "1" }

// request  -> CMD_IN
{ "method": "set", "ns": "deviceState", "prop": "WEAPON_AMMO", "value": 24, "id": "2" }

// response <- CMD_OUT
{ "status": "ok", "ns": "deviceState", "prop": "WEAPON_AMMO", "id": "2" }

// ...and because the value changed, an event arrives on EVENTS_OUT:
{ "ns": "deviceState", "prop": "WEAPON_AMMO", "value": 24 }