Nyx000/acinfinity-ble
GitHub: Nyx000/acinfinity-ble
针对 AC Infinity UIS 控制器的纯净版蓝牙 LE 协议实现,支持本地直接读写设备数据,完全脱离厂商云端。
Stars: 0 | Forks: 0
# acinfinity-ble
一个针对 AC Infinity UIS 协议的纯净版 Bluetooth LE 实现——直接读取传感器并
向控制器写入设置,无需供应商云账号,也不依赖
网络。
零运行时依赖。包含 165 个测试。基于 **Controller 69 Pro**(固件
版本 ≥ 6,多端口)和一款 UIS 电源插排进行开发。
## 缘由
官方应用通过 BLE 与控制器通信,并将所有数据镜像同步到 AC Infinity 的
云端。如果你想要进行本地自动化——例如 Home Assistant、Raspberry Pi 或你自己的调度程序——你
就需要底层的通信协议,而该协议并未公开。本仓库记录了该协议,
保留了其出处,并提供了一个经过测试的实现。
它是从一个正在运行的种植帐篷遥测系统中提取出来的,自 2026 年 6 月以来,
它一直在驱动真实的硬件持续运行。
## 状态
| 领域 | 状态 |
|---|---|
| GATT service / characteristic UUIDs | 已确认 |
| 帧封装 + CRC16 | 已确认,在 20,000 个随机向量及每一帧捕获的参考数据中,与官方应用位级一致 (bit-identical) |
| 传感器读取(self-stream V6, A5 TLV 查询) | 已确认,针对不同设备类型 |
| 端口模式激活 (`0x10`) | 已在实际硬件上确认,字节精确匹配 |
| AUTO 阈值 (`0x13`) | 编码器已针对固件 ≥ 6 确认(10 字节块);*写入* (write) 的数据抓取仍未完成 |
| VPD (`0x51`) | 已确认所有版本 |
| 亮度 (`0x21`) | 已确认 |
| 温度单位 (`0x20`) | 已确认 — `1` = °C, `0` = °F |
| 校准 (`0x24`) | **部分完成。** 字节 1 和 2 直接映射到 UI 步进器;字节 0 尚未解决 |
**已知未解决的项目均标记为未解决 (unresolved)。** 请参阅
[`docs/protocol/wire-protocol.md`](docs/protocol/wire-protocol.md) 以获取每一个未决问题的
完整说明,包括一次失败的数据抓取尝试及其原因。
### 设置捆绑包 (settings-bundle) 陷阱
在编写任何代码之前,这点值得了解。控制器设置**始终作为一个捆绑的写入操作发送**,
绝不会按单个字段发送。一个单独的单字段写入——比如说,仅仅修改温度单位——
会在 BLE 上发送**零字节**,并且不报告任何错误。它会静默地成为空操作 (no-op)。
任何针对设置字段的编码器都必须对整个捆绑包执行读取-修改-写入 (read-modify-write) 操作。
这类 Bug 是你针对自己的编码器进行的单元测试永远无法捕获的,
因为你的编码器逻辑是正确的,但设备直接忽略了它。
## 安装
```
git clone https://github.com/Nyx000/acinfinity-ble
cd acinfinity-ble
npm install # dev dependencies only — there are no runtime dependencies
npm test
```
BLE 传输通过一个使用 [`bleak`](https://github.com/hbldh/bleak) 的小型 Python 边车 (sidecar) 程序进行,
这是唯一支持的传输方式。`src/acinfinity/ble-sidecar.py` 就是这个边车程序;
请将 `BLE_SIDECAR_PYTHON` 和 `BLE_SIDECAR_SCRIPT` 指向你的解释器和该文件。
```
CONTROLLER_SOURCE=ble \
BLE_CONTROLLER_MAC=XX:XX:XX:XX:XX:XX \
BLE_POWERSTRIP_MAC=XX:XX:XX:XX:XX:XX \
BLE_SIDECAR_PYTHON=/usr/bin/python3 \
BLE_SIDECAR_SCRIPT=./src/acinfinity/ble-sidecar.py \
npm run ble:check
```
`CONTROLLER_SOURCE` 默认为 `mock`,因此除非你主动要求,否则程序不会触碰无线电。
## 目录结构
```
src/acinfinity/ protocol core — framing, CRC, encoders, decoders, transport
src/lib/ small pure helpers (hex, MAC, units, VPD, setpoints)
src/audit/ mode-ID → human name mapping
docs/protocol/ the wire protocol and how each claim was established
test/ 165 tests
.claude/skills/ the live-capture methodology, as a runnable procedure
```
## 验证方式
单纯的静态分析被认为是不够的,事实证明的确如此。
该协议最初是通过反编译供应商的 Android 应用逆向得到的。随后
通过三种独立的方式进行了重新验证:在运行中的应用上通过进程内钩子 (hooks) 捕获真实的 GATT
写入操作、对新获取的 APK 进行第二次独立反编译,以及进行主机控制器接口 (HCI) 嗅探。**那次检查推翻了本项目之前已经记录并相信的两个发现**——
在这两种情况下,发布的产品代码是对的,而文档中记录的协议是错的。
因此,`docs/protocol/` 中的每一项声明都附带了它的证据,并且来源之间的
分歧被如实记录下来,而不是被掩盖过去。如果某个问题尚未解决,文档中会明确说明。
## 法律声明
这是为了实现互操作性而进行的工作。这里记录的协议事实——字节布局、选择器、校验和、
GATT UUIDs——是通过分析合法获取的程序确定的,其唯一目的是
让独立编写的软件能够与操作者自己拥有的硬件进行通信。
- **没有复制或重新分发任何供应商代码。** 没有 APK,没有反编译器输出,也没有
反编译的源代码。形如 `jm1.java:1348` 的引用只是指引,让读者可以
自行重新推导出某个发现;它们并不是供应商的代码。
- **不包含任何供应商资产** —— 没有 UI 字符串,没有图片,没有品牌标识。
- 协议事实不属于受版权保护的主题。
- 未与 AC Infinity 有任何附属关系,也未获得其认可或支持。“AC Infinity” 和 “UIS” 是
其所有者的商标,此处使用它们仅仅是为了说明本软件与什么硬件进行通信。
向硬件写入数据存在实际风险。请参阅 [`LICENSE`](LICENSE) 中的免责声明,并且
对于任何新的写入操作,最好通过与读取回的数据进行比对来验证。
## 贡献
来自其他 UIS 设备的数据抓取 (Captures) 是任何人能添加的最有用的内容——尤其是
固件 < 6 的单端口控制器,本实现对它们的处理是基于反编译推导的,而
不是基于实际运行中的硬件证据。数据抓取的操作步骤位于
[`.claude/skills/ble-app-capture/SKILL.md`](.claude/skills/ble-app-capture/SKILL.md) 中。
如果你要添加协议声明,请说明你是如何确立它的。没有出处的发现
正是本仓库极力想要避免的东西。
## 许可证
MIT — 请参阅 [`LICENSE`](LICENSE)。
标签:数据可视化, 智能家居, 本地自动化, 物联网, 自动化攻击, 蓝牙低功耗, 逆向工具, 通信协议, 零依赖