SEC_Warehouse/docs/unified-ble-flow.md

169 lines
7.2 KiB
Markdown
Raw Permalink 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.

# 统一 BLE 连接与控制流程ED713 / ED719
## 1. 标准连接流程图(文字版)
1. 初始化阶段
- `openBluetoothAdapter`
- 注册监听:`onBluetoothAdapterStateChange`、`onBLEConnectionStateChange`、`onBLECharacteristicValueChange`
2. 搜索阶段
- 优先过滤扫描:`startBluetoothDevicesDiscovery({ services:[0x00F4] })`
- 超时无结果则无过滤兜底扫描
- 选择目标设备 `deviceId`
3. 连接与发现阶段
- `createBLEConnection(deviceId)`
- `getBLEDeviceServices`,定位服务 `0x00F4`
- `getBLEDeviceCharacteristics`,识别 `F401/F402/F403/F501/F301/F302`
- 订阅通知:`notify(F301)=true`、`notify(F302)=true`
4. 标准业务阶段
- 读取设备信息:`read(F501)`
- 鉴权:`write(F402, A7分包key)`,监听 `F301` 状态码
- 当前项目约定:**已知密钥 = 设备 MAC 去分隔符后 + `0000`**,例如 `10:52:1C:81:64:F4``10521C8164F40000`
- 鉴权成功后进行功能操作:
- WiFi 配网:`write(F401, A7分包ssid|pass)`
- 控制命令:`write(F403, [cmd])`
- 雷达数据:`cmd=0xA1` 开始、`cmd=0xA2` 停止,解析 `F302`
5. 收尾阶段
- 停止扫描 / 断开连接 / 关闭适配器
- 清理监听器与状态
## 2. 目录结构
```text
utils/ble/
core/
bleCore.js # 蓝牙核心能力(连接/发现/读写/订阅/重连)
controller.js # 标准流程编排scan->connect->discover->auth
errors.js # 统一异常
eventBus.js # 回调分发
packet.js # A7 分包工具
retry.js # 重试工具
state.js # 状态模型
modules/
auth.js # 鉴权流程读MSG + 写KEY
wifi.js # WiFi配置流程
radar.js # 雷达控制流程
parsers/
commonParser.js # MSG/STATE/雷达通用解析
index.js # 解析聚合出口
protocols/
profiles.js # ED713/ED719/UNKNOWN profile 差异配置
utils/
bytes.js # 字节/高低位工具
hex.js # hex/utf8 转换
uuid.js # UUID 标准化与比较
index.js # 统一出口
```
## 3. 公共方法列表
- 蓝牙核心
- `createBleCore(options)`
- `openAdapter/getAdapterState/closeAdapter`
- `startDiscovery/stopDiscovery`
- `connect/disconnect`
- `discoverServices/discoverCharacteristics`
- `readCharacteristic/writeCharacteristic/notifyCharacteristic`
- 流程编排
- `createUnifiedBleController(options)`
- `standardConnectFlow({ deviceId, key })`
- `scanAndPickDevice/connectAndDiscover/cleanup`
- 业务模块
- `createAuthModule(ble).ensureAuthorized(key)`
- `createAuthModule(ble).ensureAuthorizedByMac({ suffix: '0000' })`
- `createWifiModule(ble).configureWifi(ssid, password)`
- `createRadarModule(ble).startRadarStream()/stopRadarStream()/writeFallParams()`
- 工具
- `buildA7Packets(payload, packetConfig)`
- `bytesToHex/hexToBytes/utf8ToBytes/bytesToUtf8`
- `splitToLowHigh/joinLowHigh/readUint16LE/readUint32LE`
- `normalizeUuid/toFullUuid/uuidEquals`
## 4. 核心流程代码示例
```js
import {
createUnifiedBleController,
DEVICE_PROFILE
} from '@/utils/ble'
const bleController = createUnifiedBleController({
profileId: DEVICE_PROFILE.UNKNOWN,
reconnect: { enabled: true, retries: 2, delay: 1000 }
})
async function runStandardFlow({ key, ssid, password }) {
try {
// 1) 连接 + 服务发现 + 自动订阅F301/F302 + 鉴权
const session = await bleController.standardConnectFlow({ key })
// 2) 读取设备信息(如需要可再次读取)
const info = await bleController.auth.readDeviceInfo()
// 3) WiFi 配置
const wifiResult = await bleController.wifi.configureWifi(ssid, password)
// 4) 雷达控制
await bleController.radar.startRadarStream()
return {
session,
info,
wifiResult
}
} finally {
// 页面退出或流程结束时清理
await bleController.cleanup()
}
}
```
## 5. ED713/ED719 兼容策略
- 相同 UUID 与鉴权主流程统一抽象。
- 差异通过 `profiles.js` 配置:
- `radar.notifySignature`: ED713=`0x7c`ED719=`0x67`
- `cmd.supportsNarrowMode`: ED713=true
- `cmd.supportsFallParam67`: ED719=true
- 未知设备先用 `UNKNOWN`,收到 `F302` 数据后按签名字节自动识别 profile。
## 6. 修改记录
### 2026-04-30 对照协议文档第二轮修复
#### commonParser.js
- `parseDeviceInfo(payload, profileId)`: 重写为按 ED713/ED719 分路解析
- ED713MAC[0:6] + bindStatus[6] + 其它[7:10] + productId[10:12] + baseBoard[12] + coreBoard[13] + 其它[14:16] + deviceType[16] + wifiStatus[17] + cellularStatus[18]
- ED719布局与 ED713 一致bindStatus/productId 偏移相同,文档仅省略标注),复用 `parseEd713DeviceInfo`
- `parseEd719Radar`: 修正 `shieldNum` 从 bytes[27] → bytes[24](按文档结构体偏移累加 header[4]+event+people+num+nodata+height+mode+beeper+left+right+front+back+sensitive+nodata1+stateDelay=24
- 新增 `wallOption`、`peopleHaveSwitch`、`peopleActivitySwitch` 字段解析
#### radar.js
- `setNarrowMode(enabled)`: 修正命令格式,从单字节 `0x7C`/`0x7D` 改为两字节 `[0x7C, flag]`flag 0=关 1=开(符合协议文档 CMD=0x7C + 1byte参数
#### auth.js
- `readDeviceInfo(options)`: 新增 `msgTimeout` 参数与 4 秒超时保护,防止 UUID_MSG 无回包时页面挂死
- `readDeviceInfo()`: 调用 `parseDeviceInfo` 时传入 `ble.getProfile().id`
- `ensureAuthorized`/`ensureAuthorizedByMac`: 透传 `options``readDeviceInfo`
- `writeKeyAndExpectStates`: `rejectOnUnexpected``true` 改为 `false`,避免设备中间态(-1/0直接 reject 阻断鉴权
- `ensureAuthorizedWithDeviceInfo`: 移除 `bindStatus === null` 分支ED719 实际布局与 ED713 一致bindStatus 可正常读取)
#### controller.js
- 特征分发器 `createCharacteristicDispatcher``parseDeviceInfo` 调用传入 `profile.id`
#### bleCore.js
- `closeAdapter()`: 新增重置 `adapterStateHandler`/`connectionStateHandler`/`characteristicValueHandler`/`deviceFoundHandler` 为 `null`,确保 `openAdapter``init()` 可重新注册所有原生监听
#### pages/device/config.vue
- `openWifiPanel`: `prepareWifiConfig` 超时从 `800000` 改为 `8000`,新增 `msgTimeout: 4000`
- `wifiPanelVisible = true` 后加 `await this.$nextTick()` 确保 Vue DOM 更新后再调原生 toast
#### hooks/useBluetoothDiscovery.js
- 新增 `SCAN_DURATION_MS = 30000`,蓝牙搜索 30 秒后自动停止
- `startSearch`: 搜索开始前同步设置 `isSearching = true`(避免异步导致无法暂停);先 `stopDiscoverySilently()``resetDeviceMap()`(新搜索刷新数据);启动 30 秒自动停止定时器
- `startSearch`: `stopDiscoverySilently()` 后执行完整适配器重置(`unwatch*` 注销所有原生监听 → `closeAdapter` 关闭适配器 → `initialized = false`),由 `ensureInitialized` 重新打开并注册全部监听,确保每次搜索都从干净适配器状态开始,修复二次搜索找不到设备的问题
- `stopSearch`: 移除 `resetDeviceMap()` 调用,暂停搜索时保留已发现设备数据;清除自动停止定时器
### 2026-04-29 对照协议文档修复
(初次修复,记录同上,已被 2026-04-30 条目覆盖)