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

Commit

Permalink
ONVIF subscription can now be disabled (polling will be used)
Browse files Browse the repository at this point in the history
  • Loading branch information
cpainchaud committed Jan 5, 2023
1 parent 5d29fcb commit 19b8881
Show file tree
Hide file tree
Showing 6 changed files with 37 additions and 9 deletions.
11 changes: 8 additions & 3 deletions custom_components/reolink_dev/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
CONF_THUMBNAIL_PATH,
CONF_STREAM_FORMAT,
CONF_MOTION_STATES_UPDATE_FALLBACK_DELAY,
CONF_ONVIF_SUBSCRIPTION_DISABLED,
DEFAULT_SMTP_PORT,
COORDINATOR,
MOTION_UPDATE_COORDINATOR,
Expand Down Expand Up @@ -94,15 +95,18 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
entry.data[CONF_USERNAME],
entry.data[CONF_PASSWORD],
)
await push.subscribe(base.event_id)
if not base.onvif_subscription_disabled:
await push.subscribe(base.event_id)

await push.set_smtp_port(entry.options.get(CONF_SMTP_PORT, DEFAULT_SMTP_PORT))
hass.data[DOMAIN][base.push_manager] = push

async def async_update_data():
"""Perform the actual updates."""

async with async_timeout.timeout(base.timeout):
await push.renew()
if not base.onvif_subscription_disabled:
await push.renew()
await base.update_states()

coordinator = DataUpdateCoordinator(
Expand All @@ -124,7 +128,7 @@ async def async_update_motion_states():
# Force a refresh of motion sensors (in case Webhook is broken)
if base.sensor_motion_detection is not None:
# hass.bus.async_fire(base.event_id, {"motion": False})
await base.sensor_motion_detection.handle_event(Event(base.event_id, {"motion": True}))
await base.sensor_motion_detection.handle_event(Event(base.event_id, {"motion": True, "available": True}))

coordinator_motion_update = DataUpdateCoordinator(
hass,
Expand Down Expand Up @@ -167,6 +171,7 @@ async def update_listener(hass: HomeAssistant, entry: ConfigEntry):
motion_state_coordinator: DataUpdateCoordinator = hass.data[DOMAIN][entry.entry_id][MOTION_UPDATE_COORDINATOR]

base.motion_states_update_fallback_delay = entry.options[CONF_MOTION_STATES_UPDATE_FALLBACK_DELAY]
base.onvif_subscription_disabled = entry.options[CONF_ONVIF_SUBSCRIPTION_DISABLED]

if motion_state_coordinator.update_interval != base.motion_states_update_fallback_delay:
if base.motion_states_update_fallback_delay is None or base.motion_states_update_fallback_delay <= 0:
Expand Down
6 changes: 6 additions & 0 deletions custom_components/reolink_dev/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
CONF_STREAM,
CONF_STREAM_FORMAT,
CONF_MOTION_STATES_UPDATE_FALLBACK_DELAY,
CONF_ONVIF_SUBSCRIPTION_DISABLED,
DEFAULT_USE_HTTPS,
DEFAULT_CHANNEL,
DEFAULT_MOTION_OFF_DELAY,
Expand All @@ -52,6 +53,7 @@
DEFAULT_STREAM_FORMAT,
DEFAULT_TIMEOUT,
DEFAULT_MOTION_STATES_UPDATE_FALLBACK_DELAY,
DEFAULT_ONVIF_SUBSCRIPTION_DISABLED,
DOMAIN,
PUSH_MANAGER,
SESSION_RENEW_THRESHOLD,
Expand Down Expand Up @@ -156,6 +158,10 @@ def __init__(
else:
self.motion_states_update_fallback_delay = options[CONF_MOTION_STATES_UPDATE_FALLBACK_DELAY]

self.onvif_subscription_disabled = DEFAULT_ONVIF_SUBSCRIPTION_DISABLED
if CONF_ONVIF_SUBSCRIPTION_DISABLED in options:
self.onvif_subscription_disabled = options[CONF_ONVIF_SUBSCRIPTION_DISABLED]

from .binary_sensor import MotionSensor, ObjectDetectedSensor

self.sensor_motion_detection: Optional[MotionSensor] = None
Expand Down
18 changes: 12 additions & 6 deletions custom_components/reolink_dev/binary_sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -105,11 +105,19 @@ async def handle_event(self, event):

try:
self._available = event.data["available"]
return
except KeyError:
pass

if not self._available:
if self._base.sensor_person_detection is not None and self._base.sensor_person_detection.available:
await self._base.sensor_person_detection.handle_event(
Event(self._base.event_id, {"available": False}))
if self._base.sensor_vehicle_detection is not None and self._base.sensor_vehicle_detection.available:
await self._base.sensor_vehicle_detection.handle_event(
Event(self._base.event_id, {"available": False}))
if self._base.sensor_pet_detection is not None and self._base.sensor_pet_detection.available:
await self._base.sensor_pet_detection.handle_event(
Event(self._base.event_id, {"available": False}))
return

try:
Expand Down Expand Up @@ -151,13 +159,13 @@ async def handle_event(self, event):
# send an event to AI based motion sensor entities
if self._base.sensor_person_detection is not None:
await self._base.sensor_person_detection.handle_event(
Event(self._base.event_id, {"ai_refreshed": True}))
Event(self._base.event_id, {"ai_refreshed": True, "available": True}))
if self._base.sensor_vehicle_detection is not None:
await self._base.sensor_vehicle_detection.handle_event(
Event(self._base.event_id, {"ai_refreshed": True}))
Event(self._base.event_id, {"ai_refreshed": True, "available": True}))
if self._base.sensor_pet_detection is not None:
await self._base.sensor_pet_detection.handle_event(
Event(self._base.event_id, {"ai_refreshed": True}))
Event(self._base.event_id, {"ai_refreshed": True, "available": True}))

if self.enabled:
self.async_schedule_update_ha_state()
Expand Down Expand Up @@ -271,7 +279,6 @@ def available(self):
return self._base.api.ai_state and self._base.api.session_active
return self._available


@property
def device_class(self):
"""Return the class of this device."""
Expand All @@ -290,7 +297,6 @@ async def handle_event(self, event):
if new_availability != self._available:
self._available = new_availability
self.async_schedule_update_ha_state()
return
except KeyError:
pass

Expand Down
8 changes: 8 additions & 0 deletions custom_components/reolink_dev/config_flow.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
CONF_STREAM_FORMAT,
CONF_THUMBNAIL_PATH,
CONF_MOTION_STATES_UPDATE_FALLBACK_DELAY,
CONF_ONVIF_SUBSCRIPTION_DISABLED,
DEFAULT_SMTP_PORT,
DEFAULT_MOTION_OFF_DELAY,
DEFAULT_USE_HTTPS,
Expand All @@ -39,6 +40,7 @@
DEFAULT_THUMBNAIL_PATH,
DEFAULT_TIMEOUT,
DEFAULT_MOTION_STATES_UPDATE_FALLBACK_DELAY,
DEFAULT_ONVIF_SUBSCRIPTION_DISABLED,
DOMAIN,
)

Expand Down Expand Up @@ -200,6 +202,12 @@ async def async_step_init(self, user_input=None): # pylint: disable=unused-argu
CONF_MOTION_OFF_DELAY, DEFAULT_MOTION_OFF_DELAY
),
): vol.All(vol.Coerce(int), vol.Range(min=0)),
vol.Required(
CONF_ONVIF_SUBSCRIPTION_DISABLED,
default=self.config_entry.options.get(
CONF_ONVIF_SUBSCRIPTION_DISABLED, DEFAULT_ONVIF_SUBSCRIPTION_DISABLED
),
): vol.All(vol.Coerce(bool)),
vol.Required(
CONF_MOTION_STATES_UPDATE_FALLBACK_DELAY,
default=self.config_entry.options.get(
Expand Down
2 changes: 2 additions & 0 deletions custom_components/reolink_dev/const.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
CONF_PLAYBACK_MONTHS = "playback_months"
CONF_THUMBNAIL_PATH = "playback_thumbnail_path"
CONF_MOTION_STATES_UPDATE_FALLBACK_DELAY = "motion_states_update_fallback_delay"
CONF_ONVIF_SUBSCRIPTION_DISABLED = "onvif_subscription_disabled"

DEFAULT_USE_HTTPS = True
DEFAULT_CHANNEL = 1
Expand All @@ -33,6 +34,7 @@
DEFAULT_STREAM = "main"
DEFAULT_STREAM_FORMAT = "h264"
DEFAULT_MOTION_STATES_UPDATE_FALLBACK_DELAY = 30
DEFAULT_ONVIF_SUBSCRIPTION_DISABLED = False

DEFAULT_TIMEOUT = 30
DEFAULT_PLAYBACK_MONTHS = 2
Expand Down
1 change: 1 addition & 0 deletions custom_components/reolink_dev/translations/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
"stream": "Stream",
"timeout": "Timeout (seconds)",
"smtp_port": "SMTP port for AI detection events (0 to disable)",
"onvif_subscription_disabled": "Disable ONVIF event subscription (use polling instead)",
"motion_states_update_fallback_delay": "Motion states update fallback delay (seconds, 0 or less to disable): Reolink's event subscription is not always reliable, this will help to avoid event misses",
"motion_off_delay": "Motion sensor off delay (seconds)",
"playback_months": "Playback range (months)",
Expand Down

0 comments on commit 19b8881

Please sign in to comment.