mirror of
https://github.com/home-assistant/core.git
synced 2025-07-23 13:17:32 +00:00
Remove all ice_servers on native sync WebRTC cameras (#129819)
This commit is contained in:
parent
f6e36615d6
commit
df796d432e
@ -827,6 +827,9 @@ class Camera(Entity, cached_properties=CACHED_PROPERTIES_WITH_ATTR_):
|
||||
"""Return the WebRTC client configuration and extend it with the registered ice servers."""
|
||||
config = self._async_get_webrtc_client_configuration()
|
||||
|
||||
if not self._webrtc_sync_offer:
|
||||
# Until 2024.11, the frontend was not resolving any ice servers
|
||||
# The async approach was added 2024.11 and new integrations need to use it
|
||||
ice_servers = [
|
||||
server
|
||||
for servers in self.hass.data.get(DATA_ICE_SERVERS, [])
|
||||
@ -834,9 +837,7 @@ class Camera(Entity, cached_properties=CACHED_PROPERTIES_WITH_ATTR_):
|
||||
]
|
||||
config.configuration.ice_servers.extend(ice_servers)
|
||||
|
||||
config.get_candidates_upfront = (
|
||||
self._webrtc_sync_offer or self._legacy_webrtc_provider is not None
|
||||
)
|
||||
config.get_candidates_upfront = self._legacy_webrtc_provider is not None
|
||||
|
||||
return config
|
||||
|
||||
|
@ -1,13 +1,14 @@
|
||||
"""Test helpers for camera."""
|
||||
|
||||
from collections.abc import AsyncGenerator, Generator
|
||||
from unittest.mock import AsyncMock, PropertyMock, patch
|
||||
from unittest.mock import AsyncMock, Mock, PropertyMock, patch
|
||||
|
||||
import pytest
|
||||
|
||||
from homeassistant.components import camera
|
||||
from homeassistant.components.camera.const import StreamType
|
||||
from homeassistant.components.camera.webrtc import WebRTCAnswer, WebRTCSendMessage
|
||||
from homeassistant.config_entries import ConfigEntry, ConfigFlow
|
||||
from homeassistant.const import Platform
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers.device_registry import DeviceInfo
|
||||
@ -15,6 +16,15 @@ from homeassistant.setup import async_setup_component
|
||||
|
||||
from .common import STREAM_SOURCE, WEBRTC_ANSWER
|
||||
|
||||
from tests.common import (
|
||||
MockConfigEntry,
|
||||
MockModule,
|
||||
mock_config_flow,
|
||||
mock_integration,
|
||||
mock_platform,
|
||||
setup_test_component_platform,
|
||||
)
|
||||
|
||||
|
||||
@pytest.fixture(autouse=True)
|
||||
async def setup_homeassistant(hass: HomeAssistant) -> None:
|
||||
@ -142,3 +152,66 @@ def mock_stream_source_fixture() -> Generator[AsyncMock]:
|
||||
return_value=STREAM_SOURCE,
|
||||
) as mock_stream_source:
|
||||
yield mock_stream_source
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
async def mock_camera_webrtc_native_sync_offer(hass: HomeAssistant) -> None:
|
||||
"""Initialize a test camera with native sync WebRTC 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
|
||||
# overwritten(implemented) or not
|
||||
class MockCamera(camera.Camera):
|
||||
"""Mock Camera Entity."""
|
||||
|
||||
_attr_name = "Test"
|
||||
_attr_supported_features: camera.CameraEntityFeature = (
|
||||
camera.CameraEntityFeature.STREAM
|
||||
)
|
||||
_attr_frontend_stream_type: camera.StreamType = camera.StreamType.WEB_RTC
|
||||
|
||||
async def stream_source(self) -> str | None:
|
||||
return STREAM_SOURCE
|
||||
|
||||
async def async_handle_web_rtc_offer(self, offer_sdp: str) -> str | None:
|
||||
return WEBRTC_ANSWER
|
||||
|
||||
domain = "test"
|
||||
|
||||
entry = MockConfigEntry(domain=domain)
|
||||
entry.add_to_hass(hass)
|
||||
|
||||
async def async_setup_entry_init(
|
||||
hass: HomeAssistant, config_entry: ConfigEntry
|
||||
) -> bool:
|
||||
"""Set up test config entry."""
|
||||
await hass.config_entries.async_forward_entry_setups(
|
||||
config_entry, [camera.DOMAIN]
|
||||
)
|
||||
return True
|
||||
|
||||
async def async_unload_entry_init(
|
||||
hass: HomeAssistant, config_entry: ConfigEntry
|
||||
) -> bool:
|
||||
"""Unload test config entry."""
|
||||
await hass.config_entries.async_forward_entry_unload(
|
||||
config_entry, camera.DOMAIN
|
||||
)
|
||||
return True
|
||||
|
||||
mock_integration(
|
||||
hass,
|
||||
MockModule(
|
||||
domain,
|
||||
async_setup_entry=async_setup_entry_init,
|
||||
async_unload_entry=async_unload_entry_init,
|
||||
),
|
||||
)
|
||||
setup_test_component_platform(
|
||||
hass, camera.DOMAIN, [MockCamera()], from_config_entry=True
|
||||
)
|
||||
mock_platform(hass, f"{domain}.config_flow", Mock())
|
||||
|
||||
with mock_config_flow(domain, ConfigFlow):
|
||||
assert await hass.config_entries.async_setup(entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
|
@ -25,7 +25,6 @@ from homeassistant.components.camera.const import (
|
||||
)
|
||||
from homeassistant.components.camera.helper import get_camera_from_entity_id
|
||||
from homeassistant.components.websocket_api import TYPE_RESULT
|
||||
from homeassistant.config_entries import ConfigEntry, ConfigFlow
|
||||
from homeassistant.const import (
|
||||
ATTR_ENTITY_ID,
|
||||
EVENT_HOMEASSISTANT_STARTED,
|
||||
@ -38,18 +37,12 @@ from homeassistant.helpers import entity_registry as er, issue_registry as ir
|
||||
from homeassistant.setup import async_setup_component
|
||||
from homeassistant.util import dt as dt_util
|
||||
|
||||
from .common import EMPTY_8_6_JPEG, STREAM_SOURCE, WEBRTC_ANSWER, mock_turbo_jpeg
|
||||
from .common import EMPTY_8_6_JPEG, STREAM_SOURCE, mock_turbo_jpeg
|
||||
|
||||
from tests.common import (
|
||||
MockConfigEntry,
|
||||
MockModule,
|
||||
async_fire_time_changed,
|
||||
help_test_all,
|
||||
import_and_test_deprecated_constant_enum,
|
||||
mock_config_flow,
|
||||
mock_integration,
|
||||
mock_platform,
|
||||
setup_test_component_platform,
|
||||
)
|
||||
from tests.typing import ClientSessionGenerator, WebSocketGenerator
|
||||
|
||||
@ -986,62 +979,13 @@ async def test_camera_capabilities_hls(
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("mock_camera_webrtc_native_sync_offer")
|
||||
async def test_camera_capabilities_webrtc(
|
||||
hass: HomeAssistant,
|
||||
hass_ws_client: WebSocketGenerator,
|
||||
) -> None:
|
||||
"""Test WebRTC camera capabilities."""
|
||||
|
||||
# Cannot use the fixture mock_camera_web_rtc as it's mocking Camera.async_handle_web_rtc_offer
|
||||
# Camera capabilities are determined by by checking if the function was overwritten(implemented) or not
|
||||
class MockCamera(camera.Camera):
|
||||
"""Mock Camera Entity."""
|
||||
|
||||
_attr_name = "Test"
|
||||
_attr_supported_features: camera.CameraEntityFeature = (
|
||||
camera.CameraEntityFeature.STREAM
|
||||
)
|
||||
|
||||
async def stream_source(self) -> str | None:
|
||||
return STREAM_SOURCE
|
||||
|
||||
async def async_handle_web_rtc_offer(self, offer_sdp: str) -> str | None:
|
||||
return WEBRTC_ANSWER
|
||||
|
||||
domain = "test"
|
||||
|
||||
entry = MockConfigEntry(domain=domain)
|
||||
entry.add_to_hass(hass)
|
||||
|
||||
async def async_setup_entry_init(
|
||||
hass: HomeAssistant, config_entry: ConfigEntry
|
||||
) -> bool:
|
||||
"""Set up test config entry."""
|
||||
await hass.config_entries.async_forward_entry_setups(config_entry, [DOMAIN])
|
||||
return True
|
||||
|
||||
async def async_unload_entry_init(
|
||||
hass: HomeAssistant, config_entry: ConfigEntry
|
||||
) -> bool:
|
||||
"""Unload test config entry."""
|
||||
await hass.config_entries.async_forward_entry_unload(config_entry, DOMAIN)
|
||||
return True
|
||||
|
||||
mock_integration(
|
||||
hass,
|
||||
MockModule(
|
||||
domain,
|
||||
async_setup_entry=async_setup_entry_init,
|
||||
async_unload_entry=async_unload_entry_init,
|
||||
),
|
||||
)
|
||||
setup_test_component_platform(hass, DOMAIN, [MockCamera()], from_config_entry=True)
|
||||
mock_platform(hass, f"{domain}.config_flow", Mock())
|
||||
|
||||
with mock_config_flow(domain, ConfigFlow):
|
||||
assert await hass.config_entries.async_setup(entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
await _test_capabilities(
|
||||
hass, hass_ws_client, "camera.test", {StreamType.WEB_RTC}, {StreamType.WEB_RTC}
|
||||
)
|
||||
|
@ -393,6 +393,29 @@ async def test_ws_get_client_config(
|
||||
}
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("mock_camera_webrtc_native_sync_offer")
|
||||
async def test_ws_get_client_config_sync_offer(
|
||||
hass: HomeAssistant, hass_ws_client: WebSocketGenerator
|
||||
) -> None:
|
||||
"""Test get WebRTC client config, when camera is supporting sync offer."""
|
||||
await async_setup_component(hass, "camera", {})
|
||||
await hass.async_block_till_done()
|
||||
|
||||
client = await hass_ws_client(hass)
|
||||
await client.send_json_auto_id(
|
||||
{"type": "camera/webrtc/get_client_config", "entity_id": "camera.test"}
|
||||
)
|
||||
msg = await client.receive_json()
|
||||
|
||||
# Assert WebSocket response
|
||||
assert msg["type"] == TYPE_RESULT
|
||||
assert msg["success"]
|
||||
assert msg["result"] == {
|
||||
"configuration": {},
|
||||
"getCandidatesUpfront": False,
|
||||
}
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("mock_camera_webrtc")
|
||||
async def test_ws_get_client_config_custom_config(
|
||||
hass: HomeAssistant, hass_ws_client: WebSocketGenerator
|
||||
|
Loading…
x
Reference in New Issue
Block a user