Handle a few more transient onvif errors (#91473)

pull/91498/head
J. Nick Koston 2023-04-16 02:06:30 -10:00 committed by GitHub
parent e7373d979b
commit cb6ffa5b03
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 44 additions and 49 deletions

View File

@ -1,5 +1,7 @@
"""The ONVIF integration."""
from httpx import RequestError
from onvif.exceptions import ONVIFAuthError, ONVIFError, ONVIFTimeoutError
from zeep.exceptions import Fault
from homeassistant.components.ffmpeg import CONF_EXTRA_ARGUMENTS
from homeassistant.components.stream import CONF_RTSP_TRANSPORT, RTSP_TRANSPORTS
@ -27,9 +29,25 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
device = ONVIFDevice(hass, entry)
if not await device.async_setup():
try:
await device.async_setup()
except RequestError as err:
await device.device.close()
return False
raise ConfigEntryNotReady(
f"Could not connect to camera {device.device.host}:{device.device.port}: {err}"
) from err
except Fault as err:
await device.device.close()
# We do no know if the credentials are wrong or the camera is
# still booting up, so we will retry later
raise ConfigEntryNotReady(
f"Could not connect to camera, verify credentials are correct: {err}"
) from err
except ONVIFError as err:
await device.device.close()
raise ConfigEntryNotReady(
f"Could not setup camera {device.device.host}:{device.device.port}: {err}"
) from err
if not device.available:
raise ConfigEntryNotReady()

View File

@ -85,7 +85,7 @@ class ONVIFDevice:
"""Return the password of this device."""
return self.config_entry.data[CONF_PASSWORD]
async def async_setup(self) -> bool:
async def async_setup(self) -> None:
"""Set up the device."""
self.device = get_device(
self.hass,
@ -96,57 +96,34 @@ class ONVIFDevice:
)
# Get all device info
try:
await self.device.update_xaddrs()
await self.async_check_date_and_time()
await self.device.update_xaddrs()
await self.async_check_date_and_time()
# Create event manager
assert self.config_entry.unique_id
self.events = EventManager(
self.hass, self.device, self.config_entry.unique_id
)
# Create event manager
assert self.config_entry.unique_id
self.events = EventManager(self.hass, self.device, self.config_entry.unique_id)
# Fetch basic device info and capabilities
self.info = await self.async_get_device_info()
LOGGER.debug("Camera %s info = %s", self.name, self.info)
self.capabilities = await self.async_get_capabilities()
LOGGER.debug("Camera %s capabilities = %s", self.name, self.capabilities)
self.profiles = await self.async_get_profiles()
LOGGER.debug("Camera %s profiles = %s", self.name, self.profiles)
# Fetch basic device info and capabilities
self.info = await self.async_get_device_info()
LOGGER.debug("Camera %s info = %s", self.name, self.info)
self.capabilities = await self.async_get_capabilities()
LOGGER.debug("Camera %s capabilities = %s", self.name, self.capabilities)
self.profiles = await self.async_get_profiles()
LOGGER.debug("Camera %s profiles = %s", self.name, self.profiles)
# No camera profiles to add
if not self.profiles:
return False
# No camera profiles to add
if not self.profiles:
raise ONVIFError("No camera profiles found")
if self.capabilities.ptz:
self.device.create_ptz_service()
if self.capabilities.ptz:
self.device.create_ptz_service()
# Determine max resolution from profiles
self.max_resolution = max(
profile.video.resolution.width
for profile in self.profiles
if profile.video.encoding == "H264"
)
except RequestError as err:
LOGGER.warning(
"Couldn't connect to camera '%s', but will retry later. Error: %s",
self.name,
err,
)
self.available = False
await self.device.close()
except Fault as err:
LOGGER.error(
(
"Couldn't connect to camera '%s', please verify "
"that the credentials are correct. Error: %s"
),
self.name,
err,
)
return False
return True
# Determine max resolution from profiles
self.max_resolution = max(
profile.video.resolution.width
for profile in self.profiles
if profile.video.encoding == "H264"
)
async def async_stop(self, event=None):
"""Shut it all down."""