Files
qianbian/tools/gpio_probe.py

100 lines
3.3 KiB
Python
Raw Permalink 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.
#!/usr/bin/env python3
"""GPIO_MAP 候选实证探针 v2(单 TCP/单 BLE 会话;候选间 SPOTA 复位)。
安全:max_blocks=2 不写 END;MEM_DEV FF 复位会话;断连即弃。
用法:.venv/bin/python tools/gpio_probe.py [host] [port]
"""
import asyncio
import json
import sys
import time
HOST = sys.argv[1] if len(sys.argv) > 1 else "192.168.61.35"
PORT = int(sys.argv[2]) if len(sys.argv) > 2 else 8971
DEVICE = "18:BC:5A:5D:BF:28"
IMAGE_HEX = open("analysis/firmware/fw_tst.img", "rb").read().hex()
CANDIDATES = [
("A 现行 {00,00,06,05}", "00000605"),
("B LE(0x05060040) {40,00,06,05}", "40000605"),
("C BE(0x05060040) {05,06,00,40}", "05060040"),
]
RESET_MEM_DEV = "000000ff"
class Bridge:
def __init__(self):
self.next_id = 0
async def open(self):
try:
self.w.close()
except Exception:
pass
self.r, self.w = await asyncio.open_connection(HOST, PORT)
async def rpc(self, op, wait=120, **kw):
self.next_id += 1
rid = self.next_id
self.w.write(json.dumps({"id": rid, "op": op, **kw}).encode() + b"\n")
await self.w.drain()
events = []
while True:
line = await asyncio.wait_for(self.r.readline(), wait)
if not line:
raise ConnectionError("bridge EOF")
msg = json.loads(line)
if "event" in msg:
events.append(msg)
else:
return msg, events
async def connect_until_awake(self, tries=12):
for i in range(tries):
try:
resp, _ = await self.rpc("connect", 150, address=DEVICE,
timeout=30, subscribe=False)
except (ConnectionError, asyncio.TimeoutError):
print(" 连接通道中断,重开 TCP...")
await self.open()
continue
if resp.get("ok"):
print(f"连接成功(第 {i + 1} 次)")
return True
print(f" 等待设备唤醒... ({i + 1}/{tries})")
await asyncio.sleep(15)
return False
async def main():
b = Bridge()
await b.open()
if not await b.connect_until_awake():
print("设备持续未醒,退出")
return
for name, gh in CANDIDATES:
t0 = time.time()
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())