Home Assistant Unofficial Reference 2024.12.1
config_flow.py
Go to the documentation of this file.
1 """Config flow to configure the Obihai integration."""
2 
3 from __future__ import annotations
4 
5 from socket import gaierror, gethostbyname
6 from typing import Any
7 
8 from pyobihai import PyObihai
9 import voluptuous as vol
10 
11 from homeassistant.components import dhcp
12 from homeassistant.config_entries import ConfigFlow, ConfigFlowResult
13 from homeassistant.const import CONF_HOST, CONF_PASSWORD, CONF_USERNAME
14 from homeassistant.core import HomeAssistant
15 from homeassistant.helpers.device_registry import format_mac
16 
17 from .connectivity import validate_auth
18 from .const import DEFAULT_PASSWORD, DEFAULT_USERNAME, DOMAIN
19 
20 DATA_SCHEMA = vol.Schema(
21  {
22  vol.Required(CONF_HOST): str,
23  vol.Required(
24  CONF_USERNAME,
25  default=DEFAULT_USERNAME,
26  ): str,
27  vol.Required(
28  CONF_PASSWORD,
29  default=DEFAULT_PASSWORD,
30  ): str,
31  }
32 )
33 
34 
36  hass: HomeAssistant, user_input: dict[str, Any]
37 ) -> PyObihai | None:
38  """Manage Obihai options."""
39 
40  if user_input[CONF_USERNAME] and user_input[CONF_PASSWORD]:
41  return await hass.async_add_executor_job(
42  validate_auth,
43  user_input[CONF_HOST],
44  user_input[CONF_USERNAME],
45  user_input[CONF_PASSWORD],
46  )
47 
48  # Don't bother authenticating if we've already determined the credentials are invalid
49  return None
50 
51 
52 class ObihaiFlowHandler(ConfigFlow, domain=DOMAIN):
53  """Config flow for Obihai."""
54 
55  VERSION = 2
56  discovery_schema: vol.Schema | None = None
57  _dhcp_discovery_info: dhcp.DhcpServiceInfo | None = None
58 
59  async def async_step_user(
60  self, user_input: dict[str, Any] | None = None
61  ) -> ConfigFlowResult:
62  """Handle a flow initialized by the user."""
63 
64  errors: dict[str, str] = {}
65  ip: str | None = None
66 
67  if user_input is not None:
68  try:
69  ip = await self.hass.async_add_executor_job(
70  gethostbyname, user_input[CONF_HOST]
71  )
72  except gaierror:
73  errors["base"] = "cannot_connect"
74 
75  if ip:
76  if pyobihai := await async_validate_creds(self.hass, user_input):
77  device_mac = await self.hass.async_add_executor_job(
78  pyobihai.get_device_mac
79  )
80  await self.async_set_unique_idasync_set_unique_id(format_mac(device_mac))
81  self._abort_if_unique_id_configured_abort_if_unique_id_configured()
82 
83  return self.async_create_entryasync_create_entryasync_create_entry(
84  title=user_input[CONF_HOST],
85  data=user_input,
86  )
87  errors["base"] = "invalid_auth"
88 
89  data_schema = self.discovery_schemadiscovery_schema or DATA_SCHEMA
90  return self.async_show_formasync_show_formasync_show_form(
91  step_id="user",
92  errors=errors,
93  data_schema=self.add_suggested_values_to_schemaadd_suggested_values_to_schema(data_schema, user_input),
94  )
95 
96  async def async_step_dhcp(
97  self, discovery_info: dhcp.DhcpServiceInfo
98  ) -> ConfigFlowResult:
99  """Prepare configuration for a DHCP discovered Obihai."""
100 
101  self._dhcp_discovery_info_dhcp_discovery_info = discovery_info
102  return await self.async_step_dhcp_confirm()
103 
104  async def async_step_dhcp_confirm(
105  self, user_input: dict[str, Any] | None = None
106  ) -> ConfigFlowResult:
107  """Attempt to confirm."""
108  assert self._dhcp_discovery_info_dhcp_discovery_info
109  await self.async_set_unique_idasync_set_unique_id(format_mac(self._dhcp_discovery_info_dhcp_discovery_info.macaddress))
110  self._abort_if_unique_id_configured_abort_if_unique_id_configured()
111 
112  if user_input is None:
113  credentials = {
114  CONF_HOST: self._dhcp_discovery_info_dhcp_discovery_info.ip,
115  CONF_PASSWORD: DEFAULT_PASSWORD,
116  CONF_USERNAME: DEFAULT_USERNAME,
117  }
118  if await async_validate_creds(self.hass, credentials):
119  self.discovery_schemadiscovery_schema = self.add_suggested_values_to_schemaadd_suggested_values_to_schema(
120  DATA_SCHEMA, credentials
121  )
122  else:
123  self.discovery_schemadiscovery_schema = self.add_suggested_values_to_schemaadd_suggested_values_to_schema(
124  DATA_SCHEMA,
125  {
126  CONF_HOST: self._dhcp_discovery_info_dhcp_discovery_info.ip,
127  CONF_USERNAME: "",
128  CONF_PASSWORD: "",
129  },
130  )
131 
132  # Show the confirmation dialog
133  return self.async_show_formasync_show_formasync_show_form(
134  step_id="dhcp_confirm",
135  data_schema=self.discovery_schemadiscovery_schema,
136  description_placeholders={CONF_HOST: self._dhcp_discovery_info_dhcp_discovery_info.ip},
137  )
138 
139  return await self.async_step_userasync_step_userasync_step_user(user_input=user_input)
ConfigFlowResult async_step_user(self, dict[str, Any]|None user_input=None)
Definition: config_flow.py:61
None _abort_if_unique_id_configured(self, dict[str, Any]|None updates=None, bool reload_on_update=True, *str error="already_configured")
ConfigFlowResult async_step_dhcp(self, DhcpServiceInfo discovery_info)
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_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)
vol.Schema add_suggested_values_to_schema(self, vol.Schema data_schema, Mapping[str, Any]|None suggested_values)
_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)
PyObihai|None async_validate_creds(HomeAssistant hass, dict[str, Any] user_input)
Definition: config_flow.py:37