WebSocket API
Boppo exposes a WebSocket API at wss://boppo-<SERIAL_NUMBER>.local/ws for real-time control of lights, audio, and button event streaming.
Connecting to this endpoint automatically starts the websocket_server activity on the Boppo tablet (and stops any currently running activity). Only one WebSocket session is active at a time, a new connection closes any existing connection.
If you are looking to develop an activity using the WebSocket API, you can use an existing library that implements the protocol below.
- Rust:
boppo_websocket
The API defined below is the low level networking protocol:
Authentication
The WebSocket upgrade request must include an Authorization HTTP header:
Authorization: Bearer <password>
Connections without a valid token are rejected immediately.
The device uses a self-signed TLS certificate. See the HTTPS documentation for details.
Messages: Device → Client
All messages are UTF-8 encoded text frames and are sent as a single frame without fragmentation.
Button Event
The device sends a text frame whenever a top button is pressed or released:
button <index> <p|r> <currently_pressed>
<index>— zero-based button index (0–9)p— button pressedr— button released<currently_pressed>— a bit set of each of the top 10 buttons encoded as hex where each bit represents a button (1 = pressed, 0 = released)
Example: button 3 p 9 means button index 3 was pressed and button 0 was already pressed
Sound Finished
The device sends a text frame whenever a sound within a Controller finishes playing:
sound_finished <controller_id>
<controller_id>— theidof the controller from the SoundInstruction
Error Message
An error message from the device. These are unstructured and can be logged to aid in debugging.
error_message <message>
<message>— the error message text
Messages: Client → Device
All messages are sent as a single WebSocket frame (all text except set_lights which is binary). Fragmented messages are not supported. Messages are limited to 256 bytes.
set_lights
Sets the color of all 40 lights at once.
set_lights <120 bytes>
The frame begins with the ASCII prefix set_lights (note the trailing space) followed immediately by 120 bytes of raw RGB data — 3 bytes per light (red, green, blue), for all 40 lights in order. See Button Layout for the light ordering.
Because the payload contains raw binary after the ASCII prefix, this message should be sent as a binary WebSocket frame.
play_sound
Plays a sound described by a SoundInstruction encoded in JSON.
play_sound <json>
The frame is play_sound (with a trailing space) followed by a SoundInstruction JSON.
The path (if any) is relative to /sd/activities/user/.
To receive sound_finished notifications or to control a sound with set_sound_param, wrap it in a Controller SoundInstruction with an id.
Example — play a file:
play_sound "my_activity/beep.wav"
Example — play a controllable looping sound:
play_sound {"i": "controller", "sound": {"i": "repeat", "sound": "my_activity/music.wav"}, "id": 1, "volume": 0.8}
See the SoundInstruction reference for the full format.
set_sound_param
Modifies a currently playing sound that was started with a Controller SoundInstruction.
set_sound_param <json>
The frame is set_sound_param (with a trailing space) followed by a JSON object:
| Field | Type | Required | Description |
|---|---|---|---|
controller_id | number | Yes | The id of the controller from the SoundInstruction |
pause | boolean | No | Pause or unpause the sound |
stop | boolean | No | Set to true to stop and discard the sound |
volume | number | No | New volume multiplier |
speed | number | No | New playback speed multiplier |
Example — pause a sound:
set_sound_param {"controller_id": 1, "pause": true}
Example — stop a sound:
set_sound_param {"controller_id": 1, "stop": true}
stop_all_sounds
Stops all currently playing sounds and clears all tracked sound IDs.
stop_all_sounds
This command takes no arguments.
execute_command
Executes a system command on the device. See Commands for a list of available commands.
execute_command <command>
<command>— the command line to execute