1 """Config flow for the Total Connect component."""
3 from __future__
import annotations
5 from collections.abc
import Mapping
6 from typing
import TYPE_CHECKING, Any
8 from total_connect_client.client
import TotalConnectClient
9 from total_connect_client.exceptions
import AuthenticationError
10 import voluptuous
as vol
22 from .const
import AUTO_BYPASS, CODE_REQUIRED, CONF_USERCODES, DOMAIN
24 PASSWORD_DATA_SCHEMA = vol.Schema({vol.Required(CONF_PASSWORD): str})
28 """Total Connect config flow."""
32 client: TotalConnectClient
35 """Initialize the config flow."""
36 self.
usernameusername: str |
None =
None
37 self.
passwordpassword: str |
None =
None
38 self.
usercodesusercodes: dict[int, str |
None] = {}
41 self, user_input: dict[str, str] |
None =
None
42 ) -> ConfigFlowResult:
43 """Handle a flow initiated by the user."""
46 if user_input
is not None:
48 username = user_input[CONF_USERNAME]
49 password = user_input[CONF_PASSWORD]
55 client = await self.hass.async_add_executor_job(
56 TotalConnectClient, username, password,
None
58 except AuthenticationError:
59 errors[
"base"] =
"invalid_auth"
67 data_schema = vol.Schema(
68 {vol.Required(CONF_USERNAME): str, vol.Required(CONF_PASSWORD): str}
72 step_id=
"user", data_schema=data_schema, errors=errors
76 self, user_input: dict[str, str] |
None =
None
77 ) -> ConfigFlowResult:
78 """Handle the user locations and associated usercodes."""
80 if user_input
is not None:
81 for location_id
in self.
usercodesusercodes:
82 if self.
usercodesusercodes[location_id]
is None:
83 valid = await self.hass.async_add_executor_job(
84 self.
clientclient.locations[location_id].set_usercode,
85 user_input[CONF_USERCODES],
88 self.
usercodesusercodes[location_id] = user_input[CONF_USERCODES]
90 errors[CONF_LOCATION] =
"usercode"
94 for location_id
in self.
usercodesusercodes:
95 if self.
usercodesusercodes[location_id]
is None:
98 if not errors
and complete:
100 title=
"Total Connect",
102 CONF_USERNAME: self.
usernameusername,
103 CONF_PASSWORD: self.
passwordpassword,
109 number_locations = await self.hass.async_add_executor_job(
110 self.
clientclient.get_number_locations,
112 if number_locations < 1:
114 for location_id
in self.
clientclient.locations:
115 self.
usercodesusercodes[location_id] =
None
118 location_codes: VolDictType = {}
119 location_for_user =
""
120 for location_id
in self.
usercodesusercodes:
121 if self.
usercodesusercodes[location_id]
is None:
122 location_for_user =
str(location_id)
131 data_schema = vol.Schema(location_codes)
134 data_schema=data_schema,
136 description_placeholders={
"location_id": location_for_user},
140 self, entry_data: Mapping[str, Any]
141 ) -> ConfigFlowResult:
142 """Perform reauth upon an authentication error or no usercode."""
143 self.
usernameusername = entry_data[CONF_USERNAME]
149 self, user_input: dict[str, str] |
None =
None
150 ) -> ConfigFlowResult:
151 """Dialog that informs the user that reauth is required."""
153 if user_input
is None:
155 step_id=
"reauth_confirm",
156 data_schema=PASSWORD_DATA_SCHEMA,
160 await self.hass.async_add_executor_job(
163 user_input[CONF_PASSWORD],
166 except AuthenticationError:
167 errors[
"base"] =
"invalid_auth"
169 step_id=
"reauth_confirm",
171 data_schema=PASSWORD_DATA_SCHEMA,
176 assert existing_entry
is not None
178 CONF_USERNAME: self.
usernameusername,
179 CONF_PASSWORD: user_input[CONF_PASSWORD],
182 self.hass.config_entries.async_update_entry(existing_entry, data=new_entry)
184 self.hass.async_create_task(
185 self.hass.config_entries.async_reload(existing_entry.entry_id)
193 config_entry: ConfigEntry,
194 ) -> TotalConnectOptionsFlowHandler:
195 """Get options flow."""
200 """TotalConnect options flow handler."""
203 self, user_input: dict[str, bool] |
None =
None
204 ) -> ConfigFlowResult:
205 """Manage the options."""
206 if user_input
is not None:
211 data_schema=vol.Schema(
ConfigFlowResult async_step_user(self, dict[str, str]|None user_input=None)
ConfigFlowResult async_step_locations(self, dict[str, str]|None user_input=None)
ConfigFlowResult async_step_reauth_confirm(self, dict[str, str]|None user_input=None)
ConfigFlowResult async_step_reauth(self, Mapping[str, Any] entry_data)
TotalConnectOptionsFlowHandler async_get_options_flow(ConfigEntry config_entry)
ConfigFlowResult async_step_init(self, dict[str, bool]|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)
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)
ConfigEntry config_entry(self)
None config_entry(self, ConfigEntry value)
_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)