Skip to content

Commit d904d47

Browse files
committed
tools: nice errors on broadcast failures
If a notification broadcast fails, display a nice error instead of a full exception backtrace. Signed-off-by: Jordan Yates <jordan@embeint.com>
1 parent 5b8846f commit d904d47

2 files changed

Lines changed: 25 additions & 12 deletions

File tree

src/infuse_iot/tools/gateway.py

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,10 @@ def __init__(
126126
self.ddb = ddb
127127
self.rpc = rpc_server
128128

129+
def notification_broadcast(self, notification: ClientNotification):
130+
if self.server:
131+
self.server.broadcast(notification)
132+
129133
def query_device_key(self, cb_event: threading.Event | None = None):
130134
def security_state_done(pkt: PacketReceived, _: int, response: bytes):
131135
cloud_key = response[:32]
@@ -204,7 +208,7 @@ def _handle_local_tdf(self, pkt: PacketReceived):
204208
if_addr = interface.Address.BluetoothLeAddr.from_tdf_struct(reading.data[0].address)
205209
infuse_id = self._common.ddb.infuse_id_from_bluetooth(if_addr)
206210
if infuse_id:
207-
self._common.server.broadcast(ClientNotificationConnectionDropped(infuse_id))
211+
self._common.notification_broadcast(ClientNotificationConnectionDropped(infuse_id))
208212

209213
def _handle_serial_frame(self, frame: bytearray):
210214
try:
@@ -244,10 +248,9 @@ def _handle_serial_frame(self, frame: bytearray):
244248
elif pkt.ptype == InfuseType.KEY_IDS:
245249
self._common.query_device_key(None)
246250

251+
# Forward to clients
247252
notification = ClientNotificationEpacketReceived(pkt)
248-
if self._common.server:
249-
# Forward to clients
250-
self._common.server.broadcast(notification)
253+
self._common.notification_broadcast(notification)
251254
except (ValueError, KeyError) as e:
252255
print(f"Decode failed ({e})")
253256

@@ -322,19 +325,19 @@ def _bt_connect_cb(self, pkt: PacketReceived, rc: int, response: bytes):
322325
else:
323326
self._connected[infuse_id] = 1
324327
rsp = ClientNotificationConnectionCreated(infuse_id, 244 - ctypes.sizeof(CtypeBtGattFrame) - 16)
325-
self._common.server.broadcast(rsp)
328+
self._common.notification_broadcast(rsp)
326329

327330
def _handle_conn_request(self, req: GatewayRequestConnectionRequest):
328331
assert self._common.server is not None
329332

330333
if req.infuse_id == InfuseID.GATEWAY or req.infuse_id == self._common.ddb.gateway:
331334
# Local gateway always connected
332-
self._common.server.broadcast(ClientNotificationConnectionCreated(req.infuse_id, 512))
335+
self._common.notification_broadcast(ClientNotificationConnectionCreated(req.infuse_id, 512))
333336
return
334337

335338
state = self._common.ddb.devices.get(req.infuse_id, None)
336339
if state is None or state.bt_addr is None:
337-
self._common.server.broadcast(ClientNotificationConnectionFailed(req.infuse_id))
340+
self._common.notification_broadcast(ClientNotificationConnectionFailed(req.infuse_id))
338341
return
339342

340343
subs = 0
@@ -403,7 +406,7 @@ def _handle_observed_devices(self):
403406
if self._common.ddb.gateway == device:
404407
info["gateway"] = True
405408
observed_devices[device] = info
406-
self._common.server.broadcast(ClientNotificationObservedDevices(observed_devices))
409+
self._common.notification_broadcast(ClientNotificationObservedDevices(observed_devices))
407410

408411
def _iter(self) -> None:
409412
if self._common.server is None:

src/infuse_iot/tools/native_bt.py

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
PacketReceived,
3131
)
3232
from infuse_iot.socket_comms import (
33+
ClientNotification,
3334
ClientNotificationConnectionCreated,
3435
ClientNotificationConnectionFailed,
3536
ClientNotificationEpacketReceived,
@@ -64,6 +65,12 @@ def __init__(self, database: DeviceDatabase, server: LocalServer, bleak_mapping:
6465
self._queues: dict[int, asyncio.Queue] = {}
6566
self._tasks: dict[int, asyncio.Task] = {}
6667

68+
def wrapped_broadcast(self, notifcation: ClientNotification):
69+
try:
70+
self._server.broadcast(notifcation)
71+
except OSError as e:
72+
Console.log_error(f"Failed to broadcast notification: {str(e)}")
73+
6774
def notification_handler(self, _characteristic: BleakGATTCharacteristic, data: bytearray):
6875
try:
6976
hdr, decr = CtypeBtGattFrame.decrypt(self._db, None, bytes(data))
@@ -89,7 +96,7 @@ def notification_handler(self, _characteristic: BleakGATTCharacteristic, data: b
8996
bytes(decr),
9097
)
9198
Console.log_rx(pkt.ptype, len(data))
92-
self._server.broadcast(ClientNotificationEpacketReceived(pkt))
99+
self.wrapped_broadcast(ClientNotificationEpacketReceived(pkt))
93100

94101
async def create_connection_internal(
95102
self, request: GatewayRequestConnectionRequest, dev: BLEDevice, queue: asyncio.Queue
@@ -118,7 +125,7 @@ async def create_connection_internal(
118125

119126
Console.log_info(f"{dev}: Connected (MTU {client.mtu_size})")
120127

121-
self._server.broadcast(
128+
self.wrapped_broadcast(
122129
ClientNotificationConnectionCreated(
123130
request.infuse_id,
124131
# ATT header uses 3 bytes of the MTU
@@ -174,7 +181,7 @@ def datagram_received(self, data: bytes, addr: tuple[str | Any, int]):
174181

175182
ble_dev = self._mapping.get(request.infuse_id, None)
176183
if ble_dev is None:
177-
self._server.broadcast(ClientNotificationConnectionFailed(request.infuse_id))
184+
self.wrapped_broadcast(ClientNotificationConnectionFailed(request.infuse_id))
178185
return
179186

180187
# Create queue for further data transfer
@@ -251,7 +258,10 @@ def simple_callback(self, device: BLEDevice, data: AdvertisementData):
251258
Console.log_rx(hdr.type, len(payload))
252259
pkt = PacketReceived([hop], hdr.type, decr)
253260
notification = ClientNotificationEpacketReceived(pkt)
254-
self.server.broadcast(notification)
261+
try:
262+
self.server.broadcast(notification)
263+
except OSError as e:
264+
Console.log_error(f"Failed to broadcast notification: {str(e)}")
255265

256266
async def async_bt_receiver(self):
257267
loop = asyncio.get_event_loop()

0 commit comments

Comments
 (0)