Skip to content

Commit 78d2b11

Browse files
authored
Only setup the notify handler once (#116)
1 parent 486d32b commit 78d2b11

File tree

1 file changed

+17
-15
lines changed

1 file changed

+17
-15
lines changed

switchbot/devices/device.py

Lines changed: 17 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,7 @@ def __init__(
113113
self._expected_disconnect = False
114114
self.loop = asyncio.get_event_loop()
115115
self._callbacks: list[Callable[[], None]] = []
116+
self._notify_future: asyncio.Future[bytearray] | None = None
116117

117118
def advertisement_changed(self, advertisement: SwitchBotAdvertisement) -> bool:
118119
"""Check if the advertisement has changed."""
@@ -238,6 +239,7 @@ async def _ensure_connected(self):
238239
resolved = self._resolve_characteristics(await client.get_services())
239240
self._client = client
240241
self._reset_disconnect_timer()
242+
await self._start_notify()
241243

242244
def _resolve_characteristics(self, services: BleakGATTServiceCollection) -> bool:
243245
"""Resolve characteristics."""
@@ -335,35 +337,35 @@ async def _send_command_locked(self, key: str, command: bytes) -> bytes:
335337
await self._execute_forced_disconnect()
336338
raise
337339

340+
def _notification_handler(self, _sender: int, data: bytearray) -> None:
341+
"""Handle notification responses."""
342+
if self._notify_future and not self._notify_future.done():
343+
self._notify_future.set_result(data)
344+
return
345+
_LOGGER.debug("%s: Received unsolicited notification: %s", self.name, data)
346+
347+
async def _start_notify(self) -> None:
348+
"""Start notification."""
349+
_LOGGER.debug("%s: Subscribe to notifications; RSSI: %s", self.name, self.rssi)
350+
await self._client.start_notify(self._read_char, self._notification_handler)
351+
338352
async def _execute_command_locked(self, key: str, command: bytes) -> bytes:
339353
"""Execute command and read response."""
340354
assert self._client is not None
341355
if not self._read_char:
342356
raise CharacteristicMissingError(READ_CHAR_UUID)
343357
if not self._write_char:
344358
raise CharacteristicMissingError(WRITE_CHAR_UUID)
345-
future: asyncio.Future[bytearray] = asyncio.Future()
359+
self._notify_future = asyncio.Future()
346360
client = self._client
347361

348-
def _notification_handler(_sender: int, data: bytearray) -> None:
349-
"""Handle notification responses."""
350-
if future.done():
351-
_LOGGER.debug("%s: Notification handler already done", self.name)
352-
return
353-
future.set_result(data)
354-
355-
_LOGGER.debug("%s: Subscribe to notifications; RSSI: %s", self.name, self.rssi)
356-
await client.start_notify(self._read_char, _notification_handler)
357-
358362
_LOGGER.debug("%s: Sending command: %s", self.name, key)
359363
await client.write_gatt_char(self._write_char, command, False)
360364

361365
async with async_timeout.timeout(5):
362-
notify_msg = await future
366+
notify_msg = await self._notify_future
363367
_LOGGER.debug("%s: Notification received: %s", self.name, notify_msg)
364-
365-
_LOGGER.debug("%s: UnSubscribe to notifications", self.name)
366-
await client.stop_notify(self._read_char)
368+
self._notify_future = None
367369

368370
if notify_msg == b"\x07":
369371
_LOGGER.error("Password required")

0 commit comments

Comments
 (0)