Ensure onvif retries setup if camera fails to respond correctly (#91866)
This commit is contained in:
parent
6013584b7b
commit
82340907c2
2 changed files with 27 additions and 10 deletions
|
@ -31,6 +31,8 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
|||
|
||||
try:
|
||||
await device.async_setup()
|
||||
if not entry.data.get(CONF_SNAPSHOT_AUTH):
|
||||
await async_populate_snapshot_auth(hass, device, entry)
|
||||
except RequestError as err:
|
||||
await device.device.close()
|
||||
raise ConfigEntryNotReady(
|
||||
|
@ -52,9 +54,6 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
|||
if not device.available:
|
||||
raise ConfigEntryNotReady()
|
||||
|
||||
if not entry.data.get(CONF_SNAPSHOT_AUTH):
|
||||
await async_populate_snapshot_auth(hass, device, entry)
|
||||
|
||||
hass.data[DOMAIN][entry.unique_id] = device
|
||||
|
||||
device.platforms = [Platform.BUTTON, Platform.CAMERA]
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
"""Support for ONVIF Cameras with FFmpeg as decoder."""
|
||||
from __future__ import annotations
|
||||
|
||||
import asyncio
|
||||
|
||||
from haffmpeg.camera import CameraMjpeg
|
||||
from onvif.exceptions import ONVIFError
|
||||
import voluptuous as vol
|
||||
|
@ -110,6 +112,7 @@ class ONVIFCameraEntity(ONVIFBaseEntity, Camera):
|
|||
== HTTP_BASIC_AUTHENTICATION
|
||||
)
|
||||
self._stream_uri: str | None = None
|
||||
self._stream_uri_future: asyncio.Future[str] | None = None
|
||||
|
||||
@property
|
||||
def name(self) -> str:
|
||||
|
@ -130,7 +133,7 @@ class ONVIFCameraEntity(ONVIFBaseEntity, Camera):
|
|||
|
||||
async def stream_source(self):
|
||||
"""Return the stream source."""
|
||||
return self._stream_uri
|
||||
return await self._async_get_stream_uri()
|
||||
|
||||
async def async_camera_image(
|
||||
self, width: int | None = None, height: int | None = None
|
||||
|
@ -158,10 +161,10 @@ class ONVIFCameraEntity(ONVIFBaseEntity, Camera):
|
|||
self.device.name,
|
||||
)
|
||||
|
||||
assert self._stream_uri
|
||||
stream_uri = await self._async_get_stream_uri()
|
||||
return await ffmpeg.async_get_image(
|
||||
self.hass,
|
||||
self._stream_uri,
|
||||
stream_uri,
|
||||
extra_cmd=self.device.config_entry.options.get(CONF_EXTRA_ARGUMENTS),
|
||||
width=width,
|
||||
height=height,
|
||||
|
@ -173,9 +176,10 @@ class ONVIFCameraEntity(ONVIFBaseEntity, Camera):
|
|||
|
||||
ffmpeg_manager = get_ffmpeg_manager(self.hass)
|
||||
stream = CameraMjpeg(ffmpeg_manager.binary)
|
||||
stream_uri = await self._async_get_stream_uri()
|
||||
|
||||
await stream.open_camera(
|
||||
self._stream_uri,
|
||||
stream_uri,
|
||||
extra_cmd=self.device.config_entry.options.get(CONF_EXTRA_ARGUMENTS),
|
||||
)
|
||||
|
||||
|
@ -190,13 +194,27 @@ class ONVIFCameraEntity(ONVIFBaseEntity, Camera):
|
|||
finally:
|
||||
await stream.close()
|
||||
|
||||
async def async_added_to_hass(self) -> None:
|
||||
"""Run when entity about to be added to hass."""
|
||||
async def _async_get_stream_uri(self) -> str:
|
||||
"""Return the stream URI."""
|
||||
if self._stream_uri:
|
||||
return self._stream_uri
|
||||
if self._stream_uri_future:
|
||||
return await self._stream_uri_future
|
||||
loop = asyncio.get_running_loop()
|
||||
self._stream_uri_future = loop.create_future()
|
||||
try:
|
||||
uri_no_auth = await self.device.async_get_stream_uri(self.profile)
|
||||
except (asyncio.TimeoutError, Exception) as err: # pylint: disable=broad-except
|
||||
LOGGER.error("Failed to get stream uri: %s", err)
|
||||
if self._stream_uri_future:
|
||||
self._stream_uri_future.set_exception(err)
|
||||
raise
|
||||
url = URL(uri_no_auth)
|
||||
url = url.with_user(self.device.username)
|
||||
url = url.with_password(self.device.password)
|
||||
self._stream_uri = str(url)
|
||||
self._stream_uri_future.set_result(self._stream_uri)
|
||||
return self._stream_uri
|
||||
|
||||
async def async_perform_ptz(
|
||||
self,
|
||||
|
|
Loading…
Add table
Reference in a new issue