Home Assistant Unofficial Reference 2024.12.1
config_flow.py
Go to the documentation of this file.
1 """Config flow for RTSPtoWebRTC."""
2 
3 from __future__ import annotations
4 
5 import logging
6 from typing import Any
7 from urllib.parse import urlparse
8 
9 import rtsp_to_webrtc
10 import voluptuous as vol
11 
12 from homeassistant.config_entries import (
13  ConfigEntry,
14  ConfigFlow,
15  ConfigFlowResult,
16  OptionsFlow,
17 )
18 from homeassistant.const import CONF_HOST, CONF_PORT
19 from homeassistant.core import callback
20 from homeassistant.helpers.aiohttp_client import async_get_clientsession
21 from homeassistant.helpers.service_info.hassio import HassioServiceInfo
22 
23 from . import CONF_STUN_SERVER, DATA_SERVER_URL, DOMAIN
24 
25 _LOGGER = logging.getLogger(__name__)
26 
27 DATA_SCHEMA = vol.Schema({vol.Required(DATA_SERVER_URL): str})
28 
29 
30 class RTSPToWebRTCConfigFlow(ConfigFlow, domain=DOMAIN):
31  """RTSPtoWebRTC config flow."""
32 
33  _hassio_discovery: dict[str, Any]
34 
35  async def async_step_user(
36  self, user_input: dict[str, Any] | None = None
37  ) -> ConfigFlowResult:
38  """Configure the RTSPtoWebRTC server url."""
39  if self._async_current_entries_async_current_entries():
40  return self.async_abortasync_abortasync_abort(reason="single_instance_allowed")
41 
42  if user_input is None:
43  return self.async_show_formasync_show_formasync_show_form(step_id="user", data_schema=DATA_SCHEMA)
44 
45  url = user_input[DATA_SERVER_URL]
46  result = urlparse(url)
47  if not all([result.scheme, result.netloc]):
48  return self.async_show_formasync_show_formasync_show_form(
49  step_id="user",
50  data_schema=DATA_SCHEMA,
51  errors={DATA_SERVER_URL: "invalid_url"},
52  )
53 
54  if error_code := await self._test_connection(url):
55  return self.async_show_formasync_show_formasync_show_form(
56  step_id="user",
57  data_schema=DATA_SCHEMA,
58  errors={"base": error_code},
59  )
60 
61  await self.async_set_unique_idasync_set_unique_id(DOMAIN)
62  return self.async_create_entryasync_create_entryasync_create_entry(
63  title=url,
64  data={DATA_SERVER_URL: url},
65  )
66 
67  async def _test_connection(self, url: str) -> str | None:
68  """Test the connection and return any relevant errors."""
69  client = rtsp_to_webrtc.client.Client(async_get_clientsession(self.hass), url)
70  try:
71  await client.heartbeat()
72  except rtsp_to_webrtc.exceptions.ResponseError as err:
73  _LOGGER.error("RTSPtoWebRTC server failure: %s", str(err))
74  return "server_failure"
75  except rtsp_to_webrtc.exceptions.ClientError as err:
76  _LOGGER.error("RTSPtoWebRTC communication failure: %s", str(err))
77  return "server_unreachable"
78  return None
79 
80  async def async_step_hassio(
81  self, discovery_info: HassioServiceInfo
82  ) -> ConfigFlowResult:
83  """Prepare configuration for the RTSPtoWebRTC server add-on discovery."""
84  if self._async_current_entries_async_current_entries():
85  return self.async_abortasync_abortasync_abort(reason="single_instance_allowed")
86 
87  self._hassio_discovery_hassio_discovery = discovery_info.config
88  return await self.async_step_hassio_confirm()
89 
90  async def async_step_hassio_confirm(
91  self, user_input: dict[str, Any] | None = None
92  ) -> ConfigFlowResult:
93  """Confirm Add-on discovery."""
94  errors = None
95  if user_input is not None:
96  # Validate server connection once user has confirmed
97  host = self._hassio_discovery_hassio_discovery[CONF_HOST]
98  port = self._hassio_discovery_hassio_discovery[CONF_PORT]
99  url = f"http://{host}:{port}"
100  if error_code := await self._test_connection(url):
101  return self.async_abortasync_abortasync_abort(reason=error_code)
102 
103  if user_input is None or errors:
104  # Show initial confirmation or errors from server validation
105  return self.async_show_formasync_show_formasync_show_form(
106  step_id="hassio_confirm",
107  description_placeholders={"addon": self._hassio_discovery_hassio_discovery["addon"]},
108  errors=errors,
109  )
110 
111  return self.async_create_entryasync_create_entryasync_create_entry(
112  title=self._hassio_discovery_hassio_discovery["addon"],
113  data={DATA_SERVER_URL: url},
114  )
115 
116  @staticmethod
117  @callback
119  config_entry: ConfigEntry,
120  ) -> OptionsFlow:
121  """Create an options flow."""
122  return OptionsFlowHandler()
123 
124 
126  """RTSPtoWeb Options flow."""
127 
128  async def async_step_init(
129  self, user_input: dict[str, Any] | None = None
130  ) -> ConfigFlowResult:
131  """Manage the options."""
132  if user_input is not None:
133  return self.async_create_entryasync_create_entry(title="", data=user_input)
134 
135  return self.async_show_formasync_show_form(
136  step_id="init",
137  data_schema=vol.Schema(
138  {
139  vol.Optional(
140  CONF_STUN_SERVER,
141  description={
142  "suggested_value": self.config_entryconfig_entryconfig_entry.options.get(
143  CONF_STUN_SERVER
144  ),
145  },
146  ): str,
147  }
148  ),
149  )
ConfigFlowResult async_step_init(self, dict[str, Any]|None user_input=None)
Definition: config_flow.py:130
ConfigFlowResult async_step_user(self, dict[str, Any]|None user_input=None)
Definition: config_flow.py:37
ConfigEntry|None async_set_unique_id(self, str|None unique_id=None, *bool raise_on_progress=True)
ConfigFlowResult async_create_entry(self, *str title, Mapping[str, Any] data, str|None description=None, Mapping[str, str]|None description_placeholders=None, Mapping[str, Any]|None options=None)
list[ConfigEntry] _async_current_entries(self, bool|None include_ignore=None)
ConfigFlowResult async_step_hassio(self, HassioServiceInfo discovery_info)
ConfigFlowResult async_abort(self, *str reason, Mapping[str, str]|None description_placeholders=None)
ConfigFlowResult async_show_form(self, *str|None step_id=None, vol.Schema|None data_schema=None, dict[str, str]|None errors=None, Mapping[str, str]|None description_placeholders=None, bool|None last_step=None, str|None preview=None)
OptionsFlow async_get_options_flow(ConfigEntry config_entry)
None config_entry(self, ConfigEntry value)
str
_FlowResultT async_show_form(self, *str|None step_id=None, vol.Schema|None data_schema=None, dict[str, str]|None errors=None, Mapping[str, str]|None description_placeholders=None, bool|None last_step=None, str|None preview=None)
_FlowResultT async_create_entry(self, *str|None title=None, Mapping[str, Any] data, str|None description=None, Mapping[str, str]|None description_placeholders=None)
_FlowResultT async_abort(self, *str reason, Mapping[str, str]|None description_placeholders=None)
aiohttp.ClientSession async_get_clientsession(HomeAssistant hass, bool verify_ssl=True, socket.AddressFamily family=socket.AF_UNSPEC, ssl_util.SSLCipherList ssl_cipher=ssl_util.SSLCipherList.PYTHON_DEFAULT)