Knight1/vanmoof-ble
GitHub: Knight1/vanmoof-ble
通过 BLE 协议与 VanMoof S5/A5 电动自行车直接通信的 Python 工具,支持身份验证、车辆控制、状态查询与实时遥测。
Stars: 3 | Forks: 0
# VanMoof BLE 通信
一个通过低功耗蓝牙 (BLE) 与 VanMoof S5 和 A5 电动自行车通信的 Python 工具。可在任何带有蓝牙的计算机或设备上直接对您的自行车进行身份验证、控制和查询。
## 功能
- **身份验证** - 基于 Ed25519 证书的 BLE 身份验证
- **锁定 / 解锁** - 远程锁定和解锁自行车
- **警报** - 布防、撤防和触发警报
- **声音** - 车铃(单/双叮)、喇叭和自定义声音
- **电源控制** - 开启/关闭自行车电子设备,启用/禁用助力模式
- **助力等级** - 设置电机助力等级 (0-4)
- **灯光** - 控制前灯模式(关闭、开启、自动)
- **速度区域** - 设置速度区域(EU 25 km/h、US 32 km/h、JP 24 km/h)
- **状态查询** - 查询锁定状态、警报、灯光、电源、电池等
- **设备信息** - 从 BLE GATT 读取固件版本、型号、序列号
- **BLE 扫描** - 发现附近的 VanMoof 自行车
- **原始命令** - 发送任意十六进制命令以进行协议探索
- **调试模式** - 完整的数据包记录,带有可选的时间戳
## 前置条件
- VanMoof S5 或 A5 自行车
- Python 3.8+
- 具备低功耗蓝牙功能的设备
- 自行车证书和私钥(参见 [vanmoof-certificates](https://github.com/Knight1/vanmoof-certificates))
## 安装说明
```
git clone https://github.com/Knight1/vanmoof-ble.git
cd vanmoof-ble
python3 -m venv venv
source venv/bin/activate
pip install -r requirements.txt
```
## 使用说明
### CLI 选项
| 选项 | 描述 |
|------------------|------------------------------------------------------------|
| `--privkey` | Base64 编码的 Ed25519 私钥 |
| `--cert` | Base64 编码的证书(CA 签名 + CBOR payload) |
| `--mac` | 自行车的蓝牙 MAC 地址 |
| `--scan` | 扫描附近的 VanMoof 自行车 |
| `--debug` | 启用详细的数据包记录 |
| `--timestamp` | 在 TX/RX 日志中添加时间戳 |
| `--ignore-expiry`| 即使证书已过期仍继续执行 |
### 扫描自行车
```
python main.py --scan
```
### 连接和身份验证
```
python main.py --privkey "YOUR_BASE64_PRIVATE_KEY" --cert "YOUR_BASE64_CERTIFICATE"
```
### 使用特定 MAC 地址
```
python main.py --privkey "..." --cert "..." --mac "XX:XX:XX:XX:XX:XX"
```
自行车的 BLE 地址在每次重启后都会更改。使用 `--scan` 来查找它,或者如果您已经知道它,请指定 `--mac`。
### 调试模式
```
python main.py --privkey "..." --cert "..." --debug --timestamp
```
## 交互式命令
连接并进行身份验证后,可以使用以下命令:
### 锁定 / 安全
| 命令 | 描述 | BLE 数据包 (hex) |
|-----------|--------------------------|-------------------------|
| `unlock` | 解锁自行车 | `81 00 03 01 00 A0 01` |
| `lock` | 锁定自行车 | `81 00 03 01 00 A0 00` |
| `arm` | 布防(启用)警报 | `81 00 03 01 01 A0 01` |
| `disarm` | 撤防(禁用)警报 | `81 00 03 01 01 A0 00` |
| `alarm` | 触发警报声 | `81 00 03 01 02 A0 01` |
### 声音
| 命令 | 描述 | BLE 数据包 (hex) |
|---------------|--------------------------|-------------------------|
| `bell` | 单次车铃叮 | `81 00 03 02 00 A0 01` |
| `bell2` | 双次车铃叮 | `81 00 03 02 00 A0 02` |
| `horn` | 喇叭声 | `81 00 03 02 01 A0 01` |
| `beep` | 播放默认声音 | `81 00 03 01 00 21 01` |
| `sound ` | 按 ID 播放声音 | `81 00 03 01 00 21 ` |
### 骑行控制
| 命令 | 描述 | BLE 数据包 (hex) |
|------------|--------------------------|-------------------------|
| `poweron` | 开启电子设备 | `81 00 03 03 00 A0 01` |
| `poweroff` | 关闭电子设备 | `81 00 03 03 00 A0 00` |
| `booston` | 启用助力模式 | `81 00 03 03 01 A0 01` |
| `boostoff` | 禁用助力模式 | `81 00 03 03 01 A0 00` |
### 电源与配置
| 命令 | 描述 | BLE 数据包 (hex) |
|-------------------------|--------------------------|-------------------------|
| `power <0-4>` | 设置助力等级 | `81 00 04 30 00 A0 ` |
| `lights ` | 设置灯光模式 | `81 00 03 01 00 6B ` |
| `region ` | 设置速度区域 | `81 00 04 30 01 A0 ` |
### 遥测(实时传感器数据)
自行车开机后会通过 BLE 通知流式传输实时遥测数据。可用的传感器因型号和固件版本而异。
| 命令 | 描述 |
|----------------|------------------------------------------------------|
| `monitor` | 启动实时遥测显示(按 Ctrl+C 停止) |
| `sensors` | 显示最后已知的传感器读数 |
| `subscribe` | 激活遥测数据流(开启自行车电源) |
可用的传感器读数:
| 传感器 | 描述 | 单位 |
|------------------|--------------------------------|--------|
| Speed | 当前自行车速度 | km/h |
| Pedal RPM | 踏频 | RPM |
| Pedal Torque | 脚踏扭矩 | Nm |
| Boost Button | 助力按钮已按下 | - |
| Battery | 电池充电水平 | % |
| Assist Level | 当前电机助力等级 | 0-4 |
| Motor Temp | 电机温度 | C |
| Driver Temp | 电机驱动器/控制器温度 | C |
| Module Temp | 主模块温度 | C |
| Light Sensor | 环境光水平 | - |
| Humidity | 湿度传感器 | % |
| Air Quality | 空气质量指数 (S6) | AQI |
### 信息
| 命令 | 描述 |
|--------------------|-----------------------------------------------------|
| `status` | 显示最后接收到的 CBOR 状态 |
| `info` | 显示自行车信息(凭证、GATT 设备信息) |
| `battery` | 查询电池电量 |
| `services` | 列出所有 BLE GATT 服务和特征 |
| `query ` | 查询特定状态(见下文) |
查询目标:`lock`、`alarm`、`lights`、`power`、`boost`、`level`、`region`、`battery`、`all`
### 实用工具
| 命令 | 描述 |
|--------------------|-----------------------------------------------------|
| `raw ` | 发送原始十六进制字节(例如,`raw 81 00 03 01 00 A0 01`) |
| `help` | 显示所有可用命令 |
| `quit` | 断开连接并退出 |
## 项目结构
```
vanmoof-ble/
├── main.py # Main BLE client application
├── requirements.txt # Python dependencies
├── README.md # This file
├── commands/ # BLE command modules
│ ├── alarm.py # Alarm arm/disarm/trigger
│ ├── info.py # Status queries, device info, GATT services
│ ├── lights.py # Light mode control
│ ├── lock.py # Lock/unlock
│ ├── power.py # Assist level control
│ ├── region.py # Speed region control (EU/US/JP)
│ ├── ride.py # Power on/off, boost
│ ├── sound.py # Bell, horn, sounds
│ └── telemetry.py # Real-time sensor data streaming
├── utils/ # Utility modules
│ ├── credentials_utils.py # Certificate parsing & key validation
│ ├── crypto_utils.py # Ed25519 signing & key loading
│ └── protocol_utils.py # Packet builders (read/write/config/auth)
└── docs/
└── PROTOCOL.md # Complete BLE protocol reference
```
## 协议概述
有关完整的协议规范,请参见 [docs/PROTOCOL.md](docs/PROTOCOL.md)。
VanMoof S5/A5 在单个 GATT 特征(`e3d80001-3416-4a54-b011-68d41fdcbfcf`)上使用自定义的 BLE 协议:
1. **初始交换** - 自行车发送 `{enc: false, auth: false}`,客户端回显该数据
2. **证书** - 客户端发送 CA 签名的证书(64 字节签名 + CBOR payload)
3. **挑战-响应** - 自行车发送 16 字节的 nonce,客户端使用 Ed25519 密钥进行签名
4. **确认** - 自行车回复 `{auth: true}` 进行确认
### 数据包格式
```
[frame_byte] [0x00] [module/length] [subtype] [payload...]
Modules: 0x02 = Read 0x03 = Write 0x04 = Configure
```
### 命令组
| 组 | Hex | 命令 |
|-----------|--------|----------------------------------------|
| Security | `0x01` | 锁定、警报、灯光、声音 |
| Sound | `0x02` | 车铃、喇叭 |
| Ride | `0x03` | 电源开启/关闭、助力 |
| Config | `0x30` | 助力等级、速度区域 |
## 提取凭证以进行调试
### 从 Android 设备(需要 root 或开发者模式)
```
adb root
adb shell
cat /data/data/nl.samsonit.vanmoofapp/shared_prefs/VANMOOF.xml
```
获取证书数据:
```
cd /data/data/nl.samsonit.vanmoofapp/databases
sqlite3 rider-app-database
SELECT id, name FROM bikes;
SELECT * FROM bike_certificate;
```
## Frida 脚本
这些脚本用于分析 VanMoof Android 应用以了解 BLE 协议。需要安装 [Frida](https://frida.re/)。
### 用法
```
frida -U -f nl.samsonit.vanmoofapp -l frida/ble_sniffer.js
```
## 贡献
欢迎贡献!请随时提交 Pull Request ❤️
标签:Python, 无后门, 智能硬件, 物联网控制, 电动自行车, 蓝牙低能耗, 逆向工具