Skip to content

Commit

Permalink
Call async_refresh_providers when camera entity feature changes (home…
Browse files Browse the repository at this point in the history
  • Loading branch information
emontnemery authored and frenck committed Nov 6, 2024
1 parent 3b840c6 commit c18d509
Show file tree
Hide file tree
Showing 3 changed files with 70 additions and 1 deletion.
20 changes: 20 additions & 0 deletions homeassistant/components/camera/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -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] = {}
Expand Down Expand Up @@ -783,6 +785,9 @@ def async_update_token(self) -> None:
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:
Expand Down Expand Up @@ -892,6 +897,21 @@ def camera_capabilities(self) -> CameraCapabilities:

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."""
Expand Down
2 changes: 1 addition & 1 deletion tests/components/camera/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
49 changes: 49 additions & 0 deletions tests/components/camera/test_init.py
Original file line number Diff line number Diff line change
Expand Up @@ -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())

0 comments on commit c18d509

Please sign in to comment.