@@ -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