Skip to content

Commit e96f087

Browse files
committed
Improve keepalive recovery handling
1 parent 8c97a24 commit e96f087

3 files changed

Lines changed: 45 additions & 7 deletions

File tree

pyintesishome2/intesisbase.py

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -73,18 +73,23 @@ async def _set_value(self, device_id, uid, value):
7373
"""Internal method to send a value to the device."""
7474
raise NotImplementedError()
7575

76-
async def _send_command(self, command: str):
76+
async def _send_command(self, command: str, *, wait_for_response: bool = True):
7777
try:
7878
_LOGGER.debug("Preparing to send command: %s", command)
79-
self._received_response.clear()
80-
if not self._writer:
79+
if wait_for_response:
80+
self._received_response.clear()
81+
if not self._writer or self._writer.is_closing():
8182
_LOGGER.error("No writer available. Cannot send command.")
83+
self._connected = False
8284
return
8385
_LOGGER.debug("Writer state: %r", self._writer)
8486
encoded_command = command.encode("ascii")
8587
_LOGGER.debug("Encoded command: %r (length: %d)", encoded_command, len(encoded_command))
8688
self._writer.write(encoded_command)
8789
await self._writer.drain()
90+
if not wait_for_response:
91+
_LOGGER.debug("Command sent without waiting for response.")
92+
return
8893
_LOGGER.debug("Command sent and drained. Waiting for response event.")
8994
timeout = 15.0
9095
start_time = asyncio.get_event_loop().time()
@@ -161,6 +166,18 @@ async def _data_received(self):
161166
finally:
162167
self._connected = False
163168
self._connecting = False
169+
if self._keepalive_task:
170+
await self._cancel_task_if_exists(self._keepalive_task)
171+
self._keepalive_task = None
172+
if self._writer:
173+
self._writer.close()
174+
try:
175+
await self._writer.wait_closed()
176+
except Exception as exc: # pylint: disable=broad-except
177+
_LOGGER.debug("Error while waiting for writer to close: %s", exc)
178+
self._writer = None
179+
self._reader = None
180+
self._receive_task = None
164181
await self._send_update_callback()
165182

166183
def _update_device_state(self, device_id, uid, value):
@@ -197,7 +214,9 @@ async def stop(self):
197214
"""Public method for shutting down connectivity."""
198215
self._connected = False
199216
await self._cancel_task_if_exists(self._receive_task)
217+
self._receive_task = None
200218
await self._cancel_task_if_exists(self._keepalive_task)
219+
self._keepalive_task = None
201220
if self._writer:
202221
self._writer.close()
203222
await self._writer.wait_closed()

pyintesishome2/intesisbox.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -167,7 +167,13 @@ async def _send_keepalive(self):
167167
try:
168168
while True:
169169
await asyncio.sleep(30)
170-
await self._send_command("GET,1:AMBTEMP")
170+
if not self._connected:
171+
_LOGGER.debug("Stopping keepalive task because connection is inactive")
172+
break
173+
if not self._writer or self._writer.is_closing():
174+
_LOGGER.warning("Keepalive aborted because writer is not available")
175+
break
176+
await self._send_command("GET,1:AMBTEMP", wait_for_response=False)
171177
except asyncio.CancelledError:
172178
_LOGGER.debug("Cancelled the keepalive task")
173179

pyintesishome2/intesishome.py

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -78,12 +78,25 @@ async def _send_keepalive(self):
7878
try:
7979
while True:
8080
await asyncio.sleep(120)
81-
_LOGGER.debug("sending keepalive to {self._device_type}")
82-
device_id = str(next(iter(self._devices)))
81+
if not self._connected:
82+
_LOGGER.debug("Stopping keepalive task because connection is inactive")
83+
break
84+
if not self._writer or self._writer.is_closing():
85+
_LOGGER.warning("Keepalive aborted because writer is not available")
86+
break
87+
if not self._devices:
88+
_LOGGER.debug("No devices registered; skipping keepalive ping")
89+
continue
90+
_LOGGER.debug("sending keepalive to %s", self._device_type)
91+
try:
92+
device_id = str(next(iter(self._devices)))
93+
except StopIteration:
94+
_LOGGER.debug("No device id available for keepalive")
95+
continue
8396
message = (
8497
f'{{"command":"get","data":{{"deviceId":{device_id},"uid":10}}}}'
8598
)
86-
await self._send_command(message)
99+
await self._send_command(message, wait_for_response=False)
87100
except asyncio.CancelledError:
88101
_LOGGER.debug("Cancelled the keepalive task")
89102

0 commit comments

Comments
 (0)