Skip to content

Commit

Permalink
Mark onvif events as stale when the subscription renewal fails (#91567)
Browse files Browse the repository at this point in the history
  • Loading branch information
bdraco authored Apr 22, 2023
1 parent dccef10 commit bba225a
Showing 1 changed file with 50 additions and 4 deletions.
54 changes: 50 additions & 4 deletions homeassistant/components/onvif/event.py
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,12 @@ def async_webhook_working(self) -> None:
LOGGER.debug("%s: Switching to webhook for events", self.name)
self.pullpoint_manager.async_pause()

@callback
def async_mark_events_stale(self) -> None:
"""Mark all events as stale when the subscriptions fail since we are out of sync."""
self._events.clear()
self.async_callback_listeners()


class PullPointManager:
"""ONVIF PullPoint Manager.
Expand Down Expand Up @@ -316,7 +322,13 @@ async def _async_start_pullpoint(self) -> bool:
try:
try:
started = await self._async_create_pullpoint_subscription()
except RemoteProtocolError:
except RequestError:
#
# We should only need to retry on RemoteProtocolError but some cameras
# are flaky and sometimes do not respond to the Renew request so we
# retry on RequestError as well.
#
# For RemoteProtocolError:
# http://datatracker.ietf.org/doc/html/rfc2616#section-8.1.4 allows the server
# to close the connection at any time, we treat this as a normal and try again
# once since we do not want to declare the camera as not supporting PullPoint
Expand Down Expand Up @@ -433,10 +445,24 @@ async def _async_renew_pullpoint(self) -> bool:
# The first time we renew, we may get a Fault error so we
# suppress it. The subscription will be restarted in
# async_restart later.
await self._pullpoint_subscription.Renew(SUBSCRIPTION_RELATIVE_TIME)
try:
await self._pullpoint_subscription.Renew(SUBSCRIPTION_RELATIVE_TIME)
except RequestError:
#
# We should only need to retry on RemoteProtocolError but some cameras
# are flaky and sometimes do not respond to the Renew request so we
# retry on RequestError as well.
#
# For RemoteProtocolError:
# http://datatracker.ietf.org/doc/html/rfc2616#section-8.1.4 allows the server
# to close the connection at any time, we treat this as a normal and try again
# once since we do not want to mark events as stale
# if it just happened to close the connection at the wrong time.
await self._pullpoint_subscription.Renew(SUBSCRIPTION_RELATIVE_TIME)
LOGGER.debug("%s: Renewed PullPoint subscription", self._name)
return True
except RENEW_ERRORS as err:
self._event_manager.async_mark_events_stale()
LOGGER.debug(
"%s: Failed to renew PullPoint subscription; %s",
self._name,
Expand Down Expand Up @@ -634,7 +660,13 @@ async def _async_start_webhook(self) -> bool:
try:
try:
await self._async_create_webhook_subscription()
except RemoteProtocolError:
except RequestError:
#
# We should only need to retry on RemoteProtocolError but some cameras
# are flaky and sometimes do not respond to the Renew request so we
# retry on RequestError as well.
#
# For RemoteProtocolError:
# http://datatracker.ietf.org/doc/html/rfc2616#section-8.1.4 allows the server
# to close the connection at any time, we treat this as a normal and try again
# once since we do not want to declare the camera as not supporting webhooks
Expand Down Expand Up @@ -662,10 +694,24 @@ async def _async_renew_webhook(self) -> bool:
if not self._webhook_subscription:
return False
try:
await self._webhook_subscription.Renew(SUBSCRIPTION_RELATIVE_TIME)
try:
await self._webhook_subscription.Renew(SUBSCRIPTION_RELATIVE_TIME)
except RequestError:
#
# We should only need to retry on RemoteProtocolError but some cameras
# are flaky and sometimes do not respond to the Renew request so we
# retry on RequestError as well.
#
# For RemoteProtocolError:
# http://datatracker.ietf.org/doc/html/rfc2616#section-8.1.4 allows the server
# to close the connection at any time, we treat this as a normal and try again
# once since we do not want to mark events as stale
# if it just happened to close the connection at the wrong time.
await self._webhook_subscription.Renew(SUBSCRIPTION_RELATIVE_TIME)
LOGGER.debug("%s: Renewed Webhook subscription", self._name)
return True
except RENEW_ERRORS as err:
self._event_manager.async_mark_events_stale()
LOGGER.debug(
"%s: Failed to renew webhook subscription %s",
self._name,
Expand Down

0 comments on commit bba225a

Please sign in to comment.