SEC_Warehouse/docs/unified-ble-flow.md

7.2 KiB
Raw Permalink Blame History

统一 BLE 连接与控制流程ED713 / ED719

1. 标准连接流程图(文字版)

  1. 初始化阶段
  • openBluetoothAdapter
  • 注册监听:onBluetoothAdapterStateChangeonBLEConnectionStateChangeonBLECharacteristicValueChange
  1. 搜索阶段
  • 优先过滤扫描:startBluetoothDevicesDiscovery({ services:[0x00F4] })
  • 超时无结果则无过滤兜底扫描
  • 选择目标设备 deviceId
  1. 连接与发现阶段
  • createBLEConnection(deviceId)
  • getBLEDeviceServices,定位服务 0x00F4
  • getBLEDeviceCharacteristics,识别 F401/F402/F403/F501/F301/F302
  • 订阅通知:notify(F301)=truenotify(F302)=true
  1. 标准业务阶段
  • 读取设备信息:read(F501)
  • 鉴权:write(F402, A7分包key),监听 F301 状态码
  • 当前项目约定:已知密钥 = 设备 MAC 去分隔符后 + 0000,例如 10:52:1C:81:64:F410521C8164F40000
  • 鉴权成功后进行功能操作:
    • WiFi 配网:write(F401, A7分包ssid|pass)
    • 控制命令:write(F403, [cmd])
    • 雷达数据:cmd=0xA1 开始、cmd=0xA2 停止,解析 F302
  1. 收尾阶段
  • 停止扫描 / 断开连接 / 关闭适配器
  • 清理监听器与状态

2. 目录结构

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. 核心流程代码示例

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=0x7cED719=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
  • 新增 wallOptionpeopleHaveSwitchpeopleActivitySwitch 字段解析

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: 透传 optionsreadDeviceInfo
  • writeKeyAndExpectStates: rejectOnUnexpectedtrue 改为 false,避免设备中间态(-1/0直接 reject 阻断鉴权
  • ensureAuthorizedWithDeviceInfo: 移除 bindStatus === null 分支ED719 实际布局与 ED713 一致bindStatus 可正常读取)

controller.js

  • 特征分发器 createCharacteristicDispatcherparseDeviceInfo 调用传入 profile.id

bleCore.js

  • closeAdapter(): 新增重置 adapterStateHandler/connectionStateHandler/characteristicValueHandler/deviceFoundHandlernull,确保 openAdapterinit() 可重新注册所有原生监听

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 条目覆盖)