docs: 新增蓝牙通信协议文档,训练任务书蓝牙协议改为引用

This commit is contained in:
Admin
2026-09-15 14:28:59 +08:00
parent 99d8f411be
commit 43a27c48d4
2 changed files with 804 additions and 251 deletions
+3 -251
View File
@@ -33,17 +33,6 @@
- [A.4 主控命令帧](#a4-主控命令帧)
- [A.5 常用命令示例](#a5-常用命令示例)
- [附录 B:蓝牙通信协议](#附录-b蓝牙通信协议)
- [B.1 总体设计](#b1-总体设计)
- [B.2 GATT 服务与特征](#b2-gatt-服务与特征)
- [B.3 帧格式](#b3-帧格式)
- [B.4 Notify 分包与重组](#b4-notify-分包与重组)
- [B.5 命令码](#b5-命令码)
- [B.6 TLV 编码](#b6-tlv-编码)
- [B.7 TLV 类型](#b7-tlv-类型)
- [B.8 结果码](#b8-结果码)
- [B.9 设备状态码](#b9-设备状态码)
- [B.10 主要命令交互](#b10-主要命令交互)
- [B.11 异步长命令模型](#b11-异步长命令模型)
---
@@ -323,245 +312,8 @@ CHECKSUM = (sum(frame[0] .. frame[帧长-4])) & 0xFF // 位于 frame[帧长
## 附录 B:蓝牙通信协议
### B.1 总体设计
蓝牙通信协议(GATT 服务与特征、帧格式、TLV 编码、命令码、结果码、状态码、主动推送、客户端接入要求等)统一见同目录文档:
1. 所有业务数据统一封装为 TLV 二进制帧,通过 GATT Notify 分包发送。
2. 客户端必须先按特征 UUID 分流,再按命令字 `CMD` 解析。
3. `b1/b2` 为一问一答通道:客户端写 `b1`,设备从 `b2` 通知响应。
4. `a1/a2/b3` 为主动推送通道,不参与请求响应匹配。
5. 命令结果只以 `TLV_RESULT_CODE` 为准。
6. 状态变化通过 `b3` 推送,与命令结果解耦。
### [`蓝牙通信协议.md`](蓝牙通信协议.md)
### B.2 GATT 服务与特征
**Radar Data Service**`a8c1e5c0-3d5d-4a9d-8d5e-7c8b6a4e2f1a`
| 名称 | UUID | 属性 | 方向 | 职责 |
| --- | --- | --- | --- | --- |
| a1 | `beb5483e-36e1-4688-b7f5-ea07361b26a1` | NOTIFY | 设备→客户端 | 连续雷达数据推送 |
| a2 | `beb5483e-36e1-4688-b7f5-ea07361b26a2` | NOTIFY | 设备→客户端 | 雷达状态推送 |
**Device Config Service**`a8c1e5c0-3d5d-4a9d-8d5e-7c8b6a4e2f1b`
| 名称 | UUID | 属性 | 方向 | 职责 |
| --- | --- | --- | --- | --- |
| b1 | `beb5483e-36e1-4688-b7f5-ea07361b26b1` | WRITE | 客户端→设备 | 命令写入 |
| b2 | `beb5483e-36e1-4688-b7f5-ea07361b26b2` | NOTIFY | 设备→客户端 | 命令响应 |
| b3 | `beb5483e-36e1-4688-b7f5-ea07361b26b3` | NOTIFY | 设备→客户端 | 设备信息 / 状态推送 |
### B.3 帧格式
```
SOF1 SOF2 VERSION CMD SEQ LEN_H LEN_L PAYLOAD CRC_H CRC_L
AA 55 01 xx xx xx xx ... xx xx
```
| 字段 | 长度 | 说明 |
| --- | --- | --- |
| SOF1 / SOF2 | 2 | 固定 `0xAA 0x55` |
| VERSION | 1 | 协议版本,当前 `0x01` |
| CMD | 1 | 命令码 |
| SEQ | 1 | 命令请求序列号;主动推送由设备侧决定(`b3``a2` 固定为 `0``a1` 连续推送为设备侧自增),客户端对主动推送不按 `seq` 匹配 |
| LEN | 2 | PAYLOAD 长度,大端 |
| PAYLOAD | N | TLV 数据区 |
| CRC | 2 | CRC16-CCITT,大端 |
- **CRC 计算范围**:从 VERSION 到 PAYLOAD 末尾,不含 SOF1/SOF2 与 CRC 本身。
- **CRC 参数**:多项式 `0x1021`,初值 `0xFFFF`,输入/输出不反转,无最终异或(CRC16-CCITT-FALSE)。
- **最小帧长**:9 字节(空载荷)。
### B.4 Notify 分包与重组
Notify 单包可能小于整帧,设备按固定 **20 字节**分片发送。客户端必须为 `a1 / a2 / b2 / b3` **各维护一个重组缓冲区**,按帧头 + LEN + CRC 提取完整帧。
### B.5 命令码
| 命令 | 值 | 通道 | 说明 |
| --- | --- | --- | --- |
| CMD_PING | `0x01` | b1/b2 | Ping |
| CMD_QUERY_STATUS | `0x10` | b1/b2 | 查询设备状态 |
| CMD_QUERY_RADAR | `0x12` | b1/b2 | 查询雷达快照 |
| CMD_START_CONTINUOUS | `0x14` | b1/b2 | 启动连续推送 |
| CMD_STOP_CONTINUOUS | `0x16` | b1/b2 | 停止连续推送 |
| CMD_RADAR_SLEEP_QUERY | `0x17` | b1/b2 | 雷达睡眠查询开关 |
| CMD_CONTINUOUS_PUSH | `0x18` | a1 | 连续数据主动推送 |
| CMD_DEVICE_INFO_PUSH | `0x19` | b3 | 设备信息 / 状态推送 |
| CMD_RADAR_STATUS_PUSH | `0x1A` | a2 | 雷达状态推送 |
| CMD_WIFI_SCAN | `0x20` | b1/b2 | WiFi 扫描 |
| CMD_WIFI_CONFIG | `0x22` | b1/b2 | WiFi 配网 |
| CMD_GET_SAVED_WIFI | `0x24` | b1/b2 | 查询已保存 WiFi |
| CMD_DELETE_SAVED_WIFI | `0x26` | b1/b2 | 删除已保存 WiFi |
| CMD_ERROR_RESP | `0x7E` | b2 | 协议层错误响应 |
### B.6 TLV 编码
```
TYPE(1) LEN_H(1) LEN_L(1) VALUE(N)
```
### B.7 TLV 类型
**设备信息**
| TLV | 值 | 类型 | 说明 |
| --- | --- | --- | --- |
| TLV_RESULT_CODE | `0x02` | uint8 | 结果码 |
| TLV_TIMESTAMP | `0x04` | uint32 | 时间戳(ms |
| TLV_PROTOCOL_VERSION | `0x05` | string | 协议版本 |
| TLV_DEVICE_SN | `0x06` | uint64 | 设备序列号 |
| TLV_FIRMWARE_VERSION | `0x07` | string | 固件版本 |
| TLV_DEVICE_TYPE | `0x08` | string | 设备类型 |
| TLV_MAC_ADDRESS | `0x09` | string | MAC 地址 |
**雷达数据**
| TLV | 值 | 类型 | 说明 |
| --- | --- | --- | --- |
| TLV_HEART_RATE_X10 | `0x10` | uint16 | 心率 ×10 |
| TLV_BREATH_RATE_X10 | `0x11` | uint16 | 呼吸率 ×10 |
| TLV_PRESENCE | `0x12` | uint8 | 人体存在 |
| TLV_MOTION | `0x13` | uint8 | 运动状态 |
| TLV_SLEEP_STATE | `0x14` | uint8 | 睡眠状态 |
| TLV_DISTANCE_CM | `0x15` | uint16 | 距离(cm |
| TLV_POS_X_MM | `0x16` | int16 | X 坐标(mm |
| TLV_POS_Y_MM | `0x17` | int16 | Y 坐标(mm |
| TLV_POS_Z_MM | `0x18` | int16 | Z 坐标(mm |
| TLV_BODY_MOVEMENT | `0x19` | uint8 | 体动 |
**WiFi**
| TLV | 值 | 类型 | 说明 |
| --- | --- | --- | --- |
| TLV_SSID | `0x20` | string | WiFi 名称 |
| TLV_PASSWORD | `0x21` | string | WiFi 密码 |
| TLV_WIFI_COUNT | `0x22` | uint16 | WiFi 数量 |
| TLV_WIFI_ITEM | `0x23` | block | WiFi 列表项 |
| TLV_RSSI | `0x24` | int8 | 信号强度 |
| TLV_SECURITY | `0x25` | uint8 | 加密类型 |
**控制与状态**
| TLV | 值 | 类型 | 说明 |
| --- | --- | --- | --- |
| TLV_INTERVAL_MS | `0x31` | uint16 | 推送间隔(ms |
| TLV_RADAR_SLEEP_ENABLED | `0x32` | uint8 | 雷达睡眠查询开关 |
| TLV_DEVICE_STATUS | `0x33` | uint8 | b3 状态推送 |
| TLV_WIFI_STATUS | `0x34` | uint8 | WiFi 状态 |
| TLV_MQTT_STATUS | `0x35` | uint8 | MQTT 状态 |
| TLV_RADAR_SLEEP_STATUS | `0x36` | uint8 | 雷达睡眠查询状态 |
| TLV_LED_ENABLED | `0x37` | uint8 | 指示灯开关 |
**通用**
| TLV | 值 | 类型 | 说明 |
| --- | --- | --- | --- |
| TLV_IP_ADDRESS | `0x41` | string | IP 地址 |
| TLV_WIFI_CONFIGURED | `0x42` | uint8 | 是否已保存 WiFi |
| TLV_WIFI_CONNECTED | `0x43` | uint8 | WiFi 是否连接 |
| TLV_ECHO_CONTENT | `0x44` | string | 回显内容 |
**波形**
| TLV | 值 | 类型 | 说明 |
| --- | --- | --- | --- |
| TLV_HEART_WAVEFORM | `0x60` | uint8 | 心跳波形(原值 + 128 |
| TLV_BREATH_WAVEFORM | `0x61` | uint8 | 呼吸波形(原值 + 128 |
### B.8 结果码
| 结果码 | 值 | 说明 |
| --- | --- | --- |
| SUCCESS | `0x00` | 成功 |
| PROCESSING | `0x01` | 已接收,处理中 |
| ERR_PROTO_CMD_UNKNOWN | `0x13` | 未知命令 |
| ERR_PROTO_PARAM_MISSING | `0x14` | 参数缺失 |
| ERR_PROTO_PARAM_INVALID | `0x15` | 参数非法 |
| ERR_PROTO_BUSY | `0x16` | 设备忙 |
| ERR_PROTO_FRAME_TOO_LARGE | `0x18` | 帧过大 |
| ERR_WIFI_SCAN_TIMEOUT | `0x20` | 扫描超时 |
| ERR_WIFI_SSID_NOT_FOUND | `0x21` | 未找到 SSID |
| ERR_WIFI_WRONG_PASSWORD | `0x22` | 密码错误 |
| ERR_WIFI_SIGNAL_WEAK | `0x25` | 信号弱 |
| ERR_WIFI_BUSY | `0x26` | WiFi 忙 |
| ERR_DEV_STATE_INVALID | `0x40` | 状态不允许 |
| ERR_DEV_STORAGE_FAIL | `0x41` | 存储失败 |
| ERR_DEV_QUEUE_FULL | `0x42` | 队列已满 |
### B.9 设备状态码
用于 `TLV_DEVICE_STATUS` / `TLV_WIFI_STATUS` / `TLV_MQTT_STATUS` / `TLV_RADAR_SLEEP_STATUS`
| 状态 | 值 |
| --- | --- |
| WIFI_DISCONNECTED | `0x10` |
| WIFI_CONNECTING | `0x11` |
| WIFI_CONNECTED | `0x12` |
| WIFI_FAILED | `0x13` |
| DEV_MQTT_DISCONNECTED | `0x20` |
| DEV_MQTT_CONNECTING | `0x21` |
| DEV_MQTT_CONNECTED | `0x22` |
| DEV_MQTT_FAILED | `0x23` |
| RADAR_SLEEP_QUERY_DISABLED | `0x30` |
| RADAR_SLEEP_QUERY_ENABLED | `0x31` |
| LED_DISABLED | `0x32` |
| LED_ENABLED | `0x33` |
### B.10 主要命令交互
**CMD_QUERY_STATUS0x10**
- 请求:无载荷。
- 响应(b2):`TLV_RESULT_CODE` + 设备信息 TLV`TLV_PROTOCOL_VERSION``TLV_FIRMWARE_VERSION``TLV_DEVICE_TYPE``TLV_MAC_ADDRESS`,存在 SN 时附 `TLV_DEVICE_SN`+ `TLV_WIFI_CONFIGURED``TLV_WIFI_CONNECTED``TLV_IP_ADDRESS`(已连接时)、`TLV_SSID`(已连接时)、`TLV_WIFI_STATUS``TLV_MQTT_STATUS``TLV_RADAR_SLEEP_STATUS``TLV_LED_ENABLED`
**CMD_QUERY_RADAR0x12**
- 请求:无载荷。
- 响应(b2):`TLV_RESULT_CODE` + `TLV_PRESENCE``TLV_HEART_RATE_X10``TLV_BREATH_RATE_X10``TLV_MOTION``TLV_DISTANCE_CM``TLV_POS_X_MM``TLV_POS_Y_MM``TLV_POS_Z_MM``TLV_BODY_MOVEMENT``seq` 与请求一致。
**CMD_START_CONTINUOUS0x14**
- 请求:`TLV_INTERVAL_MS`(有效范围 100~10000 ms)。
- 响应:`TLV_RESULT_CODE`,成功时附 `TLV_INTERVAL_MS`;参数缺失/非法返回对应错误码。
- 启动后设备按间隔通过 `a1` 推送 `CMD_CONTINUOUS_PUSH(0x18)` 帧。
**CMD_STOP_CONTINUOUS0x16**
- 请求无载荷;停止推送,幂等操作,始终返回 `SUCCESS`
**CMD_CONTINUOUS_PUSH0x18a1 推送)**
- 载荷:`TLV_TIMESTAMP``TLV_PRESENCE``TLV_HEART_RATE_X10``TLV_BREATH_RATE_X10``TLV_MOTION``TLV_DISTANCE_CM` 等。
**CMD_WIFI_SCAN0x20**
- 请求无载荷。先回 `PROCESSING`;完成后回 `TLV_RESULT_CODE` + `TLV_WIFI_COUNT` + 多个 `TLV_WIFI_ITEM`(每项含 `TLV_SSID``TLV_RSSI``TLV_SECURITY`)。
**CMD_WIFI_CONFIG0x22**
- 请求:`TLV_SSID``TLV_PASSWORD`
- 先回 `PROCESSING`(可含 `TLV_SSID`);完成后回 `SUCCESS` + `TLV_SSID` + `TLV_IP_ADDRESS`,失败回对应错误码。
**CMD_GET_SAVED_WIFI0x24**
- 响应:`TLV_RESULT_CODE` + `TLV_WIFI_COUNT` + 多个 `TLV_WIFI_ITEM`
**CMD_DELETE_SAVED_WIFI0x26**
- 请求:`TLV_SSID`;响应:`TLV_RESULT_CODE`
**CMD_DEVICE_INFO_PUSH0x19b3 推送)**
- `seq = 0`;载荷为 `TLV_DEVICE_STATUS`,或设备信息 TLV`TLV_RESULT_CODE`、协议版本、固件版本、设备类型、MAC、SN 等)。仅在状态变化时推送。
### B.11 异步长命令模型
适用于 `CMD_WIFI_SCAN``CMD_WIFI_CONFIG`
```
客户端 --b1--> 请求
设备 --b2--> 原命令码, 原 seq, RESULT_CODE = PROCESSING(0x01)
... 后台处理 ...
设备 --b2--> 原命令码, 原 seq, RESULT_CODE = SUCCESS 或 ERR_XXX + 业务 TLV
```
运行状态(WiFi 等)通过 `b3``CMD_DEVICE_INFO_PUSH(0x19)` + `TLV_DEVICE_STATUS` 推送。
本文不再重复协议细节,实现时以上述文档为准。