169 lines
7.2 KiB
Markdown
169 lines
7.2 KiB
Markdown
# 统一 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 分路解析
|
||
- ED713:MAC[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 条目覆盖)
|