1 """Config flow for sia integration."""
3 from __future__
import annotations
5 from collections.abc
import Mapping
6 from copy
import deepcopy
10 from pysiaalarm
import (
11 InvalidAccountFormatError,
12 InvalidAccountLengthError,
13 InvalidKeyFormatError,
14 InvalidKeyLengthError,
17 import voluptuous
as vol
31 CONF_ADDITIONAL_ACCOUNTS,
33 CONF_IGNORE_TIMESTAMPS,
39 from .hub
import SIAHub
41 _LOGGER = logging.getLogger(__name__)
43 HUB_SCHEMA = vol.Schema(
45 vol.Required(CONF_PORT): int,
46 vol.Optional(CONF_PROTOCOL, default=
"TCP"): vol.In([
"TCP",
"UDP"]),
47 vol.Required(CONF_ACCOUNT): str,
48 vol.Optional(CONF_ENCRYPTION_KEY): str,
49 vol.Required(CONF_PING_INTERVAL, default=1): int,
50 vol.Required(CONF_ZONES, default=1): int,
51 vol.Optional(CONF_ADDITIONAL_ACCOUNTS, default=
False): bool,
55 ACCOUNT_SCHEMA = vol.Schema(
57 vol.Required(CONF_ACCOUNT): str,
58 vol.Optional(CONF_ENCRYPTION_KEY): str,
59 vol.Required(CONF_PING_INTERVAL, default=1): int,
60 vol.Required(CONF_ZONES, default=1): int,
61 vol.Optional(CONF_ADDITIONAL_ACCOUNTS, default=
False): bool,
65 DEFAULT_OPTIONS = {CONF_IGNORE_TIMESTAMPS:
False, CONF_ZONES:
None}
69 """Validate the input by the user."""
71 SIAAccount.validate_account(data[CONF_ACCOUNT], data.get(CONF_ENCRYPTION_KEY))
72 except InvalidKeyFormatError:
73 return {
"base":
"invalid_key_format"}
74 except InvalidKeyLengthError:
75 return {
"base":
"invalid_key_length"}
76 except InvalidAccountFormatError:
77 return {
"base":
"invalid_account_format"}
78 except InvalidAccountLengthError:
79 return {
"base":
"invalid_account_length"}
81 _LOGGER.exception(
"Unexpected exception from SIAAccount")
82 return {
"base":
"unknown"}
83 if not 1 <= data[CONF_PING_INTERVAL] <= 1440:
84 return {
"base":
"invalid_ping"}
89 """Validate the zones field."""
90 if data[CONF_ZONES] == 0:
91 return {
"base":
"invalid_zones"}
96 """Handle a config flow for sia."""
103 config_entry: ConfigEntry,
104 ) -> SIAOptionsFlowHandler:
105 """Get the options flow for this handler."""
109 """Initialize the config flow."""
110 self.
_data_data: dict[str, Any] = {}
111 self._options: Mapping[str, Any] = {CONF_ACCOUNTS: {}}
114 self, user_input: dict[str, Any] |
None =
None
115 ) -> ConfigFlowResult:
116 """Handle the initial user step."""
117 errors: dict[str, str] |
None =
None
118 if user_input
is not None:
120 if user_input
is None or errors
is not None:
122 step_id=
"user", data_schema=HUB_SCHEMA, errors=errors
127 self, user_input: dict[str, Any] |
None =
None
128 ) -> ConfigFlowResult:
129 """Handle the additional accounts steps."""
130 errors: dict[str, str] |
None =
None
131 if user_input
is not None:
133 if user_input
is None or errors
is not None:
135 step_id=
"add_account", data_schema=ACCOUNT_SCHEMA, errors=errors
140 self, user_input: dict[str, Any]
141 ) -> ConfigFlowResult:
142 """Handle the user_input, check if configured and route to the right next step or create entry."""
147 if user_input[CONF_ADDITIONAL_ACCOUNTS]:
150 title=TITLE.format(self.
_data_data[CONF_PORT]),
151 data=self.
_data_data,
152 options=self._options,
156 """Parse the user_input and store in data and options attributes.
158 If there is a port in the input or no data, assume it is fully new and overwrite.
159 Add the default options and overwrite the zones in options.
161 if not self.
_data_data
or user_input.get(CONF_PORT):
163 CONF_PORT: user_input[CONF_PORT],
164 CONF_PROTOCOL: user_input[CONF_PROTOCOL],
167 account = user_input[CONF_ACCOUNT]
168 self.
_data_data[CONF_ACCOUNTS].append(
170 CONF_ACCOUNT: account,
171 CONF_ENCRYPTION_KEY: user_input.get(CONF_ENCRYPTION_KEY),
172 CONF_PING_INTERVAL: user_input[CONF_PING_INTERVAL],
175 self._options[CONF_ACCOUNTS].setdefault(account, deepcopy(DEFAULT_OPTIONS))
176 self._options[CONF_ACCOUNTS][account][CONF_ZONES] = user_input[CONF_ZONES]
180 """Handle SIA options."""
182 def __init__(self, config_entry: ConfigEntry) ->
None:
183 """Initialize SIA options flow."""
185 self.
hubhub: SIAHub |
None =
None
189 self, user_input: dict[str, Any] |
None =
None
190 ) -> ConfigFlowResult:
191 """Manage the SIA options."""
193 assert self.
hubhub
is not None
194 assert self.
hubhub.sia_accounts
is not None
199 self, user_input: dict[str, Any] |
None =
None
200 ) -> ConfigFlowResult:
201 """Create the options step for a account."""
202 errors: dict[str, str] |
None =
None
203 if user_input
is not None:
205 if user_input
is None or errors
is not None:
209 description_placeholders={
"account": account},
210 data_schema=vol.Schema(
214 default=self.
optionsoptions[CONF_ACCOUNTS][account][CONF_ZONES],
217 CONF_IGNORE_TIMESTAMPS,
218 default=self.
optionsoptions[CONF_ACCOUNTS][account][
219 CONF_IGNORE_TIMESTAMPS
229 self.
optionsoptions[CONF_ACCOUNTS][account][CONF_IGNORE_TIMESTAMPS] = user_input[
230 CONF_IGNORE_TIMESTAMPS
232 self.
optionsoptions[CONF_ACCOUNTS][account][CONF_ZONES] = user_input[CONF_ZONES]
239 """Return if this is the last step."""
ConfigFlowResult async_handle_data_and_route(self, dict[str, Any] user_input)
ConfigFlowResult async_step_add_account(self, dict[str, Any]|None user_input=None)
SIAOptionsFlowHandler async_get_options_flow(ConfigEntry config_entry)
None _update_data(self, dict[str, Any] user_input)
ConfigFlowResult async_step_user(self, dict[str, Any]|None user_input=None)
ConfigFlowResult async_step_init(self, dict[str, Any]|None user_input=None)
ConfigFlowResult async_step_options(self, dict[str, Any]|None user_input=None)
None __init__(self, ConfigEntry config_entry)
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)
None _async_abort_entries_match(self, dict[str, Any]|None match_dict=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)
dict[str, str]|None validate_input(dict[str, Any] data)
dict[str, str]|None validate_zones(dict[str, Any] data)