fix(bridge): notify 通道 1f1f/331f 双候选 + services 诊断 op,build=3
This commit is contained in:
1 parent
89335e0e82
commit
92a8661088
1 file changed
+27
-3
+27
-3
@@ -27,12 +27,15 @@ import platform
|
|||||||
import sys
|
import sys
|
||||||
|
|
||||||
PROTOCOL_VERSION = 1
|
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_SERVICE_UUID = "13187b10-eba9-a3ba-044e-83d3217d9a38"
|
||||||
EPD_CHAR_UUID = "4b646063-6264-f3a7-8941-e65356ea82fe"
|
EPD_CHAR_UUID = "4b646063-6264-f3a7-8941-e65356ea82fe"
|
||||||
RXTX_SERVICE_UUID = "00001f10-0000-1000-8000-00805f9b34fb"
|
RXTX_SERVICE_UUID = "00001f10-0000-1000-8000-00805f9b34fb"
|
||||||
RXTX_CHAR_UUID = "00001f1f-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-"
|
DEVICE_NAME_PREFIX = "NRF-"
|
||||||
|
|
||||||
SPOTA_SERVICE_UUID = "0000fef5-0000-1000-8000-00805f9b34fb"
|
SPOTA_SERVICE_UUID = "0000fef5-0000-1000-8000-00805f9b34fb"
|
||||||
@@ -63,6 +66,7 @@ class BleSession:
|
|||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.client = None
|
self.client = None
|
||||||
|
self.notify_char = None
|
||||||
self._id_buf = bytearray()
|
self._id_buf = bytearray()
|
||||||
self._id_event = asyncio.Event()
|
self._id_event = asyncio.Event()
|
||||||
|
|
||||||
@@ -94,8 +98,26 @@ class BleSession:
|
|||||||
raise RuntimeError(f"设备解析失败(扫描未见 {address})")
|
raise RuntimeError(f"设备解析失败(扫描未见 {address})")
|
||||||
self.client = BleakClient(dev, timeout=timeout)
|
self.client = BleakClient(dev, timeout=timeout)
|
||||||
await self.client.connect()
|
await self.client.connect()
|
||||||
await self.client.start_notify(RXTX_CHAR_UUID, self._on_notify)
|
# notify 通道:1f1f 优先,331f 兜底(固件两 handle 同入分发器,notify 位可能只在 331f)
|
||||||
return {"address": address, "name": dev.name}
|
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):
|
def _on_notify(self, _sender, data: bytearray):
|
||||||
self._id_buf.extend(data)
|
self._id_buf.extend(data)
|
||||||
@@ -228,6 +250,8 @@ class BridgeServer:
|
|||||||
return await self.ble.request_device_id(float(req.get("timeout", 8.0)))
|
return await self.ble.request_device_id(float(req.get("timeout", 8.0)))
|
||||||
if op == "close":
|
if op == "close":
|
||||||
return await self.ble.close() or {}
|
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}")
|
raise ValueError(f"unknown op {op!r}")
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in new issue
Block a user