生命周期
- 设备进入推送模式后主动连接 `/api/device/session`。
- 服务器分配 4 位数字短期设备码,并给该码 30 分钟 TTL。
- 用户在网站输入设备码,把一个或多个 badge job 加入队列。
- 设备轮询 `/api/device/queue`,下载 `imageUrl`,显示后 ACK。
- TTL 到期或设备重新注册后,旧码不能继续接收任务。
- 设备轮询收到 400/404 时丢弃本地码,并重新注册领取新码。
device integration contract
overview
网站和设备之间只共享短期设备码、队列任务和素材 URL。第一版走 HTTP/JSON,USB/BLE 用 newline-delimited JSON 命令帧,后续二进制分片可以在同一命令族里扩展。
设备没有保存 Wi-Fi 时开启热点 `Badge-xxxxxx`,密码 `badge1234`。用户连上后访问 `http://192.168.4.1`,写入 `ssid`、`password`、`serverBase`。如果已保存 Wi-Fi 但服务器连不上,屏幕会显示推送服务不可用并提示检查 Wi-Fi/服务器地址。
POST http://192.168.4.1/api/config首次注册不带 `code`,服务器负责分配;续期时设备可以带上当前 `code`。
{
"deviceId": "m5-001122334455",
"model": "m5stack-stopwatch",
"firmwareVersion": "0.1.0",
"capabilities": {
"width": 466,
"height": 466,
"shape": "round",
"formats": ["png", "webp"],
"transports": ["wifi", "usb-serial", "ble-gatt"]
}
}POST /api/device/session设备屏幕显示响应里的 `code`,网站只需要用户手动输入这个短期码。
{
"ok": true,
"data": {
"code": "0427",
"expiresAt": "2026-05-24T12:30:00.000Z"
}
}{
"code": "0427",
"jobs": [{
"title": "Neon badge",
"format": "png",
"animation": "static",
"width": 466,
"height": 466,
"imageDataUrl": "data:image/png;base64,..."
}]
}POST /api/device/queue设备按 `code` 和 `deviceId` 拉取任务。服务端会把 `queued` 标记为 `delivered`,设备显示成功后再 ACK。
GET /api/device/queue?code=0427&deviceId=m5-001122334455设备完成下载和显示后回传任务 ID,服务端标记 `acked`。
PATCH /api/device/queue{"code":"0427","jobId":"job-id"}URL 模式写入一行 JSON,设备再下载 `imageUrl`。ESP-IDF 固件额外支持离线 PNG:先写 begin JSON,再直接写 PNG bytes。
{"type":"badge.push.v1","payload":{"title":"Badge","format":"png","animation":"static","width":466,"height":466,"imageUrl":"https://..."}}{"type":"badge.usb.image.begin.v1","payload":{"title":"Badge","format":"png","animation":"static","width":466,"height":466,"size":123456}}
<raw PNG bytes follow immediately>当前保留 UUID 合约,后续需要加分片、CRC 和 notify 进度。
service 6f7d0001-2b44-46d8-8d52-bad600000001write 6f7d0002-2b44-46d8-8d52-bad600000001