mothercup/SmartAssiter/docs/修改记录_2026-09-05_真机联调_BLE通道隔离与SAF选包.md
evan.liu 3e87d333cb App: adapt to firmware V1.00.23 BLE protocol + field debugging fixes
- BluetoothManager: per-characteristic isolated channels (per-UUID read
  queue/timeout/dispatch, no cross-char write blocking), 10007 delayed
  retry for read/write, 300ms link settle after discovery, full tx/rx
  hex logging
- McmCli/McmInfo/McmOta: command/response, TLV parse and OTA frame logs
- home.vue: Auto refresh switch (polling off by default, no GATT
  interference with OTA), MTU-then-load sequencing
- ota.vue: SAF file picker via plus.android (ACTION_GET_CONTENT) with
  Scanner whole-stream read + magic self-check + per-byte fallback;
  default path moved to _doc (Android 10+ scoped storage)
- docs: change logs for 2026-09-04 protocol adaptation and 2026-09-05
  field debugging; AGENTS.md updated
2026-09-05 06:45:04 +08:00

4.2 KiB
Raw Permalink Blame History

修改记录 2026-09-05:真机联调——BLE 通道按特征值隔离 + SAF 选包 + 全链路日志

背景

V1.00.23 协议适配(见 2026-09-04 修改记录)后真机联调,依次踩到并解决: 连接后读超时/写 10007、OTA 页读包失败(Android 10+ 分区存储)、 plus 桥 byte[] 不回写导致读包内容错误等。本轮全部修复并加了可定位问题的日志。

改动清单

src/BluetoothManager.ts(核心:读写按特征值隔离成独立通道)

  • 读改为按特征 UUID 分键的独立队列(readQueues/readActiveMap/readTimers): 同一特征上的读串行(e0003 分包读不与 e0004 轮询读交错);不同特征互不阻塞, 一路超时/失败不影响其他通道;onBLECharacteristicValueChange 按 characteristicId 直接分发到对应通道
  • 写无任何跨特征等待(writeChar 直接发);断连时逐通道排空各自队列
  • 10007 "property not support" 延时重试:读和写各一次(1600ms)——实测安卓 链路未稳定时会误报 10007(特征属性明明支持写),参考 DCloud 社区已知问题
  • 链路稳定期:scanServices 成功后 300ms 内不发出 GATT 操作(连接级一次性)
  • 全链路日志:连接/断开事件、tx/rx <特征短名> <长度> <hex>(截断标注总长)、 读发起/超时、10007 重试提示

实测根因记录:home 页曾在 bleState=0 时并发调 setMtu 与读 e0004, 读被安卓无声丢弃(3s 超时),后续写全部被拖进 10007;通道隔离 + 时序修正后消失。

src/mcm/McmCli.ts

  • 日志:[CLI] >> 命令 / [CLI] << (NB, status=0) <JSON 化应答>,失败带底层 errMsg 原文;CliResult 新增 errMsg 字段

src/mcm/McmInfo.ts

  • 日志:[INFO] TLV NB parsed: {...};读失败打 [INFO] read failed

src/mcm/McmOta.ts

  • 帧日志:BEGIN/END/ABORT 全帧 hex;每条 OTA_RSP 打 echo/status/offset + hex; 坏帧内容一并打出(DATA 帧体不逐条打,避免刷屏)

pages/tabbar/home.vue

  • Auto refresh (2s) 开关,缺省关闭:不再自动周期读 e0004,避免轮询占用 GATT 干扰 OTA/CLI;开关打开才轮询(立即查一次 + 2s 周期); 连接就绪回调与 onShow 两个自动启动点都已按开关门控
  • 连接初始化改串行:先 setMtu(247),回调里再 loadDeviceInfo()(消除 GATT 并发撞车)

pages/tabbar/ota.vue(选包/读包重做)

Android 10+ 分区存储(targetSdk≥29)禁止直读 /sdcard/Download(plus 报 code 15),uni.chooseFile 在 App 端 vue3 又不存在,最终方案:

  • Choose File 按钮:plus.android 起 Intent.ACTION_GET_CONTENT 系统 SAF 选择器(免权限,可直接选 Download 里的包)
  • 读包:ContentResolver.openInputStream(uri) → java.util.Scanner 按 ISO-8859-1 整流读成 String 过桥(字节 1:1 映射,规避 byte[] 参数按值拷贝、 read(buf) 写不回 JS 侧的桥限制——曾读出整块填充字节 0x41)→ 读回自验 magic(11 BA 10 CA)→ 不符自动重开流落逐字节 read() 直读(int 返回值 过桥,二进制绝对精确,每 16KB 打进度)
  • 全程日志:picker 拉起/onActivityResult 返回码/uri 原文/读取模式/字节数/ 文件头 hex/magic 校验结论;失败分支带异常原文
  • 手动路径方式保留:默认 _doc/mothercup_ble_ota.bin(应用私有目录,可 adb push 进去);解析失败时日志带实际读到的长度+头部 hex,便于区分"读错"与"格式错"
  • window.plus 改 globalThis.plus(App 端 vue3 无 window 对象)

验证(真机)

  • e0004 参数特征读通:TLV 33B 解析正确(V1.00.23 / APP1 / 21.2℃ / 3335mV / uptime / 堆剩余),10007 与读超时不再出现
  • SAF 选包读通:111168B 与包文件一致
  • parseCombo 逻辑在 PC 侧 node 用真实 mothercup_ble_ota.bin 逐字节验证: magic/hdr_len/total_size/payload_crc/逐 bank crc 全对(协议符合性确认无误)

待办

  • BLE OTA 全流程真机(Start Upgrade → 复位 → 回连复核 PASS)
  • 修改记录 2026-09-04 的实机验证项随本轮一并闭环