Skip to content

Commit

Permalink
Improve responsiveness to failure
Browse files Browse the repository at this point in the history
When a disconnect error is received when waiting for a reply, this change responds earlier than previous version that always waited 2 seconds to try again.
  • Loading branch information
mattsaxon committed Apr 29, 2019
1 parent 85fef1f commit 6b0be3b
Showing 1 changed file with 27 additions and 12 deletions.
39 changes: 27 additions & 12 deletions pysonofflan/sonoffdevice.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,8 @@ def __init__(self,
logger=self.logger
)

self.message_received_event = asyncio.Event()
self.message_ping_event = asyncio.Event()
self.message_acknowledged_event = asyncio.Event()
self.params_updated_event = asyncio.Event()

self.tasks.append(self.loop.create_task(self.send_updated_params_loop()))
Expand Down Expand Up @@ -133,6 +134,7 @@ async def setup_connection(self, retry):
self.logger.error('Unexpected error in receive_message_loop(): %s', format(ex) )

finally:
self.message_ping_event.set()
self.logger.debug('finally: closing websocket from setup_connection')
await self.client.close_connection()

Expand Down Expand Up @@ -198,14 +200,23 @@ async def send_updated_params_loop(self):
)

try:
self.message_received_event.clear()
self.message_ping_event.clear()
self.message_acknowledged_event.clear()
await self.client.send(update_message)

await asyncio.wait_for(self.message_received_event.wait(), 2)
await asyncio.wait_for(self.message_ping_event.wait(), 2)

self.params_updated_event.clear()
self.logger.debug('Update message sent, event cleared, should '
'loop now')
if self.message_acknowledged_event.is_set():
self.params_updated_event.clear()
self.logger.debug('Update message sent, event cleared, should '
'loop now')
else:
self.logger.warn(
"we didn't get an acknowledge message, we have probably been disconnected!")
# message 'ping', but not an acknowledgement, so loop
# if we were disconnected we will wait for reconnection
# if it was another type of message, we will resend change


except websockets.exceptions.ConnectionClosed:
self.logger.error('Connection closed unexpectedly in send()')
Expand Down Expand Up @@ -245,6 +256,7 @@ async def handle_message(self, message):
"""

self.messages_received +=1 # ensure debug messages are unique to stop deduplication by logger
self.message_ping_event.set()

response = json.loads(message)

Expand All @@ -257,7 +269,7 @@ async def handle_message(self, message):
self.basic_info = response

if self.client.connected_event.is_set(): # only mark message as accepted if we are already online (otherwise this is an initial connection message)
self.message_received_event.set()
self.message_acknowledged_event.set()

if self.callback_after_update is not None:
await self.callback_after_update(self)
Expand All @@ -267,17 +279,20 @@ async def handle_message(self, message):
self.logger.debug(
'Message: %i: Received update from device, updating internal state to: %s'
, self.messages_received , response['params'] )

self.client.connected_event.set()
self.client.disconnected_event.clear()

if not self.client.connected_event.is_set():
self.client.connected_event.set()
self.client.disconnected_event.clear()
send_update = True

if not self.params_updated_event.is_set(): # only update internal state if there is not a new message queued to be sent

if self.params != response['params']: # only send client update message if there is a change
self.params = response['params']
send_update = True

if self.callback_after_update is not None:
await self.callback_after_update(self)
if send_update and self.callback_after_update is not None:
await self.callback_after_update(self)

else:
self.logger.error(
Expand Down

0 comments on commit 6b0be3b

Please sign in to comment.