2alf/iM.Master-SDK

GitHub: 2alf/iM.Master-SDK

通过逆向工程 BLE 协议实现的 Python 机器人控制 SDK,支持本地 LLM 与视觉的自主驾驶扩展。

Stars: 3 | Forks: 0

# iM.Master SDK ### 用于逆向工程的 BLE 机器人的 Python SDK。 **使用 Python 驾驶 iM.Master 机器人。**
无需官方应用,无需配对,无需连接云端。 如果你愿意,可以把方向盘交给本地 LLM,并给它装上眼睛。 [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE) [![Python 3.10+](https://img.shields.io/badge/python-3.10%2B-blue.svg)](https://www.python.org/downloads/) [![Platform](https://img.shields.io/badge/robot%20control-Raspberry%20Pi-c51a4a.svg)](docs/BLUETOOTH.md) [![Protocol](https://img.shields.io/badge/BLE%20protocol-reverse%20engineered-brightgreen.svg)](docs/BLUETOOTH.md) [![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg)](CONTRIBUTING.md) hero
## 目录 - [这是什么?](#what-is-this) - [核心亮点](#highlights) - [安装](#install) - [快速入门:使用 Python 驾驶](#quickstart-drive-from-python) - [教程:AI 扩展插件完整流程](#tutorial-the-ai-addon-start-to-finish) - [选择你的 LLM 后端](#choosing-your-llm-backend) - [支持哪些机器人?](#which-robots-does-this-work-with) - [SDK 逐模块详解](#the-sdk-module-by-module) - [通信协议](#the-protocol) - [项目结构](#project-layout) - [测试](#testing) - [故障排除](#troubleshooting) - [贡献指南](#contributing) - [安全与负责任地使用](#safety-and-responsible-use) - [许可证](#license) ## 这是什么? iM.Master 是一款玩具机器人,出厂时只提供了一个手机应用。没有遥控器, 没有 API,也没有文档。本 SDK 剖析了其应用使用的蓝牙通信机制,并在 Python 中重建了 整个控制链路,让你可以通过代码驾驶机器人: ``` from immaster.robot import Robot with Robot() as bot: bot.for_duration("forward", 2.0) # forward for 2 seconds, then auto-stop bot.spin_cw() # spin in place bot.stop() ``` 所以这里的核心是一个纯粹的 Python 机器人接口。核心代码没有任何 依赖,完全使用纯粹的标准库。 此外还有一个可选的 AI 扩展插件。比如,将一部旧手机作为摄像头对准机器人, 在 Pi 上运行目标检测,然后让一个轻量级的本地 LLM 决定如何 移动。机器人可以自己去找一个杯子并开过去,而所有这些都直接在 设备上运行。
The core SDK drives the robot body from Python; the optional AI addon (camera, detector, local LLM) is a layer on top that calls the same Robot API.
## 核心亮点 - 🔓 **真正的逆向工程协议。** 蓝牙低功耗 (BLE) 传统广播,company id `0x53A6`,带有 popcount 校验和的 14 字节差速驱动帧。解码自 真实的抓包数据,并完整记录在 [docs/BLUETOOTH.md](docs/BLUETOOTH.md) 中。 - 🐍 **纯粹的 Python API。** `Robot().forward()`、`spin_cw()`、`for_duration(...)`。 支持命名动作、直接车轮控制以及连续驾驶。 - 🛡️ **安全看门狗。** 如果你的控制循环卡死或崩溃,机器人会自动停止, 而不是一头撞到墙上。 - 🧩 **零依赖核心。** 协议与机器人控制仅使用标准 库。AI 扩展功能均为按需启用。 - 🔌 **可插拔组件。** LLM 后端、摄像头和检测器分别是一个 微型接口,因此你可以接入 Ollama 或 llama.cpp,使用手机或 Pi Camera。 - 💻 **无硬件也能运行。** `DryRobot` 和 `IMMASTER_DRY_RUN=1` 让你能 在笔记本电脑上运行整个流程,甚至包括 LLM 循环。
robot spinning in circles (freed bot is a happy-spinny bot!) ## 安装 你可以使用 pip:(请在 [PyPI](https://pypi.org/project/immaster-sdk/0.1.0/) 上确认版本) ``` pip install immaster-sdk ``` 或者克隆本代码仓库。 ``` git clone https://github.com/2alf/immasterSDK.git cd immasterSDK pip install -e . # core SDK: pure standard library, no dependencies pip install -e ".[vision]" # optional AI addon (Pillow + numpy for camera/detection) pip install -e ".[dev]" # tests ``` ## 快速入门:使用 Python 驾驶 ### 1. 构建和解码数据帧(在任何地方,无需硬件) ``` from immaster.protocol import build_frame, decode_frame, Wheel build_frame(Wheel.FWD, Wheel.FWD).hex() # 'ae4a0700000000c50000c504c399' (forward) decode_frame(bytes.fromhex('ae4a0700000000c90000c904c399')) # (Wheel.REV, Wheel.FWD) (spin) ``` ### 2. 驾驶机器人(在 Pi 上,以 root 身份) ``` from immaster.robot import Robot with Robot() as bot: bot.for_duration("forward", 2.0) # scripted: forward for 2s, then auto-stop bot.spin_cw() # continuous: keeps spinning... bot.keepalive() # ...refresh the watchdog to hold it bot.set_wheels(1, 0) # raw per-wheel control (left fwd, right stop) bot.stop() ``` 请以 root 身份运行,因为原始 BLE 需要它: ``` sudo -E python3 my_script.py ``` 移动是带状态且连续的。像 `spin_cw()` 这样的调用会设置当前的 指令并立即返回,同时后台线程会持续广播该指令。如果在大约 1.5 秒内没有任何指令刷新,看门狗就会让机器人停止。 命名动作包括 `forward`、`reverse`、`spin_cw`、`spin_ccw`、`veer_left`、 `veer_right`、`back_left`、`back_right` 和 `stop`。每个轮子只有开启、关闭或 反转状态,没有比例速度。这是机器人的协议决定的, 而不是 SDK 的限制。 ### 3. 使用本地 LLM 驾驶 不需要摄像头或任何视觉硬件也能让模型来驾驶。这是完整的 AI 循环,只需大约 15 行代码,使用 [Ollama](https://ollama.com) 或任何其他 后端: ``` import json from immaster.robot import Robot from immaster.llm import make_llm from immaster import agent llm = make_llm("ollama") # or "hailo" / "openai" messages = [{"role": "system", "content": agent.SYSTEM_PROMPT}, {"role": "user", "content": "Goal: drive forward briefly, then spin. First action?"}] with Robot() as bot: for _ in range(8): reply = llm.chat(messages) action = agent.parse_action(reply) # pull one JSON action out of the reply if not action: continue result = agent.dispatch_action(bot, action) # execute it on the robot messages += [{"role": "assistant", "content": reply}, {"role": "user", "content": f"Result: {json.dumps(result)}. Next action, or stop."}] if action.get("action") == "stop" or action.get("tool") == "stop": break ``` 在此基础上添加摄像头和检测器,你就可以实现下一节中完整的“感知-思考-行动”循环。 ## 教程:AI 扩展插件完整流程 这是本项目进行过的完全端到端的实际设置:将一部旧手机作为机器人的 眼睛,在 Pi 上进行目标检测,由一个轻量级的本地 LLM 负责选择动作。
The see-think-act loop: the camera grabs a frame, the detector labels objects, the local LLM picks a move, the robot executes it, and the loop repeats.
**你需要准备什么** - iM.Master 机器人 🤖 - 运行 Raspberry Pi OS (64 位) 的 Raspberry Pi。机器人控制仅限 Linux 系统。 - 一个摄像头,例如带有 IP 摄像头应用的旧手机(Android 或 iOS)。本项目使用 Android 上的 [IP Webcam](https://play.google.com/store/apps/details?id=com.pas.webcam) 构建。 - 本地 LLM 运行环境:[Ollama](https://ollama.com)(最简单)或 Hailo-Ollama。 - 可选,用于目标检测的:Hailo AI HAT+2 (Hailo-10H) 并安装了 Hailo SDK。 没有它,你仍然可以像 [快速入门步骤 3](#quickstart-drive-from-python) 中那样进行仅 LLM 驾驶。 **步骤 1. 将代码下载到 Pi 上** ``` git clone https://github.com/2alf/immasterSDK.git cd immasterSDK python3 -m venv .venv && source .venv/bin/activate pip install -e ".[vision]" ``` **步骤 2. 确认你可以驾驶机器人(尚不涉及 AI)** ``` sudo -E python3 -c "from immaster.robot import Robot; b=Robot(); b.for_duration('forward',1.5); b.close()" ``` 机器人应该会向前行驶约 1.5 秒然后停止。如果没有,请在添加任何其他东西之前查阅 [故障排除](#troubleshooting)。 **步骤 3. 将手机变成机器人的眼睛** 1. 安装一个 IP 摄像头应用并启动其服务器。记下快照 URL。对于 IP Webcam,地址为 `http://:8080/shot.jpg`(如果你设置了登录,请添加 `user:pass@`)。 2. 将手机安装在机器人上,面向前方。 3. 从 Pi 测试视频流: ``` export IPCAM_URL="http://user:pass@:8080/shot.jpg" python3 -c "from immaster.camera import IPCamera; print('got', len(IPCamera().capture() or b''), 'bytes')" ``` 返回的字节数不为零说明视觉系统正常。 **步骤 4. 在 Pi 上部署大脑 (Ollama)** ``` curl -fsSL https://ollama.com/install.sh | sh ollama pull qwen2.5:1.5b ``` 更倾向于在 Hailo NPU 上运行模型?请参考 [选择你的 LLM 后端](#choosing-your-llm-backend)。 **步骤 5. 在 Hailo NPU 上进行目标检测(可选)** YOLO 检测使用 HailoRT (`hailo_platform`) 外加一个 YOLO `.hef` 模型。它们都包含 在 Hailo SDK 中(`sudo apt install hailo-h10-all`)。默认的模型路径是 `/usr/share/hailo-models/yolov11m_h10.hef`(可通过 `HAILO_HEF` 覆盖)。这是 唯一一个不在 PyPI 上的组件。没有 Hailo 硬件?请改用 [快速入门步骤 3](#quickstart-drive-from-python) 中的仅 LLM 驾驶。 **步骤 6. 干跑整个循环(不产生实际移动)** ``` IMMASTER_DRY_RUN=1 python3 -m examples.find_and_go --backend ollama "find a cup" ``` 你将看到检测结果和模型选择的动作打印在终端上, 而不会碰到机器人。这是在机器人真正开动之前,检查摄像头、检测器和 LLM 是否能顺利通信的好方法。 **步骤 7. 真正运行驾驶** ``` sudo -E python3 -m examples.find_and_go --backend ollama --voice --monitor \ "find a cup and go to it" ``` - 在手机上打开 `http://:8090` 并点击 *Enable voice* 听机器人 进行语音播报。 - `Ctrl+C` 随时可以干净地停止程序,并且机器人最终一定会处于停止状态。 就这样:一个能够看见、决策并自动驾驶的廉价离线玩具。 ## 选择你的 LLM 后端 大脑是可以替换的。你不会被锁定在一个运行环境上。使用 `--backend`(或 `LLM_BACKEND` 环境变量)进行选择: ``` python3 -m examples.find_and_go --backend ollama "find a cup" # real Ollama (CPU/GPU) python3 -m examples.find_and_go --backend hailo "find a cup" # a model on the Hailo NPU python3 -m examples.find_and_go --backend openai "find a cup" # llama.cpp / LM Studio / vLLM ``` 在代码中也是同样的逻辑: ``` from immaster.llm import make_llm llm = make_llm("hailo") # or "ollama", or "openai" reply = llm.chat([{"role": "user", "content": "..."}]) ``` | 后端 | 目标平台 | 默认 endpoint | 环境变量覆盖 | |---------|---------|------------------|--------------| | `ollama` | 真实的 Ollama (CPU/GPU) | `http://localhost:11434` | `OLLAMA_HOST`, `LLM_MODEL` | | `hailo` | Hailo-Ollama(模型在 NPU 上) | `http://localhost:8000` | `HAILO_HOST`, `LLM_MODEL` | | `openai` | llama.cpp / LM Studio / vLLM | `http://localhost:11434/v1` | `LLM_BASE`, `LLM_MODEL`, `LLM_API_KEY` | Ollama(CPU 或 GPU)和 Hailo-Ollama(NPU 上的模型)都享有同等的优先支持。本 项目最初在 Hailo-Ollama 上运行,后来也在真实的 Ollama 上运行过,两者均可正常工作。`openai` 涵盖了任何兼容 OpenAI 的本地服务器。需要未列出的运行环境? 在 [`immaster/llm.py`](immaster/llm.py) 中继承 `LLMBackend` 类,实现 `chat()`, 并进行注册即可。 ## 支持哪些机器人? 该协议是从某一台实体机器人中解码出来的,所以这里如实说明其适用范围: - **相同产品型号:几乎肯定兼容。** 控制方案存在于 机器人的固件中。它具有固定的 BLE company id(`0x53A6`)、固定的帧结构, 以及无需配对、无设备地址的无连接广播。任何使用相同固件的 机器人都会对相同的数据帧做出反应。这里的任何内容都与具体设备的序列号或 MAC 地址无关。 - **一个副作用。** 由于这是无目标的广播,它会同时驱动 BLE 范围内的 该型号的所有机器人。无法做到只与其中一台通信。这是 该玩具本身的工作原理,而非此处的 bug。 - **不同个体间的差异。** 车轮方向,即哪个电机是“左”, 以及前进方向是否真的是向前。如果你的机器人行驶方向相反或镜像,请翻转 [`immaster/protocol.py`](immaster/protocol.py) 中 `COMMANDS` 表的映射。 - **其他或贴牌的 iM.Master 变体:未经测试。** 不同的硬件 版本可能会使用不同的 company id 或帧格式。如果你的设备没有 响应,请抓取其流量并与 [docs/BLUETOOTH.md](docs/BLUETOOTH.md) 进行比对,该文档也可作为移植指南。 因此:本项目针对的是当初被解码的那台 iM.Master,应该兼容 同型号的其他设备,但目前仅在作者自己的机器人上得到确认。 ## SDK 逐模块详解 **核心部分,负责移动机器人(纯标准库):** | 模块 | 运行位置 | 用途 | |--------|-----------|---------| | [`protocol.py`](immaster/protocol.py) | 任何地方 | 纯粹的帧/校验和逻辑。不涉及 BLE。可进行单元测试。 | | [`driver.py`](immaster/driver.py) | Pi (root) | 原始 HCI 传输以及连续广播的广播器线程。 | | [`robot.py`](immaster/robot.py) | Pi (root) | 高级 `Robot` API:命名动作和安全看门狗。 | | [`testing.py`](immaster/testing.py) | 任何地方 | `DryRobot` 替身,用于脱离硬件的测试。 | **可选的 AI 插件,允许本地模型进行驾驶。** 每一个动态部分都是微型接口背后的 可插拔组件,因此你可以直接加入自己的实现: | 模块 | 接口 → 内置实现 | 用途 | |--------|----------------------|---------| | [`llm.py`](immaster/llm.py) | `LLMBackend` → Ollama / Hailo-Ollama / OpenAI-API | 大脑。选择一个后端或编写你自己的。 | | [`camera.py`](immaster/camera.py) | `Camera` → `IPCamera`, `StaticImage` | 眼睛的输入。手机网络摄像头、文件或你自己的来源。 | | [`detect.py`](immaster/detect.py) | `ObjectDetector` → `Detector` (Hailo YOLO) | 将一帧画面检测结果。可替换为任何模型。 | | [`agent.py`](immaster/agent.py) | | JSON-action 工具规范、prompt、解析器和调度器。 | | [`personas.py`](immaster/personas.py) | | 位于严格控制契约之上的 Persona prompt 层。 | | [`vision.py`](immaster/vision.py) | | 图像辅助功能:亮度以及“我卡住了吗?”的帧变化提示。 | | [`voice.py`](immaster/voice.py) | | 语音输出(浏览器音频输出)。 | 每个接口都只有一个方法。要添加大脑,请继承 `LLMBackend` 并实现 `chat(messages) -> str`。要添加摄像头,请继承 `Camera` 并实现 `capture() -> bytes`。要添加检测器,请继承 `ObjectDetector` 并实现 `detect(jpeg) -> list[dict]`。循环调用的是接口,因此任何实现 都可以在不修改循环本身的情况下直接工作。 保持代码整洁的规则是:`protocol.py` 绝不触碰硬件,因此你可以在 任何机器上构建和解码帧。所有与 BLE 交互的内容都位于 `driver.py` 之下。 ## 通信协议 机器人不是通过 GATT 控制的。它是通过持续发送的 BLE manufacturer-specific advertising packets 来驱动的。只有在数据包持续发送的情况下,车轮才会转动。
The 14-byte drive frame: fixed header (ae 4a 07), padding, the B7 motor byte, a copy of B7, a popcount checksum, and a fixed trailer. B7 = 0xC0 | (left<<2) | right, where each wheel is 0 stop / 1 forward / 2 reverse.
每个轮子只有开启、关闭或反转状态。协议中任何地方都 没有比例速度。这就是整个控制面,但它仍然能实现干净的差速 驱动:前进、后退、原地旋转和弧线转弯。 完整的详细文档在 [docs/BLUETOOTH.md](docs/BLUETOOTH.md) 中。 ## 项目结构 ``` immaster/ the SDK protocol.py pure frame/checksum logic (core, no BLE) driver.py raw HCI + continuous-advertising broadcaster (core, Pi) robot.py high-level Robot API + watchdog (core, Pi) testing.py DryRobot for off-hardware runs llm.py LLM backends ┐ camera.py Camera sources (IPCamera, ...) │ detect.py ObjectDetector + Hailo YOLO │ agent.py JSON-action LLM dispatch ├─ optional addon personas.py persona prompt layer │ vision.py image cues (brightness, stuck) │ voice.py voice out ┘ examples/ find_and_go.py the working see-think-act loop (camera + detection + local LLM) docs/ BLUETOOTH.md full protocol reverse-engineering write-up assets/ README diagrams (SVG) tests/ pure-logic unit tests (protocol, agent, llm, camera; no hardware) ``` ## 测试 ``` pip install -e ".[dev]" pytest -q ``` 测试涵盖了协议、LLM 调度逻辑、后端选择和 摄像头层。全都是纯软件的,不依赖硬件,并且在 Python 3.10 到 3.12 的 CI 中全部通过。 ## 故障排除 | 症状 | 原因及修复方法 | |---------|---------------| | `PermissionError: raw HCI requires root` | 使用 `sudo -E python3 ...` 运行。原始 BLE 需要 root 权限,而 `-E` 会保留你的环境变量。 | | `RuntimeError: HciBroadcaster only runs on Linux` | 你不在 Linux 系统上。机器人只能从 Pi 或其他 Linux 设备上控制。解码帧、LLM 循环和测试均可在任何地方运行。 | | 脚本运行,**机器人没有移动** | (1) 范围内的另一个 iM.Master 也做出了反应。这是广播,所以属于预期行为。(2) 你的设备车轮是镜像的;请调整 [`immaster/protocol.py`](immaster/protocol.py) 中的 `COMMANDS` 表。(3) 确保没有其他程序占用 `hci0`。 | | `camera unreachable` / `capture()` 返回 `None` | 检查 `IPCAM_URL`,确保手机的摄像头应用正在运行,确保两者在同一个 LAN 中,并检查 URL 中是否包含任何 `user:pass@` 登录信息。 | | LLM `Connection refused` / 超时 | 启动运行环境:针对 `--backend ollama` 运行 `ollama serve` 和 `ollama pull `,或者针对 `--backend hailo` 在 `:8000` 上运行 Hailo-Ollama 服务器。检查 `OLLAMA_HOST` / `HAILO_HOST`。 | | `ModuleNotFoundError: hailo_platform` 或 `Detector()` 失败 | 未安装 HailoRT。安装 Hailo SDK (`sudo apt install hailo-h10-all`),或者跳过检测并使用 [快速入门步骤 3](#quickstart-drive-from-python) 中的仅 LLM 驾驶。 | | 模型未返回动作或重复自身 | 小模型的怪癖;循环会对其稍作推动。尝试不同的 `LLM_MODEL` 或更少的步骤。 | | 动作被缩短 | 如果没有刷新指令,看门狗会在大约 1.5 秒后停止。使用 `for_duration()`,它会自动为你刷新指令,或者在你的循环中调用 `keepalive()`。 | ## 贡献指南 欢迎各种贡献:新的示例行为、对其他基于广播驱动的 BLE 机器人的支持、新的后端、摄像头或检测器,以及感知方面的 改进。请查阅 [CONTRIBUTING.md](CONTRIBUTING.md) 和 [行为准则](CODE_OF_CONDUCT.md)。 ## 安全与负责任地使用 本说明文档描述了用于你自己拥有的机器人的互操作控制路径,仅供学习和 研究。请记住,广播会驱动范围内的该型号的所有机器人。 请在开阔场地驾驶,保持看门狗开启,并时刻留意自主运行状态。 ## 许可证 [MIT](LICENSE)。你可以随心所欲地使用,但不提供任何担保。本 SDK 不附属于 iM.Master 机器人的制造商,也未得其认可。该名称仅用于标识 本 SDK 所通信的硬件。
标签:AI风险缓解, Python, 云资产清单, 无后门, 本地大模型, 机器人, 蓝牙低功耗, 逆向工具, 逆向工程