andrewlyeats/roborock-q10-cli
GitHub: andrewlyeats/roborock-q10-cli
一个非官方的 Roborock Q10 扫地机器人 CLI 工具及逆向工程协议文档,解决了从终端和脚本直接驱动纯云端设备的需求。
Stars: 1 | Forks: 0
# Roborock Q10 (B01) — 协议笔记 + 可用的 CLI



这是对 Roborock Q10 S5+ 如何与 Roborock 云端通信进行逆向工程的笔记,并附带了一个 CLI
(`vac.py`)作为其可行的证明。Q10 S5+ 是一款 **“B01”设备:仅限云端**,没有局域网
控制路径;每一条命令都是通过 Roborock 的 MQTT broker(或其 REST API)中转的。
**只想使用你的扫地机器人?** [Home Assistant Roborock 集成][ha] 可能已经
通过 GUI 覆盖了它。这个代码库是为那些想要**理解或扩展 B01 协议**,
或者从终端 / cron / 自己的脚本中驱动扫地机器人的人准备的。
**状态:** 一个个人项目,按原样分享。非官方,无保修,不承诺提供支持 — 请参阅
下方的免责声明。
### 本文档所涵盖的内容(值得阅读的部分)
- **B01 地图格式** — 房间网格是 LZ4 压缩的;路径/位置以 protocol-301
帧的形式到达。端到端解码为带有标签的平面图 — 从帧头读取网格尺寸,
并且每次地图的路径↔网格配准会自动适配(原点并未在数据流中传输)。
→ [DESIGN_NOTES.md](DESIGN_NOTES.md),[`decode_map.py`](decode_map.py)
- **云端写入路径** — 房间清扫和计划任务写入通过 REST `/jobs` 调用进行,该调用需要
**Hawk *body* 签名**;如果弄错了,看起来完全就像“写入不起作用 / token 范围不对”,
但事实并非如此。→ [DESIGN_NOTES.md](DESIGN_NOTES.md)
- **单连接 daemon** — 保持一个 MQTT 连接来处理所有命令,以避免触发
账户级别的 `135` 速率限制,否则该限制会同时锁定 CLI *和* App。→ [DESIGN_NOTES.md](DESIGN_NOTES.md)
- **B01 数据点字典** — 每个数据点的含义及其 payload 如何解码(机器人
发出约 44 个;在 `status` 中仅建模了约 19 个)。→ [DP_DICTIONARY.md](DP_DICTIONARY.md)
已验证与仍待解决的内容范围详见 [CAPABILITIES.md](CAPABILITIES.md)(支持 / 不支持 /
未知)和 [ROADMAP.md](ROADMAP.md)。
## ⚠️ 免责声明
这是一个**非官方的**、社区逆向工程的工具 — **不附属于、不受认可,也不受**
Roborock 支持。它通过 Roborock 云端与你自己的账户通信,并依赖于厂商随时可能更改的未公开
内部机制。**按原样提供,无任何保修,使用风险自负。**
命令是可逆的,并且该项目倾向于安全(例如 `clean-rooms --dry-run` 会发布一个
*已禁用* 的任务),但你要对自己的设备和账户负责 — 不要在无法承受干扰的硬件或
账户上运行它。
## 已测试的硬件
| 项目 | 已测试 |
|---|---|
| 型号 | Roborock Q10 S5+ (`roborock.vacuum.ss07`,B01 协议) |
| 固件 | **最后针对 03.11.24 验证** (2026-06) |
| Python | 3.11 (需要 3.11+) · `python-roborock` 5.14.x |
其他 Roborock 型号**未经测试** — 它们可能共享 B01 协议(在这种情况下,大部分内容
应该可行)或者有所不同。欢迎提供其他型号的报告([CONTRIBUTING.md](CONTRIBUTING.md))。
固件更新可能会与此处记录的内容产生偏差。
## 设置
需要 Python **≥3.11** 以及 `requirements.txt` 中的依赖(python-roborock,lz4,Pillow):
`pip install -r requirements.txt`(或使用 `requirements.lock.txt` 获取确切已知良好的锁定版本)。
首次认证(仅一次):
```
./vac.py login --email you@example.com # emails you a 6-digit code
./vac.py discover # fetches + caches your device list
```
`login` 将 token 保存到 `~/.roborock_vac.json`(已被 gitignore;schema 见
[`credentials.example.json`](credentials.example.json));`discover` 将设备/家庭数据缓存到
`~/.roborock_vac_cache.pkl`,以便后续调用无需重新请求云端。
## Daemon
一个小型后台 daemon 会保持**一个**持久的云端连接,并通过
本地 socket 处理每一条命令,因此命令不会每次都重新连接(也不会触发 `135`)。当有 daemon 运行时,这是
默认路径;如果没有,命令会提示如何启动它。它已**通过实时验证** — 一个保持的
连接在不重新连接的情况下处理了读取、监听和长达一小时的清扫。(具体机制 — 逐步升级的
退避、`--careful` 停止文件、自动 `135` 恢复状态 — 详见
[DESIGN_NOTES.md](DESIGN_NOTES.md)。)
```
./vac.py daemon start --careful # recommended: holds one connection, stops on the first 135/auth complaint
./vac.py daemon status # device, health, last update, taps
./vac.py daemon stop
./vac.py daemon restart # e.g. after `pip install -U python-roborock`
./vac.py status --force # run ONE command standalone (own session; avoid repeating)
```
**遥测监听**(daemon 可以看到整个数据流,因此捕获在其中进行 — 可选,默认关闭):
```
./vac.py daemon record --events ev.jsonl # every decoded data-point
./vac.py daemon record --novel new.jsonl # first-seen DP names (catch new behaviors)
./vac.py daemon record --bytes raw.jsonl # raw frames (incl. binary/map)
./vac.py daemon record --off
```
## 使用方法
日常命令:
```
./vac.py status # battery, state, fan, water, mode, clean time/area (+--json)
./vac.py start | pause | resume | stop | dock | dock-empty | find
./vac.py rooms # list rooms on the current map (id + name)
./vac.py clean-rooms kitchen study # clean only those rooms (full cycle; +--fan/--water/--route/--count)
./vac.py fan turbo # quiet | balanced | turbo | max | max_plus
./vac.py water high # off | low | medium | high
./vac.py mode vac_and_mop # vac_and_mop | vacuum | mop
./vac.py consumables # brush/filter/sensor life counters (+--json)
./vac.py dnd on --start 22:00 --end 08:00 # also: dnd off
# Cloud schedules(通过 REST API 存储在服务器端):
./vac.py schedule list # id · time · rooms · fan/water
./vac.py schedule add --time 09:00 --days mon,wed,fri --rooms kitchen study
./vac.py schedule enable|disable|delete
```
捕获与解码(逆向工程接口):
```
./vac.py watch # live table of the modeled status fields (--out clean.csv for CSV)
./vac.py watch --raw --out clean.jsonl # EVERY decoded data-point, one JSON object per line
./vac.py map # render the labeled floor plan -> map_rooms.png (+ map_path.svg if cleaning)
./vac.py watch --bytes --out cap.jsonl && ./decode_map.py cap.jsonl # low-level: byte capture -> offline decode
./vac.py history --from-capture clean.jsonl # decode the per-clean back-catalog from a capture
./vac.py raw STATUS # send any raw B01 data-point (run `raw BADNAME` to list them)
```
有多个机器人?添加 `--device `(通过 `./vac.py discover` 获取 DUID)。大多数 B01 命令是
即发即忘的(无响应主体);对于没有专用命令的功能,`raw` 是逃生舱口。
## 文件
| 路径 | 用途 |
|---|---|
| `vac.py` | CLI |
| `decode_map.py` | 从 `watch --bytes` 捕获中解码实时地图/路径(包括网格地理配准) |
| `check_roborock_api.py` | 金丝雀测试:验证此工具依赖的 `python-roborock` 内部组件仍然存在(升级后运行) |
| `clean.csv` | 示例 `watch --out` 输出(一次拖地运行;无害的遥测数据,无 PII) |
| [CAPABILITIES.md](CAPABILITIES.md) | 每一项交互,范围明确:支持 / 不支持 / 未知 |
| [DP_DICTIONARY.md](DP_DICTIONARY.md) | 每个数据点的含义 + 解码格式 |
| [DESIGN_NOTES.md](DESIGN_NOTES.md) | 为什么以这种方式工作 + 逆向工程发现 |
| [ROADMAP.md](ROADMAP.md) | 哪些可行,哪些已计划,已知的限制 |
| `credentials.example.json` | `login` 写入 `~/.roborock_vac.json` 的登录文件 schema |
| `~/.roborock_vac.json` · `~/.roborock_vac_cache.pkl` | 登录 token · 缓存的家庭数据(已 gitignore) |
## 已知限制
- **仅限云端。** 此型号(B01 协议)无本地控制。
- **地图。** `vac.py map` 渲染房间网格(颜色编码,带有房间名称标签)。即使在回充时,网格也会继续
流式传输;清扫路径 + 实时位置仅在清扫*期间*流式传输。地理配准:
网格尺寸来自帧头,并且每次捕获的路径↔网格原点(未在流中传输)
都会自动适配 → `map_overlay.png`。障碍物仅限云端(不在此数据中) — 该
库本身并不提供这些内容。
- **房间清扫**(`clean-rooms`)会为指定的房间发起一次性的 REST `/jobs` 清扫;
`--dry-run` 会发布一个无效的*已禁用*任务。一个完整的周期(出仓 → 清扫 → 回充 → 充电)已
通过实时验证。任务会在大约 2 分钟后触发(已计划,并非立即执行)。详见 [DESIGN_NOTES.md](DESIGN_NOTES.md)。
- **结构化地图变更为只读** — 虚拟墙、禁扫/禁拖区、房间
拆分/合并/重命名可以解码,但无法从这里进行设置。
- **某些设置以云端为准**(音量 / 童锁 / 增强 / 勿扰) — 写入可能会回滚;
请在 App 中更改这些设置。运行时设置(风机/水量/模式)会保留。
- **耗材**显示已使用小时数 + 剩余百分比%(已与 App 确认:主刷 300 小时 / 边刷 200 小时 /
滤网 150 小时)。
## 构建于 / 相关项目
这是一个建立在他人工作基础之上的非官方 CLI + daemon — 完整致谢见 [CREDITS.md](CREDITS.md):
- [python-roborock][pr] — 此项目依赖的库。
- [Home Assistant Roborock 集成][ha] — daemon 所遵循的单连接协调器模式。
- [local_roborock_server](https://github.com/Python-roborock/local_roborock_server) /
[Valetudo](https://github.com/Hypfer/Valetudo) — 如果你想要一个完整的*本地*云端替代方案。
- [XiaomiRobotVacuumProtocol](https://github.com/marcelrv/XiaomiRobotVacuumProtocol),
[dustcloud](https://github.com/dgiese/dustcloud) — 协议逆向工程的脉络。
## 贡献与许可
欢迎做出贡献 — 特别是来自其他 Roborock 型号的报告
([CONTRIBUTING.md](CONTRIBUTING.md))。在对真实的机器人进行测试之前,请阅读上方的
**温和对待云端** 说明以及 [DESIGN_NOTES.md](DESIGN_NOTES.md)。基于 [MIT 许可证](LICENSE) 授权。
## 在 AI 辅助下构建
在人类指导下使用 AI 编码助手(Anthropic 的 Claude Opus 4.8 和 Claude Sonnet 4.6)开发 —
包括代码、逆向工程和文档。人类审查了这项工作,并在真实设备上运行了所有的实时
测试。详见 [CREDITS.md](CREDITS.md)。
标签:Python, 无后门, 智能家居, 机器人, 物联网, 逆向工具