Skip to content
This repository has been archived by the owner on Apr 6, 2023. It is now read-only.

Retry setup at boot time + better handling of 'not available' state when relying only on active polling only #557

Merged
merged 2 commits into from
Aug 31, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 7 additions & 2 deletions custom_components/reolink_dev/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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:
Expand Down
32 changes: 26 additions & 6 deletions custom_components/reolink_dev/binary_sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -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):
Expand Down Expand Up @@ -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:
Expand Down Expand Up @@ -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):
Expand All @@ -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
Expand Down Expand Up @@ -301,6 +320,7 @@ async def handle_event(self, event):

if not object_found:
self._available = False
self.async_schedule_update_ha_state()



Expand Down