Box2Robot — Robotic Arm Control Skill
Control ESP32-based robotic arms through a cloud server API. Move servos, record trajectories, calibrate, capture images, voice interaction, and orchestrate AI training/inference — all from a single CLI.
Official skill published by the Box2Robot team (https://robot.box2ai.com).
Safety & Supervision
This skill controls physical robotic hardware and camera/microphone peripherals.
- Human supervision required: Do NOT run autonomously without operator oversight. Servo torque and motion commands cause physical movement that could injure people or damage objects.
- Destructive operations (
device.factory_reset, device.wifi_clear, calibrate.center_offset) require explicit user confirmation before execution.
- Privacy-sensitive operations (
camera.snapshot, camera.voice_start, camera.record_audio_start) access camera and microphone — only invoke with user consent.
- No OS shell access: The
exec command routes named Actions through the HTTP API (e.g., exec servo.move). The shell command is an interactive REPL that dispatches CLI subcommands — neither executes arbitrary OS commands. All operations are HTTP requests to B2R_SERVER.
- Token sensitivity:
~/.b2r_token stores a JWT that grants device control. Treat it like an SSH key. Delete it when no longer needed.
Credential Flow
login → POST /api/auth/login → JWT token
→ saved to ~/.b2r_token (mode 0600, owner-only)
→ all subsequent commands use this token automatically
→ override with B2R_TOKEN env var
→ delete ~/.b2r_token to revoke
All network calls go exclusively to B2R_SERVER (default: https://robot.box2ai.com). No other endpoints are contacted.
Setup
# Install dependency
pip install aiohttp
# Login (one-time, token cached to ~/.b2r_token)
python b2r.py login <username> <password>
# Or set environment variables
export B2R_SERVER="https://robot.box2ai.com"
export B2R_TOKEN="<jwt_token>"
export B2R_DEVICE="B2R-XXXXXXXXXXXX"
CLI Quick Reference
Device & Status
b2r.py devices # List devices (* = online)
b2r.py status # Servo positions, load, temperature
Servo Control
b2r.py torque on # Lock servos
b2r.py torque off # Release (allows manual dragging)
b2r.py home # Safe return to home position
b2r.py move <servo_id> <pos> [spd] # Move a single servo
# Position: 0-4095 (center 2048), Speed: 0-4000 (default 1000)
Recording & Playback
b2r.py record start # Start recording
b2r.py record stop [name] # Stop and save
b2r.py play # List all trajectories
b2r.py play <traj_id> # Play a trajectory
Camera & Data
b2r.py snapshot # Camera snapshot
b2r.py frame [cam_id] [output.jpg] # Download latest camera frame (JPEG)
b2r.py calibrate [servo_id] # Auto-calibrate (0 = all)
b2r.py download <traj_id> [dir] # Download trajectory images (HTTP GET only)
Action System (79 Actions)
Invoke via b2r.py exec <action_name>. Parameters in JSON or key=value format.
device (Device Management)
| Action | Description |
|---|
device.list | List devices |
device.status | Device status (control mode + servos) |
device.bind | Bind device (requires bind_code) |
device.unbind | Unbind device |
device.rename | Rename device |
device.factory_reset | [DESTRUCTIVE] Factory reset — requires user confirmation |
servo (Servo Control)
| Action | Parameters | Description |
|---|
servo.status | device_id | Read position/load/temperature |
servo.move | device_id, servo_id, position, [speed] | Move single servo |
servo.move_batch | device_id, commands:[{id,position,speed}] | Batch move |
servo.torque | device_id, enable:bool | Toggle torque |
servo.go_home | device_id | Return to home position |
servo.set_id | device_id, old_id, new_id | Burn servo ID |
recording (Recording & Playback)
| Action | Parameters | Description |
|---|
record.start | device_id, [mode], [camera_id] | Start recording (single/dual/phone) |
record.stop | device_id, [name] | Stop recording |
trajectory.list | device_id | List trajectories |
trajectory.play | device_id, trajectory_id | Play trajectory |
trajectory.stop | device_id, trajectory_id | Stop playback |
trajectory.delete | device_id, trajectory_id | Delete trajectory |
pairing (Leader-Follower)
| Action | Parameters | Description |
|---|
pairing.create | leader_id, follower_ids, [use_espnow] | Create pairing |
pairing.disconnect | leader_id | Disconnect |
pairing.connect | leader_id | Reconnect |
pairing.delete | leader_id | Delete pairing |
espnow.discover | — | Scan nearby devices |
calibration
| Action | Parameters | Description |
|---|
calibrate.auto | device_id, [servo_id=0] | Auto-calibrate (0 = all) |
calibrate.manual | device_id, servos:[{id,min,max,mid}] | Manual calibration |
calibrate.center_offset | device_id | Write EEPROM center offset |
camera (Camera & Voice)
Privacy note: Snapshot and voice commands access camera/microphone hardware. Only invoke with user consent.
| Action | Parameters | Description |
|---|
camera.snapshot | device_id | [PRIVACY] Take photo |
camera.stream_mode | device_id, mode | Stream mode (idle/preview/inference) |
camera.voice_start | device_id | [PRIVACY] Enable microphone |
camera.voice_stop | device_id | Disable microphone |
camera.tts | device_id, prompt | Text-to-speech |
training (Training & Inference)
| Action | Parameters | Description |
|---|
training.submit | name, dataset_ids, [model_type] | Submit training job |
training.list | [page] | Job list |
training.deploy | job_id, arm_device_id, gpu_device_id | Deploy inference |
training.stop_inference | job_id | Stop inference |
store (Skill Store)
| Action | Parameters | Description |
|---|
store.list | [search], [category] | Browse store |
store.execute | task_id, device_id | Execute skill |
config (Configuration)
| Action | Parameters | Description |
|---|
config.get | device_id | View config |
config.set | device_id, params:{key:val} | Update config |
config.speed | device_id, speed(100-4000) | Set speed |
config.volume | device_id, volume(0-255) | Volume |
Natural Language
Via b2r.py say "text":
| Input | Maps to |
|---|
| "go home" / "回零位" | servo.go_home |
| "release torque" / "释放力矩" | servo.torque(False) |
| "start recording" / "开始录制" | record.start |
| "take a photo" / "拍照" | camera.snapshot |
| "auto calibrate" / "自动校准" | calibrate.auto |
| "move servo 1 to 2048" | servo.move(1, 2048) |
Preflight Checks
Agents must verify before executing:
| Step | Check | On Failure |
|---|
| 1 | Device online | "Device offline — check power" |
| 2 | Device type = arm | "Not a robotic arm" |
| 3 | Control mode = idle | release_control first |
| 4 | Calibration exists | calibrate.auto first |
| 5 | Servo count matches | Trajectory vs device axis count |
Orchestration Examples
"Teach you to pour water, record 5 demos"
1. torque off
2. camera.stream_mode(cam_id, "preview")
3. Loop 5x:
record.start(mode="single", camera_id)
[user demonstrates]
record.stop(name="pour_water_{n}")
4. training.submit(name="pour_water", dataset_ids)
Visual Inference Loop
1. training.deploy(job_id, arm_id, gpu_id, cam_id)
2. GPU auto-loop: image → inference → command → arm
3. training.stop_inference(job_id)
HTTP API Direct Access
# Login
curl -X POST https://robot.box2ai.com/api/auth/login \
-H "Content-Type: application/json" \
-d '{"username":"xxx","password":"xxx"}'
# Move servo
curl -X POST https://robot.box2ai.com/api/device/B2R-xxx/command \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{"id":1,"position":2048,"speed":1000}'
Environment Variables
| Variable | Description | Default |
|---|
B2R_SERVER | Server URL | https://robot.box2ai.com |
B2R_TOKEN | JWT token (overrides ~/.b2r_token) | — |
B2R_DEVICE | Default device ID | — |