refactor(tools): gpio_probe v2 单会话+复位+守候

This commit is contained in:
agent committed 2026-07-29 04:26:26 +00:00
1 parent ff46d2985b
commit ff9f2f84fd
1 file changed
+61 -38
+61 -38
View File
@@ -1,5 +1,6 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
"""GPIO_MAP 候选实证探针(安全:max_blocks=2,不发 END,断连即弃)。 """GPIO_MAP 候选实证探针 v2(单 TCP/单 BLE 会话;候选间 SPOTA 复位)。
安全:max_blocks=2 不写 END;MEM_DEV FF 复位会话;断连即弃。
用法:.venv/bin/python tools/gpio_probe.py [host] [port] 用法:.venv/bin/python tools/gpio_probe.py [host] [port]
""" """
import asyncio import asyncio
@@ -17,51 +18,73 @@ CANDIDATES = [
("B LE(0x05060040) {40,00,06,05}", "40000605"), ("B LE(0x05060040) {40,00,06,05}", "40000605"),
("C BE(0x05060040) {05,06,00,40}", "05060040"), ("C BE(0x05060040) {05,06,00,40}", "05060040"),
] ]
RESET_MEM_DEV = "000000ff"
async def rpc(r, w, i, op, **kw): class Bridge:
w.write(json.dumps({"id": i, "op": op, **kw}).encode() + b"\n") def __init__(self):
await w.drain() self.next_id = 0
events = []
while True:
msg = json.loads(await asyncio.wait_for(r.readline(), 120))
if "event" in msg:
events.append(msg)
else:
return msg, events
async def open(self):
self.r, self.w = await asyncio.open_connection(HOST, PORT)
async def probe(name, gpio_hex): async def rpc(self, op, timeout=120, **kw):
r, w = await asyncio.open_connection(HOST, PORT) self.next_id += 1
try: rid = self.next_id
c, _ = await rpc(r, w, 1, "connect", address=DEVICE, timeout=40, self.w.write(json.dumps({"id": rid, "op": op, **kw}).encode() + b"\n")
subscribe=False) await self.w.drain()
if not c.get("ok"): events = []
print(f"{name}: 连接失败 {c.get('error')}") while True:
return line = await asyncio.wait_for(self.r.readline(), timeout)
t0 = time.time() if not line:
resp, events = await rpc(r, w, 2, "ota", image=IMAGE_HEX, raise ConnectionError("bridge EOF")
gpio_map=gpio_hex, max_blocks=2) msg = json.loads(line)
verdict = "?" if "event" in msg:
codes = [] events.append(msg)
for ev in events: else:
if ev.get("stage", "").endswith("_status") or "info_status" in ev.get("stage", ""): return msg, events
codes += ev.get("codes", [])
if ev.get("event") == "ota_progress": async def connect_until_awake(self, tries=12):
verdict = f"✅ 块{ev['block']} 确认(2)" for i in range(tries):
if resp.get("ok"): resp, _ = await self.rpc("connect", 150, address=DEVICE,
verdict = verdict if "✅" in verdict else "探针停止(无块确认)" timeout=30, subscribe=False)
else: if resp.get("ok"):
verdict = f"❌ {resp.get('error')}" print(f"连接成功(第 {i + 1} 次)")
print(f"{name}: {verdict} 状态码序列={codes} ({time.time()-t0:.1f}s)") return True
finally: print(f" 等待设备唤醒... ({i + 1}/{tries})")
w.close() await asyncio.sleep(15)
return False
async def main(): async def main():
b = Bridge()
await b.open()
if not await b.connect_until_awake():
print("设备持续未醒,退出")
return
for name, gh in CANDIDATES: for name, gh in CANDIDATES:
await probe(name, gh) t0 = time.time()
await asyncio.sleep(3) resp, events = await b.rpc("ota", 180, image=IMAGE_HEX,
gpio_map=gh, max_blocks=2)
codes, confirmed = [], 0
for ev in events:
st = ev.get("stage", "")
if st.endswith("_status") or "info_status" in st:
codes += ev.get("codes", [])
if ev.get("event") == "ota_progress":
confirmed = ev["block"]
if confirmed:
verdict = f"✅ 块{confirmed} 确认(引脚正确!)"
elif resp.get("ok"):
verdict = "探针停(无块确认)"
else:
verdict = f"❌ {resp.get('error')}"
print(f"{name}: {verdict} 状态码={codes} ({time.time() - t0:.1f}s)")
# SPOTA 会话复位,避免缓冲跨候选累积
await b.rpc("write", 30, char="spota_mem_dev",
data=RESET_MEM_DEV, response=True)
await asyncio.sleep(2)
print("探针完成")
asyncio.run(main()) asyncio.run(main())