21 KiB
进度日志 (PROGRESS)
最终状态以 2026-07-29 收官节与后续各节为准。本节(2026-07-24)为首日快照, 其中 G3/G4 的"协议级/工具级"标注已被 2026-07-28/29 实机验证超越:G3 ✅实机(除 K1 停车牌待查)、 G4 ✅路径B达标、测试 132→208、交付物扩展为 SDK+CLI+bridge+MCP。
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/服务器调用 |
三线逆向关键结论
- 协议:双通道 GATT(EPD 图像+RXTX 命令),全部 opcode 见 docs/protocol.md §4。
- 激活可离线绕过(firmware-analysis §4.3):激活码 =
ror2(((MAC[i]<<1)&0xFF)^0xEF)%101(i=0..5),EFEF 设备 ID 可无损反解 MAC;EF 不门禁任何命令。 - SUOTA 可用(§5):藏在 0x221F 服务,任务 0xFC 四消息,接收方校验 pQ 头+长度+XOR 写 Flash 0x38000 备 bank。
- 固件 no-op 命令:E9/EA/WIFI 在本固件版本被忽略(§3.3)。
- 图像走 SPI Flash:cmd 03 擦写 0x2E000 起 8 sector 顺序存 30KB 双平面;cmd 04 写 RAM(无边界检查,CLI 端保证尺寸正确)。
- 驱动 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.pydocs/:protocol.md / architecture.md / firmware-analysis.mdanalysis/:web 抓取与协议原始报告、apk 反编译报告与中间产物、firmware 反汇编产物tests/:132 测试全绿
遗留(需实机)→ 已备好执行器
执行入口:.venv/bin/python tools/field_test.py(计划 docs/field-test-plan.md,结果自动写 docs/field-test-result.md)
- 真机功能回归(设备不在 BLE 范围内;扫到 17 台其他 BLE 设备无 NRF- 前缀)→ 阶段 1–8
- SUOTA 首刷验证(建议先用仅改版本字符串的镜像)→ 阶段 9(
--ota才执行,脚本自动制作等长测试镜像+回滚) --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 链路故障。
下一步选项(待用户定):
- 在 192.168.61.35(dongle 物理机)原生部署运行 field_test.py
- 修 usbip 链路(宿主侧内核/配置)或改用原生蓝牙机器
- 用户指认一台允许 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 上执行(任选):
- 推荐:直接在 .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 - 修 usbip-host:查
uname -r(<5.x 内核有已知 usbip 中断 URB bug);重挂usbip attach;或换 VirtualHere/usbredir 等替代转发。 - 任何修复后回本 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 RPCsrc/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 排障到底 + 安全收尾(用户决策)
三层根因全部定位并修复,推进至设备内部最终门禁:
- 传输层:asyncio StreamReader 64KiB 行限制 → 144KB 镜像请求永不到达(此前三轮"静默"真凶;空镜像探针 0.6s 全通证明管线无恙)。build 9 修复。
- 协议层:状态码 16 = MEM_DEV 信息应答(固件反汇编 0x07FCB770 实证),非失败。build 10 修复。
- 引脚层: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 测试全绿。
打结①:对时(北京时间)命令待发——设备长睡眠,守候监视中,醒即执行并回报。
2026-07-30:A 组补测收官 + 典狱长案例
A 组终态:
| 组 | 结果 |
|---|---|
| 对时北京 | ✅ time --tz 8(set 2026-07-29T23:33 北京时) |
| toggles/LUT/no-op 12 步 | ✅ 命令层 12/12 落地;期间用户无异常反馈,屏幕后续确认健康 |
| 六抖动算法 | ✅ 6/6 上传(none/floyd/atkinson/bayer/stucki/jarvis) |
| 六模板 | ✅ 6/6 上传(custom/schedule/memo/businesscard/course/qrcode) |
| 日历倒计时+upload_rili+关闭 | ✅ 命令层全通 |
| K1 停车牌 | d8 变体(EF+nibble 打包)已发送;显示与否用户未回报,维持待查 |
| sleep 时段 | 命令可用;隔夜观察归用户 |
| 典狱长 v1 线稿 | ✅ 上屏(FIND_EDGES 处理) |
| 典狱长 v2 官图 | ✅ 上屏(用户目视确认)+ 发现槽位覆盖自动重绘机制 |
图片输入机制评审(field-test-result.md §图片输入机制 review):源图→400×300 适配→管线→上传→显示全链可编程;已量化图 --algo none 直通;槽位覆盖即重绘。
闭环:A 组除 sleep 隔夜观察与 K1 待查外全部完成;review 记录入库(field-test-result.md)。
2026-07-30:SDK 化重构 + 0.1.0 release(tag v0.1.0)
重构(二次开发基座):
- 包结构:
transports/(base 协议 / local bleak / bridge RPC)+firmware/(image 解析重打包 / ota)分包;bridge_server入包(ppclock-bridge命令);fw 工具入 SDK 域(tools/fw.py 保留垫片) PPClient门面:via_local/via_bridge(host,mac)/via_uri/scan_devices+ 全设备操作;Transport协议开放自定义传输注入- release 0.1.0:
__version__、CHANGELOG.md、git tagv0.1.0(commit 2b90d38) - AI-native 文档:
llms.txt(项目卡)+docs/sdk/API.md(签名级参考+Bridge RPC+不变量)+ README 改 SDK 向 - 165 测试全绿(新增 test_client.py 14 项门面测试)
2026-07-31:ppclock-mcp 0.2.0——AI-native MCP 服务器(单层部署)
交付(分支 feat/ppclock-mcp,SDD 五任务+终审+修复波):
- 三新模块:
device_manager.py(方案 C:按需连接+空闲超时保持+串行锁+掉线重连重试一次)/mcp_tools.py(13 高层工具+统一 ok/error 契约)/mcp_server.py(stdio+streamable HTTP 双模,PPCLOCK_MCP_TOKEN 鉴权,非回环强制 token,--allowed-hosts Host 白名单) - 规格 spec + 实施计划入库(docs/superpowers/specs|plans);207 测试全绿(新增 42)
- 终审关键修复:全部 fake 曾只说英文 TransportError——真实 bleak 抛中文
transports.local.TransportError(与 base 同名互不继承)与未包装 BleakError;捕获面/错误码映射已按真实异常语义重写(类型优先、中英文消息次之) - Windows 实测(熠管家,banyWinServer 192.168.61.35,C:\ppclock):stdio 全链路通过(scan→connect→set_time→upload_image 15000+15000→set_mode image0;远程无法目视上屏);HTTP LAN Host 421(mcp DNS 重绑定防护)已修为 --allowed-hosts,复测已命中(401/421/200/device_status ok,2026-07-31,详见 spec 末节)
- 环境事实:mcp 钉 >=1.23,<2(2.0 移除 FastMCP/memory API;1.23 起有 transport_security + CVE-2025-66416 修复;实测 1.29.0)
2026-07-31:0.2.0-beta release + 常驻部署(生产性测试开始)
- release:节点审计 8 项必修落地(版本 7 处统一 0.2.0b1、mcp 地板 >=1.23、--allowed-hosts 空串自锁修复+回归、文档数 208、DECISIONS 留痕);tag
v0.2.0-beta@ 5130bb7(旧 v0.2.0 删除);208 测试全绿 - 常驻部署(熠管家,banyWinServer):SYSTEM 计划任务
BanyTech-PPCLOCK-MCP(AtStartup + 999 次/1 分钟恢复 + runner 5 秒子进程重启);token CSPRNG 生成 ACL 仅 SYSTEM/Administrators;日志C:\ProgramData\OpenClaw\ppclock-mcp\logs\;验证:LAN 200/device_status ok/杀进程 5 秒自动拉起复 200;8971 与防火墙不变 - 运维记录:
/home/cwmine/vps/host-win/maintain_logs/2026-07-31_ppclock-mcp-production-test-service.md;运行问题经 Bridge taskppclock-mcp-ops回报本 session 统一迭代 - 文档:docs/sdk/MCP.md(工具参考+部署)、README/llms.txt/API.md/CHANGELOG 同步;工具清单 tools/mcp_windows_deploy.md
会话时间线
- 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 工具链;文档终稿
生产接口实测(2026-07-31,熠管家代跑,原始 JSON 入库):
- A 疑案闭环:「connected=false」为 OpenClaw 侧解析误读(读了顶层 connected/mac 而非 data.*,缺字段强转 false),非服务问题;原始 payload data.connected=true / data.mac=18:BC:5A:5D:BF:28 / connect_count=2
- B 授权六步全过(每步 HTTP 200/isError=false/ok=true):set_time tz=8 → upload_image slot0(bytes 15000+15000)→ set_mode image0 → countdown 2026-12-31 目标 → countdown_off(自回滚)→ device_status connected=true;屏显目视归用户
- 观察项:supervisor.log 09:16-09:18 曾现 exit -1 每 6 秒重启循环约 2 分钟(疑端口占用竞态,runner 加日志重定向后 09:20:50 起稳定至今)——运维关注,非代码缺陷结论待续观
- 目视闭环(2026-07-31):首轮"屏幕未变"系夹具顺序缺陷(countdown(mode=clock) 覆盖 image0 可见态);单步 set_mode(image0) 复测,用户目视确认 MCP-PROD-TEST 测试图上屏——生产链路 agent→MCP→BLE→屏 全链目视闭环
2026-08-02:Gitea 远端上线(治理闭环)
- 熠管家在 Gitea(git.b.aeroprop.xyz)chenwei 账户下创建空仓库 qianbian(API 复核 empty=true)
- 本机认证:~/.ssh/id_ed25519 已在 Gitea 注册(key 名 chenwei@bany.tech@openclaw-server)
- origin 已添加并全历史推送(ls-remote HEAD 与本地一致:3ce4fc0)
- 治理落地:GOVERNANCE §6(remote/分支/身份/推送检查/大文件/同步纪律)+ DECISIONS 2026-08-01(含 URL 与认证方式)
- 推送前审计:secret 扫描干净(仅协议格式串与测试口令)、提交身份 agent/chenwei 两类诚实并存不改写