Migrate onvif to use onvif-zeep-async 4.0.1 with aiohttp (#146297)

This commit is contained in:
J. Nick Koston
2025-06-07 13:39:59 -05:00
committed by GitHub
parent a979f884f9
commit 636b484d9d
7 changed files with 43 additions and 18 deletions

View File

@ -5,7 +5,7 @@ from contextlib import suppress
from http import HTTPStatus
import logging
from httpx import RequestError
import aiohttp
from onvif.exceptions import ONVIFError
from onvif.util import is_auth_error, stringify_onvif_error
from zeep.exceptions import Fault, TransportError
@ -49,7 +49,7 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
await device.async_setup()
if not entry.data.get(CONF_SNAPSHOT_AUTH):
await async_populate_snapshot_auth(hass, device, entry)
except RequestError as err:
except (TimeoutError, aiohttp.ClientError) as err:
await device.device.close()
raise ConfigEntryNotReady(
f"Could not connect to camera {device.device.host}:{device.device.port}: {err}"
@ -119,7 +119,7 @@ async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
if device.capabilities.events and device.events.started:
try:
await device.events.async_stop()
except (ONVIFError, Fault, RequestError, TransportError):
except (TimeoutError, ONVIFError, Fault, aiohttp.ClientError, TransportError):
LOGGER.warning("Error while stopping events: %s", device.name)
return await hass.config_entries.async_unload_platforms(entry, device.platforms)

View File

@ -1,8 +1,9 @@
"""Constants for the onvif component."""
import asyncio
import logging
from httpx import RequestError
import aiohttp
from onvif.exceptions import ONVIFError
from zeep.exceptions import Fault, TransportError
@ -48,4 +49,10 @@ SERVICE_PTZ = "ptz"
# Some cameras don't support the GetServiceCapabilities call
# and will return a 404 error which is caught by TransportError
GET_CAPABILITIES_EXCEPTIONS = (ONVIFError, Fault, RequestError, TransportError)
GET_CAPABILITIES_EXCEPTIONS = (
ONVIFError,
Fault,
aiohttp.ClientError,
asyncio.TimeoutError,
TransportError,
)

View File

@ -9,7 +9,7 @@ import os
import time
from typing import Any
from httpx import RequestError
import aiohttp
import onvif
from onvif import ONVIFCamera
from onvif.exceptions import ONVIFError
@ -235,7 +235,7 @@ class ONVIFDevice:
LOGGER.debug("%s: Retrieving current device date/time", self.name)
try:
device_time = await device_mgmt.GetSystemDateAndTime()
except (RequestError, Fault) as err:
except (TimeoutError, aiohttp.ClientError, Fault) as err:
LOGGER.warning(
"Couldn't get device '%s' date/time. Error: %s", self.name, err
)
@ -303,7 +303,7 @@ class ONVIFDevice:
# Set Date and Time ourselves if Date and Time is set manually in the camera.
try:
await self.async_manually_set_date_and_time()
except (RequestError, TransportError, IndexError, Fault):
except (TimeoutError, aiohttp.ClientError, TransportError, IndexError, Fault):
LOGGER.warning("%s: Could not sync date/time on this camera", self.name)
self._async_log_time_out_of_sync(cam_date_utc, system_date)

View File

@ -6,8 +6,8 @@ import asyncio
from collections.abc import Callable
import datetime as dt
import aiohttp
from aiohttp.web import Request
from httpx import RemoteProtocolError, RequestError, TransportError
from onvif import ONVIFCamera
from onvif.client import (
NotificationManager,
@ -16,7 +16,7 @@ from onvif.client import (
)
from onvif.exceptions import ONVIFError
from onvif.util import stringify_onvif_error
from zeep.exceptions import Fault, ValidationError, XMLParseError
from zeep.exceptions import Fault, TransportError, ValidationError, XMLParseError
from homeassistant.components import webhook
from homeassistant.config_entries import ConfigEntry
@ -34,10 +34,23 @@ from .parsers import PARSERS
UNHANDLED_TOPICS: set[str] = {"tns1:MediaControl/VideoEncoderConfiguration"}
SUBSCRIPTION_ERRORS = (Fault, TimeoutError, TransportError)
CREATE_ERRORS = (ONVIFError, Fault, RequestError, XMLParseError, ValidationError)
CREATE_ERRORS = (
ONVIFError,
Fault,
aiohttp.ClientError,
asyncio.TimeoutError,
XMLParseError,
ValidationError,
)
SET_SYNCHRONIZATION_POINT_ERRORS = (*SUBSCRIPTION_ERRORS, TypeError)
UNSUBSCRIBE_ERRORS = (XMLParseError, *SUBSCRIPTION_ERRORS)
RENEW_ERRORS = (ONVIFError, RequestError, XMLParseError, *SUBSCRIPTION_ERRORS)
RENEW_ERRORS = (
ONVIFError,
aiohttp.ClientError,
asyncio.TimeoutError,
XMLParseError,
*SUBSCRIPTION_ERRORS,
)
#
# We only keep the subscription alive for 10 minutes, and will keep
# renewing it every 8 minutes. This is to avoid the camera
@ -372,13 +385,13 @@ class PullPointManager:
"%s: PullPoint skipped because Home Assistant is not running yet",
self._name,
)
except RemoteProtocolError as err:
except aiohttp.ServerDisconnectedError as err:
# Either a shutdown event or the camera closed the connection. Because
# 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. Some
# cameras may close the connection if there are no messages to pull.
LOGGER.debug(
"%s: PullPoint subscription encountered a remote protocol error "
"%s: PullPoint subscription encountered a server disconnected error "
"(this is normal for some cameras): %s",
self._name,
stringify_onvif_error(err),
@ -394,7 +407,12 @@ class PullPointManager:
# Treat errors as if the camera restarted. Assume that the pullpoint
# subscription is no longer valid.
self._pullpoint_manager.resume()
except (XMLParseError, RequestError, TimeoutError, TransportError) as err:
except (
XMLParseError,
aiohttp.ClientError,
TimeoutError,
TransportError,
) as err:
LOGGER.debug(
"%s: PullPoint subscription encountered an unexpected error and will be retried "
"(this is normal for some cameras): %s",

View File

@ -8,5 +8,5 @@
"documentation": "https://www.home-assistant.io/integrations/onvif",
"iot_class": "local_push",
"loggers": ["onvif", "wsdiscovery", "zeep"],
"requirements": ["onvif-zeep-async==3.2.5", "WSDiscovery==2.1.2"]
"requirements": ["onvif-zeep-async==4.0.1", "WSDiscovery==2.1.2"]
}

2
requirements_all.txt generated
View File

@ -1584,7 +1584,7 @@ ondilo==0.5.0
onedrive-personal-sdk==0.0.14
# homeassistant.components.onvif
onvif-zeep-async==3.2.5
onvif-zeep-async==4.0.1
# homeassistant.components.opengarage
open-garage==0.2.0

View File

@ -1349,7 +1349,7 @@ ondilo==0.5.0
onedrive-personal-sdk==0.0.14
# homeassistant.components.onvif
onvif-zeep-async==3.2.5
onvif-zeep-async==4.0.1
# homeassistant.components.opengarage
open-garage==0.2.0