Skip to content

Commit

Permalink
Fix #144 error handling on device is unresponsive
Browse files Browse the repository at this point in the history
Correct error handling and trigger automatic reload when there is no
response from the device during setup. It also detects IP address
changes and automatically reconfigures with the new IP address.
  • Loading branch information
nao-pon committed Oct 17, 2023
1 parent bb0c2a7 commit 56bf984
Show file tree
Hide file tree
Showing 2 changed files with 63 additions and 6 deletions.
17 changes: 12 additions & 5 deletions custom_components/echonetlite/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
from homeassistant.core import HomeAssistant
from homeassistant.util import Throttle
from homeassistant.const import Platform
from homeassistant.exceptions import ConfigEntryNotReady
from .const import DOMAIN, USER_OPTIONS, TEMP_OPTIONS, CONF_FORCE_POLLING, MISC_OPTIONS
from pychonet.lib.udpserver import UDPServer

Expand Down Expand Up @@ -144,7 +145,8 @@ def unload_config_entry():
_LOGGER.debug(
f"Called unload_config_entry() try to remove {host} from server._state."
)
server._state.pop(host)
if server._state.get(host):
server._state.pop(host)

entry.async_on_unload(unload_config_entry)

Expand Down Expand Up @@ -238,10 +240,15 @@ def unload_config_entry():
)

echonetlite = ECHONETConnector(instance, hass.data[DOMAIN]["api"], entry)
await echonetlite.async_update()
hass.data[DOMAIN][entry.entry_id].append(
{"instance": instance, "echonetlite": echonetlite}
)
try:
await asyncio.wait_for(echonetlite.async_update(), timeout=20)
hass.data[DOMAIN][entry.entry_id].append(
{"instance": instance, "echonetlite": echonetlite}
)
except asyncio.exceptions.TimeoutError as ex:
raise ConfigEntryNotReady(
f"Connection error while connecting to {host}: {ex}"
) from ex

_LOGGER.debug(f"Plaform entry data - {entry.data}")

Expand Down
52 changes: 51 additions & 1 deletion custom_components/echonetlite/config_flow.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import voluptuous as vol

from homeassistant import config_entries
from homeassistant.config_entries import ConfigEntryState
from homeassistant.core import HomeAssistant, callback
from homeassistant.data_entry_flow import FlowResult
from homeassistant.exceptions import HomeAssistantError
Expand Down Expand Up @@ -106,6 +107,47 @@ async def validate_input(
raise ErrorConnect("cannot_connect")
state = server._state[host]
uid = state["uid"]

# check ip addr changed
if user_input.get("newhost"):
config_entry = None
old_host = None
entries = hass.config_entries.async_entries(DOMAIN)

for entry in entries:
instances = []
_data = entry.data
for _instance in _data.get("instances", []):
instance = _instance.copy()
if old_host or instance.get("uid") == uid:
old_host = instance["host"]
instance["host"] = host
instances.append(instance)
if old_host:
config_entry = entry
_LOGGER.info(
f"ECHONET registed node found uid is {uid}, conig entry id is {entry.entry_id}."
)
break

if old_host:
_LOGGER.info(f"ECHONET registed node IP hanged from {old_host} to {host}.")
_LOGGER.info(f"New instances data is {instances}")
if server._state.get(old_host):
server._state.pop(old_host)
hass.config_entries.async_update_entry(
config_entry, data={"instances": instances}
)

# Wait max 30 secs for entry loaded
for x in range(0, 300):
await asyncio.sleep(0.1)
if entry.state == ConfigEntryState.LOADED:
await hass.config_entries.async_reload(entry.entry_id)
break

raise ErrorIpChanged(host)

manufacturer = state["manufacturer"]
if not isinstance(manufacturer, str):
# If unable to resolve the manufacturer,
Expand Down Expand Up @@ -274,10 +316,14 @@ async def async_discover_newhost(hass, host):
_LOGGER.info(f"received newip discovery: {host}")
if host not in _detected_hosts.keys():
try:
instance_list = await validate_input(hass, {"host": host})
instance_list = await validate_input(
hass, {"host": host, "newhost": True}
)
_LOGGER.debug(f"ECHONET Node detected in {host}")
except ErrorConnect as e:
_LOGGER.debug(f"ECHONET Node Error Connect ({e})")
except ErrorIpChanged as e:
_LOGGER.info(f"ECHONET Detected Node IP Changed to '{e}'")
else:
if len(instance_list):
_detected_hosts.update({host: instance_list})
Expand All @@ -289,6 +335,10 @@ class ErrorConnect(HomeAssistantError):
"""Error to indicate we cannot connect."""


class ErrorIpChanged(HomeAssistantError):
"""Error to indicate we cannot connect."""


class OptionsFlowHandler(config_entries.OptionsFlow):
def __init__(self, config):
self._config_entry = config
Expand Down

0 comments on commit 56bf984

Please sign in to comment.