# BLE 协议冲突与问题清单

更新时间：2026-05-11

## 结论

当前补充协议与旧 BLE 协议、原小程序实现存在实质冲突。由于项目当前优先目标是尽快真机跑通，执行口径调整为：**先以新补充协议为准，旧协议作为历史参考和后续逐步补齐的扩展协议**。

小程序已先接入新协议的最小可跑通路径：`FFE1` 数据通信服务 / Command 写入，`FFE4` Status 订阅，Command 直接写 33 字节参数块。旧协议中的 `0xAA 0x55 | length | type | payload | XOR checksum` 帧结构暂时保留在代码中，但不作为当前治疗参数下发主路径。

新补充的 `协议简述.docx` 仍然缺少绑定、停止、查询、ACK、Status/ADC 完整字节表等内容；这些不再阻塞首轮跑通，但会影响后续完整交互和状态展示，需要继续补齐。

## 资料来源

| 来源 | 当前用途 | 说明 |
| --- | --- | --- |
| `docs/protocols/通信协议_小程序与光子美容仪设备.docx` | 旧 BLE 协议来源 | 现有 BLE 代码和架构文档主要基于此协议 |
| `docs/protocols/协议简述.docx` | 供应商补充协议 | 2026-05-11 归档，内容较短，主要描述 33 字节 Command 和 Status notify |
| `docs/protocols/协议简述-补充解析.md` | 补充协议解析稿 | 已抽取补充协议中的 UUID、特征、33 字节字段 |
| `miniprogram/services/ble/protocol.js` | 当前实现 | 新协议优先：`PROTOCOL_MODE = vendor_33`，生成 33 字节 Command |
| `miniprogram/services/ble/commands.js` | 当前实现 | `setParams()` 直接写 33 字节；旧命令保留为后续兼容 |
| `miniprogram/services/ble/connection.js` | 当前实现 | 发现 `FFE1` command，订阅 `FFE4` status |

## P0 阻塞问题

这些问题不解决，真机 BLE 联调大概率不通。

| 问题 | 旧协议/当前代码 | 补充协议 | 影响 |
| --- | --- | --- | --- |
| UUID 分配冲突 | `FFE1` 是数据通信服务，`FFE4` 是 Command，`FFE5` 是 Status | `FFE1` 同时写作数据通信服务和 Command，`FFE4` 是 Status | 小程序可能写错 characteristic，也可能订阅错 notify |
| Command 写入格式冲突 | 写入完整帧：`0xAA55 + length + type + payload + checksum` | 只描述 33 字节 Command 参数块 | 如果固件只收裸 33 字节，当前写入会被拒绝；如果固件收旧帧，按补充协议改也会失败 |
| 命令字机制缺失 | 有 `0x01` 设置参数、`0x02` 启动、`0x03` 停止、`0x04` 查询、`0x05` 绑定、`0x06` 解绑 | 未出现命令 type | 无法判断 33 字节是“设置参数”还是“设置并启动”，也无法覆盖停止/查询/绑定 |
| ACK 机制冲突 | 每次写命令会等待 `0x22 ACK`，5 秒超时后失败 | 未说明 ACK/NACK | 即使设备执行了命令，只要不回 ACK，小程序仍会判定失败并重试 |
| Status notify 格式缺失 | 当前解析 `0x21 STATUS_REPORT` 的 14 字节 payload | 只写“设备状态及 ADC 值，Read + Notify” | 小程序无法正确解析设备状态、电量、温度、ADC 或错误码 |
| 校验规则不一致 | 当前 XOR 覆盖帧头、长度、type、payload | Byte33 是异或校验，但未写范围 | 校验范围不同会导致设备丢包或小程序丢通知 |

## P1 高风险不一致

这些问题不一定让连接失败，但会让参数含义、治疗流程或数据记录出错。

| 问题 | 当前实现 | 补充协议/文档缺口 | 风险 |
| --- | --- | --- | --- |
| 治疗参数模型不同 | `region_mask + wavelength + brightness + duration_ms + mode` | IO1-IO5 各自包含红灯、红外、紫外、暖黄光强和电流增益 | 当前 UI 和协议无法表达每个 IO 的独立光强/电流 |
| 时间字段不同 | `duration_ms` 为 4 字节大端毫秒 | Byte31-32 为保持时间高/低字节 | 单位、范围和字节序不明，可能导致治疗时长错误 |
| IO 与面部区域无映射 | 当前用 7 个区域 bit：左脸、右脸、额头、下巴、鼻部、左眼、右眼 | 只定义 IO1-IO5 | 无法从小程序区域选择稳定生成 IO 参数 |
| 光强取值范围不明 | 当前 brightness 默认 200，波长单选 | 四种灯光每个 IO 一个强度 | 不知道是 0-100、0-255、PWM、DAC 还是其他单位 |
| 电流增益定义不明 | 当前没有电流增益字段 | 每个 IO 2 字节电流增益 | 不知道单位、范围、字节序和安全上限 |
| 启动/停止语义不明 | `SET_PARAMS` 后还会发 `START`，停止发 `STOP` | 补充协议只描述 Command 参数块 | 如果写 33 字节会立即启动，当前双命令流程不适用；如果不会启动，还缺 START 定义 |
| 绑定命令长度疑似错误 | 架构文档写 `userId(8B)`，代码实际用 `uint32ToBytes()` 生成 4B | 补充协议未覆盖绑定 | 绑定流程可能与固件预期不一致，需要单独确认 |

## P2 文档和实现需要收敛的问题

| 问题 | 当前状态 | 建议 |
| --- | --- | --- |
| 权威协议未指定 | 旧协议、架构文档、补充协议并存 | 明确“最终以哪一份为准”，或把补充协议定义为旧协议的某个命令 payload |
| `FFE1` 被同时当服务和特征 | 补充协议中表述冲突 | 要求供应商给出完整 GATT 表：service UUID、characteristic UUID、properties |
| Status/ADC 字节表缺失 | 只有功能描述，无字段定义 | 补齐每个字节的含义、长度、单位、字节序和上报频率 |
| 错误码缺失 | 当前代码有 `0x00-0x0C` 错误码 | 确认固件是否实现这些错误码，或给出新错误码表 |
| 分包/MTU 未定义 | 当前默认一条写入就是完整命令 | 33 字节裸包可能超过默认 20 字节 BLE payload，需要确认 MTU 或分包策略 |
| OTA 未受补充协议覆盖 | 当前旧协议包含 OTA 特征 | 补充协议没有 OTA 说明 | OTA 是否仍按旧协议，需要确认 |

## 对当前代码的具体影响

### `protocol.js`

- `SERVICE.DATA_COMM = FFE1` 与补充协议的 `FFE1 Command` 表述冲突。
- `CHAR.COMMAND = FFE4` 与补充协议的 `FFE4 Status` 冲突。
- `CHAR.STATUS = FFE5` 在补充协议中未出现。
- `buildFrame()` 固定生成 `0xAA55` 帧，无法生成补充协议的裸 33 字节 Command。
- `parseFrame()` 只接受 `0xAA55` 帧，无法解析补充协议可能上报的裸 Status/ADC 数据。
- `parseStatusReport()` 固定要求 14 字节旧格式，与补充协议的 ADC 上报不匹配。

### `commands.js`

- `writeCommand()` 每次自动追加 `seq` 并等待 ACK；补充协议没有 `seq` 和 ACK。
- `setParams()` 只能下发单一波长、全局亮度和全局时长，无法生成 IO1-IO5 的 33 字节参数矩阵。
- `startTreatment()`、`stopTreatment()`、`queryStatus()`、`bindDevice()`、`unbindDevice()` 都依赖旧命令字；补充协议没有对应定义。
- `bindDevice()` 目前把 `userId` 编成 4 字节，但旧架构文档写的是 8 字节，存在独立的实现疑点。

### `connection.js`

- 发现特征时会把 `FFE4` 当命令写入特征，把 `FFE5` 当状态通知特征。
- 如果新固件实际用 `FFE1` 写命令、`FFE4` 发通知，当前连接后会找不到正确 command/status，或者写入/订阅目标错误。
- notify 回调会先调用 `parseFrame()`；如果新固件直接上报 Status/ADC 裸数据，当前代码会直接丢弃。

## 需要供应商/固件侧确认的问题

优先级按联调阻塞程度排序：

1. 最终 GATT 表：`FFE0`、`FFE1`、`FFE2`、`FFE3`、`FFE4`、`FFE5`、`FFE6`、`FFE7`、`FFE8`、`FFE9` 分别是什么，属性是 read/write/notify 哪些。
2. Command 写入到底是旧帧格式，还是直接写 33 字节。
3. 如果是 33 字节，是否需要分包；如果需要，分包格式是什么。
4. Byte33 XOR 对哪些字节计算，初始值是多少，校验字节本身是否参与最终校验。
5. 33 字节 Command 的语义：只设置参数，还是设置后立即启动。
6. 停止、暂停、恢复、查询状态、绑定、解绑是否仍有命令；命令格式是什么。
7. 是否需要 ACK/NACK；如果需要，ACK/NACK 的 characteristic、字节格式、错误码表是什么。
8. Byte31-32 保持时间的单位、范围和字节序。
9. IO1-IO5 与灯板/面部区域的对应关系。
10. 红灯、红外、紫外、暖黄光强的取值范围、单位和安全限制。
11. 电流增益高/低字节的单位、范围、字节序和安全限制。
12. Status/ADC notify 的完整字节布局、上报周期和单位。
13. 旧协议中的 `FFE5`、`FFE6`、OTA 相关特征是否还保留。
14. 绑定流程是否由 BLE 完成；`userId` 是 4 字节还是 8 字节。

## 建议处理方案

### 方案 A：补充协议只是 `SET_PARAMS` 的新 payload

如果供应商确认旧帧、旧 UUID、旧 ACK 都保留，只是 `0x01 SET_PARAMS` 的 payload 变成 33 字节：

- 保留 `FFE1` 服务、`FFE4` command、`FFE5` status。
- 保留 `0xAA55` 帧封装、`type`、`seq`、ACK。
- 新增 `buildVendorCommand33()` 生成 33 字节参数块。
- 修改 `setParams()`，让旧 UI 参数转换成 IO1-IO5 默认矩阵。
- 补 Status/ADC 新解析逻辑。

这是对当前代码影响最小的路线。

### 方案 B：补充协议完全替代旧协议

如果供应商确认新固件只接受 `FFE1` 裸 33 字节写入、`FFE4` 裸 Status notify：

- `protocol.js` 需要新增或切换成新协议模式。
- `connection.js` 的 command/status characteristic 发现逻辑要改。
- `commands.js` 的 ACK、seq、旧命令字重试机制不能直接沿用。
- 绑定、停止、查询状态、异常处理、治疗完成都需要供应商补齐协议后再实现。

这个方案会影响小程序治疗主链路，不能只改一个 UUID。

## 当前建议

当前已经按方案 B 的最小版本推进。后续建议：

1. 真机联调优先验证 `FFE1` 写入 33 字节是否能启动设备。
2. 抓取 `FFE4` notify 原始字节，补 Status/ADC 字节表。
3. 要求供应商补停止、查询、异常、完成、绑定这些命令是否存在。
4. 后续再决定是否把旧 `0xAA55` 帧协议作为兼容模式保留。
