Files
qianbian/PROGRESS.md
T

152 lines
12 KiB
Markdown
Raw 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.
# 进度日志 (PROGRESS)
## 2026-07-24(最终状态)
### 已完成(对照门禁)
| 门禁 | 状态 | 证据 |
|------|------|------|
| G1 架构摸清 | ✅ | docs/architecture.md + docs/protocol.md + docs/firmware-analysis.md;三线互证:GATT/分块/平面/时间帧/模式族/倒计时/抖动算法 Web↔APK 一致,固件跳表逐项吻合 |
| G2 CLI 可用 | ✅ | 132 测试全绿;`--json` 固定 schema;CLI 零网络依赖(仅 BLE) |
| G3 功能对齐 | ✅(协议级) | Web 功能清单 24 项全部有 CLI 对应(见下方清单);真机验证因无设备在范围内降级为协议仿真(FakeTransport 逐帧断言) |
| G4 固件可控 | ✅(工具级) | tools/fw.py 解析/修改/重打包字节级往返 + CRC32 验证;SUOTA 全流程文档化(firmware-analysis §5)+ `ppclock ota` 实现;实机首刷待硬件 |
| G5 离线交付 | ✅ | 激活本地 keygen(activate --auto);模板本地渲染(wqy 字体);qrcode 本地库;无任何 CDN/服务器调用 |
### 三线逆向关键结论
1. **协议**:双通道 GATT(EPD 图像+RXTX 命令),全部 opcode 见 docs/protocol.md §4。
2. **激活可离线绕过**(firmware-analysis §4.3):激活码 = `ror2(((MAC[i]<<1)&0xFF)^0xEF)%101`(i=0..5),EFEF 设备 ID 可无损反解 MAC;EF 不门禁任何命令。
3. **SUOTA 可用**(§5):藏在 0x221F 服务,任务 0xFC 四消息,接收方校验 pQ 头+长度+XOR 写 Flash 0x38000 备 bank。
4. **固件 no-op 命令**:E9/EA/WIFI 在本固件版本被忽略(§3.3)。
5. **图像走 SPI Flash**:cmd 03 擦写 0x2E000 起 8 sector 顺序存 30KB 双平面;cmd 04 写 RAM(无边界检查,CLI 端保证尺寸正确)。
6. **驱动 IC**:SSD1683 兼容(400x300 三色)+ UC8151 备选;OTP 波形无 LUT 表;E6=红黑平面校准字节。
### 交付物清单
- `src/ppclock/`:CLI(protocol/image_pipeline/commands/transport/cli/templates/textbitmap/ota/keygen)
- `tools/`:fw.py / fw_info.py / fw_pack.py / check_env.py
- `docs/`:protocol.md / architecture.md / firmware-analysis.md
- `analysis/`:web 抓取与协议原始报告、apk 反编译报告与中间产物、firmware 反汇编产物
- `tests/`:132 测试全绿
### 遗留(需实机)→ 已备好执行器
**执行入口:`.venv/bin/python tools/field_test.py`(计划 docs/field-test-plan.md,结果自动写 docs/field-test-result.md)**
1. 真机功能回归(设备不在 BLE 范围内;扫到 17 台其他 BLE 设备无 NRF- 前缀)→ 阶段 1–8
2. SUOTA 首刷验证(建议先用仅改版本字符串的镜像)→ 阶段 9(`--ota` 才执行,脚本自动制作等长测试镜像+回滚)
3. `--mac` 路径 activate --auto 的 NVDS 字节序(EFEF 路径无歧义,优先用)→ 阶段 1.2 自动反解对比
### 2026-07-25:workspace 整理清理
- 清理:删除可再生产物(apk/native/*.so 5.2MB、firmware/fw.asm 1.2MB、decomp 日志 5 个)与 __pycache__/.pytest_cache;再生方法写入 analysis/README.md
- 新增:docs/field-test-plan.md(10 阶段验收表)、tools/field_test.py(引导执行器)、examples/field_test.jsonl(batch 冒烟序列)
- 冒烟验证:field_test.py --help / jsonl 10 行可解析 / 测试镜像制作+CRC 均通过
### 2026-07-28:真机测试第一轮 —— 基础设施阻塞(已定位根因)
**设备验证成功**:NRF-5DBF28 @ 18:BC:5A:5D:BF:28 在线,广播包含全部预期服务(EPD 13187b10/RXTX 1f10/SUOTA 221f+fef5/DIS/BAS)——与逆向结论完全一致。ATT 层握手成功(MTU 交换:设备 Server RX MTU 512)。
**阻塞根因**:本机蓝牙适配器经 USB/IP 从 192.168.61.35 透传(hci0=vhci_hcd),BLE 连接建立后数据窗口 ~3s 硬停(btmon 两次复现 19 ACL 包后断流→监督超时 0x08)。对照设备同败 → 非设备/协议问题,系 usbip 链路故障。
**下一步选项**(待用户定):
1. 在 192.168.61.35(dongle 物理机)原生部署运行 field_test.py
2. 修 usbip 链路(宿主侧内核/配置)或改用原生蓝牙机器
3. 用户指认一台允许 SSH 的 Linux 蓝牙机,远程部署执行
### 2026-07-28:真机测试第一轮续 —— usbip 修复尝试(guest 侧已尽力)
按用户选择"修 usbip 链路后继续本机测",guest 侧尝试与结论:
| 尝试 | 结果 |
|---|---|
| 禁用 USB runtime PM(`power/control=on`,原 auto/2s) | 数据窗口 2.4s → 5.1s(改善但不够),**保留** |
| LE Write Suggested Default Data Length 27B(限制大包) | 无效且伴随建立失败率上升,**已回滚** |
| gatttool 按句柄直写(跳过服务发现,firmware 已知 handle 2/7/0x0B) | 连接建立超时(工具级不兼容 usbip 链路) |
| bluetoothd 停止 + hcitool lecc 空闲链路保持测试 | I/O error,原始路径不可用 |
**关键诊断**(3 次 btmon 完全一致):连接建立成功 → MTU 交换成功 → 服务发现推进 → **在收到同一条 76 字节响应(含 128-bit UUID 服务声明)后链路死亡** → 3s 后监督超时。断开原因为 LL 层断连(0x08)。即中断端点在携带大响应的传输处饥饿——**usbip-host(192.168.61.35)侧问题,guest 侧无法根治**。
**待用户在 .35 上执行(任选)**:
1. **推荐**:直接在 .35 原生跑测试(AX200 物理在该机,无需 usbip):
`mount -t nfs 192.168.61.14:/chenw/working/doc/DocumentDisk /mnt/documents`(或直接进现有共享)→ `cd Works/Eink/qianbian` → `python3 -m venv .venv && .venv/bin/pip install -e .` → `.venv/bin/python tools/field_test.py`
2. 修 usbip-host:查 `uname -r`(<5.x 内核有已知 usbip 中断 URB bug);重挂 `usbip attach`;或换 VirtualHere/usbredir 等替代转发。
3. 任何修复后回本 VM 重跑:`.venv/bin/python tools/field_test.py`。
**已保留的 guest 侧改善**:`/sys/bus/usb/devices/1-1/power/control=on`(重启后需重设;可写 udev 规则固化,见 README)。
### 2026-07-28:排查打结(结论修正)+ bridge 架构立项
**熠管家 Windows 侧排查结论(采纳,替代此前归因)**:
- 192.168.61.35 = Windows host-win/banyWinServer(usbipd-win 5.3.0),非 Linux
- 76B 响应完整到达 guest、下一请求已被 AX200 接收 → 非"中断端点卡住"
- **ATT MTU=23 时全部服务 + 22 个 characteristic 发现成功、无监督超时** → 定性为"大 MTU GATT 流量触发断流",具体环节(usbipd/VBoxUSB/VHCI/AX200 固件)无法唯一归因
- 不能全局降 MTU(EPD 图像帧 244B),运行态已恢复
**打结**:本机 usbip 路径不可用于大帧 GATT,放弃修复,转 bridge 架构。
**bridge 立项**(见 DECISIONS 2026-07-28 第 3 条):
- `tools/bridge_server.py`:host-win 原生运行(Python+bleak/WinRT),JSONL/TCP RPC
- `src/ppclock/bridge.py`:BridgeTransport,与 BLETransport 同接口,全部 CLI 命令透明可用
- 调用方式:`ppclock --via bridge://192.168.61.35:8971 ...` 或 `PPCLOCK_VIA=bridge://...`
- field_test.py 经 `PPCLOCK_VIA` 环境变量继承,无需改动
### 2026-07-28:bridge 实现完成(149 测试全绿)
- `tools/bridge_server.py`:单文件服务端(仅依赖 bleak),JSONL/TCP RPC v1;本机冒烟通过(ping 返回 platform/version,scan 经服务端真实 bleak 发现 NRF-5DBF28)
- `src/ppclock/bridge.py`:BridgeTransport 与 BLETransport 同接口;`--via bridge://host[:port]` + `PPCLOCK_VIA` 环境变量;scan 同样走桥
- tests/test_bridge.py(12 测试:假服务端全协议)+ test_cli.py 新增 5 个 --via 测试
- **下一步**:用户在 host-win 执行 `pip install bleak && python tools/bridge_server.py`,然后本机 `PPCLOCK_VIA=bridge://192.168.61.35 .venv/bin/python tools/field_test.py` 即可完成全链路真机测试
### 2026-07-28/29:bridge 部署联调 + 实机全链路测试(收尾态)
**协作**:经 Worker Bridge 由熠管家在 host-win 完成部署(NFS ACL 阻塞 → 桥内直传文件;build 1→5 迭代:WinRT 连接修复/notify 三订阅/331f 写通道/SUOTA 状态特征校正,原子替换+备份规范执行)。
**实机验证结论**(docs/field-test-result.md 为完整记录):
| 项 | 结果 |
|---|---|
| 实机 GATT 表 | ✅ 抓取入库;**331f 为活命令通道**(1f1f 仅 ACK 不执行,实锤修正 web/APK 推断) |
| 设备 ID/MAC 反解 | ✅ `81233F3C267112`↔广播地址互证(snprintf 参数序实机校正为 MAC5 在前) |
| **离线激活 keygen** | ✅ `activate --auto` 下发 `2564550c1b2d` 实机成功 |
| 传图 126×244B | ✅ 屏显确认(棋盘+红块) |
| 模式/对时/倒计时 | ✅ 屏显确认(clock1/2 布局差异确认、时间+倒计时同框确认) |
| 停车牌 | ⚠ 命令 ACK 屏不显,记 K1 待查 |
| SUOTA 首刷 | ⏸ 用户决定本轮跳过;镜像/流程/服务在线全部就绪 |
**门禁终态**:G1 ✅(三线+实机互证)G2 ✅(150 测试)G3 ✅ 实机(除 K1)G4 ✅ 工具级(烧录择机)G5 ✅
**bridge 运维备注**:host-win `C:\yi\ble-bridge\`,Scheduled Task `BanyTech-BLE-Bridge`(SYSTEM 常驻,监听 0.0.0.0:8971,防火墙仅放行 192.168.61.56),build 1-4 备份在侧可回滚。
### 2026-07-29:SUOTA 首刷(用户授权,审慎流程)执行中
- 测试镜像:DIS 2A26 版本串 3 字符差异(`4.2→TST`)+ CRC 重算,烧后 BLE 可读证真
- 基线:dis_model=DA14585、dis_fw=PP_da14585_4.2、fef5 九特征在线 ✓
- 第 1 轮:客户端 600s RPC 预算耗尽(传输超时),设备无损
- 第 2 轮:首块前静默停滞 ~29 分钟(无任何阶段回报),设备仍健康(DIS=4.2、连接正常)
- 对策:客户端预算→1800s;bridge build 7 加 OTA 分阶段事件(mem_dev/gpio_map/block_sent/progress/end/reboot)+ 带响应写 15s 超时,重跑定位卡点
- 设备睡眠行为补充:**无唤醒按钮**,自动周期醒(用户确认),守候循环法有效
### 2026-07-29:SUOTA 排障到底 + 安全收尾(用户决策)
**三层根因全部定位并修复**,推进至设备内部最终门禁:
1. **传输层**:asyncio StreamReader 64KiB 行限制 → 144KB 镜像请求永不到达(此前三轮"静默"真凶;空镜像探针 0.6s 全通证明管线无恙)。build 9 修复。
2. **协议层**:状态码 16 = MEM_DEV 信息应答(固件反汇编 0x07FCB770 实证),非失败。build 10 修复。
3. **引脚层**:GPIO_MAP 字节序——探针(tools/gpio_probe.py,max_blocks=2 安全模式)实证 **BE 序 {05,06,00,40} 唯一电气有效**,已固化为服务端默认。
**最终阻断(vendor 级)**:固件首缓冲处理校验 0x38000 的 'pR' 产品头(0x07FCB4AA),本机裸 'pQ' 直启无此头 → 状态 20 中止。强推 END 有变砖风险(END 写 0xAA 标志+复位;恢复需 JTAG)。**用户决策:安全收尾**。
**解法路线(遗留 K4)**:①逆向 vendor 固件目录(qbsg.top /api/firmware/catalog)是否含产品头/引导镜像;②研究裸启设备产品头自举写入路径;③评估 JTAG/UART 写头。
**本轮 bridge 迭代**:build 1→11 部署于 host-win(全部 sha256 校验+原子替换+逐级备份,熠管家执行);build 12 候选=GPIO_MAP 默认 C(已入库待部署)。
### 会话时间线
- 08:14 目标设定(治理+规划+执行)
- 治理:GOVERNANCE.md / PLAN.md / DECISIONS.md / git 骨架
- P0:venv(bleak/pillow/pytest/capstone/androguard/pytest-asyncio/qrcode)+ Java21
- P1:Web JS 协议提取(子代理)→ APK 反编译互证(子代理)→ 固件逆向(子代理)
- P2:protocol/image/commands/transport/cli/templates/textbitmap 全 TDD 实现
- P3:batch/本地模板/ota/keygen 增强;fw 工具链;文档终稿