From 3512cb95990f289a038611709a4c3fba33898373 Mon Sep 17 00:00:00 2001 From: Robert Resch Date: Fri, 25 Oct 2024 10:18:55 +0200 Subject: [PATCH] Use webrtc-models package (#129032) --- homeassistant/components/camera/__init__.py | 3 +- homeassistant/components/camera/webrtc.py | 23 ++++++- homeassistant/components/nest/camera.py | 8 ++- .../components/rtsp_to_webrtc/__init__.py | 7 +- homeassistant/core.py | 2 +- homeassistant/core_config.py | 2 +- homeassistant/package_constraints.txt | 1 + homeassistant/util/webrtc.py | 69 ------------------- pyproject.toml | 1 + requirements.txt | 1 + tests/test_core_config.py | 6 +- 11 files changed, 40 insertions(+), 83 deletions(-) delete mode 100644 homeassistant/util/webrtc.py diff --git a/homeassistant/components/camera/__init__.py b/homeassistant/components/camera/__init__.py index 3555fad1099..c759f5704cf 100644 --- a/homeassistant/components/camera/__init__.py +++ b/homeassistant/components/camera/__init__.py @@ -20,6 +20,7 @@ from aiohttp import hdrs, web import attr from propcache import cached_property import voluptuous as vol +from webrtc_models import RTCIceServer from homeassistant.components import websocket_api from homeassistant.components.http import KEY_AUTHENTICATED, HomeAssistantView @@ -63,7 +64,6 @@ from homeassistant.helpers.network import get_url from homeassistant.helpers.template import Template from homeassistant.helpers.typing import ConfigType, VolDictType from homeassistant.loader import bind_hass -from homeassistant.util.webrtc import RTCIceServer, WebRTCClientConfiguration from .const import ( # noqa: F401 _DEPRECATED_STREAM_TYPE_HLS, @@ -87,6 +87,7 @@ from .prefs import CameraPreferences, DynamicStreamSettings # noqa: F401 from .webrtc import ( DATA_ICE_SERVERS, CameraWebRTCProvider, + WebRTCClientConfiguration, async_get_supported_providers, async_register_ice_servers, async_register_rtsp_to_web_rtc_provider, # noqa: F401 diff --git a/homeassistant/components/camera/webrtc.py b/homeassistant/components/camera/webrtc.py index 7a30e330aec..12cca6fabd9 100644 --- a/homeassistant/components/camera/webrtc.py +++ b/homeassistant/components/camera/webrtc.py @@ -4,15 +4,16 @@ from __future__ import annotations import asyncio from collections.abc import Awaitable, Callable, Iterable +from dataclasses import dataclass, field from typing import TYPE_CHECKING, Any, Protocol import voluptuous as vol +from webrtc_models import RTCConfiguration, RTCIceServer from homeassistant.components import websocket_api from homeassistant.core import HomeAssistant, callback from homeassistant.helpers import config_validation as cv from homeassistant.util.hass_dict import HassKey -from homeassistant.util.webrtc import RTCIceServer from .const import DATA_COMPONENT, DOMAIN, StreamType from .helper import get_camera_from_entity_id @@ -29,6 +30,26 @@ DATA_ICE_SERVERS: HassKey[list[Callable[[], Iterable[RTCIceServer]]]] = HassKey( ) +@dataclass(kw_only=True) +class WebRTCClientConfiguration: + """WebRTC configuration for the client. + + Not part of the spec, but required to configure client. + """ + + configuration: RTCConfiguration = field(default_factory=RTCConfiguration) + data_channel: str | None = None + + def to_frontend_dict(self) -> dict[str, Any]: + """Return a dict that can be used by the frontend.""" + data: dict[str, Any] = { + "configuration": self.configuration.to_dict(), + } + if self.data_channel is not None: + data["dataChannel"] = self.data_channel + return data + + class CameraWebRTCProvider(Protocol): """WebRTC provider.""" diff --git a/homeassistant/components/nest/camera.py b/homeassistant/components/nest/camera.py index c03decb1572..ee035ce8d11 100644 --- a/homeassistant/components/nest/camera.py +++ b/homeassistant/components/nest/camera.py @@ -20,7 +20,12 @@ from google_nest_sdm.device import Device from google_nest_sdm.device_manager import DeviceManager from google_nest_sdm.exceptions import ApiException -from homeassistant.components.camera import Camera, CameraEntityFeature, StreamType +from homeassistant.components.camera import ( + Camera, + CameraEntityFeature, + StreamType, + WebRTCClientConfiguration, +) from homeassistant.components.stream import CONF_EXTRA_PART_WAIT_TIME from homeassistant.config_entries import ConfigEntry from homeassistant.core import HomeAssistant @@ -28,7 +33,6 @@ from homeassistant.exceptions import HomeAssistantError from homeassistant.helpers.entity_platform import AddEntitiesCallback from homeassistant.helpers.event import async_track_point_in_utc_time from homeassistant.util.dt import utcnow -from homeassistant.util.webrtc import WebRTCClientConfiguration from .const import DATA_DEVICE_MANAGER, DOMAIN from .device_info import NestDeviceInfo diff --git a/homeassistant/components/rtsp_to_webrtc/__init__.py b/homeassistant/components/rtsp_to_webrtc/__init__.py index ee55171e9e9..59b8077e398 100644 --- a/homeassistant/components/rtsp_to_webrtc/__init__.py +++ b/homeassistant/components/rtsp_to_webrtc/__init__.py @@ -24,12 +24,9 @@ import logging from rtsp_to_webrtc.client import get_adaptive_client from rtsp_to_webrtc.exceptions import ClientError, ResponseError from rtsp_to_webrtc.interface import WebRTCClientInterface +from webrtc_models import RTCIceServer from homeassistant.components import camera -from homeassistant.components.camera.webrtc import ( - RTCIceServer, - async_register_ice_servers, -) from homeassistant.config_entries import ConfigEntry from homeassistant.core import HomeAssistant, callback from homeassistant.exceptions import ConfigEntryNotReady, HomeAssistantError @@ -66,7 +63,7 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: def get_servers() -> list[RTCIceServer]: return [RTCIceServer(urls=[server])] - entry.async_on_unload(async_register_ice_servers(hass, get_servers)) + entry.async_on_unload(camera.async_register_ice_servers(hass, get_servers)) async def async_offer_for_stream_source( stream_source: str, diff --git a/homeassistant/core.py b/homeassistant/core.py index 530853caff2..0e6e6e3bd5b 100644 --- a/homeassistant/core.py +++ b/homeassistant/core.py @@ -47,6 +47,7 @@ from urllib.parse import urlparse from propcache import cached_property, under_cached_property from typing_extensions import TypeVar import voluptuous as vol +from webrtc_models import RTCConfiguration import yarl from . import util @@ -119,7 +120,6 @@ from .util.unit_system import ( UnitSystem, get_unit_system, ) -from .util.webrtc import RTCConfiguration # Typing imports that create a circular dependency if TYPE_CHECKING: diff --git a/homeassistant/core_config.py b/homeassistant/core_config.py index 34fefbd8841..af1486a3940 100644 --- a/homeassistant/core_config.py +++ b/homeassistant/core_config.py @@ -10,6 +10,7 @@ from typing import Any, Final from urllib.parse import urlparse import voluptuous as vol +from webrtc_models import RTCIceServer from . import auth from .auth import mfa_modules as auth_mfa_modules, providers as auth_providers @@ -54,7 +55,6 @@ from .helpers.entity_values import EntityValues from .util.hass_dict import HassKey from .util.package import is_docker_env from .util.unit_system import get_unit_system, validate_unit_system -from .util.webrtc import RTCIceServer _LOGGER = logging.getLogger(__name__) diff --git a/homeassistant/package_constraints.txt b/homeassistant/package_constraints.txt index 5fa508bdf3e..3449459281a 100644 --- a/homeassistant/package_constraints.txt +++ b/homeassistant/package_constraints.txt @@ -64,6 +64,7 @@ uv==0.4.22 voluptuous-openapi==0.0.5 voluptuous-serialize==2.6.0 voluptuous==0.15.2 +webrtc-models==0.0.0b2 yarl==1.16.0 zeroconf==0.135.0 diff --git a/homeassistant/util/webrtc.py b/homeassistant/util/webrtc.py deleted file mode 100644 index fd5545af492..00000000000 --- a/homeassistant/util/webrtc.py +++ /dev/null @@ -1,69 +0,0 @@ -"""WebRTC container classes.""" - -from __future__ import annotations - -from dataclasses import dataclass, field -from typing import Any - - -@dataclass -class RTCIceServer: - """RTC Ice Server. - - See https://www.w3.org/TR/webrtc/#rtciceserver-dictionary - """ - - urls: list[str] | str - username: str | None = None - credential: str | None = None - - def to_frontend_dict(self) -> dict[str, Any]: - """Return a dict that can be used by the frontend.""" - - data = { - "urls": self.urls, - } - if self.username is not None: - data["username"] = self.username - if self.credential is not None: - data["credential"] = self.credential - return data - - -@dataclass -class RTCConfiguration: - """RTC Configuration. - - See https://www.w3.org/TR/webrtc/#rtcconfiguration-dictionary - """ - - ice_servers: list[RTCIceServer] = field(default_factory=list) - - def to_frontend_dict(self) -> dict[str, Any]: - """Return a dict that can be used by the frontend.""" - if not self.ice_servers: - return {} - - return { - "iceServers": [server.to_frontend_dict() for server in self.ice_servers] - } - - -@dataclass(kw_only=True) -class WebRTCClientConfiguration: - """WebRTC configuration for the client. - - Not part of the spec, but required to configure client. - """ - - configuration: RTCConfiguration = field(default_factory=RTCConfiguration) - data_channel: str | None = None - - def to_frontend_dict(self) -> dict[str, Any]: - """Return a dict that can be used by the frontend.""" - data: dict[str, Any] = { - "configuration": self.configuration.to_frontend_dict(), - } - if self.data_channel is not None: - data["dataChannel"] = self.data_channel - return data diff --git a/pyproject.toml b/pyproject.toml index d388548eb5e..37e79cc0274 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -74,6 +74,7 @@ dependencies = [ "voluptuous-serialize==2.6.0", "voluptuous-openapi==0.0.5", "yarl==1.16.0", + "webrtc-models==0.0.0b2", ] [project.urls] diff --git a/requirements.txt b/requirements.txt index b3affec82f9..e364d0f08df 100644 --- a/requirements.txt +++ b/requirements.txt @@ -44,3 +44,4 @@ voluptuous==0.15.2 voluptuous-serialize==2.6.0 voluptuous-openapi==0.0.5 yarl==1.16.0 +webrtc-models==0.0.0b2 diff --git a/tests/test_core_config.py b/tests/test_core_config.py index b51db79993f..ef42cb64bb8 100644 --- a/tests/test_core_config.py +++ b/tests/test_core_config.py @@ -7,6 +7,7 @@ from unittest.mock import patch import pytest from voluptuous import Invalid, MultipleInvalid +from webrtc_models import RTCConfiguration, RTCIceServer from homeassistant.const import ( ATTR_ASSUMED_STATE, @@ -28,7 +29,6 @@ from homeassistant.core_config import ( ) from homeassistant.helpers import issue_registry as ir from homeassistant.helpers.entity import Entity -from homeassistant.util import webrtc as webrtc_util from homeassistant.util.unit_system import ( METRIC_SYSTEM, US_CUSTOMARY_SYSTEM, @@ -423,8 +423,8 @@ async def test_loading_configuration(hass: HomeAssistant) -> None: assert hass.config.country == "SE" assert hass.config.language == "sv" assert hass.config.radius == 150 - assert hass.config.webrtc == webrtc_util.RTCConfiguration( - [webrtc_util.RTCIceServer(urls=["stun:custom_stun_server:3478"])] + assert hass.config.webrtc == RTCConfiguration( + [RTCIceServer(urls=["stun:custom_stun_server:3478"])] )