Use RTCIceCandidateInit instead of RTCIceCandidate (#130901)

This commit is contained in:
Robert Resch 2024-11-19 03:41:50 +01:00 committed by GitHub
parent 00250843c6
commit 999f3e0d77
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
10 changed files with 72 additions and 29 deletions

View File

@ -20,7 +20,7 @@ from aiohttp import hdrs, web
import attr import attr
from propcache import cached_property, under_cached_property from propcache import cached_property, under_cached_property
import voluptuous as vol import voluptuous as vol
from webrtc_models import RTCIceCandidate, RTCIceServer from webrtc_models import RTCIceCandidateInit, RTCIceServer
from homeassistant.components import websocket_api from homeassistant.components import websocket_api
from homeassistant.components.http import KEY_AUTHENTICATED, HomeAssistantView from homeassistant.components.http import KEY_AUTHENTICATED, HomeAssistantView
@ -865,7 +865,7 @@ class Camera(Entity, cached_properties=CACHED_PROPERTIES_WITH_ATTR_):
return config return config
async def async_on_webrtc_candidate( async def async_on_webrtc_candidate(
self, session_id: str, candidate: RTCIceCandidate self, session_id: str, candidate: RTCIceCandidateInit
) -> None: ) -> None:
"""Handle a WebRTC candidate.""" """Handle a WebRTC candidate."""
if self._webrtc_provider: if self._webrtc_provider:

View File

@ -11,7 +11,12 @@ import logging
from typing import TYPE_CHECKING, Any, Protocol from typing import TYPE_CHECKING, Any, Protocol
import voluptuous as vol import voluptuous as vol
from webrtc_models import RTCConfiguration, RTCIceCandidate, RTCIceServer from webrtc_models import (
RTCConfiguration,
RTCIceCandidate,
RTCIceCandidateInit,
RTCIceServer,
)
from homeassistant.components import websocket_api from homeassistant.components import websocket_api
from homeassistant.core import HomeAssistant, callback from homeassistant.core import HomeAssistant, callback
@ -78,7 +83,7 @@ class WebRTCAnswer(WebRTCMessage):
class WebRTCCandidate(WebRTCMessage): class WebRTCCandidate(WebRTCMessage):
"""WebRTC candidate.""" """WebRTC candidate."""
candidate: RTCIceCandidate candidate: RTCIceCandidate | RTCIceCandidateInit
def as_dict(self) -> dict[str, Any]: def as_dict(self) -> dict[str, Any]:
"""Return a dict representation of the message.""" """Return a dict representation of the message."""
@ -146,7 +151,7 @@ class CameraWebRTCProvider(ABC):
@abstractmethod @abstractmethod
async def async_on_webrtc_candidate( async def async_on_webrtc_candidate(
self, session_id: str, candidate: RTCIceCandidate self, session_id: str, candidate: RTCIceCandidateInit
) -> None: ) -> None:
"""Handle the WebRTC candidate.""" """Handle the WebRTC candidate."""
@ -338,7 +343,7 @@ async def ws_candidate(
) -> None: ) -> None:
"""Handle WebRTC candidate websocket command.""" """Handle WebRTC candidate websocket command."""
await camera.async_on_webrtc_candidate( await camera.async_on_webrtc_candidate(
msg["session_id"], RTCIceCandidate(msg["candidate"]) msg["session_id"], RTCIceCandidateInit(msg["candidate"])
) )
connection.send_message(websocket_api.result_message(msg["id"])) connection.send_message(websocket_api.result_message(msg["id"]))

View File

@ -16,7 +16,7 @@ from go2rtc_client.ws import (
WsError, WsError,
) )
import voluptuous as vol import voluptuous as vol
from webrtc_models import RTCIceCandidate from webrtc_models import RTCIceCandidateInit
from homeassistant.components.camera import ( from homeassistant.components.camera import (
Camera, Camera,
@ -264,7 +264,7 @@ class WebRTCProvider(CameraWebRTCProvider):
value: WebRTCMessage value: WebRTCMessage
match message: match message:
case WebRTCCandidate(): case WebRTCCandidate():
value = HAWebRTCCandidate(RTCIceCandidate(message.candidate)) value = HAWebRTCCandidate(RTCIceCandidateInit(message.candidate))
case WebRTCAnswer(): case WebRTCAnswer():
value = HAWebRTCAnswer(message.sdp) value = HAWebRTCAnswer(message.sdp)
case WsError(): case WsError():
@ -277,7 +277,7 @@ class WebRTCProvider(CameraWebRTCProvider):
await ws_client.send(WebRTCOffer(offer_sdp, config.configuration.ice_servers)) await ws_client.send(WebRTCOffer(offer_sdp, config.configuration.ice_servers))
async def async_on_webrtc_candidate( async def async_on_webrtc_candidate(
self, session_id: str, candidate: RTCIceCandidate self, session_id: str, candidate: RTCIceCandidateInit
) -> None: ) -> None:
"""Handle the WebRTC candidate.""" """Handle the WebRTC candidate."""

View File

@ -19,7 +19,7 @@ from google_nest_sdm.camera_traits import (
from google_nest_sdm.device import Device from google_nest_sdm.device import Device
from google_nest_sdm.device_manager import DeviceManager from google_nest_sdm.device_manager import DeviceManager
from google_nest_sdm.exceptions import ApiException from google_nest_sdm.exceptions import ApiException
from webrtc_models import RTCIceCandidate from webrtc_models import RTCIceCandidateInit
from homeassistant.components.camera import ( from homeassistant.components.camera import (
Camera, Camera,
@ -304,7 +304,7 @@ class NestWebRTCEntity(NestCameraBaseEntity):
self._refresh_unsub[session_id] = refresh.unsub self._refresh_unsub[session_id] = refresh.unsub
async def async_on_webrtc_candidate( async def async_on_webrtc_candidate(
self, session_id: str, candidate: RTCIceCandidate self, session_id: str, candidate: RTCIceCandidateInit
) -> None: ) -> None:
"""Ignore WebRTC candidates for Nest cloud based cameras.""" """Ignore WebRTC candidates for Nest cloud based cameras."""
return return

View File

@ -6,7 +6,7 @@ components. Instead call the service directly.
from unittest.mock import Mock from unittest.mock import Mock
from webrtc_models import RTCIceCandidate from webrtc_models import RTCIceCandidateInit
from homeassistant.components.camera import ( from homeassistant.components.camera import (
Camera, Camera,
@ -66,7 +66,7 @@ class SomeTestProvider(CameraWebRTCProvider):
send_message(WebRTCAnswer(answer="answer")) send_message(WebRTCAnswer(answer="answer"))
async def async_on_webrtc_candidate( async def async_on_webrtc_candidate(
self, session_id: str, candidate: RTCIceCandidate self, session_id: str, candidate: RTCIceCandidateInit
) -> None: ) -> None:
"""Handle the WebRTC candidate.""" """Handle the WebRTC candidate."""

View File

@ -4,7 +4,7 @@ from collections.abc import AsyncGenerator, Generator
from unittest.mock import AsyncMock, Mock, PropertyMock, patch from unittest.mock import AsyncMock, Mock, PropertyMock, patch
import pytest import pytest
from webrtc_models import RTCIceCandidate from webrtc_models import RTCIceCandidateInit
from homeassistant.components import camera from homeassistant.components import camera
from homeassistant.components.camera.const import StreamType from homeassistant.components.camera.const import StreamType
@ -192,7 +192,7 @@ async def mock_test_webrtc_cameras(hass: HomeAssistant) -> None:
send_message(WebRTCAnswer(WEBRTC_ANSWER)) send_message(WebRTCAnswer(WEBRTC_ANSWER))
async def async_on_webrtc_candidate( async def async_on_webrtc_candidate(
self, session_id: str, candidate: RTCIceCandidate self, session_id: str, candidate: RTCIceCandidateInit
) -> None: ) -> None:
"""Handle a WebRTC candidate.""" """Handle a WebRTC candidate."""
# Do nothing # Do nothing

View File

@ -7,7 +7,7 @@ from unittest.mock import ANY, AsyncMock, Mock, PropertyMock, mock_open, patch
import pytest import pytest
from syrupy.assertion import SnapshotAssertion from syrupy.assertion import SnapshotAssertion
from webrtc_models import RTCIceCandidate from webrtc_models import RTCIceCandidateInit
from homeassistant.components import camera from homeassistant.components import camera
from homeassistant.components.camera import ( from homeassistant.components.camera import (
@ -954,7 +954,7 @@ async def _test_capabilities(
send_message(WebRTCAnswer("answer")) send_message(WebRTCAnswer("answer"))
async def async_on_webrtc_candidate( async def async_on_webrtc_candidate(
self, session_id: str, candidate: RTCIceCandidate self, session_id: str, candidate: RTCIceCandidateInit
) -> None: ) -> None:
"""Handle the WebRTC candidate.""" """Handle the WebRTC candidate."""

View File

@ -6,7 +6,7 @@ from typing import Any
from unittest.mock import AsyncMock, Mock, patch from unittest.mock import AsyncMock, Mock, patch
import pytest import pytest
from webrtc_models import RTCIceCandidate, RTCIceServer from webrtc_models import RTCIceCandidate, RTCIceCandidateInit, RTCIceServer
from homeassistant.components.camera import ( from homeassistant.components.camera import (
DATA_ICE_SERVERS, DATA_ICE_SERVERS,
@ -481,11 +481,30 @@ async def test_websocket_webrtc_offer(
assert msg["success"] assert msg["success"]
@pytest.mark.filterwarnings(
"ignore:Using RTCIceCandidate is deprecated. Use RTCIceCandidateInit instead"
)
@pytest.mark.usefixtures("mock_stream_source", "mock_camera")
async def test_websocket_webrtc_offer_webrtc_provider_deprecated(
hass: HomeAssistant,
hass_ws_client: WebSocketGenerator,
register_test_provider: SomeTestProvider,
) -> None:
"""Test initiating a WebRTC stream with a webrtc provider with the deprecated class."""
await _test_websocket_webrtc_offer_webrtc_provider(
hass,
hass_ws_client,
register_test_provider,
WebRTCCandidate(RTCIceCandidate("candidate")),
{"type": "candidate", "candidate": "candidate"},
)
@pytest.mark.parametrize( @pytest.mark.parametrize(
("message", "expected_frontend_message"), ("message", "expected_frontend_message"),
[ [
( (
WebRTCCandidate(RTCIceCandidate("candidate")), WebRTCCandidate(RTCIceCandidateInit("candidate")),
{"type": "candidate", "candidate": "candidate"}, {"type": "candidate", "candidate": "candidate"},
), ),
( (
@ -503,6 +522,23 @@ async def test_websocket_webrtc_offer_webrtc_provider(
register_test_provider: SomeTestProvider, register_test_provider: SomeTestProvider,
message: WebRTCMessage, message: WebRTCMessage,
expected_frontend_message: dict[str, Any], expected_frontend_message: dict[str, Any],
) -> None:
"""Test initiating a WebRTC stream with a webrtc provider."""
await _test_websocket_webrtc_offer_webrtc_provider(
hass,
hass_ws_client,
register_test_provider,
message,
expected_frontend_message,
)
async def _test_websocket_webrtc_offer_webrtc_provider(
hass: HomeAssistant,
hass_ws_client: WebSocketGenerator,
register_test_provider: SomeTestProvider,
message: WebRTCMessage,
expected_frontend_message: dict[str, Any],
) -> None: ) -> None:
"""Test initiating a WebRTC stream with a webrtc provider.""" """Test initiating a WebRTC stream with a webrtc provider."""
client = await hass_ws_client(hass) client = await hass_ws_client(hass)
@ -934,7 +970,7 @@ async def test_ws_webrtc_candidate(
assert response["type"] == TYPE_RESULT assert response["type"] == TYPE_RESULT
assert response["success"] assert response["success"]
mock_on_webrtc_candidate.assert_called_once_with( mock_on_webrtc_candidate.assert_called_once_with(
session_id, RTCIceCandidate(candidate) session_id, RTCIceCandidateInit(candidate)
) )
@ -986,7 +1022,7 @@ async def test_ws_webrtc_candidate_webrtc_provider(
assert response["type"] == TYPE_RESULT assert response["type"] == TYPE_RESULT
assert response["success"] assert response["success"]
mock_on_webrtc_candidate.assert_called_once_with( mock_on_webrtc_candidate.assert_called_once_with(
session_id, RTCIceCandidate(candidate) session_id, RTCIceCandidateInit(candidate)
) )
@ -1088,7 +1124,7 @@ async def test_webrtc_provider_optional_interface(hass: HomeAssistant) -> None:
send_message(WebRTCAnswer(answer="answer")) send_message(WebRTCAnswer(answer="answer"))
async def async_on_webrtc_candidate( async def async_on_webrtc_candidate(
self, session_id: str, candidate: RTCIceCandidate self, session_id: str, candidate: RTCIceCandidateInit
) -> None: ) -> None:
"""Handle the WebRTC candidate.""" """Handle the WebRTC candidate."""
@ -1098,7 +1134,9 @@ async def test_webrtc_provider_optional_interface(hass: HomeAssistant) -> None:
await provider.async_handle_async_webrtc_offer( await provider.async_handle_async_webrtc_offer(
Mock(), "offer_sdp", "session_id", Mock() Mock(), "offer_sdp", "session_id", Mock()
) )
await provider.async_on_webrtc_candidate("session_id", RTCIceCandidate("candidate")) await provider.async_on_webrtc_candidate(
"session_id", RTCIceCandidateInit("candidate")
)
provider.async_close_session("session_id") provider.async_close_session("session_id")

View File

@ -18,7 +18,7 @@ from go2rtc_client.ws import (
WsError, WsError,
) )
import pytest import pytest
from webrtc_models import RTCIceCandidate from webrtc_models import RTCIceCandidateInit
from homeassistant.components.camera import ( from homeassistant.components.camera import (
DOMAIN as CAMERA_DOMAIN, DOMAIN as CAMERA_DOMAIN,
@ -423,7 +423,7 @@ async def message_callbacks(
[ [
( (
WebRTCCandidate("candidate"), WebRTCCandidate("candidate"),
HAWebRTCCandidate(RTCIceCandidate("candidate")), HAWebRTCCandidate(RTCIceCandidateInit("candidate")),
), ),
( (
WebRTCAnswer(ANSWER_SDP), WebRTCAnswer(ANSWER_SDP),
@ -459,7 +459,7 @@ async def test_on_candidate(
session_id = "session_id" session_id = "session_id"
# Session doesn't exist # Session doesn't exist
await camera.async_on_webrtc_candidate(session_id, RTCIceCandidate("candidate")) await camera.async_on_webrtc_candidate(session_id, RTCIceCandidateInit("candidate"))
assert ( assert (
"homeassistant.components.go2rtc", "homeassistant.components.go2rtc",
logging.DEBUG, logging.DEBUG,
@ -479,7 +479,7 @@ async def test_on_candidate(
) )
ws_client.reset_mock() ws_client.reset_mock()
await camera.async_on_webrtc_candidate(session_id, RTCIceCandidate("candidate")) await camera.async_on_webrtc_candidate(session_id, RTCIceCandidateInit("candidate"))
ws_client.send.assert_called_once_with(WebRTCCandidate("candidate")) ws_client.send.assert_called_once_with(WebRTCCandidate("candidate"))
assert caplog.record_tuples == [] assert caplog.record_tuples == []

View File

@ -9,12 +9,12 @@ from uiprotect.api import DEVICE_UPDATE_INTERVAL
from uiprotect.data import Camera as ProtectCamera, CameraChannel, StateType from uiprotect.data import Camera as ProtectCamera, CameraChannel, StateType
from uiprotect.exceptions import NvrError from uiprotect.exceptions import NvrError
from uiprotect.websocket import WebsocketState from uiprotect.websocket import WebsocketState
from webrtc_models import RTCIceCandidateInit
from homeassistant.components.camera import ( from homeassistant.components.camera import (
CameraEntityFeature, CameraEntityFeature,
CameraState, CameraState,
CameraWebRTCProvider, CameraWebRTCProvider,
RTCIceCandidate,
StreamType, StreamType,
WebRTCSendMessage, WebRTCSendMessage,
async_get_image, async_get_image,
@ -77,7 +77,7 @@ class MockWebRTCProvider(CameraWebRTCProvider):
"""Handle the WebRTC offer and return the answer via the provided callback.""" """Handle the WebRTC offer and return the answer via the provided callback."""
async def async_on_webrtc_candidate( async def async_on_webrtc_candidate(
self, session_id: str, candidate: RTCIceCandidate self, session_id: str, candidate: RTCIceCandidateInit
) -> None: ) -> None:
"""Handle the WebRTC candidate.""" """Handle the WebRTC candidate."""