diff --git a/custom_components/elro_connects/__init__.py b/custom_components/elro_connects/__init__.py index 1889b40..a052d85 100644 --- a/custom_components/elro_connects/__init__.py +++ b/custom_components/elro_connects/__init__.py @@ -1,10 +1,12 @@ """The Elro Connects integration.""" from __future__ import annotations +import copy from datetime import timedelta import logging from elro.api import K1 +from elro.device import ATTR_DEVICE_STATE, STATE_OFFLINE, STATE_UNKNOWN from homeassistant.config_entries import ConfigEntry from homeassistant.const import SERVICE_RELOAD, Platform @@ -27,8 +29,27 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: async def _async_update_data() -> dict[int, dict]: """Update data via API.""" nonlocal current_device_set + # get state from coordinator cash in case the current state is unknown + coordinator_update: dict[int, dict] = copy.deepcopy(coordinator.data or {}) + # set initial state to offline + for device_id, state_base in coordinator_update.items(): + state_base[ATTR_DEVICE_STATE] = STATE_OFFLINE try: await elro_connects_api.async_update() + device_update = copy.deepcopy(elro_connects_api.data) + for device_id, device_data in device_update.items(): + if device_id not in coordinator_update: + # new device, or known state + coordinator_update[device_id] = device_data + elif device_data[ATTR_DEVICE_STATE] == STATE_UNKNOWN: + # update device state only, other data is not valid + coordinator_update[device_id][ATTR_DEVICE_STATE] = device_data[ + ATTR_DEVICE_STATE + ] + else: + # update full state + coordinator_update[device_id] = device_data + except K1.K1ConnectionError as err: raise UpdateFailed(err) from err new_set = set(elro_connects_api.data.keys()) @@ -43,7 +64,7 @@ async def _async_update_data() -> dict[int, dict]: {}, blocking=False, ) - return elro_connects_api.data + return coordinator_update async def async_reload(call: ServiceCall) -> None: """Reload the integration.""" diff --git a/custom_components/elro_connects/device.py b/custom_components/elro_connects/device.py index 833907a..2fb1853 100644 --- a/custom_components/elro_connects/device.py +++ b/custom_components/elro_connects/device.py @@ -18,7 +18,7 @@ from homeassistant.config_entries import ConfigEntry from homeassistant.const import ATTR_NAME, CONF_HOST, CONF_PORT from homeassistant.core import HomeAssistant, callback -from homeassistant.helpers import device_registry as dr, entity_registry as er +from homeassistant.helpers import device_registry as dr from homeassistant.helpers.entity import DeviceInfo, EntityDescription from homeassistant.helpers.update_coordinator import ( CoordinatorEntity, @@ -66,7 +66,6 @@ async def async_update(self) -> None: """Synchronize with the K1 connector.""" new_data: dict[int, dict] = {} try: - self._retry_count += 1 # Only connect the first time or if there were recent issues if not self._connected: await self.async_connect() @@ -78,6 +77,7 @@ async def async_update(self) -> None: self._retry_count = 0 self._data = new_data except K1.K1ConnectionError as err: + self._retry_count += 1 self._connected = False if not self._data or self._retry_count >= MAX_RETRIES: raise K1.K1ConnectionError(err) from err @@ -139,17 +139,7 @@ def name(self) -> str: @callback def _handle_coordinator_update(self): """Fetch state from the device.""" - if self._device_id in self.coordinator.data: - self.data = self.coordinator.data[self._device_id] - else: - # device removed, remove entity - _LOGGER.debug( - "Entity %s was removed from the connector, cleaning up", self.entity_id - ) - entity_registry = er.async_get(self.hass) - if entity_registry.async_get(self.entity_id): - entity_registry.async_remove(self.entity_id) - + self.data = self.coordinator.data[self._device_id] self.async_write_ha_state() @property diff --git a/custom_components/elro_connects/manifest.json b/custom_components/elro_connects/manifest.json index 117a880..957f6b4 100644 --- a/custom_components/elro_connects/manifest.json +++ b/custom_components/elro_connects/manifest.json @@ -7,5 +7,5 @@ "requirements": ["lib-elro-connects==0.4.1"], "codeowners": ["@jbouwh"], "iot_class": "local_polling", - "version": "0.1.1" + "version": "0.1.2" } diff --git a/tests/elro_connects/test_init.py b/tests/elro_connects/test_init.py index 474d47c..2b9ae6c 100644 --- a/tests/elro_connects/test_init.py +++ b/tests/elro_connects/test_init.py @@ -103,7 +103,7 @@ async def test_configure_platforms_dynamically( assert hass.states.get("siren.eerste_etage") is not None assert hass.states.get("siren.zolder") is not None - # Remove device 1 from api data, entity should be removed + # Remove device 1 from api data, entity should appear offline with an unknown state updated_status_data.pop(1) mock_k1_connector["result"].return_value = updated_status_data @@ -111,6 +111,6 @@ async def test_configure_platforms_dynamically( async_fire_time_changed(hass, time) await hass.async_block_till_done() - assert hass.states.get("siren.beganegrond") is None + assert hass.states.get("siren.beganegrond").state == "unknown" assert hass.states.get("siren.eerste_etage") is not None assert hass.states.get("siren.zolder") is not None