Skip to content

Commit 5d70cd1

Browse files
authored
Improve re-connect logic to be more robust (#80)
1 parent 225814a commit 5d70cd1

File tree

4 files changed

+40
-8
lines changed

4 files changed

+40
-8
lines changed

custom_components/remote_homeassistant/__init__.py

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@
5858
CONF_REMOTE_INFO,
5959
DOMAIN,
6060
)
61-
from .rest_api import async_get_discovery_info
61+
from .rest_api import UnsupportedVersion, async_get_discovery_info
6262

6363
_LOGGER = logging.getLogger(__name__)
6464

@@ -371,14 +371,20 @@ async def _async_instance_get_info():
371371
self._access_token,
372372
self._verify_ssl,
373373
)
374+
except OSError:
375+
_LOGGER.exception("failed to connect")
376+
except UnsupportedVersion:
377+
_LOGGER.error("Unsupported version, at least 0.111 is required.")
374378
except Exception:
375379
_LOGGER.exception("failed to fetch instance info")
376-
return None
380+
return None
377381

378382
@callback
379383
def _async_instance_id_match(info):
380384
"""Verify if remote instance id matches the expected id."""
381-
if info["uuid"] != self._entry.unique_id:
385+
if not info:
386+
return False
387+
if info and info["uuid"] != self._entry.unique_id:
382388
_LOGGER.error(
383389
"instance id not matching: %s != %s",
384390
info["uuid"],
@@ -395,8 +401,8 @@ def _async_instance_id_match(info):
395401
while True:
396402
info = await _async_instance_get_info()
397403

398-
# If an instance id is set, verify we are talking to correct instance
399-
if not (info or _async_instance_id_match(info)):
404+
# Verify we are talking to correct instance
405+
if not _async_instance_id_match(info):
400406
self.set_connection_state(STATE_RECONNECTING)
401407
await asyncio.sleep(10)
402408
continue
@@ -434,6 +440,7 @@ async def _heartbeat_loop(self):
434440

435441
_LOGGER.debug("Sending ping")
436442
event = asyncio.Event()
443+
437444
def resp(message):
438445
_LOGGER.debug("Got pong: %s", message)
439446
event.set()
@@ -477,7 +484,10 @@ async def _disconnected(self):
477484
self._hass.states.async_remove(entity)
478485
if self._heartbeat_task is not None:
479486
self._heartbeat_task.cancel()
480-
await self._heartbeat_task
487+
try:
488+
await self._heartbeat_task
489+
except asyncio.CancelledError:
490+
pass
481491
if self._remove_listener is not None:
482492
self._remove_listener()
483493

custom_components/remote_homeassistant/config_flow.py

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,13 @@
2525
from homeassistant.core import callback
2626

2727
from . import async_yaml_to_config_entry
28-
from .rest_api import ApiProblem, CannotConnect, InvalidAuth, async_get_discovery_info
28+
from .rest_api import (
29+
ApiProblem,
30+
CannotConnect,
31+
InvalidAuth,
32+
UnsupportedVersion,
33+
async_get_discovery_info,
34+
)
2935
from .const import (
3036
CONF_REMOTE_CONNECTION,
3137
CONF_SECURE,
@@ -100,6 +106,8 @@ async def async_step_user(self, user_input=None):
100106
errors["base"] = "cannot_connect"
101107
except InvalidAuth:
102108
errors["base"] = "invalid_auth"
109+
except UnsupportedVersion:
110+
errors["base"] = "unsupported_version"
103111
except Exception: # pylint: disable=broad-except
104112
_LOGGER.exception("Unexpected exception")
105113
errors["base"] = "unknown"

custom_components/remote_homeassistant/rest_api.py

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,14 @@ class InvalidAuth(exceptions.HomeAssistantError):
2121
"""Error to indicate there is invalid auth."""
2222

2323

24+
class BadResponse(exceptions.HomeAssistantError):
25+
"""Error to indicate a bad response was received."""
26+
27+
28+
class UnsupportedVersion(exceptions.HomeAssistantError):
29+
"""Error to indicate an unsupported version of Home Assistant."""
30+
31+
2432
async def async_get_discovery_info(hass, host, port, secure, access_token, verify_ssl):
2533
"""Get discovery information from server."""
2634
url = API_URL.format(
@@ -45,4 +53,9 @@ async def async_get_discovery_info(hass, host, port, secure, access_token, verif
4553
async with session.get(url + "discovery_info") as resp:
4654
if resp.status != 200:
4755
raise ApiProblem()
48-
return await resp.json()
56+
json = await resp.json()
57+
if not isinstance(json, dict):
58+
raise BadResponse(f"Bad response data: {json}")
59+
if "uuid" not in json:
60+
raise UnsupportedVersion()
61+
return json

custom_components/remote_homeassistant/translations/en.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
"api_problem": "Bad response from server",
1818
"cannot_connect": "Failed to connect to server",
1919
"invalid_auth": "Invalid credentials",
20+
"unsupported_version": "Unsupported version. At least version 0.111 is required.",
2021
"unknown": "An unknown error occurred"
2122
},
2223
"abort": {

0 commit comments

Comments
 (0)