diff --git a/homeassistant/components/onvif/device.py b/homeassistant/components/onvif/device.py index d7f50f6744e..8c000852c48 100644 --- a/homeassistant/components/onvif/device.py +++ b/homeassistant/components/onvif/device.py @@ -11,7 +11,7 @@ from httpx import RequestError import onvif from onvif import ONVIFCamera from onvif.exceptions import ONVIFError -from zeep.exceptions import Fault +from zeep.exceptions import Fault, XMLParseError from homeassistant.config_entries import ConfigEntry from homeassistant.const import ( @@ -284,7 +284,7 @@ class ONVIFDevice: snapshot = media_capabilities and media_capabilities.SnapshotUri pullpoint = False - with suppress(ONVIFError, Fault, RequestError): + with suppress(ONVIFError, Fault, RequestError, XMLParseError): pullpoint = await self.events.async_start() ptz = False diff --git a/homeassistant/components/onvif/event.py b/homeassistant/components/onvif/event.py index 710e84f93bf..8b09ee99079 100644 --- a/homeassistant/components/onvif/event.py +++ b/homeassistant/components/onvif/event.py @@ -5,6 +5,7 @@ import asyncio from collections.abc import Callable from contextlib import suppress import datetime as dt +from logging import DEBUG, WARNING from httpx import RemoteProtocolError, TransportError from onvif import ONVIFCamera, ONVIFService @@ -20,7 +21,6 @@ from .parsers import PARSERS UNHANDLED_TOPICS = set() SUBSCRIPTION_ERRORS = ( - XMLParseError, Fault, asyncio.TimeoutError, TransportError, @@ -122,20 +122,32 @@ class EventManager: if self._subscription: # Suppressed. The subscription may no longer exist. - with suppress(*SUBSCRIPTION_ERRORS): + try: await self._subscription.Unsubscribe() + except (XMLParseError, *SUBSCRIPTION_ERRORS) as err: + LOGGER.debug( + "Failed to unsubscribe ONVIF PullPoint subscription for '%s';" + " This is normal if the device restarted: %s", + self.unique_id, + err, + ) self._subscription = None try: restarted = await self.async_start() - except SUBSCRIPTION_ERRORS: + except (XMLParseError, *SUBSCRIPTION_ERRORS) as err: restarted = False + # Device may not support subscriptions so log at debug level + # when we get an XMLParseError + LOGGER.log( + DEBUG if isinstance(err, XMLParseError) else WARNING, + "Failed to restart ONVIF PullPoint subscription for '%s'; " + "Retrying later: %s", + self.unique_id, + err, + ) if not restarted: - LOGGER.warning( - "Failed to restart ONVIF PullPoint subscription for '%s'. Retrying", - self.unique_id, - ) # Try again in a minute self._unsub_refresh = async_call_later(self.hass, 60, self.async_restart) elif self._listeners: @@ -154,8 +166,7 @@ class EventManager: .isoformat(timespec="seconds") .replace("+00:00", "Z") ) - with suppress(*SUBSCRIPTION_ERRORS): - await self._subscription.Renew(termination_time) + await self._subscription.Renew(termination_time) def async_schedule_pull(self) -> None: """Schedule async_pull_messages to run.""" @@ -178,8 +189,11 @@ class EventManager: except RemoteProtocolError: # Likely a shutdown event, nothing to see here return - except SUBSCRIPTION_ERRORS as err: - LOGGER.warning( + except (XMLParseError, *SUBSCRIPTION_ERRORS) as err: + # Device may not support subscriptions so log at debug level + # when we get an XMLParseError + LOGGER.log( + DEBUG if isinstance(err, XMLParseError) else WARNING, "Failed to fetch ONVIF PullPoint subscription messages for '%s': %s", self.unique_id, err,