1
0
mirror of https://github.com/home-assistant/core.git synced 2025-12-20 02:48:57 +00:00

Allow fetching the Cloud ICE servers (#157774)

This commit is contained in:
Paulus Schoutsen
2025-12-02 16:02:30 -05:00
committed by GitHub
parent 5b1829f3a1
commit e857abb43f
3 changed files with 67 additions and 5 deletions

View File

@@ -71,6 +71,7 @@ class CloudClient(Interface):
self._google_config_init_lock = asyncio.Lock() self._google_config_init_lock = asyncio.Lock()
self._relayer_region: str | None = None self._relayer_region: str | None = None
self._cloud_ice_servers_listener: Callable[[], None] | None = None self._cloud_ice_servers_listener: Callable[[], None] | None = None
self._ice_servers: list[RTCIceServer] = []
@property @property
def base_path(self) -> Path: def base_path(self) -> Path:
@@ -117,6 +118,11 @@ class CloudClient(Interface):
"""Return the connected relayer region.""" """Return the connected relayer region."""
return self._relayer_region return self._relayer_region
@property
def ice_servers(self) -> list[RTCIceServer]:
"""Return the current ICE servers."""
return self._ice_servers
async def get_alexa_config(self) -> alexa_config.CloudAlexaConfig: async def get_alexa_config(self) -> alexa_config.CloudAlexaConfig:
"""Return Alexa config.""" """Return Alexa config."""
if self._alexa_config is None: if self._alexa_config is None:
@@ -203,11 +209,8 @@ class CloudClient(Interface):
ice_servers: list[RTCIceServer], ice_servers: list[RTCIceServer],
) -> Callable[[], None]: ) -> Callable[[], None]:
"""Register cloud ice server.""" """Register cloud ice server."""
self._ice_servers = ice_servers
def get_ice_servers() -> list[RTCIceServer]: return async_register_ice_servers(self._hass, lambda: self._ice_servers)
return ice_servers
return async_register_ice_servers(self._hass, get_ice_servers)
async def async_register_cloud_ice_servers_listener( async def async_register_cloud_ice_servers_listener(
prefs: CloudPreferences, prefs: CloudPreferences,
@@ -268,6 +271,7 @@ class CloudClient(Interface):
async def logout_cleanups(self) -> None: async def logout_cleanups(self) -> None:
"""Cleanup some stuff after logout.""" """Cleanup some stuff after logout."""
self._ice_servers = []
await self.prefs.async_set_username(None) await self.prefs.async_set_username(None)
if self._alexa_config: if self._alexa_config:

View File

@@ -99,6 +99,7 @@ def async_setup(hass: HomeAssistant) -> None:
websocket_api.async_register_command(hass, websocket_hook_delete) websocket_api.async_register_command(hass, websocket_hook_delete)
websocket_api.async_register_command(hass, websocket_remote_connect) websocket_api.async_register_command(hass, websocket_remote_connect)
websocket_api.async_register_command(hass, websocket_remote_disconnect) websocket_api.async_register_command(hass, websocket_remote_disconnect)
websocket_api.async_register_command(hass, websocket_webrtc_ice_servers)
websocket_api.async_register_command(hass, google_assistant_get) websocket_api.async_register_command(hass, google_assistant_get)
websocket_api.async_register_command(hass, google_assistant_list) websocket_api.async_register_command(hass, google_assistant_list)
@@ -1107,6 +1108,7 @@ async def alexa_sync(
@websocket_api.websocket_command({"type": "cloud/tts/info"}) @websocket_api.websocket_command({"type": "cloud/tts/info"})
@callback
def tts_info( def tts_info(
hass: HomeAssistant, hass: HomeAssistant,
connection: websocket_api.ActiveConnection, connection: websocket_api.ActiveConnection,
@@ -1134,3 +1136,22 @@ def tts_info(
) )
connection.send_result(msg["id"], {"languages": result}) connection.send_result(msg["id"], {"languages": result})
@websocket_api.websocket_command(
{
vol.Required("type"): "cloud/webrtc/ice_servers",
}
)
@_require_cloud_login
@callback
def websocket_webrtc_ice_servers(
hass: HomeAssistant,
connection: websocket_api.ActiveConnection,
msg: dict[str, Any],
) -> None:
"""Handle get WebRTC ICE servers websocket command."""
connection.send_result(
msg["id"],
[server.to_dict() for server in hass.data[DATA_CLOUD].client.ice_servers],
)

View File

@@ -22,6 +22,7 @@ from hass_nabucasa.payments_api import PaymentsApiError
from hass_nabucasa.remote import CertificateStatus from hass_nabucasa.remote import CertificateStatus
import pytest import pytest
from syrupy.assertion import SnapshotAssertion from syrupy.assertion import SnapshotAssertion
from webrtc_models import RTCIceServer
from homeassistant.components import system_health from homeassistant.components import system_health
from homeassistant.components.alexa import errors as alexa_errors from homeassistant.components.alexa import errors as alexa_errors
@@ -2186,3 +2187,39 @@ async def test_download_support_package_integration_load_error(
req = await cloud_client.get("/api/cloud/support_package") req = await cloud_client.get("/api/cloud/support_package")
assert req.status == HTTPStatus.OK assert req.status == HTTPStatus.OK
assert await req.text() == snapshot assert await req.text() == snapshot
async def test_websocket_ice_servers(
hass: HomeAssistant,
hass_ws_client: WebSocketGenerator,
cloud: MagicMock,
setup_cloud: None,
) -> None:
"""Test getting ICE servers."""
cloud.client._ice_servers = [
RTCIceServer(urls="stun:stun.l.bla.com:19302"),
RTCIceServer(
urls="turn:turn.example.com:3478", username="user", credential="pass"
),
]
client = await hass_ws_client(hass)
await client.send_json_auto_id({"type": "cloud/webrtc/ice_servers"})
response = await client.receive_json()
assert response["success"]
assert response["result"] == [
{"urls": "stun:stun.l.bla.com:19302"},
{
"urls": "turn:turn.example.com:3478",
"username": "user",
"credential": "pass",
},
]
cloud.id_token = None
await client.send_json_auto_id({"type": "cloud/webrtc/ice_servers"})
response = await client.receive_json()
assert not response["success"]
assert response["error"]["code"] == "not_logged_in"