mirror of
https://github.com/home-assistant/core.git
synced 2025-04-24 09:17:53 +00:00
Fix unifiprotect supported features being set too late (#129850)
This commit is contained in:
parent
0b56ef5699
commit
3584c710b9
@ -156,7 +156,8 @@ async def async_setup_entry(
|
||||
async_add_entities(_async_camera_entities(hass, entry, data))
|
||||
|
||||
|
||||
_EMPTY_CAMERA_FEATURES = CameraEntityFeature(0)
|
||||
_DISABLE_FEATURE = CameraEntityFeature(0)
|
||||
_ENABLE_FEATURE = CameraEntityFeature.STREAM
|
||||
|
||||
|
||||
class ProtectCamera(ProtectDeviceEntity, Camera):
|
||||
@ -195,24 +196,20 @@ class ProtectCamera(ProtectDeviceEntity, Camera):
|
||||
self._attr_name = f"{camera_name} (insecure)"
|
||||
# only the default (first) channel is enabled by default
|
||||
self._attr_entity_registry_enabled_default = is_default and secure
|
||||
# Set the stream source before finishing the init
|
||||
# because async_added_to_hass is too late and camera
|
||||
# integration uses async_internal_added_to_hass to access
|
||||
# the stream source which is called before async_added_to_hass
|
||||
self._async_set_stream_source()
|
||||
|
||||
@callback
|
||||
def _async_set_stream_source(self) -> None:
|
||||
disable_stream = self._disable_stream
|
||||
channel = self.channel
|
||||
|
||||
if not channel.is_rtsp_enabled:
|
||||
disable_stream = False
|
||||
|
||||
enable_stream = not self._disable_stream and channel.is_rtsp_enabled
|
||||
rtsp_url = channel.rtsps_url if self._secure else channel.rtsp_url
|
||||
|
||||
# _async_set_stream_source called by __init__
|
||||
# pylint: disable-next=attribute-defined-outside-init
|
||||
self._stream_source = None if disable_stream else rtsp_url
|
||||
if self._stream_source:
|
||||
self._attr_supported_features = CameraEntityFeature.STREAM
|
||||
else:
|
||||
self._attr_supported_features = _EMPTY_CAMERA_FEATURES
|
||||
source = rtsp_url if enable_stream else None
|
||||
self._attr_supported_features = _ENABLE_FEATURE if source else _DISABLE_FEATURE
|
||||
self._stream_source = source
|
||||
|
||||
@callback
|
||||
def _async_update_device_from_protect(self, device: ProtectDeviceType) -> None:
|
||||
|
@ -4,6 +4,7 @@ from __future__ import annotations
|
||||
|
||||
from unittest.mock import AsyncMock, Mock
|
||||
|
||||
import pytest
|
||||
from uiprotect.api import DEVICE_UPDATE_INTERVAL
|
||||
from uiprotect.data import Camera as ProtectCamera, CameraChannel, StateType
|
||||
from uiprotect.exceptions import NvrError
|
||||
@ -12,8 +13,13 @@ from uiprotect.websocket import WebsocketState
|
||||
from homeassistant.components.camera import (
|
||||
CameraEntityFeature,
|
||||
CameraState,
|
||||
CameraWebRTCProvider,
|
||||
RTCIceCandidate,
|
||||
StreamType,
|
||||
WebRTCSendMessage,
|
||||
async_get_image,
|
||||
async_get_stream_source,
|
||||
async_register_webrtc_provider,
|
||||
)
|
||||
from homeassistant.components.unifiprotect.const import (
|
||||
ATTR_BITRATE,
|
||||
@ -22,6 +28,7 @@ from homeassistant.components.unifiprotect.const import (
|
||||
ATTR_HEIGHT,
|
||||
ATTR_WIDTH,
|
||||
DEFAULT_ATTRIBUTION,
|
||||
DOMAIN,
|
||||
)
|
||||
from homeassistant.components.unifiprotect.utils import get_camera_base_name
|
||||
from homeassistant.const import (
|
||||
@ -31,11 +38,12 @@ from homeassistant.const import (
|
||||
STATE_UNAVAILABLE,
|
||||
Platform,
|
||||
)
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.core import HomeAssistant, callback
|
||||
from homeassistant.helpers import device_registry as dr, entity_registry as er
|
||||
from homeassistant.setup import async_setup_component
|
||||
|
||||
from .utils import (
|
||||
Camera,
|
||||
MockUFPFixture,
|
||||
adopt_devices,
|
||||
assert_entity_counts,
|
||||
@ -46,6 +54,45 @@ from .utils import (
|
||||
)
|
||||
|
||||
|
||||
class MockWebRTCProvider(CameraWebRTCProvider):
|
||||
"""WebRTC provider."""
|
||||
|
||||
@property
|
||||
def domain(self) -> str:
|
||||
"""Return the integration domain of the provider."""
|
||||
return DOMAIN
|
||||
|
||||
@callback
|
||||
def async_is_supported(self, stream_source: str) -> bool:
|
||||
"""Return if this provider is supports the Camera as source."""
|
||||
return True
|
||||
|
||||
async def async_handle_async_webrtc_offer(
|
||||
self,
|
||||
camera: Camera,
|
||||
offer_sdp: str,
|
||||
session_id: str,
|
||||
send_message: WebRTCSendMessage,
|
||||
) -> None:
|
||||
"""Handle the WebRTC offer and return the answer via the provided callback."""
|
||||
|
||||
async def async_on_webrtc_candidate(
|
||||
self, session_id: str, candidate: RTCIceCandidate
|
||||
) -> None:
|
||||
"""Handle the WebRTC candidate."""
|
||||
|
||||
@callback
|
||||
def async_close_session(self, session_id: str) -> None:
|
||||
"""Close the session."""
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
async def web_rtc_provider(hass: HomeAssistant) -> None:
|
||||
"""Fixture to enable WebRTC provider for camera entities."""
|
||||
await async_setup_component(hass, "camera", {})
|
||||
async_register_webrtc_provider(hass, MockWebRTCProvider())
|
||||
|
||||
|
||||
def validate_default_camera_entity(
|
||||
hass: HomeAssistant,
|
||||
camera_obj: ProtectCamera,
|
||||
@ -283,6 +330,26 @@ async def test_basic_setup(
|
||||
await validate_no_stream_camera_state(hass, doorbell, 3, entity_id, features=0)
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("web_rtc_provider")
|
||||
async def test_webrtc_support(
|
||||
hass: HomeAssistant,
|
||||
ufp: MockUFPFixture,
|
||||
camera_all: ProtectCamera,
|
||||
) -> None:
|
||||
"""Test webrtc support is available."""
|
||||
camera_high_only = camera_all.copy()
|
||||
camera_high_only.channels = [c.copy() for c in camera_all.channels]
|
||||
camera_high_only.name = "Test Camera 1"
|
||||
camera_high_only.channels[0].is_rtsp_enabled = True
|
||||
camera_high_only.channels[1].is_rtsp_enabled = False
|
||||
camera_high_only.channels[2].is_rtsp_enabled = False
|
||||
await init_entry(hass, ufp, [camera_high_only])
|
||||
entity_id = validate_default_camera_entity(hass, camera_high_only, 0)
|
||||
state = hass.states.get(entity_id)
|
||||
assert state
|
||||
assert StreamType.WEB_RTC in state.attributes["frontend_stream_type"]
|
||||
|
||||
|
||||
async def test_adopt(
|
||||
hass: HomeAssistant, ufp: MockUFPFixture, camera: ProtectCamera
|
||||
) -> None:
|
||||
|
Loading…
x
Reference in New Issue
Block a user