Add support for Add-on discovery in rtsp_to_webrtc (#63211)
Co-authored-by: Franck Nijhof <git@frenck.dev>pull/63389/head
parent
46e61008ea
commit
d7b080b285
|
@ -9,6 +9,8 @@ import rtsp_to_webrtc
|
|||
import voluptuous as vol
|
||||
|
||||
from homeassistant import config_entries
|
||||
from homeassistant.components.hassio import HassioServiceInfo
|
||||
from homeassistant.const import CONF_HOST, CONF_PORT
|
||||
from homeassistant.data_entry_flow import FlowResult
|
||||
from homeassistant.helpers.aiohttp_client import async_get_clientsession
|
||||
|
||||
|
@ -22,6 +24,8 @@ DATA_SCHEMA = vol.Schema({vol.Required(DATA_SERVER_URL): str})
|
|||
class RTSPToWebRTCConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
|
||||
"""RTSPtoWebRTC config flow."""
|
||||
|
||||
_hassio_discovery: dict[str, Any]
|
||||
|
||||
async def async_step_user(
|
||||
self, user_input: dict[str, Any] | None = None
|
||||
) -> FlowResult:
|
||||
|
@ -41,21 +45,11 @@ class RTSPToWebRTCConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
|
|||
errors={DATA_SERVER_URL: "invalid_url"},
|
||||
)
|
||||
|
||||
errors = {}
|
||||
client = rtsp_to_webrtc.client.Client(async_get_clientsession(self.hass), url)
|
||||
try:
|
||||
await client.heartbeat()
|
||||
except rtsp_to_webrtc.exceptions.ResponseError as err:
|
||||
_LOGGER.error("RTSPtoWebRTC server failure: %s", str(err))
|
||||
errors["base"] = "server_failure"
|
||||
except rtsp_to_webrtc.exceptions.ClientError as err:
|
||||
_LOGGER.error("RTSPtoWebRTC communication failure: %s", str(err))
|
||||
errors["base"] = "server_unreachable"
|
||||
if errors:
|
||||
if error_code := await self._test_connection(url):
|
||||
return self.async_show_form(
|
||||
step_id="user",
|
||||
data_schema=DATA_SCHEMA,
|
||||
errors=errors,
|
||||
errors={"base": error_code},
|
||||
)
|
||||
|
||||
await self.async_set_unique_id(DOMAIN)
|
||||
|
@ -63,3 +57,51 @@ class RTSPToWebRTCConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
|
|||
title=url,
|
||||
data={DATA_SERVER_URL: url},
|
||||
)
|
||||
|
||||
async def _test_connection(self, url: str) -> str | None:
|
||||
"""Test the connection and return any relevant errors."""
|
||||
client = rtsp_to_webrtc.client.Client(async_get_clientsession(self.hass), url)
|
||||
try:
|
||||
await client.heartbeat()
|
||||
except rtsp_to_webrtc.exceptions.ResponseError as err:
|
||||
_LOGGER.error("RTSPtoWebRTC server failure: %s", str(err))
|
||||
return "server_failure"
|
||||
except rtsp_to_webrtc.exceptions.ClientError as err:
|
||||
_LOGGER.error("RTSPtoWebRTC communication failure: %s", str(err))
|
||||
return "server_unreachable"
|
||||
return None
|
||||
|
||||
async def async_step_hassio(self, discovery_info: HassioServiceInfo) -> FlowResult:
|
||||
"""Prepare confiugration for the RTSPtoWebRTC server add-on discovery."""
|
||||
if self._async_current_entries():
|
||||
return self.async_abort(reason="single_instance_allowed")
|
||||
|
||||
self._hassio_discovery = discovery_info.config
|
||||
return await self.async_step_hassio_confirm()
|
||||
|
||||
async def async_step_hassio_confirm(
|
||||
self, user_input: dict[str, Any] | None = None
|
||||
) -> FlowResult:
|
||||
"""Confirm Add-on discovery."""
|
||||
errors = None
|
||||
if user_input is not None:
|
||||
# Validate server connection once user has confirmed
|
||||
host = self._hassio_discovery[CONF_HOST]
|
||||
port = self._hassio_discovery[CONF_PORT]
|
||||
url = f"http://{host}:{port}"
|
||||
if error_code := await self._test_connection(url):
|
||||
errors = {"base": error_code}
|
||||
|
||||
if user_input is None or errors:
|
||||
# Show initial confirmation or errors from server validation
|
||||
return self.async_show_form(
|
||||
step_id="hassio_confirm",
|
||||
description_placeholders={"addon": self._hassio_discovery["addon"]},
|
||||
data_schema=vol.Schema({}),
|
||||
errors=errors,
|
||||
)
|
||||
|
||||
return self.async_create_entry(
|
||||
title=self._hassio_discovery["addon"],
|
||||
data={DATA_SERVER_URL: url},
|
||||
)
|
||||
|
|
|
@ -7,6 +7,10 @@
|
|||
"data": {
|
||||
"server_url": "RTSPtoWebRTC server URL e.g. https://example.com"
|
||||
}
|
||||
},
|
||||
"hassio_confirm": {
|
||||
"title": "RTSPtoWebRTC via Home Assistant add-on",
|
||||
"description": "Do you want to configure Home Assistant to connect to the RTSPtoWebRTC server provided by the add-on: {addon}?"
|
||||
}
|
||||
},
|
||||
"error": {
|
||||
|
|
|
@ -7,6 +7,7 @@ from unittest.mock import patch
|
|||
import rtsp_to_webrtc
|
||||
|
||||
from homeassistant import config_entries
|
||||
from homeassistant.components.hassio import HassioServiceInfo
|
||||
from homeassistant.components.rtsp_to_webrtc import DOMAIN
|
||||
from homeassistant.core import HomeAssistant
|
||||
|
||||
|
@ -31,6 +32,7 @@ async def test_web_full_flow(hass: HomeAssistant) -> None:
|
|||
result["flow_id"], {"server_url": "https://example.com"}
|
||||
)
|
||||
assert result.get("type") == "create_entry"
|
||||
assert result.get("title") == "https://example.com"
|
||||
assert "result" in result
|
||||
assert result["result"].data == {"server_url": "https://example.com"}
|
||||
|
||||
|
@ -108,3 +110,106 @@ async def test_server_failure(hass: HomeAssistant) -> None:
|
|||
assert result.get("type") == "form"
|
||||
assert result.get("step_id") == "user"
|
||||
assert result.get("errors") == {"base": "server_failure"}
|
||||
|
||||
|
||||
async def test_hassio_discovery(hass):
|
||||
"""Test supervisor add-on discovery."""
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
DOMAIN,
|
||||
data=HassioServiceInfo(
|
||||
config={
|
||||
"addon": "RTSPtoWebRTC",
|
||||
"host": "fake-server",
|
||||
"port": 8083,
|
||||
}
|
||||
),
|
||||
context={"source": config_entries.SOURCE_HASSIO},
|
||||
)
|
||||
assert result.get("type") == "form"
|
||||
assert result.get("step_id") == "hassio_confirm"
|
||||
assert result.get("description_placeholders") == {"addon": "RTSPtoWebRTC"}
|
||||
|
||||
with patch("rtsp_to_webrtc.client.Client.heartbeat"), patch(
|
||||
"homeassistant.components.rtsp_to_webrtc.async_setup_entry",
|
||||
return_value=True,
|
||||
) as mock_setup:
|
||||
result = await hass.config_entries.flow.async_configure(
|
||||
result["flow_id"], user_input={}
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert result.get("type") == "create_entry"
|
||||
assert result.get("title") == "RTSPtoWebRTC"
|
||||
assert "result" in result
|
||||
assert result["result"].data == {"server_url": "http://fake-server:8083"}
|
||||
|
||||
assert len(mock_setup.mock_calls) == 1
|
||||
|
||||
|
||||
async def test_hassio_single_config_entry(hass: HomeAssistant) -> None:
|
||||
"""Test supervisor add-on discovery only allows a single entry."""
|
||||
old_entry = MockConfigEntry(domain=DOMAIN, data={"example": True})
|
||||
old_entry.add_to_hass(hass)
|
||||
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
DOMAIN,
|
||||
data=HassioServiceInfo(
|
||||
config={
|
||||
"addon": "RTSPtoWebRTC",
|
||||
"host": "fake-server",
|
||||
"port": 8083,
|
||||
}
|
||||
),
|
||||
context={"source": config_entries.SOURCE_HASSIO},
|
||||
)
|
||||
assert result.get("type") == "abort"
|
||||
assert result.get("reason") == "single_instance_allowed"
|
||||
|
||||
|
||||
async def test_hassio_ignored(hass: HomeAssistant) -> None:
|
||||
"""Test ignoring superversor add-on discovery."""
|
||||
old_entry = MockConfigEntry(domain=DOMAIN, source=config_entries.SOURCE_IGNORE)
|
||||
old_entry.add_to_hass(hass)
|
||||
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
DOMAIN,
|
||||
data=HassioServiceInfo(
|
||||
config={
|
||||
"addon": "RTSPtoWebRTC",
|
||||
"host": "fake-server",
|
||||
"port": 8083,
|
||||
}
|
||||
),
|
||||
context={"source": config_entries.SOURCE_HASSIO},
|
||||
)
|
||||
assert result.get("type") == "abort"
|
||||
assert result.get("reason") == "single_instance_allowed"
|
||||
|
||||
|
||||
async def test_hassio_discovery_server_failure(hass: HomeAssistant) -> None:
|
||||
"""Test server failure during supvervisor add-on discovery shows an error."""
|
||||
result = await hass.config_entries.flow.async_init(
|
||||
DOMAIN,
|
||||
data=HassioServiceInfo(
|
||||
config={
|
||||
"addon": "RTSPtoWebRTC",
|
||||
"host": "fake-server",
|
||||
"port": 8083,
|
||||
}
|
||||
),
|
||||
context={"source": config_entries.SOURCE_HASSIO},
|
||||
)
|
||||
|
||||
assert result.get("type") == "form"
|
||||
assert result.get("step_id") == "hassio_confirm"
|
||||
assert not result.get("errors")
|
||||
assert "flow_id" in result
|
||||
|
||||
with patch(
|
||||
"rtsp_to_webrtc.client.Client.heartbeat",
|
||||
side_effect=rtsp_to_webrtc.exceptions.ResponseError(),
|
||||
):
|
||||
result = await hass.config_entries.flow.async_configure(result["flow_id"], {})
|
||||
assert result.get("type") == "form"
|
||||
assert result.get("step_id") == "hassio_confirm"
|
||||
assert result.get("errors") == {"base": "server_failure"}
|
||||
|
|
Loading…
Reference in New Issue