feat(bridge): build 8 notify 超时+connect subscribe 选项(OTA 净连接)

This commit is contained in:
agent committed 2026-07-29 03:15:40 +00:00
1 parent 6c46c73c21
commit cbf7629dc8
2 files changed
+16 -8

No files matched your search

+4 -2
View File
@@ -46,12 +46,13 @@ class BridgeTransport:
def __init__(self, address: str | None = None, timeout: float = 10.0, def __init__(self, address: str | None = None, timeout: float = 10.0,
*, host: str, port: int = DEFAULT_PORT, *, host: str, port: int = DEFAULT_PORT,
name_prefix: str = "NRF-"): name_prefix: str = "NRF-", subscribe: bool = True):
self.address = address self.address = address
self.timeout = timeout self.timeout = timeout
self.host = host self.host = host
self.port = port self.port = port
self.name_prefix = name_prefix self.name_prefix = name_prefix
self.subscribe = subscribe # OTA 用 False(净连接,避开订阅抖动)
self._reader: asyncio.StreamReader | None = None self._reader: asyncio.StreamReader | None = None
self._writer: asyncio.StreamWriter | None = None self._writer: asyncio.StreamWriter | None = None
self._reader_task: asyncio.Task | None = None self._reader_task: asyncio.Task | None = None
@@ -77,7 +78,8 @@ class BridgeTransport:
raise BridgeError(f"bridge 未发现 {self.name_prefix!r} 前缀设备") raise BridgeError(f"bridge 未发现 {self.name_prefix!r} 前缀设备")
self.address = devices[0]["address"] self.address = devices[0]["address"]
await self._rpc("connect", 90.0 + self.timeout, await self._rpc("connect", 90.0 + self.timeout,
address=self.address, timeout=self.timeout) address=self.address, timeout=self.timeout,
subscribe=self.subscribe)
except Exception: except Exception:
await self._teardown() await self._teardown()
raise raise
+12 -6
View File
@@ -27,7 +27,7 @@ import platform
import sys import sys
PROTOCOL_VERSION = 1 PROTOCOL_VERSION = 1
SERVER_BUILD = 7 # 2026-07-29: OTA 分阶段事件(mem_dev/gpio_map/block_sent/status)+写超时,定位卡点 SERVER_BUILD = 8 # 2026-07-29: start/stop_notify 10s 超时 + connect subscribe 选项(OTA 净连接)
EPD_SERVICE_UUID = "13187b10-eba9-a3ba-044e-83d3217d9a38" EPD_SERVICE_UUID = "13187b10-eba9-a3ba-044e-83d3217d9a38"
EPD_CHAR_UUID = "4b646063-6264-f3a7-8941-e65356ea82fe" EPD_CHAR_UUID = "4b646063-6264-f3a7-8941-e65356ea82fe"
@@ -86,7 +86,7 @@ class BleSession:
out.append({"name": name, "address": dev.address, "rssi": adv.rssi}) out.append({"name": name, "address": dev.address, "rssi": adv.rssi})
return {"devices": out} return {"devices": out}
async def connect(self, address: str, timeout: float = 15.0): async def connect(self, address: str, timeout: float = 15.0, subscribe: bool = True):
from bleak import BleakClient, BleakScanner from bleak import BleakClient, BleakScanner
await self.close() await self.close()
# Windows/WinRT 按地址直连常解析失败——先扫描拿到 BLEDevice(含地址类型/广播数据)再连 # Windows/WinRT 按地址直连常解析失败——先扫描拿到 BLEDevice(含地址类型/广播数据)再连
@@ -105,10 +105,13 @@ class BleSession:
self.client = BleakClient(dev, timeout=timeout) self.client = BleakClient(dev, timeout=timeout)
await self.client.connect() await self.client.connect()
# notify 全订阅:331f(主)+ 1f1f(部分固件)+ EPD(设备 ID 也可能经此应答) # notify 全订阅:331f(主)+ 1f1f(部分固件)+ EPD(设备 ID 也可能经此应答)
# subscribe=False 用于 OTA 净连接(避免订阅抖动影响烧录链路)
self.notify_char = [] self.notify_char = []
if subscribe:
for uuid in (ALT_NOTIFY_UUID, RXTX_CHAR_UUID, EPD_CHAR_UUID): for uuid in (ALT_NOTIFY_UUID, RXTX_CHAR_UUID, EPD_CHAR_UUID):
try: try:
await self.client.start_notify(uuid, self._on_notify) await asyncio.wait_for(
self.client.start_notify(uuid, self._on_notify), 10)
self.notify_char.append(uuid) self.notify_char.append(uuid)
except Exception: except Exception:
continue continue
@@ -167,7 +170,8 @@ class BleSession:
await asyncio.wait_for( await asyncio.wait_for(
self.client.write_gatt_char(char, data, response=True), to) self.client.write_gatt_char(char, data, response=True), to)
await self.client.start_notify(SPOTA_SERV_STATUS_UUID, _on_status) await asyncio.wait_for(
self.client.start_notify(SPOTA_SERV_STATUS_UUID, _on_status), 10)
try: try:
await w(SPOTA_MEM_DEV_UUID, MEM_DEV_SPI_FLASH) await w(SPOTA_MEM_DEV_UUID, MEM_DEV_SPI_FLASH)
yield {"event": "ota_stage", "stage": "mem_dev_ok"} yield {"event": "ota_stage", "stage": "mem_dev_ok"}
@@ -188,7 +192,8 @@ class BleSession:
yield {"event": "ota_stage", "stage": "reboot_sent"} yield {"event": "ota_stage", "stage": "reboot_sent"}
finally: finally:
try: try:
await self.client.stop_notify(SPOTA_SERV_STATUS_UUID) await asyncio.wait_for(
self.client.stop_notify(SPOTA_SERV_STATUS_UUID), 5)
except Exception: except Exception:
pass pass
@@ -252,7 +257,8 @@ class BridgeServer:
if op == "scan": if op == "scan":
return await self.ble.scan(float(req.get("timeout", 5.0))) return await self.ble.scan(float(req.get("timeout", 5.0)))
if op == "connect": if op == "connect":
return await self.ble.connect(req["address"], float(req.get("timeout", 15.0))) return await self.ble.connect(req["address"], float(req.get("timeout", 15.0)),
bool(req.get("subscribe", True)))
if op == "write": if op == "write":
return await self.ble.write(req["char"], bytes.fromhex(req["data"]), return await self.ble.write(req["char"], bytes.fromhex(req["data"]),
bool(req.get("response", True))) bool(req.get("response", True)))