1 """Config flow for BleBox devices integration."""
3 from __future__
import annotations
8 from blebox_uniapi.box
import Box
9 from blebox_uniapi.error
import (
12 UnsupportedBoxResponse,
13 UnsupportedBoxVersion,
15 from blebox_uniapi.session
import ApiHost
16 import voluptuous
as vol
23 from .
import get_maybe_authenticated_session
25 ADDRESS_ALREADY_CONFIGURED,
29 DEFAULT_SETUP_TIMEOUT,
35 _LOGGER = logging.getLogger(__name__)
39 """Create a schema with given values as default."""
40 if previous_input
is not None:
41 host = previous_input[CONF_HOST]
42 port = previous_input[CONF_PORT]
49 vol.Required(CONF_HOST, default=host): str,
50 vol.Required(CONF_PORT, default=port): int,
51 vol.Inclusive(CONF_USERNAME,
"auth"): str,
52 vol.Inclusive(CONF_PASSWORD,
"auth"): str,
58 UNSUPPORTED_VERSION:
"Outdated firmware",
59 CANNOT_CONNECT:
"Failed to identify device",
60 UNKNOWN:
"Unknown error while identifying device",
65 """Handle a config flow for BleBox devices."""
70 """Initialize the BleBox config flow."""
71 self.device_config: dict[str, Any] = {}
74 self, step, exception, schema, host, port, message_id, log_fn
76 """Handle step exceptions."""
77 log_fn(
"%s at %s:%d (%s)", LOG_MSG[message_id], host, port, exception)
82 errors={
"base": message_id},
83 description_placeholders={
"address": f
"{host}:{port}"},
87 self, discovery_info: zeroconf.ZeroconfServiceInfo
88 ) -> ConfigFlowResult:
89 """Handle zeroconf discovery."""
91 ipaddress = (discovery_info.host, discovery_info.port)
92 self.device_config[
"host"] = discovery_info.host
93 self.device_config[
"port"] = discovery_info.port
98 *ipaddress, DEFAULT_SETUP_TIMEOUT, websession, hass.loop, _LOGGER
102 product = await Box.async_from_host(api_host)
103 except UnsupportedBoxVersion:
105 except UnsupportedBoxResponse:
108 self.device_config[
"name"] = product.name
114 "title_placeholders": {
115 "name": self.device_config[
"name"],
116 "host": self.device_config[
"host"],
118 "configuration_url": f
"http://{discovery_info.host}",
124 self, user_input: dict[str, Any] |
None =
None
125 ) -> ConfigFlowResult:
126 """Handle discovery confirmation."""
127 if user_input
is not None:
129 title=self.device_config[
"name"],
131 "host": self.device_config[
"host"],
132 "port": self.device_config[
"port"],
137 step_id=
"confirm_discovery",
138 description_placeholders={
139 "name": self.device_config[
"name"],
140 "host": self.device_config[
"host"],
141 "port": self.device_config[
"port"],
146 self, user_input: dict[str, Any] |
None =
None
147 ) -> ConfigFlowResult:
148 """Handle initial user-triggered config step."""
152 if user_input
is None:
157 description_placeholders={},
160 host = user_input[CONF_HOST]
161 port = user_input[CONF_PORT]
163 username = user_input.get(CONF_USERNAME)
164 password = user_input.get(CONF_PASSWORD)
167 if host == entry.data[CONF_HOST]
and port == entry.data[CONF_PORT]:
169 reason=ADDRESS_ALREADY_CONFIGURED,
170 description_placeholders={
"address": f
"{host}:{port}"},
176 host, port, DEFAULT_SETUP_TIMEOUT, websession, hass.loop, _LOGGER
179 product = await Box.async_from_host(api_host)
181 except UnsupportedBoxVersion
as ex:
191 except UnauthorizedRequest
as ex:
193 "user", ex, schema, host, port, CANNOT_CONNECT, _LOGGER.error
198 "user", ex, schema, host, port, CANNOT_CONNECT, _LOGGER.warning
201 except RuntimeError
as ex:
203 "user", ex, schema, host, port, UNKNOWN, _LOGGER.error
207 await self.
async_set_unique_idasync_set_unique_id(product.unique_id, raise_on_progress=
False)
ConfigFlowResult async_step_confirm_discovery(self, dict[str, Any]|None user_input=None)
def handle_step_exception(self, step, exception, schema, host, port, message_id, log_fn)
ConfigFlowResult async_step_user(self, dict[str, Any]|None user_input=None)
ConfigFlowResult async_step_zeroconf(self, zeroconf.ZeroconfServiceInfo discovery_info)
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 create_schema(previous_input=None)
aiohttp.ClientSession get_maybe_authenticated_session(HomeAssistant hass, str|None password, str|None username)
IssData update(pyiss.ISS iss)
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)