From 92a866108838bb2503f10570c51aaaf03760659f Mon Sep 17 00:00:00 2001 From: agent Date: Tue, 28 Jul 2026 15:34:31 +0000 Subject: [PATCH] =?UTF-8?q?fix(bridge):=20notify=20=E9=80=9A=E9=81=93=201f?= =?UTF-8?q?1f/331f=20=E5=8F=8C=E5=80=99=E9=80=89=20+=20services=20?= =?UTF-8?q?=E8=AF=8A=E6=96=AD=20op=EF=BC=8Cbuild=3D3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tools/bridge_server.py | 30 +++++++++++++++++++++++++++--- 1 file changed, 27 insertions(+), 3 deletions(-) diff --git a/tools/bridge_server.py b/tools/bridge_server.py index feb82fc..b023ddf 100644 --- a/tools/bridge_server.py +++ b/tools/bridge_server.py @@ -27,12 +27,15 @@ import platform import sys PROTOCOL_VERSION = 1 -SERVER_BUILD = 2 # 2026-07-28: connect 改为扫描解析 BLEDevice 后连接(WinRT 兼容) +SERVER_BUILD = 3 # 2026-07-28: notify 通道 1f1f/331f 双候选 + connect 返回 GATT 表 EPD_SERVICE_UUID = "13187b10-eba9-a3ba-044e-83d3217d9a38" EPD_CHAR_UUID = "4b646063-6264-f3a7-8941-e65356ea82fe" RXTX_SERVICE_UUID = "00001f10-0000-1000-8000-00805f9b34fb" RXTX_CHAR_UUID = "00001f1f-0000-1000-8000-00805f9b34fb" +# 固件分析(firmware-analysis §2/§3):0x221f 服务的 0x331f 特征(handle 0x0B) +# 与 0x1f1f(handle 7)同入命令分发器;部分固件 notify 能力挂在 331f 上 +ALT_NOTIFY_UUID = "0000331f-0000-1000-8000-00805f9b34fb" DEVICE_NAME_PREFIX = "NRF-" SPOTA_SERVICE_UUID = "0000fef5-0000-1000-8000-00805f9b34fb" @@ -63,6 +66,7 @@ class BleSession: def __init__(self): self.client = None + self.notify_char = None self._id_buf = bytearray() self._id_event = asyncio.Event() @@ -94,8 +98,26 @@ class BleSession: raise RuntimeError(f"设备解析失败(扫描未见 {address})") self.client = BleakClient(dev, timeout=timeout) await self.client.connect() - await self.client.start_notify(RXTX_CHAR_UUID, self._on_notify) - return {"address": address, "name": dev.name} + # notify 通道:1f1f 优先,331f 兜底(固件两 handle 同入分发器,notify 位可能只在 331f) + self.notify_char = None + for uuid in (RXTX_CHAR_UUID, ALT_NOTIFY_UUID): + try: + await self.client.start_notify(uuid, self._on_notify) + self.notify_char = uuid + break + except Exception: + continue + table = self._gatt_table() + return {"address": address, "name": dev.name, + "notify_char": self.notify_char, "gatt": table} + + def _gatt_table(self): + table = [] + for s in self.client.services: + for c in s.characteristics: + table.append({"service": str(s.uuid), "char": str(c.uuid), + "handle": c.handle, "props": list(c.properties)}) + return table def _on_notify(self, _sender, data: bytearray): self._id_buf.extend(data) @@ -228,6 +250,8 @@ class BridgeServer: return await self.ble.request_device_id(float(req.get("timeout", 8.0))) if op == "close": return await self.ble.close() or {} + if op == "services": + return {"gatt": self.ble._gatt_table(), "notify_char": self.ble.notify_char} raise ValueError(f"unknown op {op!r}")