BBadgeOS国漫电子吧唧创作与推送

overview

设备码推送协议

网站和设备之间只共享短期设备码、队列任务和素材 URL。第一版走 HTTP/JSON;USB 支持 newline-delimited JSON URL 模式和 begin/ready/raw PNG 离线二进制模式。

生命周期

  1. 设备从 Home > Settings > Push Mode 进入推送模式后主动连接 /api/device/session。
  2. 服务器分配 4 位数字短期设备码,并给该码 30 分钟 TTL。
  3. 用户在网站输入设备码,把一个或多个 badge job 加入队列。
  4. 设备轮询 /api/device/queue,下载 imageUrl,显示后 ACK。
  5. 退出推送模式会停止队列轮询,并回到 Settings;再次返回才是 Home 三项菜单。
  6. TTL 到期或设备重新注册后,旧码不能继续接收任务。
  7. 设备轮询收到 400/404 时丢弃本地码,并重新注册领取新码。

AP 配网

设备没有保存 Wi-Fi,或用户打开 Settings 里的 Wi-Fi 菜单时,会开启热点 Badge-xxxxxx,密码 badge1234。用户连上后访问 http://192.168.4.1,只写入 ssid、password;同名 SSID 会更新并置顶。Wi-Fi 记录保存在 badge FAT/TF 的 system/wifi.json,密码不是明文,而是用设备 MAC 和固件盐派生密钥后加密。serverBase 由固件编译期常量固定,AP 和 USB 配网都会忽略外部传入值。串口状态会返回 wifiNetworkCount、pushModeActive、provisioning、apSsid、apPassword。

POST http://192.168.4.1/api/config{"type":"badge.config.wifi.clear.v1","payload":{}}

注册请求

首次注册不带 code,服务器负责分配;续期时设备可以带上当前 code。

{
  "deviceId": "waveshare-175g-001122334455",
  "model": "waveshare-esp32-s3-touch-amoled-1-75-g",
  "firmwareVersion": "0.3.0",
  "capabilities": {
    "width": 466,
    "height": 466,
    "shape": "round",
    "formats": ["png", "webp"],
    "transports": ["wifi", "usb-serial-binary"]
  }
}
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=waveshare-175g-001122334455

ACK

设备完成下载和显示后回传任务 ID,服务端标记 acked。

PATCH /api/device/queue
{"code":"0427","jobId":"job-id"}

随机图片

/api/device/random 只做设备型号、尺寸和格式筛选。设备请求带 deviceId 时直接返回 200 image/png,不带 deviceId 的调试请求仍返回 307 临时重定向到静态图片 URL。1.75-G 默认只预览随机图;Settings 里的 Save to Local 打开后才保存到本地。

GET /api/device/random?model=waveshare-esp32-s3-touch-amoled-1-75-g&deviceId=waveshare-175g-001122334455&width=466&height=466

USB 帧

URL 模式写入一行 JSON,设备再下载 imageUrl。ESP-IDF 固件额外支持离线 PNG:先写 begin JSON,等设备返回 usb_image_ready,再写 PNG bytes,最终等待 usb_image_displayed,失败时会返回 usb_image_not_saved 等错误。

{"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}}
<wait for {"ok":true,"message":"usb_image_ready",...}>
<write exactly 123456 raw PNG bytes>

U 盘模式

1.75-G 带 TF 卡槽;没有 TF 卡时固件使用内置 flash。U 盘模式进入后会优先使用可用的 TF 存储,否则回退到内置 flash。

system/ui/home.png · settings.png · status.png · push.png{"type":"badge.config.usbDisk.v1","payload":{}}

UI 模版文件

UI kit 的 XML 和 PNG 素材落在 /badge/system/ui/templates。主机可以先清理旧平台模版,再用受限 USB 二进制帧逐个写入模版文件;路径只允许 active.txt 或 <template-id>/<file>,用于安装 assets/ui-templates 里的裁切素材。

{"type":"badge.ui.template.cleanup.v1","payload":{}}
<wait for {"ok":true,"message":"ui_template_cleanup_done",...}>
{"type":"badge.ui.template.file.begin.v1","payload":{"path":"ink-black-cat/atlas-system-status.png","size":12345}}
<wait for {"ok":true,"message":"ui_template_file_ready",...}>
<write exactly 12345 raw file bytes>
{"type":"badge.ui.template.v1","payload":{"template":"ink-black-cat"}}

动画包交付

包含 scene/delta 的动画 badge 统一导出为 .badmotion.zip 包。Wi-Fi 队列和 USB 串口都按 badge-motion-v1 传输完整动画包;StopWatch 优先使用 USB 直连。

format: badge-motion-package-v1target: /badges/<motion-id>/