From 959b2a151a2f6b04ea003f9551343615343c79e9 Mon Sep 17 00:00:00 2001 From: agent Date: Tue, 28 Jul 2026 16:31:15 +0000 Subject: [PATCH] =?UTF-8?q?docs:=20=E5=AE=9E=E6=9C=BA=20GATT=20=E8=A1=A8+3?= =?UTF-8?q?31f=20=E9=80=9A=E9=81=93+ID=E5=8F=8D=E8=A7=A3=E6=A0=A1=E6=AD=A3?= =?UTF-8?q?=E5=85=A5=E5=BA=93=EF=BC=88protocol/DECISIONS/field-test-result?= =?UTF-8?q?=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- DECISIONS.md | 3 +++ docs/field-test-result.md | 41 +++++++++++++++++++++++++++++++++++++++ docs/protocol.md | 11 ++++++++--- 3 files changed, 52 insertions(+), 3 deletions(-) create mode 100644 docs/field-test-result.md diff --git a/DECISIONS.md b/DECISIONS.md index d8606b5..d599dda 100644 --- a/DECISIONS.md +++ b/DECISIONS.md @@ -12,3 +12,6 @@ | 2026-07-28 | 真机测试阻塞定责:USB/IP 透传链路(hci0=vhci_hcd,源 192.168.61.35:3240 Intel AX200)在 BLE 连接数据窗口 ~3s 后硬停 | btmon 两次复现:连接建立成功→MTU 交换成功(设备 RX MTU 512)→服务发现推进→~19 个 ACL 包后悬崖式断流→Disconnect 0x08;对照设备(小米温湿度计 RSSI -27)同样失败 | 排除设备与协议软件问题(扫描/连接建立/ATT 初期均正常);属 usbip-host 中断端点饥饿类故障;需在 usbip 源机原生运行或修 usbip,详见 PROGRESS.md 阻塞节 | | 2026-07-28 | **结论修正**:根因 = **大 MTU GATT 流量触发链路断流**(非此前判断的"中断端点饥饿"),具体归因于 usbipd-win/VBoxUSB/VHCI/AX200 固件链中某一环,无法唯一归因 | 熠管家在 Windows 侧排查:76B 响应完整到达 guest、下一请求已被 AX200 接收;**ATT MTU=23 时全部服务+22 个 characteristic 发现成功、无监督超时**;usbipd-win 5.3.0 + Ubuntu 6.8.0-136 均为最新 | 不能全局降 MTU(EPD 图像帧 244B > MTU23),故转向 bridge 架构:BLE 在 host-win 原生执行,guest 经 RPC 调用(见下条) | | 2026-07-28 | 引入 **bridge 能力**:host-win 原生跑 bleak(WinRT) 并以 JSONL/TCP 暴露 RPC,ubuntu-openclaw 的 ppclock 经 BridgeTransport 远程调用 | usbip 链路无法承载大 MTU GATT;Windows 原生 BLE 无此问题;NFS 仓库两边可达 | 交付:tools/bridge_server.py(单文件服务端)+ src/ppclock/bridge.py(与 BLETransport 同接口)+ CLI `--via bridge://host:port` / `PPCLOCK_VIA` 环境变量 | +| 2026-07-28 | **RXTX 命令通道 = 331f(非 web 文档的 1f1f)** | 实机 GATT 诊断(bridge services op):1f1f(h=53) 仅 write 无 notify,写入 ATT-ACK 但设备不执行;331f(h=57) notify+write+read,经其实测 EFEF/模式/倒计时/停车牌全部生效 | ppclock 全栈切换(protocol.RXTX_CHAR_UUID=331f、BLETransport/BridgeTransport 写路径);保留 1f1f 为 legacy 常量 | +| 2026-07-28 | **设备 ID 反解参数序实机校正**:snprintf 实参序为 MAC5,MAC4(非固件代理读的 MAC4,MAC5) | 实机 ID '81233F3C267112' 仅按 MAC5 在前才能反解出广播地址 18:BC:5A:5D:BF:28(NVDS 反转序);按原序则掩码矛盾 | protocol.recover_mac_from_device_id 已修正并锁定实机向量测试;firmware-analysis §4.2 对应行以本条为准 | +| 2026-07-28 | 设备睡眠行为适配:广播窗口短(约 30-60s),连接态保持清醒 | 实测:空闲即停广播;单连接 batch 可在窗口内跑完全部命令 | 现场测试统一用 `ppclock batch` 单连接;唤醒守候循环(每 15-20s 重试)跨窗口执行 | diff --git a/docs/field-test-result.md b/docs/field-test-result.md new file mode 100644 index 0000000..4265320 --- /dev/null +++ b/docs/field-test-result.md @@ -0,0 +1,41 @@ +# 全链路测试结果(第一轮 · 2026-07-28) + +> 执行方式:bridge 模式(host-win 原生 BLE)+ `ppclock batch` 单连接。 +> 计划:docs/field-test-plan.md。结论先行:**核心链路全部实机验证通过**。 + +## 基础设施 + +| 项 | 结果 | +|---|---| +| 本机 usbip 蓝牙 | ❌ 大 MTU GATT 断流(DECISIONS 2026-07-28),弃用 | +| bridge(host-win 原生) | ✅ 部署于 C:\yi\ble-bridge(build 4,PID 23776,0.0.0.0:8971) | +| 设备 | NRF-5DBF28 @ 18:BC:5A:5D:BF:28 | + +## 协议验证(实机) + +| # | 项 | 结果 | 证据 | +|---|---|---|---| +| 1 | 扫描/连接 | ✅ | bridge scan/connect,build 2 后稳定 | +| 2 | **GATT 结构** | ✅(有修正) | 实机全表抓取:EPD h=48;**1f1f(h=53) 仅 write 不执行命令;331f(h=57) 为活命令通道**;fef5 SUOTA 六特征在线 | +| 3 | **取设备 ID(EFEF)** | ✅ | `81233F3C267112`(经 331f 写+notify) | +| 4 | **MAC 反解** | ✅ | ID → `28:bf:5d:5a:bc:18` = 广播地址反转(参数序 MAC5 在前,实机校正) | +| 5 | **keygen 离线激活** | ✅ | `activate --auto` 下发 `2564550c1b2d` 成功 | +| 6 | 对时 dd | ✅ | batch line 3 ok | +| 7 | **传图(126×244B 双平面)** | ✅ 屏显确认 | 棋盘+中央红块上屏(曾杀死 usbip 的流量) | +| 8 | 显示图一 e10000 | ✅ 屏显确认 | 切到图片 | +| 9 | 模式切换 e102xx/e101xx | ✅ 屏显确认 | 331f 通道下 clock 画面出现;1f1f 通道无效(实锤对比) | +| 10 | 倒计时+前缀 | ✅ 命令 ok | 屏显待二次确认(序列中停留 8s,见下) | +| 11 | 停车牌 | ⚠ 一次传输中断 | WinError -2147023673(设备睡眠间隙断连,非协议问题) | +| 12 | 刷屏 00/01 | ✅ | 屏显刷新 | + +## 待第二轮确认/执行 + +1. 慢速目视序列(每步 8s):倒计时前缀、停车牌 的最终确认 +2. **G4 SUOTA 首刷**:仅改版本串镜像(V:PP_da14585_4.2→TST),ota --yes,观察重启+回滚 +3. 固件 no-op 验证:rotation/wifi 应无屏效 +4. 六抖动算法屏显差异、模板 6 种屏显 + +## 环境备注 + +- 设备睡眠:广播窗口 30-60s,连接态清醒;现场统一 batch 单连接+守候循环 +- bridge_server build 4:write alt=331f、notify 三订阅、EFEF 走 331f diff --git a/docs/protocol.md b/docs/protocol.md index 215fd7c..76d8940 100644 --- a/docs/protocol.md +++ b/docs/protocol.md @@ -12,10 +12,15 @@ |---|---| | 广播名前缀 | `NRF-` | | EPD Service | `13187b10-eba9-a3ba-044e-83d3217d9a38` | -| EPD Characteristic(图像+刷屏,write+notify) | `4b646063-6264-f3a7-8941-e65356ea82fe` | +| EPD Characteristic(图像+刷屏,write+notify) | `4b646063-6264-f3a7-8941-e65356ea82fe`(h=48) | | RXTX Service | `00001f10-0000-1000-8000-00805f9b34fb` | -| RXTX Characteristic(命令,write+read+notify) | `00001f1f-0000-1000-8000-00805f9b34fb` | -| `0000221f-...` | 预留,未使用 | +| **RXTX 命令通道(实机)** | **`0000331f-0000-1000-8000-00805f9b34fb`(h=57,notify+write+read,svc 0x221f)** | +| `00001f1f-...`(h=53,仅 write) | ⚠ 实机证据:写入仅 ATT-ACK **不执行**命令(2026-07-28);Web/App 文档中的"RXTX 特征",本设备弃用 | +| SUOTA Service | `0000fef5-...`(h=28-45,含自定义特征,见 §9) | + +**实机 GATT 全表(2026-07-28 bridge 诊断,设备 NRF-5DBF28)**: +GAP/GATT/DIS(2A24/2A26/2A28/2A23/2A50)/BAS(2A19 notify) + fef5 SUOTA 六特征 + EPD + 1f1f(write-only) + 331f(notify+write+read)。 +notify 订阅:设备 ID 应答案测经 **331f** 到达(EFEF 同样须写 331f);EPD/2A19 亦可订阅。 连接顺序:先 EPD service → 再 RXTX;写均用 write-with-response(`triggerRxTxCmd2` 例外,without-response)。