mirror of
https://github.com/home-assistant/core.git
synced 2025-07-23 21:27:38 +00:00
Ensure onvif retries setup if camera fails to respond correctly (#91866)
This commit is contained in:
parent
6013584b7b
commit
82340907c2
@ -31,6 +31,8 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
|||||||
|
|
||||||
try:
|
try:
|
||||||
await device.async_setup()
|
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 RequestError as err:
|
||||||
await device.device.close()
|
await device.device.close()
|
||||||
raise ConfigEntryNotReady(
|
raise ConfigEntryNotReady(
|
||||||
@ -52,9 +54,6 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
|||||||
if not device.available:
|
if not device.available:
|
||||||
raise ConfigEntryNotReady()
|
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
|
hass.data[DOMAIN][entry.unique_id] = device
|
||||||
|
|
||||||
device.platforms = [Platform.BUTTON, Platform.CAMERA]
|
device.platforms = [Platform.BUTTON, Platform.CAMERA]
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
"""Support for ONVIF Cameras with FFmpeg as decoder."""
|
"""Support for ONVIF Cameras with FFmpeg as decoder."""
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import asyncio
|
||||||
|
|
||||||
from haffmpeg.camera import CameraMjpeg
|
from haffmpeg.camera import CameraMjpeg
|
||||||
from onvif.exceptions import ONVIFError
|
from onvif.exceptions import ONVIFError
|
||||||
import voluptuous as vol
|
import voluptuous as vol
|
||||||
@ -110,6 +112,7 @@ class ONVIFCameraEntity(ONVIFBaseEntity, Camera):
|
|||||||
== HTTP_BASIC_AUTHENTICATION
|
== HTTP_BASIC_AUTHENTICATION
|
||||||
)
|
)
|
||||||
self._stream_uri: str | None = None
|
self._stream_uri: str | None = None
|
||||||
|
self._stream_uri_future: asyncio.Future[str] | None = None
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def name(self) -> str:
|
def name(self) -> str:
|
||||||
@ -130,7 +133,7 @@ class ONVIFCameraEntity(ONVIFBaseEntity, Camera):
|
|||||||
|
|
||||||
async def stream_source(self):
|
async def stream_source(self):
|
||||||
"""Return the stream source."""
|
"""Return the stream source."""
|
||||||
return self._stream_uri
|
return await self._async_get_stream_uri()
|
||||||
|
|
||||||
async def async_camera_image(
|
async def async_camera_image(
|
||||||
self, width: int | None = None, height: int | None = None
|
self, width: int | None = None, height: int | None = None
|
||||||
@ -158,10 +161,10 @@ class ONVIFCameraEntity(ONVIFBaseEntity, Camera):
|
|||||||
self.device.name,
|
self.device.name,
|
||||||
)
|
)
|
||||||
|
|
||||||
assert self._stream_uri
|
stream_uri = await self._async_get_stream_uri()
|
||||||
return await ffmpeg.async_get_image(
|
return await ffmpeg.async_get_image(
|
||||||
self.hass,
|
self.hass,
|
||||||
self._stream_uri,
|
stream_uri,
|
||||||
extra_cmd=self.device.config_entry.options.get(CONF_EXTRA_ARGUMENTS),
|
extra_cmd=self.device.config_entry.options.get(CONF_EXTRA_ARGUMENTS),
|
||||||
width=width,
|
width=width,
|
||||||
height=height,
|
height=height,
|
||||||
@ -173,9 +176,10 @@ class ONVIFCameraEntity(ONVIFBaseEntity, Camera):
|
|||||||
|
|
||||||
ffmpeg_manager = get_ffmpeg_manager(self.hass)
|
ffmpeg_manager = get_ffmpeg_manager(self.hass)
|
||||||
stream = CameraMjpeg(ffmpeg_manager.binary)
|
stream = CameraMjpeg(ffmpeg_manager.binary)
|
||||||
|
stream_uri = await self._async_get_stream_uri()
|
||||||
|
|
||||||
await stream.open_camera(
|
await stream.open_camera(
|
||||||
self._stream_uri,
|
stream_uri,
|
||||||
extra_cmd=self.device.config_entry.options.get(CONF_EXTRA_ARGUMENTS),
|
extra_cmd=self.device.config_entry.options.get(CONF_EXTRA_ARGUMENTS),
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -190,13 +194,27 @@ class ONVIFCameraEntity(ONVIFBaseEntity, Camera):
|
|||||||
finally:
|
finally:
|
||||||
await stream.close()
|
await stream.close()
|
||||||
|
|
||||||
async def async_added_to_hass(self) -> None:
|
async def _async_get_stream_uri(self) -> str:
|
||||||
"""Run when entity about to be added to hass."""
|
"""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)
|
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(uri_no_auth)
|
||||||
url = url.with_user(self.device.username)
|
url = url.with_user(self.device.username)
|
||||||
url = url.with_password(self.device.password)
|
url = url.with_password(self.device.password)
|
||||||
self._stream_uri = str(url)
|
self._stream_uri = str(url)
|
||||||
|
self._stream_uri_future.set_result(self._stream_uri)
|
||||||
|
return self._stream_uri
|
||||||
|
|
||||||
async def async_perform_ptz(
|
async def async_perform_ptz(
|
||||||
self,
|
self,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user