91 lines
2.5 KiB
Python
91 lines
2.5 KiB
Python
"""The go2rtc component."""
|
|
|
|
from go2rtc_client import Go2RtcClient, WebRTCSdpOffer
|
|
|
|
from homeassistant.components.camera import Camera
|
|
from homeassistant.components.camera.webrtc import (
|
|
CameraWebRTCProvider,
|
|
async_register_webrtc_provider,
|
|
)
|
|
from homeassistant.config_entries import ConfigEntry
|
|
from homeassistant.const import CONF_HOST
|
|
from homeassistant.core import HomeAssistant
|
|
from homeassistant.helpers.aiohttp_client import async_get_clientsession
|
|
|
|
from .const import CONF_BINARY
|
|
from .server import Server
|
|
|
|
_SUPPORTED_STREAMS = (
|
|
"bubble",
|
|
"dvrip",
|
|
"expr",
|
|
"ffmpeg",
|
|
"gopro",
|
|
"homekit",
|
|
"http",
|
|
"https",
|
|
"httpx",
|
|
"isapi",
|
|
"ivideon",
|
|
"kasa",
|
|
"nest",
|
|
"onvif",
|
|
"roborock",
|
|
"rtmp",
|
|
"rtmps",
|
|
"rtmpx",
|
|
"rtsp",
|
|
"rtsps",
|
|
"rtspx",
|
|
"tapo",
|
|
"tcp",
|
|
"webrtc",
|
|
"webtorrent",
|
|
)
|
|
|
|
|
|
async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
|
"""Set up WebRTC from a config entry."""
|
|
if binary := entry.data.get(CONF_BINARY):
|
|
# HA will manage the binary
|
|
server = Server(binary)
|
|
entry.async_on_unload(server.stop)
|
|
server.start()
|
|
|
|
client = Go2RtcClient(async_get_clientsession(hass), entry.data[CONF_HOST])
|
|
|
|
provider = WebRTCProvider(client)
|
|
entry.async_on_unload(async_register_webrtc_provider(hass, provider))
|
|
return True
|
|
|
|
|
|
class WebRTCProvider(CameraWebRTCProvider):
|
|
"""WebRTC provider."""
|
|
|
|
def __init__(self, client: Go2RtcClient) -> None:
|
|
"""Initialize the WebRTC provider."""
|
|
self._client = client
|
|
|
|
async def async_is_supported(self, stream_source: str) -> bool:
|
|
"""Return if this provider is supports the Camera as source."""
|
|
return stream_source.partition(":")[0] in _SUPPORTED_STREAMS
|
|
|
|
async def async_handle_web_rtc_offer(
|
|
self, camera: Camera, offer_sdp: str
|
|
) -> str | None:
|
|
"""Handle the WebRTC offer and return an answer."""
|
|
streams = await self._client.streams.list()
|
|
if camera.entity_id not in streams:
|
|
if not (stream_source := await camera.stream_source()):
|
|
return None
|
|
await self._client.streams.add(camera.entity_id, stream_source)
|
|
|
|
answer = await self._client.webrtc.forward_whep_sdp_offer(
|
|
camera.entity_id, WebRTCSdpOffer(offer_sdp)
|
|
)
|
|
return answer.sdp
|
|
|
|
|
|
async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
|
"""Unload a config entry."""
|
|
return True
|