1 """Config flow for UPB PIM integration."""
4 from contextlib
import suppress
7 from urllib.parse
import urlparse
10 import voluptuous
as vol
16 from .const
import DOMAIN
18 _LOGGER = logging.getLogger(__name__)
19 PROTOCOL_MAP = {
"TCP":
"tcp://",
"Serial port":
"serial://"}
20 DATA_SCHEMA = vol.Schema(
22 vol.Required(CONF_PROTOCOL, default=
"Serial port"): vol.In(
23 [
"TCP",
"Serial port"]
25 vol.Required(CONF_ADDRESS): str,
26 vol.Required(CONF_FILE_PATH, default=
""): str,
33 """Validate the user input allows us to connect."""
35 def _connected_callback():
38 connected_event = asyncio.Event()
39 file_path = data.get(CONF_FILE_PATH)
42 upb = upb_lib.UpbPim({
"url": url,
"UPStartExportFile": file_path})
44 await upb.async_connect(_connected_callback)
47 _LOGGER.error(
"Missing or invalid UPB file: %s", file_path)
50 with suppress(TimeoutError):
51 async
with asyncio.timeout(VALIDATE_TIMEOUT):
52 await connected_event.wait()
56 if not connected_event.is_set():
58 "Timed out after %d seconds trying to connect with UPB PIM at %s",
65 return (upb.network_id, {
"title":
"UPB", CONF_HOST: url, CONF_FILE_PATH: file_path})
69 if host := data.get(CONF_HOST):
72 protocol = PROTOCOL_MAP[data[CONF_PROTOCOL]]
73 address = data[CONF_ADDRESS]
74 return f
"{protocol}{address}"
78 """Handle a config flow for UPB PIM."""
84 self, user_input: dict[str, Any] |
None =
None
85 ) -> ConfigFlowResult:
86 """Handle the initial step."""
88 if user_input
is not None:
94 errors[
"base"] =
"cannot_connect"
95 except InvalidUpbFile:
96 errors[
"base"] =
"invalid_upb_file"
98 _LOGGER.exception(
"Unexpected exception")
99 errors[
"base"] =
"unknown"
101 if "base" not in errors:
108 CONF_HOST: info[CONF_HOST],
109 CONF_FILE_PATH: user_input[CONF_FILE_PATH],
114 step_id=
"user", data_schema=DATA_SCHEMA, errors=errors
118 """See if we already have a UPB PIM matching user input configured."""
120 urlparse(entry.data[CONF_HOST]).hostname
123 return urlparse(url).hostname
in existing_hosts
127 """Error to indicate we cannot connect."""
130 class InvalidUpbFile(HomeAssistantError):
131 """Error to indicate there is invalid or missing UPB config file."""
def _url_already_configured(self, url)
ConfigFlowResult async_step_user(self, dict[str, Any]|None user_input=None)
None _abort_if_unique_id_configured(self, dict[str, Any]|None updates=None, bool reload_on_update=True, *str error="already_configured")
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_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)
_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)
def _make_url_from_data(data)
def _validate_input(data)