diff --git a/custom_components/webrtc/__init__.py b/custom_components/webrtc/__init__.py index 825a9e5..a366e50 100644 --- a/custom_components/webrtc/__init__.py +++ b/custom_components/webrtc/__init__.py @@ -3,26 +3,22 @@ import time import uuid from pathlib import Path -from typing import Union from urllib.parse import urlencode, urljoin -import homeassistant.helpers.config_validation as cv import voluptuous as vol from aiohttp import web from aiohttp.web_exceptions import HTTPUnauthorized, HTTPGone, HTTPNotFound -from homeassistant.components import camera +from homeassistant.components.binary_sensor import HomeAssistant # fix tests +from homeassistant.components.camera import async_get_stream_source, async_get_image from homeassistant.components.hassio.ingress import _websocket_forward from homeassistant.components.http import HomeAssistantView from homeassistant.config_entries import ConfigEntry -from homeassistant.const import ( - EVENT_HOMEASSISTANT_STOP, - ATTR_ENTITY_ID, - CONF_URL, -) +from homeassistant.const import ATTR_ENTITY_ID, CONF_URL, EVENT_HOMEASSISTANT_STOP +from homeassistant.core import ServiceCall +from homeassistant.helpers import config_validation as cv from homeassistant.helpers.aiohttp_client import async_get_clientsession from homeassistant.helpers.network import get_url from homeassistant.helpers.template import Template -from homeassistant.helpers.typing import HomeAssistantType, ConfigType, ServiceCallType from . import utils from .utils import DOMAIN, Server @@ -60,7 +56,7 @@ HLS_SESSION = str(uuid.uuid4()) -async def async_setup(hass: HomeAssistantType, config: ConfigType): +async def async_setup(hass: HomeAssistant, config: dict): # 1. Serve lovelace card path = Path(__file__).parent / "www" for name in ("video-rtc.js", "webrtc-camera.js", "digital-ptz.js"): @@ -81,7 +77,7 @@ async def async_setup(hass: HomeAssistantType, config: ConfigType): # 6. Register webrtc.create_link and webrtc.dash_cast services: - async def create_link(call: ServiceCallType): + async def create_link(call: ServiceCall): link_id = call.data["link_id"] ttl = call.data["time_to_live"] LINKS[link_id] = { @@ -91,7 +87,7 @@ async def create_link(call: ServiceCallType): "ts": time.time() + ttl if ttl else 0, } - async def dash_cast(call: ServiceCallType): + async def dash_cast(call: ServiceCall): link_id = uuid.uuid4().hex LINKS[link_id] = { "url": call.data.get("url"), # camera URL (rtsp...) @@ -121,7 +117,7 @@ async def dash_cast(call: ServiceCallType): return True -async def async_setup_entry(hass: HomeAssistantType, entry: ConfigEntry): +async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry): # 1. If user set custom url go_url = entry.data.get(CONF_URL) @@ -147,26 +143,26 @@ async def async_setup_entry(hass: HomeAssistantType, entry: ConfigEntry): return True -async def async_unload_entry(hass: HomeAssistantType, entry: ConfigEntry): +async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry): server = hass.data[DOMAIN] if isinstance(server, Server): server.stop() return True -async def ws_connect(hass: HomeAssistantType, params: dict) -> str: +async def ws_connect(hass: HomeAssistant, params: dict) -> str: # 1. Server URL from card param server: str = params.get("server") # 2. Server URL from integration settings if not server: - server: Union[str, Server] = hass.data[DOMAIN] + server: str | Server = hass.data[DOMAIN] # 3. Server is manual binary if isinstance(server, Server): assert server.available, "WebRTC server not available" server = "http://localhost:1984/" if entity_id := params.get("entity"): - src = await camera.async_get_stream_source(hass, entity_id) + src = await async_get_stream_source(hass, entity_id) if src is None: # build link to MJPEG stream if state := hass.states.get(entity_id): @@ -184,7 +180,7 @@ async def ws_connect(hass: HomeAssistantType, params: dict) -> str: return urljoin("ws" + server[4:], "api/ws") + "?" + urlencode(query) -def _get_image_from_entity_id(hass: HomeAssistantType, entity_id: str): +def _get_image_from_entity_id(hass: HomeAssistant, entity_id: str): """Get camera component from entity_id.""" if (component := hass.data.get("image")) is None: raise Exception("Image integration not set up") @@ -195,7 +191,7 @@ def _get_image_from_entity_id(hass: HomeAssistantType, entity_id: str): return image -async def ws_poster(hass: HomeAssistantType, params: dict) -> web.Response: +async def ws_poster(hass: HomeAssistant, params: dict) -> web.Response: poster: str = params["poster"] if "{{" in poster or "{%" in poster: @@ -204,7 +200,7 @@ async def ws_poster(hass: HomeAssistantType, params: dict) -> web.Response: if poster.startswith("camera."): # support entity_id as poster - image = await camera.async_get_image(hass, poster) + image = await async_get_image(hass, poster) return web.Response(body=image.content, content_type=image.content_type) if poster.startswith("image."): @@ -309,7 +305,7 @@ async def get(self, request: web.Request, filename: str): if filename not in ("playlist.m3u8", "init.mp4", "segment.m4s", "segment.ts"): raise HTTPNotFound() - hass: HomeAssistantType = request.app["hass"] + hass: HomeAssistant = request.app["hass"] entry = hass.data[DOMAIN] url = "http://localhost:1984/" if isinstance(entry, Server) else entry url = urljoin(url, "api/hls/" + filename) + "?" + request.query_string diff --git a/custom_components/webrtc/utils.py b/custom_components/webrtc/utils.py index 5d9191c..5e32982 100644 --- a/custom_components/webrtc/utils.py +++ b/custom_components/webrtc/utils.py @@ -12,13 +12,12 @@ import jwt from aiohttp import web -from homeassistant.components.camera import Camera from homeassistant.components.frontend import add_extra_js_url from homeassistant.components.http.auth import DATA_SIGN_SECRET, SIGN_QUERY_PARAM from homeassistant.components.lovelace.resources import ResourceStorageCollection from homeassistant.core import HomeAssistant from homeassistant.helpers.aiohttp_client import async_get_clientsession -from homeassistant.helpers.entity_component import EntityComponent, DATA_INSTANCES +from homeassistant.helpers.entity_component import DATA_INSTANCES _LOGGER = logging.getLogger(__name__) diff --git a/tests/test_backward.py b/tests/test_backward.py index 2e66f1d..29d3134 100644 --- a/tests/test_backward.py +++ b/tests/test_backward.py @@ -1,9 +1,14 @@ -from homeassistant.components.media_player import MediaPlayerEntityFeature +from homeassistant.const import REQUIRED_PYTHON_VER +from custom_components.webrtc import * +from custom_components.webrtc.config_flow import * +from custom_components.webrtc.media_player import * -def test_2022_5_0(): - assert MediaPlayerEntityFeature +def test_backward(): + # https://github.com/home-assistant/core/blob/2023.2.0/homeassistant/const.py + assert REQUIRED_PYTHON_VER >= (3, 10, 0) -# def test_2023_7_0(): -# assert ImageEntity + assert async_setup_entry, async_unload_entry + assert FlowHandler + assert WebRTCPlayer