From 18cf880cbc568e25868b46a55b50809ca56b7adf Mon Sep 17 00:00:00 2001 From: Christophe Painchaud Date: Mon, 18 Jul 2022 17:28:37 +0200 Subject: [PATCH 1/2] make sensor unavailable when API call fails --- .../reolink_dev/binary_sensor.py | 32 +++++++++++++++---- 1 file changed, 26 insertions(+), 6 deletions(-) diff --git a/custom_components/reolink_dev/binary_sensor.py b/custom_components/reolink_dev/binary_sensor.py index e2014ae..8724ff8 100644 --- a/custom_components/reolink_dev/binary_sensor.py +++ b/custom_components/reolink_dev/binary_sensor.py @@ -85,10 +85,10 @@ def is_on(self): @property def available(self): - """Return True if entity is available.""" + # in case detection solely relies on callback, availability relies on active session state if self._base.motion_states_update_fallback_delay is None or self._base.motion_states_update_fallback_delay <= 0: - return self._available - return self._base.api.session_active + return self._base.api.session_active + return self._available @property def device_class(self): @@ -124,8 +124,23 @@ async def handle_event(self, event): except: _LOGGER.error("Motion states could not be queried from API") _LOGGER.error(traceback.format_exc()) + self._available = False + if self._base.sensor_person_detection is not None: + await self._base.sensor_person_detection.handle_event( + Event(self._base.event_id, {"available": False})) + if self._base.sensor_vehicle_detection is not None: + await self._base.sensor_vehicle_detection.handle_event( + Event(self._base.event_id, {"available": False})) + if self._base.sensor_pet_detection is not None: + await self._base.sensor_pet_detection.handle_event( + Event(self._base.event_id, {"available": False})) + self.async_schedule_update_ha_state() return + if not self._available: + self._available = True + self.async_schedule_update_ha_state() + if self._event_state: self._last_motion = datetime.datetime.now() else: @@ -253,8 +268,9 @@ def is_on(self): def available(self): """Return True if entity is available.""" if self._base.motion_states_update_fallback_delay is None or self._base.motion_states_update_fallback_delay <= 0: - return self._available - return self._base.api.ai_state and self._base.api.session_active + return self._base.api.ai_state and self._base.api.session_active + return self._available + @property def device_class(self): @@ -270,7 +286,10 @@ async def handle_event(self, event): """Handle incoming event for motion detection and availability.""" try: - self._available = event.data["available"] + new_availability = event.data["available"] + if new_availability != self._available: + self._available = new_availability + self.async_schedule_update_ha_state() return except KeyError: pass @@ -301,6 +320,7 @@ async def handle_event(self, event): if not object_found: self._available = False + self.async_schedule_update_ha_state() From 20a879a1d3856e36d2f6baef9a4095737b66f239 Mon Sep 17 00:00:00 2001 From: Christophe Painchaud Date: Wed, 20 Jul 2022 14:31:30 +0200 Subject: [PATCH 2/2] better handling when camera is not straight available at start time --- custom_components/reolink_dev/__init__.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/custom_components/reolink_dev/__init__.py b/custom_components/reolink_dev/__init__.py index a7903f5..8ee8fd8 100644 --- a/custom_components/reolink_dev/__init__.py +++ b/custom_components/reolink_dev/__init__.py @@ -15,6 +15,7 @@ EVENT_HOMEASSISTANT_STOP, ) from homeassistant.core import HomeAssistant, Event +from homeassistant.exceptions import ConfigEntryNotReady from homeassistant.helpers import device_registry from homeassistant.helpers.storage import STORAGE_DIR from homeassistant.helpers.update_coordinator import DataUpdateCoordinator @@ -72,8 +73,12 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: base = ReolinkBase(hass, entry.data, entry.options) base.sync_functions.append(entry.add_update_listener(update_listener)) - if not await base.connect_api(): - return False + try: + if not await base.connect_api(): + raise ConfigEntryNotReady(f"Error while trying to setup {base.name}, API failed to provide required data") + except: + raise ConfigEntryNotReady(f"Error while trying to setup {base.name}, API had hard error") + hass.data[DOMAIN][entry.entry_id] = {BASE: base} try: