BotDeviceMessage bot.device-message@1
Generated at from
openvibe-contracts v0.97.0 and
openvibe-sdk v0.26.0.
- Version
- 1.0.0
- Owner
- bot
- Visibility
- first-party
- Status
- active
- Compatibility
- backward
- Decision
- ADR-043
- Schema
https://openvibe.network/contracts/bot/device-message.v1.json
bot.device-message@1 (ADR-043 decision 5): one frame on OpenVibe.Bot's device WebSocket (wss://openvibe.bot/device), JSON with v, seq and ts on every frame. Server to device: hello, config, command, estop, heartbeat_ack, error, paired (after a pair frame), rotate (a Network-paired machine is asked to rotate its credential with Network). Device to server: pair (the only frame an unauthenticated socket may send), status, telemetry, ack, nack, heartbeat, reauth (Network-paired machines), estop_state. The job frames on the same socket are platform.job-frame@1, not this contract. This duplicates two implementations that must not drift: OpenVibe.Bot server/realtime.js (the sender and reader in Bot) and OpenVibe.Node internal/protocol/protocol.go (the Go structs of the device agent).
Fields
This schema has no named fields.
Examples
From the contract's own test fixtures: valid ones validate, rejected ones must fail.
Valid: command
{
"v": 1,
"seq": 3,
"ts": 1759600000003,
"type": "command",
"id": "cmd_01J8Z4Q9V5X1Z3BD6P9S2T5W7Y",
"ref": "op-7",
"kind": "drive",
"value": {
"throttle": 0.5,
"steer": 0
},
"deadline_ms": 1759600000300,
"operator": {
"subject": "usr_01J8Z4P7T3W9Y1AC5N8R0S4V6X",
"role": "owner"
},
"robot_id": "rob_01J8Z4M2Q0R7T9YV3K6N8P1W2X"
}Valid: config
{
"v": 1,
"seq": 2,
"ts": 1759600000002,
"type": "config",
"heartbeat_ms": 1000,
"limits": {
"max_speed": 0.6,
"max_turn": 1,
"max_command_ms": 300,
"heartbeat_ms": 1000
},
"allowed_commands": [
"drive",
"actuator",
"halt"
],
"estop_latched": false
}Valid: hello
{
"v": 1,
"seq": 1,
"ts": 1759600000001,
"type": "hello",
"session_id": "ses_1",
"device_id": "dev_01J8Z4N5S2V8X0ZB4M7Q9R3T5W",
"robot_ids": [
"rob_01J8Z4M2Q0R7T9YV3K6N8P1W2X"
],
"server_time": "2026-10-04T12:00:00.000Z"
}Valid: nack
{
"v": 1,
"seq": 5,
"ts": 1759600000005,
"type": "nack",
"id": "cmd_01J8Z4Q9V5X1Z3BD6P9S2T5W7Y",
"fault_code": "estopped",
"message": "the remote e-stop is latched"
}Valid: node-status
{
"v": 1,
"seq": 4,
"ts": 1759600000004,
"type": "status",
"firmware": "0.1.2",
"capabilities": {
"adeept_adr036": {
"drive": true
}
},
"agent_version": "0.1.2",
"device_kind": "onboard",
"os": "linux",
"arch": "arm64",
"drivers": [
{
"name": "adeept_adr036",
"driver": "pca9685",
"version": "0.1.2",
"state": "running"
}
],
"faults": [],
"estop_latched": false,
"local_stop": false,
"video": "whip"
}Valid: paired-without-video
{
"v": 1,
"seq": 1,
"ts": 1759600000001,
"type": "paired",
"device_id": "dev_01J8Z4N5S2V8X0ZB4M7Q9R3T5W",
"credential": "example-credential-shown-once",
"video": "not_configured",
"robot_ids": [
"rob_01J8Z4M2Q0R7T9YV3K6N8P1W2X"
],
"profile_id": "sim.rover",
"profile": {
"id": "sim.rover",
"version": 1,
"name": "Simulated rover",
"vendor": null,
"kind": "server",
"description": null,
"capabilities": [
"drive.differential",
"camera"
],
"variants": null,
"mapping": {
"driver": "sim"
},
"commands": {
"drive": {
"axes": {
"throttle": [
-1,
1
],
"steer": [
-1,
1
]
}
},
"say": {
"max_chars": 200
},
"halt": {}
},
"widgets": [
{
"type": "drive",
"capability": "drive.differential",
"label": "Drive",
"order": 1,
"command": {
"kind": "drive"
}
},
{
"type": "camera",
"capability": "camera",
"order": 2
}
],
"camera": null,
"limits": {
"max_speed": 1,
"max_turn": 1,
"max_command_ms": 300,
"heartbeat_ms": 1000
}
}
}Valid: rotate
{
"v": 1,
"seq": 9,
"ts": 1759600000009,
"type": "rotate"
}Valid: telemetry
{
"v": 1,
"seq": 6,
"ts": 1759600000006,
"type": "telemetry",
"battery": {
"volts": 7.6,
"percent": 81
},
"sensors": {
"distance_cm": 42
},
"events": [
{
"name": "low_battery",
"ts": 1759600000006
}
]
}Rejected: ack-extra-field
{
"v": 1,
"seq": 7,
"ts": 1759600000007,
"type": "ack",
"id": "cmd_1",
"result": "ok"
}Rejected: job-frame
{
"v": 1,
"seq": 8,
"ts": 1759600000008,
"type": "job_started",
"id": "job_01J8Z4Q9V5X1Z3BD6P9S2T5W7Y",
"started_ms": 1
}Rejected: no-seq
{
"v": 1,
"ts": 1759600000000,
"type": "heartbeat",
"t": 5
}Rejected: unknown-kind
{
"v": 1,
"seq": 3,
"ts": 1759600000003,
"type": "command",
"id": "cmd_1",
"kind": "fly"
}Validate
const contracts = require('openvibe-contracts');
contracts.validate('bot.device-message@1', value); // { valid, errors: [{ path, message }] }