Call async_refresh_providers when camera entity feature changes (#129941)

This commit is contained in:
Erik Montnemery 2024-11-06 17:37:23 +01:00 committed by GitHub
parent 9f427893b1
commit fe0a822721
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 70 additions and 1 deletions

View file

@ -472,6 +472,8 @@ class Camera(Entity, cached_properties=CACHED_PROPERTIES_WITH_ATTR_):
_attr_state: None = None # State is determined by is_on
_attr_supported_features: CameraEntityFeature = CameraEntityFeature(0)
__supports_stream: CameraEntityFeature | None = None
def __init__(self) -> None:
"""Initialize a camera."""
self._cache: dict[str, Any] = {}
@ -783,6 +785,9 @@ class Camera(Entity, cached_properties=CACHED_PROPERTIES_WITH_ATTR_):
async def async_internal_added_to_hass(self) -> None:
"""Run when entity about to be added to hass."""
await super().async_internal_added_to_hass()
self.__supports_stream = (
self.supported_features_compat & CameraEntityFeature.STREAM
)
await self.async_refresh_providers(write_state=False)
async def async_refresh_providers(self, *, write_state: bool = True) -> None:
@ -892,6 +897,21 @@ class Camera(Entity, cached_properties=CACHED_PROPERTIES_WITH_ATTR_):
return CameraCapabilities(frontend_stream_types)
@callback
def async_write_ha_state(self) -> None:
"""Write the state to the state machine.
Schedules async_refresh_providers if support of streams have changed.
"""
super().async_write_ha_state()
if self.__supports_stream != (
supports_stream := self.supported_features_compat
& CameraEntityFeature.STREAM
):
self.__supports_stream = supports_stream
self._invalidate_camera_capabilities_cache()
self.hass.async_create_task(self.async_refresh_providers())
class CameraView(HomeAssistantView):
"""Base CameraView."""

View file

@ -157,7 +157,7 @@ def mock_stream_source_fixture() -> Generator[AsyncMock]:
@pytest.fixture
async def mock_test_webrtc_cameras(hass: HomeAssistant) -> None:
"""Initialize a test WebRTC cameras."""
"""Initialize test WebRTC cameras with native RTC support."""
# Cannot use the fixture mock_camera_web_rtc as it's mocking Camera.async_handle_web_rtc_offer
# and native support is checked by verify the function "async_handle_web_rtc_offer" was

View file

@ -1005,3 +1005,52 @@ async def test_webrtc_provider_not_added_for_native_webrtc(
assert camera_obj._webrtc_provider is None
assert camera_obj._supports_native_sync_webrtc is not expect_native_async_webrtc
assert camera_obj._supports_native_async_webrtc is expect_native_async_webrtc
@pytest.mark.usefixtures("mock_camera", "mock_stream_source")
async def test_camera_capabilities_changing_non_native_support(
hass: HomeAssistant,
hass_ws_client: WebSocketGenerator,
) -> None:
"""Test WebRTC camera capabilities."""
cam = get_camera_from_entity_id(hass, "camera.demo_camera")
assert (
cam.supported_features
== camera.CameraEntityFeature.ON_OFF | camera.CameraEntityFeature.STREAM
)
await _test_capabilities(
hass,
hass_ws_client,
cam.entity_id,
{StreamType.HLS},
{StreamType.HLS, StreamType.WEB_RTC},
)
cam._attr_supported_features = camera.CameraEntityFeature(0)
cam.async_write_ha_state()
await hass.async_block_till_done()
await _test_capabilities(hass, hass_ws_client, cam.entity_id, set(), set())
@pytest.mark.usefixtures("mock_test_webrtc_cameras")
@pytest.mark.parametrize(("entity_id"), ["camera.sync", "camera.async"])
async def test_camera_capabilities_changing_native_support(
hass: HomeAssistant,
hass_ws_client: WebSocketGenerator,
entity_id: str,
) -> None:
"""Test WebRTC camera capabilities."""
cam = get_camera_from_entity_id(hass, entity_id)
assert cam.supported_features == camera.CameraEntityFeature.STREAM
await _test_capabilities(
hass, hass_ws_client, cam.entity_id, {StreamType.WEB_RTC}, {StreamType.WEB_RTC}
)
cam._attr_supported_features = camera.CameraEntityFeature(0)
cam.async_write_ha_state()
await hass.async_block_till_done()
await _test_capabilities(hass, hass_ws_client, cam.entity_id, set(), set())