# 新人项目训练任务书 ## 目录 - [一、训练目的](#一训练目的) - [二、硬件与开发环境](#二硬件与开发环境) - [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-S3(Freenove ESP32-S3 WROOM,N8R8:8MB 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_STATUS(0x10)** - 请求:无载荷。 - 响应(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_RADAR(0x12)** - 请求:无载荷。 - 响应(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_CONTINUOUS(0x14)** - 请求:`TLV_INTERVAL_MS`(有效范围 100~10000 ms)。 - 响应:`TLV_RESULT_CODE`,成功时附 `TLV_INTERVAL_MS`;参数缺失/非法返回对应错误码。 - 启动后设备按间隔通过 `a1` 推送 `CMD_CONTINUOUS_PUSH(0x18)` 帧。 **CMD_STOP_CONTINUOUS(0x16)** - 请求无载荷;停止推送,幂等操作,始终返回 `SUCCESS`。 **CMD_CONTINUOUS_PUSH(0x18,a1 推送)** - 载荷:`TLV_TIMESTAMP`、`TLV_PRESENCE`、`TLV_HEART_RATE_X10`、`TLV_BREATH_RATE_X10`、`TLV_MOTION`、`TLV_DISTANCE_CM` 等。 **CMD_WIFI_SCAN(0x20)** - 请求无载荷。先回 `PROCESSING`;完成后回 `TLV_RESULT_CODE` + `TLV_WIFI_COUNT` + 多个 `TLV_WIFI_ITEM`(每项含 `TLV_SSID`、`TLV_RSSI`、`TLV_SECURITY`)。 **CMD_WIFI_CONFIG(0x22)** - 请求:`TLV_SSID`、`TLV_PASSWORD`。 - 先回 `PROCESSING`(可含 `TLV_SSID`);完成后回 `SUCCESS` + `TLV_SSID` + `TLV_IP_ADDRESS`,失败回对应错误码。 **CMD_GET_SAVED_WIFI(0x24)** - 响应:`TLV_RESULT_CODE` + `TLV_WIFI_COUNT` + 多个 `TLV_WIFI_ITEM`。 **CMD_DELETE_SAVED_WIFI(0x26)** - 请求:`TLV_SSID`;响应:`TLV_RESULT_CODE`。 **CMD_DEVICE_INFO_PUSH(0x19,b3 推送)** - `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` 推送。