1 """Config flow to configure Xiaomi Aqara."""
4 from socket
import gaierror
7 import voluptuous
as vol
8 from xiaomi_gateway
import MULTICAST_PORT, XiaomiGateway, XiaomiGatewayDiscovery
20 DEFAULT_DISCOVERY_RETRY,
26 _LOGGER = logging.getLogger(__name__)
28 DEFAULT_GATEWAY_NAME =
"Xiaomi Aqara Gateway"
29 DEFAULT_INTERFACE =
"any"
32 GATEWAY_CONFIG = vol.Schema(
33 {vol.Optional(CONF_INTERFACE, default=DEFAULT_INTERFACE): str}
36 vol.Optional(CONF_HOST): str,
37 vol.Optional(CONF_MAC): str,
39 GATEWAY_CONFIG_HOST = GATEWAY_CONFIG.extend(CONFIG_HOST)
40 GATEWAY_SETTINGS = vol.Schema(
42 vol.Optional(CONF_KEY): vol.All(str, vol.Length(min=16, max=16)),
43 vol.Optional(CONF_NAME, default=DEFAULT_GATEWAY_NAME): str,
49 """Handle a Xiaomi Aqara config flow."""
53 selected_gateway: XiaomiGateway
54 gateways: dict[str, XiaomiGateway]
58 self.
hosthost: str |
None =
None
60 self.
sidsid: str |
None =
None
64 """Show the form belonging to the user step."""
65 schema = GATEWAY_CONFIG
66 if (self.
hosthost
is None and self.
sidsid
is None)
or errors:
67 schema = GATEWAY_CONFIG_HOST
72 self, user_input: dict[str, Any] |
None =
None
73 ) -> ConfigFlowResult:
74 """Handle a flow initialized by the user."""
75 errors: dict[str, str] = {}
76 if user_input
is None:
79 self.
interfaceinterface = user_input[CONF_INTERFACE]
82 if self.
hosthost
is None:
83 self.
hosthost = user_input.get(CONF_HOST)
84 if self.
sidsid
is None:
86 if (mac_address := user_input.get(CONF_MAC))
is not None:
90 if self.
hosthost
is not None and self.
sidsid
is not None:
97 DEFAULT_DISCOVERY_RETRY,
104 errors[CONF_HOST] =
"invalid_host"
106 errors[CONF_MAC] =
"invalid_mac"
113 xiaomi = XiaomiGatewayDiscovery(self.
interfaceinterface)
115 await self.hass.async_add_executor_job(xiaomi.discover_gateways)
117 errors[CONF_INTERFACE] =
"invalid_interface"
129 errors[
"base"] =
"discovery_error"
133 self, user_input: dict[str, str] |
None =
None
134 ) -> ConfigFlowResult:
135 """Handle multiple aqara gateways found."""
136 errors: dict[str, str] = {}
137 if user_input
is not None:
138 ip_adress = user_input[
"select_ip"]
143 select_schema = vol.Schema(
145 vol.Required(
"select_ip"): vol.In(
146 [gateway.ip_adress
for gateway
in self.
gatewaysgateways.values()]
152 step_id=
"select", data_schema=select_schema, errors=errors
156 self, discovery_info: zeroconf.ZeroconfServiceInfo
157 ) -> ConfigFlowResult:
158 """Handle zeroconf discovery."""
159 name = discovery_info.name
160 self.
hosthost = discovery_info.host
161 mac_address = discovery_info.properties.get(
"mac")
163 if not name
or not self.
hosthost
or not mac_address:
167 if not (name.startswith((ZEROCONF_GATEWAY, ZEROCONF_ACPARTNER))):
170 "Xiaomi device '%s' discovered with host %s, not identified as"
171 " xiaomi aqara gateway"
182 self.
sidsid = mac_address.replace(
":",
"")
184 unique_id = mac_address
187 {CONF_HOST: self.
hosthost, CONF_MAC: mac_address}
190 self.context.
update({
"title_placeholders": {
"name": self.
hosthost}})
195 self, user_input: dict[str, str] |
None =
None
196 ) -> ConfigFlowResult:
197 """Specify settings and connect aqara gateway."""
199 if user_input
is not None:
201 name = user_input[CONF_NAME]
202 key = user_input.get(CONF_KEY)
219 unique_id = mac_address
226 CONF_HOST: ip_adress,
228 CONF_MAC: mac_address,
230 CONF_PROTOCOL: protocol,
232 CONF_SID: self.
sidsid,
236 errors[CONF_KEY] =
"invalid_key"
239 step_id=
"settings", data_schema=GATEWAY_SETTINGS, errors=errors
ConfigFlowResult async_step_select(self, dict[str, str]|None user_input=None)
ConfigFlowResult async_step_settings(self, dict[str, str]|None user_input=None)
ConfigFlowResult async_step_zeroconf(self, zeroconf.ZeroconfServiceInfo discovery_info)
def async_show_form_step_user(self, errors)
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)
ConfigFlowResult async_step_user(self, dict[str, Any]|None user_input=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)
IssData update(pyiss.ISS iss)