Files
ESP32-learning-materials/新人项目训练任务书.md
T

568 lines
25 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 新人项目训练任务书
## 目录
- [一、训练目的](#一训练目的)
- [二、硬件与开发环境](#二硬件与开发环境)
- [2.1 硬件](#21-硬件)
- [2.2 接线](#22-接线)
- [2.3 开发环境](#23-开发环境)
- [2.4 需自行查阅的资料](#24-需自行查阅的资料)
- [三、通用要求](#三通用要求)
- [四、任务一:雷达串口数据采集并打印到串口 0](#四任务一雷达串口数据采集并打印到串口-0)
- [4.1 任务目标](#41-任务目标)
- [4.2 功能需求](#42-功能需求)
- [4.3 完成标准](#43-完成标准)
- [五、任务二:引入实时操作系统并新增蓝牙数据传输任务](#五任务二引入实时操作系统并新增蓝牙数据传输任务)
- [5.1 任务目标](#51-任务目标)
- [5.2 功能需求](#52-功能需求)
- [5.3 完成标准](#53-完成标准)
- [六、任务三:新增蓝牙配网任务](#六任务三新增蓝牙配网任务)
- [6.1 任务目标](#61-任务目标)
- [6.2 功能需求](#62-功能需求)
- [6.3 完成标准](#63-完成标准)
- [七、任务四:WiFi 配置持久化与开机自动重连](#七任务四wifi-配置持久化与开机自动重连)
- [7.1 任务目标](#71-任务目标)
- [7.2 功能需求](#72-功能需求)
- [7.3 完成标准](#73-完成标准)
- [八、训练建议](#八训练建议)
- [附录 A:雷达串口通信协议](#附录-a雷达串口通信协议)
- [A.1 物理层](#a1-物理层)
- [A.2 帧格式](#a2-帧格式)
- [A.3 控制字与数据项](#a3-控制字与数据项)
- [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-异步长命令模型)
---
## 一、训练目的
围绕"雷达数据采集 → 蓝牙数据传输 → 蓝牙配网 → 配置持久化"这一典型物联网设备开发场景,由浅入深完成四个任务,使学员掌握:
- 串口(UART)数据采集与二进制协议解析;
- 实时操作系统(FreeRTOS)下的多任务设计与任务间通信;
- 蓝牙(BLE)GATT 通信与二进制协议实现;
- 设备联网配置(扫描、连接、持久化、状态反馈)。
四个任务循序渐进,后一个任务在前一个任务的基础上扩展:
```
任务一:串口数据采集打印 任务二:RTOS 多任务 + 蓝牙数据传输 任务三:蓝牙配网 任务四:配置持久化 + 开机自动重连
雷达 ─UART─▶ 串口0 打印 采集任务 ─队列─▶ 蓝牙发送任务 扫描 / 连接 WiFi Flash 存储 ─▶ 复位自动重连
```
## 二、硬件与开发环境
### 2.1 硬件
| 项目 | 说明 |
| --- | --- |
| 主控 | ESP32-S3Freenove ESP32-S3 WROOMN8R88MB Flash / 8MB PSRAM |
| 传感器 | R60ABD1 毫米波雷达模组(UART 接口) |
| 调试 | USB 数据线连接电脑,作为串口 0 使用 |
### 2.2 接线
| 雷达模组 | ESP32-S3 | 说明 |
| --- | --- | --- |
| TX | 任意可用 RX 引脚 | 主控接收 |
| RX | 任意可用 TX 引脚 | 主控发送 |
| GND | GND | 必须共地 |
| VCC | 按模组手册供电 | 注意电压与电流要求 |
> 具体引脚、波特率、数据位/停止位/校验位以雷达模组数据手册和训练方要求为准。
### 2.3 开发环境
- VS Code + PlatformIO(或 Arduino IDE,按训练方统一要求);
- 串口调试助手(用于查看串口 0 输出);
- 蓝牙调试 App(如 nRF Connect)或微信小程序蓝牙调试工具。
### 2.4 需自行查阅的资料
- ESP32-S3 技术参考手册、Arduino-ESP32 / ESP-IDF 官方文档;
- FreeRTOS 官方文档;
- 蓝牙 GATT 规范及 ESP32 蓝牙例程;
- 本任务书 [**附录 A:雷达串口通信协议**](#附录-a雷达串口通信协议) 与 [**附录 B:蓝牙通信协议**](#附录-b蓝牙通信协议)(学员须严格按协议实现)。
## 三、通用要求
1. **独立完成**:禁止直接复制他人代码,须能独立说明实现原理。
2. **代码质量**:结构清晰、命名规范、注释完整,保证可编译、可烧录。
3. **稳定性**:长时间运行不崩溃、不丢帧、不阻塞、不触发看门狗复位。
## 四、任务一:雷达串口数据采集并打印到串口 0
### 4.1 任务目标
搭建最小工程,从雷达串口读取数据,完成组帧与校验,并通过串口 0(USB 调试口)把数据打印到电脑上。
### 4.2 功能需求
1. 正确初始化调试串口与雷达串口,串口参数依据雷达数据手册设置。
2. 从雷达串口接收字节流,依据 [**附录 A 雷达串口通信协议**](#附录-a雷达串口通信协议) 对字节流进行**组帧**。
3. 对每个完整帧进行**校验**,校验失败的帧必须丢弃并给出提示。
4. 通过串口 0 打印**人类可读的关键信息**:解析帧内容后,按字段输出人体存在、运动状态、距离、坐标、心率、呼吸、睡眠等信息(字段定义见 [附录 A](#附录-a雷达串口通信协议)),要求信息清晰、易于查看。
5. 雷达模组上电后不会主动上报,需按 [附录 A](#附录-a雷达串口通信协议) 发送使能命令后才输出数据;需实现命令帧的构造与发送(含校验和计算)。
6. 程序运行稳定,接收过程不阻塞、不丢帧,缓冲区溢出时能自动恢复。
### 4.3 完成标准
- [ ] 串口 0 能稳定输出人类可读的解析结果,字段含义正确、无乱码。
- [ ] 人体靠近/远离时,能观察到数据实时变化。
- [ ] 人为构造校验错误的帧,程序能识别并丢弃。
- [ ] 能清晰说明 [附录 A](#附录-a雷达串口通信协议) 的帧格式、校验算法与字段布局。
## 五、任务二:引入实时操作系统并新增蓝牙数据传输任务
### 5.1 任务目标
将任务一改造成基于实时操作系统(FreeRTOS)的多任务架构,并新增一个蓝牙数据传输任务,把采集到的雷达数据按 [**附录 B 蓝牙通信协议**](#附录-b蓝牙通信协议) 发送给手机端。
### 5.2 功能需求
1. **任务化改造**:引入 FreeRTOS,把任务一的"串口采集 + 组帧 + 解析"实现为一个独立任务。
2. **新增蓝牙数据传输任务**:负责蓝牙初始化、服务与特征定义、数据收发。
3. **任务解耦**:采集任务与蓝牙任务之间通过队列(或等效机制)传递数据,禁止跨任务直接读写共享变量;共享资源的访问须加互斥保护。
4. **蓝牙需提供两类通道**
- **数据通知通道**:周期性或在数据变化时向手机推送雷达数据;
- **命令通道**:接收手机写入的命令,并按命令返回对应响应。
5. **命令功能**:至少支持"启动连续推送""停止连续推送""查询一次数据",并对未知命令返回错误响应。
6. **按 [附录 B](#附录-b蓝牙通信协议) 实现蓝牙传输协议**:严格按协议规定的 GATT 服务/特征、帧格式、TLV 编码、命令码、错误码实现;要求:
- 发送端支持**分包**,接收端支持**重组**;
- 命令响应与请求通过序列号**一一对应**;
- 接收端校验 CRC 并丢弃非法帧。
7. **健壮性**:发送需做互斥与必要的节流;断开连接后停止推送,重连后按客户端命令恢复。
### 5.3 完成标准
- [ ] 手机端订阅通知特征后,能稳定收到可解析的雷达数据帧,内容随人体状态变化。
- [ ] 手机端写入查询命令,能收到匹配的响应(序列号一致、校验正确)。
- [ ] 启动 / 停止连续推送命令均生效;未知命令返回错误响应。
- [ ] 多任务运行稳定,无明显阻塞与看门狗复位。
- [ ] 能说明任务划分、队列/互斥设计,以及 [附录 B](#附录-b蓝牙通信协议) 协议的实现要点。
## 六、任务三:新增蓝牙配网任务
### 6.1 任务目标
在任务二基础上,新增一个蓝牙配网任务,按 [**附录 B 蓝牙通信协议**](#附录-b蓝牙通信协议) 的配网命令,实现通过手机蓝牙下发 WiFi 信息,使设备完成联网。
### 6.2 功能需求
1. **新增独立配网任务**:处理手机下发的配网相关命令,耗时的 WiFi 操作不得放在蓝牙回调中执行。
2. **WiFi 扫描**:扫描附近 WiFi,并返回网络列表(名称、信号强度、加密类型)。
3. **WiFi 配网**
- 接收手机下发的 SSID 与密码;
- 尝试连接目标网络;
- 向手机反馈结果:成功(含获取到的 IP)或失败及失败原因。
4. **异步反馈**:配网为异步过程,收到命令后先回"处理中",完成后再回最终结果。
5. **状态推送**:WiFi 连接中 / 已连接 / 断开 / 失败等状态变化时,主动向手机推送状态(仅在变化时推送)。
6. **错误处理**:对找不到目标网络、密码错误、信号过弱、设备忙等场景返回明确错误。
7. **并发安全**:配网期间避免与其它 WiFi 操作(如扫描、自动重连)冲突。
8. **联网校时**:WiFi 连接成功后,通过 NTP 获取当前时间,按北京时间(UTC+8)格式化后打印到串口。
### 6.3 完成标准
- [ ] 手机下发 SSID/密码后,先收到"处理中",连接成功后收到成功结果与 IP;失败时收到对应错误。
- [ ] 能返回扫描到的 WiFi 列表(名称 / 信号强度 / 加密类型)。
- [ ] WiFi 状态变化时手机端能收到状态推送。
- [ ] 蓝牙回调不被耗时操作阻塞,配网过程可稳定完成。
- [ ] WiFi 连接成功后,串口能打印出正确的北京时间(UTC+8,格式如 `2026-09-11 17:00:00`)。
## 七、任务四:WiFi 配置持久化与开机自动重连
### 7.1 任务目标
在任务三的基础上,把配网成功的 WiFi 信息保存到 Flash,使设备复位或断电重启后能自动扫描并连接已保存的 WiFi。
### 7.2 功能需求
1. **配置持久化**:配网成功后,将 SSID 与密码保存到 Flash,掉电不丢失。
2. **多网络保存**:支持保存多个 WiFi 配置,并能查询、删除已保存的网络(按训练方要求)。
3. **开机自动重连**:设备复位或上电后,读取 Flash 中已保存的 WiFi 配置,自动扫描并连接可用网络,无需重新配网。
4. **选择与重试**:存在多个已保存网络时,按信号强度或保存顺序选择合适的网络连接;连接失败按一定间隔自动重试。
5. **状态反馈**:自动重连过程中,通过 [附录 B](#附录-b蓝牙通信协议) 的状态推送通道向手机反馈 WiFi 状态变化。
6. **容错**:Flash 无配置或全部连接失败时,保持可被蓝牙配网的状态,且不阻塞其它功能。
### 7.3 完成标准
- [ ] 配网成功后配置写入 Flash,断电 / 复位后仍然存在。
- [ ] 复位后设备自动扫描并连接已保存的 WiFi,无需重新配网。
- [ ] 保存多个网络时能正确选择并连接可用网络。
- [ ] 连接失败能自动重试,且不阻塞其它功能。
- [ ] 能说明 Flash 存储结构与开机自动重连流程。
## 八、训练建议
1. 每个任务先画数据流图 / 时序图、先定协议再编码,便于自测。
2. 雷达数据可先确认帧结构与校验正确,再实现字段解析与打印。
3. 多任务开发时先明确"谁生产、谁消费、如何同步",再动手写代码。
4. 蓝牙通信建议使用调试 App 观察原始字节,确认分包与重组正确。
5. 养成记录调试过程的习惯:现象 → 定位 → 原因 → 解决,便于复盘。
---
## 附录 A:雷达串口通信协议
### A.1 物理层
| 参数 | 值 |
| --- | --- |
| 波特率 | 115200 |
| 数据位 / 停止位 / 校验 | 8 / 1 / 无(8N1 |
| 通信方式 | 主控下发命令 + 雷达主动上报 |
### A.2 帧格式
雷达与主控之间所有数据均采用如下格式,多字节字段均为**大端**:
```
53 59 | CTRL | CMD | LEN_H LEN_L | DATA... | CHECKSUM | 54 43
```
| 字段 | 长度 | 说明 |
| --- | --- | --- |
| 帧头 | 2 | 固定 `0x53 0x59` |
| CTRL 控制字 | 1 | 数据类别(人体存在 / 呼吸 / 心率 / 睡眠) |
| CMD 命令字 | 1 | 具体数据项;上报帧中最高位置 1(如 `0x03``0x83` 同义) |
| LEN | 2 | DATA 长度,大端 |
| DATA | N | 数据域 |
| CHECKSUM | 1 | 校验和 |
| 帧尾 | 2 | 固定 `0x54 0x43` |
**校验和**:从帧头第一个字节(`0x53`)累加到 DATA 最后一个字节,取累加和低 8 位,即:
```
CHECKSUM = (sum(frame[0] .. frame[帧长-4])) & 0xFF // 位于 frame[帧长-3]
```
### A.3 控制字与数据项
**CTRL = 0x80(人体存在)**
| CMD | DATA | 含义 |
| --- | --- | --- |
| `0x00` / `0x80` | 1B | 开关上报,`0x01` 为开启 |
| `0x01` | 1B | 人体存在:`0` 无人 / `1` 有人 |
| `0x02` | 1B | 运动状态:`0` 无 / `1` 静止 / `2` 活跃 |
| `0x03` | 1B | 体动参数(0~100 |
| `0x04` | 2B | 人体距离(cm |
| `0x05` | 6B | 坐标 X / Y / Z,各 2B;每值最高位为符号位(1 表示负) |
**CTRL = 0x81(呼吸)**
| CMD | DATA | 含义 |
| --- | --- | --- |
| `0x00` / `0x80` | 1B | 开关上报 |
| `0x01` | 1B | 呼吸状态 |
| `0x02` | 1B | 呼吸率(次/分) |
| `0x05` | 5B | 呼吸波形,实际值 = 字节值 − 128 |
**CTRL = 0x85(心率)**
| CMD | DATA | 含义 |
| --- | --- | --- |
| `0x00` / `0x80` | 1B | 开关上报 |
| `0x02` | 1B | 心率(BPM |
| `0x05` | 5B | 心跳波形,实际值 = 字节值 − 128 |
**CTRL = 0x84(睡眠)**
| CMD | DATA | 含义 |
| --- | --- | --- |
| `0x00` / `0x80` | 1B | 开关上报 |
| `0x01` / `0x81` | 1B | 床状态(入床 / 离床) |
| `0x03` / `0x83` | 2B | 清醒时长 |
| `0x04` / `0x84` | 2B | 浅睡时长 |
| `0x05` / `0x85` | 2B | 深睡时长 |
| `0x06` / `0x86` | 1B | 睡眠评分 |
| `0x0C` / `0x8D` | 8B | 综合状态:存在(1)、睡眠状态(1)、平均呼吸(1)、平均心率(1)、翻身次数(1)、大幅运动比例(1)、小幅运动比例(1)、呼吸暂停次数(1) |
| `0x0D` / `0x8F` | 12B | 睡眠统计:评分(1)、总睡眠时长(2)、清醒比例(1)、浅睡比例(1)、深睡比例(1)、离床时间(1)、翻身计数(1)、翻身次数(1)、平均呼吸(1)、平均心率(1)、呼吸暂停次数(1) |
| `0x0E` / `0x8E` | 1B | 异常状态 |
| `0x10` / `0x90` | 1B | 睡眠等级 |
| `0x11` / `0x91` | 1B | 挣扎报警 |
| `0x12` / `0x92` | 1B | 无人报警 |
### A.4 主控命令帧
命令帧固定为 10 字节:
```
53 59 | CTRL | CMD | 00 01 | VALUE | CHECKSUM | 54 43
```
- LEN 固定为 `0x0001`DATA 为 1 字节 `VALUE`
- CHECKSUM 为前 7 字节的累加和低 8 位。
### A.5 常用命令示例
| 作用 | 命令帧(HEX |
| --- | --- |
| 使能人体存在上报 | `53 59 80 00 00 01 01 2E 54 43` |
| 使能呼吸上报 | `53 59 81 00 00 01 01 2F 54 43` |
| 使能心率上报 | `53 59 85 00 00 01 01 33 54 43` |
| 使能睡眠上报 | `53 59 84 00 00 01 01 32 54 43` |
| 查询人体存在 | `53 59 80 80 00 01 0F BC 54 43` |
> 控制字、命令字与参数含义最终以雷达模组手册为准;上表为按本协议规则推导的示例,学员须自行验证。
---
## 附录 B:蓝牙通信协议
### B.1 总体设计
1. 所有业务数据统一封装为 TLV 二进制帧,通过 GATT Notify 分包发送。
2. 客户端必须先按特征 UUID 分流,再按命令字 `CMD` 解析。
3. `b1/b2` 为一问一答通道:客户端写 `b1`,设备从 `b2` 通知响应。
4. `a1/a2/b3` 为主动推送通道,不参与请求响应匹配。
5. 命令结果只以 `TLV_RESULT_CODE` 为准。
6. 状态变化通过 `b3` 推送,与命令结果解耦。
### 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` 推送。