mirror of
https://github.com/home-assistant/core.git
synced 2025-07-10 23:07:09 +00:00
Migrate onvif to use onvif-zeep-async 4.0.1 with aiohttp (#146297)
This commit is contained in:
parent
a979f884f9
commit
636b484d9d
@ -5,7 +5,7 @@ from contextlib import suppress
|
|||||||
from http import HTTPStatus
|
from http import HTTPStatus
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
from httpx import RequestError
|
import aiohttp
|
||||||
from onvif.exceptions import ONVIFError
|
from onvif.exceptions import ONVIFError
|
||||||
from onvif.util import is_auth_error, stringify_onvif_error
|
from onvif.util import is_auth_error, stringify_onvif_error
|
||||||
from zeep.exceptions import Fault, TransportError
|
from zeep.exceptions import Fault, TransportError
|
||||||
@ -49,7 +49,7 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
|||||||
await device.async_setup()
|
await device.async_setup()
|
||||||
if not entry.data.get(CONF_SNAPSHOT_AUTH):
|
if not entry.data.get(CONF_SNAPSHOT_AUTH):
|
||||||
await async_populate_snapshot_auth(hass, device, entry)
|
await async_populate_snapshot_auth(hass, device, entry)
|
||||||
except RequestError as err:
|
except (TimeoutError, aiohttp.ClientError) as err:
|
||||||
await device.device.close()
|
await device.device.close()
|
||||||
raise ConfigEntryNotReady(
|
raise ConfigEntryNotReady(
|
||||||
f"Could not connect to camera {device.device.host}:{device.device.port}: {err}"
|
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:
|
if device.capabilities.events and device.events.started:
|
||||||
try:
|
try:
|
||||||
await device.events.async_stop()
|
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)
|
LOGGER.warning("Error while stopping events: %s", device.name)
|
||||||
|
|
||||||
return await hass.config_entries.async_unload_platforms(entry, device.platforms)
|
return await hass.config_entries.async_unload_platforms(entry, device.platforms)
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
"""Constants for the onvif component."""
|
"""Constants for the onvif component."""
|
||||||
|
|
||||||
|
import asyncio
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
from httpx import RequestError
|
import aiohttp
|
||||||
from onvif.exceptions import ONVIFError
|
from onvif.exceptions import ONVIFError
|
||||||
from zeep.exceptions import Fault, TransportError
|
from zeep.exceptions import Fault, TransportError
|
||||||
|
|
||||||
@ -48,4 +49,10 @@ SERVICE_PTZ = "ptz"
|
|||||||
|
|
||||||
# Some cameras don't support the GetServiceCapabilities call
|
# Some cameras don't support the GetServiceCapabilities call
|
||||||
# and will return a 404 error which is caught by TransportError
|
# 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,
|
||||||
|
)
|
||||||
|
@ -9,7 +9,7 @@ import os
|
|||||||
import time
|
import time
|
||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
from httpx import RequestError
|
import aiohttp
|
||||||
import onvif
|
import onvif
|
||||||
from onvif import ONVIFCamera
|
from onvif import ONVIFCamera
|
||||||
from onvif.exceptions import ONVIFError
|
from onvif.exceptions import ONVIFError
|
||||||
@ -235,7 +235,7 @@ class ONVIFDevice:
|
|||||||
LOGGER.debug("%s: Retrieving current device date/time", self.name)
|
LOGGER.debug("%s: Retrieving current device date/time", self.name)
|
||||||
try:
|
try:
|
||||||
device_time = await device_mgmt.GetSystemDateAndTime()
|
device_time = await device_mgmt.GetSystemDateAndTime()
|
||||||
except (RequestError, Fault) as err:
|
except (TimeoutError, aiohttp.ClientError, Fault) as err:
|
||||||
LOGGER.warning(
|
LOGGER.warning(
|
||||||
"Couldn't get device '%s' date/time. Error: %s", self.name, err
|
"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.
|
# Set Date and Time ourselves if Date and Time is set manually in the camera.
|
||||||
try:
|
try:
|
||||||
await self.async_manually_set_date_and_time()
|
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)
|
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)
|
self._async_log_time_out_of_sync(cam_date_utc, system_date)
|
||||||
|
|
||||||
|
@ -6,8 +6,8 @@ import asyncio
|
|||||||
from collections.abc import Callable
|
from collections.abc import Callable
|
||||||
import datetime as dt
|
import datetime as dt
|
||||||
|
|
||||||
|
import aiohttp
|
||||||
from aiohttp.web import Request
|
from aiohttp.web import Request
|
||||||
from httpx import RemoteProtocolError, RequestError, TransportError
|
|
||||||
from onvif import ONVIFCamera
|
from onvif import ONVIFCamera
|
||||||
from onvif.client import (
|
from onvif.client import (
|
||||||
NotificationManager,
|
NotificationManager,
|
||||||
@ -16,7 +16,7 @@ from onvif.client import (
|
|||||||
)
|
)
|
||||||
from onvif.exceptions import ONVIFError
|
from onvif.exceptions import ONVIFError
|
||||||
from onvif.util import stringify_onvif_error
|
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.components import webhook
|
||||||
from homeassistant.config_entries import ConfigEntry
|
from homeassistant.config_entries import ConfigEntry
|
||||||
@ -34,10 +34,23 @@ from .parsers import PARSERS
|
|||||||
UNHANDLED_TOPICS: set[str] = {"tns1:MediaControl/VideoEncoderConfiguration"}
|
UNHANDLED_TOPICS: set[str] = {"tns1:MediaControl/VideoEncoderConfiguration"}
|
||||||
|
|
||||||
SUBSCRIPTION_ERRORS = (Fault, TimeoutError, TransportError)
|
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)
|
SET_SYNCHRONIZATION_POINT_ERRORS = (*SUBSCRIPTION_ERRORS, TypeError)
|
||||||
UNSUBSCRIBE_ERRORS = (XMLParseError, *SUBSCRIPTION_ERRORS)
|
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
|
# We only keep the subscription alive for 10 minutes, and will keep
|
||||||
# renewing it every 8 minutes. This is to avoid the camera
|
# 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",
|
"%s: PullPoint skipped because Home Assistant is not running yet",
|
||||||
self._name,
|
self._name,
|
||||||
)
|
)
|
||||||
except RemoteProtocolError as err:
|
except aiohttp.ServerDisconnectedError as err:
|
||||||
# Either a shutdown event or the camera closed the connection. Because
|
# 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
|
# 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
|
# 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.
|
# cameras may close the connection if there are no messages to pull.
|
||||||
LOGGER.debug(
|
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",
|
"(this is normal for some cameras): %s",
|
||||||
self._name,
|
self._name,
|
||||||
stringify_onvif_error(err),
|
stringify_onvif_error(err),
|
||||||
@ -394,7 +407,12 @@ class PullPointManager:
|
|||||||
# Treat errors as if the camera restarted. Assume that the pullpoint
|
# Treat errors as if the camera restarted. Assume that the pullpoint
|
||||||
# subscription is no longer valid.
|
# subscription is no longer valid.
|
||||||
self._pullpoint_manager.resume()
|
self._pullpoint_manager.resume()
|
||||||
except (XMLParseError, RequestError, TimeoutError, TransportError) as err:
|
except (
|
||||||
|
XMLParseError,
|
||||||
|
aiohttp.ClientError,
|
||||||
|
TimeoutError,
|
||||||
|
TransportError,
|
||||||
|
) as err:
|
||||||
LOGGER.debug(
|
LOGGER.debug(
|
||||||
"%s: PullPoint subscription encountered an unexpected error and will be retried "
|
"%s: PullPoint subscription encountered an unexpected error and will be retried "
|
||||||
"(this is normal for some cameras): %s",
|
"(this is normal for some cameras): %s",
|
||||||
|
@ -8,5 +8,5 @@
|
|||||||
"documentation": "https://www.home-assistant.io/integrations/onvif",
|
"documentation": "https://www.home-assistant.io/integrations/onvif",
|
||||||
"iot_class": "local_push",
|
"iot_class": "local_push",
|
||||||
"loggers": ["onvif", "wsdiscovery", "zeep"],
|
"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
2
requirements_all.txt
generated
@ -1584,7 +1584,7 @@ ondilo==0.5.0
|
|||||||
onedrive-personal-sdk==0.0.14
|
onedrive-personal-sdk==0.0.14
|
||||||
|
|
||||||
# homeassistant.components.onvif
|
# homeassistant.components.onvif
|
||||||
onvif-zeep-async==3.2.5
|
onvif-zeep-async==4.0.1
|
||||||
|
|
||||||
# homeassistant.components.opengarage
|
# homeassistant.components.opengarage
|
||||||
open-garage==0.2.0
|
open-garage==0.2.0
|
||||||
|
2
requirements_test_all.txt
generated
2
requirements_test_all.txt
generated
@ -1349,7 +1349,7 @@ ondilo==0.5.0
|
|||||||
onedrive-personal-sdk==0.0.14
|
onedrive-personal-sdk==0.0.14
|
||||||
|
|
||||||
# homeassistant.components.onvif
|
# homeassistant.components.onvif
|
||||||
onvif-zeep-async==3.2.5
|
onvif-zeep-async==4.0.1
|
||||||
|
|
||||||
# homeassistant.components.opengarage
|
# homeassistant.components.opengarage
|
||||||
open-garage==0.2.0
|
open-garage==0.2.0
|
||||||
|
Loading…
x
Reference in New Issue
Block a user