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

79 lines
4.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.

# 修改记录 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 的实机验证项随本轮一并闭环