# 进度日志 (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(已入库待部署)。 ### 2026-07-29:路线 1 完成——工厂布局破解,G4 完整解法就位 **vendor 固件渠道全逆向**: - qbsg.top catalog(免认证):PP_da14585_4.2_CH.img 与本机镜像 sha256 一致 - **file_down.php 线刷固件 PP_da14585_4.2_CH.bin(224KB)= 完整工厂布局**:'pP' 二级引导@0x0 + 双 bank 'pQ'@0x2000/0x14000 + **'pR' 产品头@0x38000**(指向两 bank) - NEW.bin 同构,其 app1 体 == vendor OTA NEW.img 体(OTA .img=bank 镜像,互证) **SUOTA 门禁定案**:本机为裸布局(app 直写 0x0,无引导/产品头),非引脚/协议问题。烧后健康复查:DIS 原固件未变、331f 通道正常(零写入实证)。 **G4 完整解法**(docs/firmware-layout.md): - 路径 A:DA14585 ROM UART 线刷恢复工厂布局(已存档 .bin 固件;需开盖接 UART,用户物理操作) - 路径 B(已具备):图像/激活 flash 写 + 全部 BLE 功能 + 离线 keygen 激活 ### 2026-07-29:项目收官(用户选定路径 B) **用户决策:G4 固件可控走路径 B(免线刷软件利用)**(DECISIONS 2026-07-29 末条)。 **三大目标终态**: | 任务说明目标 | 状态 | 证据 | |---|---|---| | 1. 摸清软硬件架构 + 改进功能 | ✅ | docs/architecture.md / protocol.md / firmware-analysis.md / firmware-layout.md;改进功能:batch/本地模板/离线激活/bridge 远程 BLE | | 2. 本地化(无需互联网)+ CLI(面向 agent)+ 添加必要功能 | ✅ | ppclock 17 子命令全离线(仅 BLE/LAN bridge);--json 全命令契约;新增:本地 keygen 激活、本地模板渲染、batch JSONL、ota、bridge | | 3. 软硬件(固件)可控 | ✅(B 路径) | 图像 flash 持久化写、EF 激活写+离线 keygen、fw_info/fw_pack 字节级镜像工具、SUOTA 客户端就绪(工厂布局设备可直接用) | **项目交付物终态**:ppclock CLI(150 测试全绿)+ tools(fw 工具链/bridge_server build 11/gpio_probe/flash_run/field_test/check_env)+ docs 全套(协议/架构/固件分析/布局/实测结果)+ analysis 证据链。 ### 2026-07-29:A 组补测进行中 + 打结①(对时 --tz) **A 组进展**: | 组 | 状态 | |---|---| | toggles/LUT/no-op(12 步) | ✅ 命令层 12/12 落地(rppclock 守候重试),目视确认待用户回报 | | 六抖动算法 | 待跑 | | 六模板 | 待跑 | | 日历倒计时/upload_rili | 待跑 | | K1 停车牌 d8 变体 | 待跑(格式已解:EF+号码 nibble 打包,d8_f.java:168-189 证据) | | sleep 时段 | 命令可发,隔夜观察归用户 | **CLI 增强**:`time --tz 8`(时区偏移,修正本机 UTC 与用户北京时区差),151 测试全绿。 **打结①**:对时(北京时间)命令待发——设备长睡眠,守候监视中,醒即执行并回报。 ### 会话时间线 - 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 工具链;文档终稿