Refactor camera.webrtc.register_ice_server (#129024)

* Refactor camera.webrtc.register_ice_server

* Apply suggestions from code review

Co-authored-by: Robert Resch <robert@resch.dev>

* Add missing import

---------

Co-authored-by: Robert Resch <robert@resch.dev>
This commit is contained in:
Erik Montnemery 2024-10-23 11:49:39 +02:00 committed by GitHub
parent eb45b89557
commit 2c79173d20
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 48 additions and 30 deletions

View File

@ -89,8 +89,8 @@ from .webrtc import (
RTCIceServer,
WebRTCClientConfiguration,
async_get_supported_providers,
async_register_ice_servers,
async_register_rtsp_to_web_rtc_provider, # noqa: F401
register_ice_server,
ws_get_client_config,
)
@ -401,10 +401,11 @@ async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
SERVICE_RECORD, CAMERA_SERVICE_RECORD, async_handle_record_service
)
async def get_ice_server() -> RTCIceServer:
return RTCIceServer(urls="stun:stun.home-assistant.io:80")
@callback
def get_ice_servers() -> list[RTCIceServer]:
return [RTCIceServer(urls="stun:stun.home-assistant.io:80")]
register_ice_server(hass, get_ice_server)
async_register_ice_servers(hass, get_ice_servers)
return True
@ -741,9 +742,11 @@ class Camera(Entity, cached_properties=CACHED_PROPERTIES_WITH_ATTR_):
"""Return the WebRTC client configuration and extend it with the registered ice servers."""
config = await self._async_get_webrtc_client_configuration()
ice_servers = await asyncio.gather(
*[server() for server in self.hass.data.get(DATA_ICE_SERVERS, [])]
)
ice_servers = [
server
for servers in self.hass.data.get(DATA_ICE_SERVERS, [])
for server in servers()
]
config.configuration.ice_servers.extend(ice_servers)
return config

View File

@ -3,7 +3,7 @@
from __future__ import annotations
import asyncio
from collections.abc import Awaitable, Callable, Coroutine
from collections.abc import Awaitable, Callable, Iterable
from dataclasses import dataclass, field
from typing import TYPE_CHECKING, Any, Protocol
@ -24,8 +24,8 @@ if TYPE_CHECKING:
DATA_WEBRTC_PROVIDERS: HassKey[set[CameraWebRTCProvider]] = HassKey(
"camera_web_rtc_providers"
)
DATA_ICE_SERVERS: HassKey[list[Callable[[], Coroutine[Any, Any, RTCIceServer]]]] = (
HassKey("camera_web_rtc_ice_servers")
DATA_ICE_SERVERS: HassKey[list[Callable[[], Iterable[RTCIceServer]]]] = HassKey(
"camera_web_rtc_ice_servers"
)
@ -188,9 +188,9 @@ async def async_get_supported_providers(
@callback
def register_ice_server(
def async_register_ice_servers(
hass: HomeAssistant,
get_ice_server_fn: Callable[[], Coroutine[Any, Any, RTCIceServer]],
get_ice_server_fn: Callable[[], Iterable[RTCIceServer]],
) -> Callable[[], None]:
"""Register a ICE server.

View File

@ -26,9 +26,12 @@ from rtsp_to_webrtc.exceptions import ClientError, ResponseError
from rtsp_to_webrtc.interface import WebRTCClientInterface
from homeassistant.components import camera
from homeassistant.components.camera.webrtc import RTCIceServer, register_ice_server
from homeassistant.components.camera.webrtc import (
RTCIceServer,
async_register_ice_servers,
)
from homeassistant.config_entries import ConfigEntry
from homeassistant.core import HomeAssistant
from homeassistant.core import HomeAssistant, callback
from homeassistant.exceptions import ConfigEntryNotReady, HomeAssistantError
from homeassistant.helpers.aiohttp_client import async_get_clientsession
@ -59,10 +62,11 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
hass.data[DOMAIN][CONF_STUN_SERVER] = entry.options.get(CONF_STUN_SERVER)
if server := entry.options.get(CONF_STUN_SERVER):
async def get_server() -> RTCIceServer:
return RTCIceServer(urls=[server])
@callback
def get_servers() -> list[RTCIceServer]:
return [RTCIceServer(urls=[server])]
entry.async_on_unload(register_ice_server(hass, get_server))
entry.async_on_unload(async_register_ice_servers(hass, get_servers))
async def async_offer_for_stream_source(
stream_source: str,

View File

@ -9,11 +9,11 @@ from homeassistant.components.camera.webrtc import (
DATA_ICE_SERVERS,
CameraWebRTCProvider,
RTCIceServer,
async_register_ice_servers,
async_register_webrtc_provider,
register_ice_server,
)
from homeassistant.components.websocket_api import TYPE_RESULT
from homeassistant.core import HomeAssistant
from homeassistant.core import HomeAssistant, callback
from homeassistant.setup import async_setup_component
from tests.typing import WebSocketGenerator
@ -131,37 +131,48 @@ async def test_async_register_ice_server(
called = 0
async def get_ice_server() -> RTCIceServer:
@callback
def get_ice_servers() -> list[RTCIceServer]:
nonlocal called
called += 1
return RTCIceServer(urls="stun:example.com")
return [
RTCIceServer(urls="stun:example.com"),
RTCIceServer(urls="turn:example.com"),
]
unregister = register_ice_server(hass, get_ice_server)
unregister = async_register_ice_servers(hass, get_ice_servers)
assert not called
camera = get_camera_from_entity_id(hass, "camera.demo_camera")
config = await camera.async_get_webrtc_client_configuration()
assert config.configuration.ice_servers == [RTCIceServer(urls="stun:example.com")]
assert config.configuration.ice_servers == [
RTCIceServer(urls="stun:example.com"),
RTCIceServer(urls="turn:example.com"),
]
assert called == 1
# register another ICE server
called_2 = 0
async def get_ice_server_2() -> RTCIceServer:
@callback
def get_ice_servers_2() -> RTCIceServer:
nonlocal called_2
called_2 += 1
return RTCIceServer(
urls=["stun:example2.com", "turn:example2.com"],
username="user",
credential="pass",
)
return [
RTCIceServer(
urls=["stun:example2.com", "turn:example2.com"],
username="user",
credential="pass",
)
]
unregister_2 = register_ice_server(hass, get_ice_server_2)
unregister_2 = async_register_ice_servers(hass, get_ice_servers_2)
config = await camera.async_get_webrtc_client_configuration()
assert config.configuration.ice_servers == [
RTCIceServer(urls="stun:example.com"),
RTCIceServer(urls="turn:example.com"),
RTCIceServer(
urls=["stun:example2.com", "turn:example2.com"],
username="user",