Home Assistant Unofficial Reference 2024.12.1
config_flow.py
Go to the documentation of this file.
1 """Config flow for SiteSage Emonitor integration."""
2 
3 import logging
4 from typing import Any
5 
6 from aioemonitor import Emonitor
7 import aiohttp
8 import voluptuous as vol
9 
10 from homeassistant.components import dhcp
11 from homeassistant.config_entries import ConfigFlow, ConfigFlowResult
12 from homeassistant.const import CONF_HOST, CONF_NAME
13 from homeassistant.core import HomeAssistant
14 from homeassistant.helpers import aiohttp_client
15 from homeassistant.helpers.device_registry import format_mac
16 
17 from . import name_short_mac
18 from .const import DOMAIN
19 
20 _LOGGER = logging.getLogger(__name__)
21 
22 
23 async def fetch_mac_and_title(hass: HomeAssistant, host):
24  """Validate the user input allows us to connect."""
25  session = aiohttp_client.async_get_clientsession(hass)
26  emonitor = Emonitor(host, session)
27  status = await emonitor.async_get_status()
28  mac_address = status.network.mac_address
29  return {"title": name_short_mac(mac_address[-6:]), "mac_address": mac_address}
30 
31 
32 class EmonitorConfigFlow(ConfigFlow, domain=DOMAIN):
33  """Handle a config flow for SiteSage Emonitor."""
34 
35  VERSION = 1
36 
37  discovered_info: dict[str, str]
38 
39  def __init__(self) -> None:
40  """Initialize Emonitor ConfigFlow."""
41  self.discovered_ipdiscovered_ip: str | None = None
42 
43  async def async_step_user(
44  self, user_input: dict[str, Any] | None = None
45  ) -> ConfigFlowResult:
46  """Handle the initial step."""
47  errors = {}
48  if user_input is not None:
49  try:
50  info = await fetch_mac_and_title(self.hass, user_input[CONF_HOST])
51  except aiohttp.ClientError:
52  errors[CONF_HOST] = "cannot_connect"
53  except Exception:
54  _LOGGER.exception("Unexpected exception")
55  errors["base"] = "unknown"
56  else:
57  await self.async_set_unique_idasync_set_unique_id(
58  format_mac(info["mac_address"]), raise_on_progress=False
59  )
60  self._abort_if_unique_id_configured_abort_if_unique_id_configured()
61  return self.async_create_entryasync_create_entryasync_create_entry(title=info["title"], data=user_input)
62 
63  return self.async_show_formasync_show_formasync_show_form(
64  step_id="user",
65  data_schema=vol.Schema(
66  {vol.Required("host", default=self.discovered_ipdiscovered_ip): str}
67  ),
68  errors=errors,
69  )
70 
71  async def async_step_dhcp(
72  self, discovery_info: dhcp.DhcpServiceInfo
73  ) -> ConfigFlowResult:
74  """Handle dhcp discovery."""
75  self.discovered_ipdiscovered_ip = discovery_info.ip
76  await self.async_set_unique_idasync_set_unique_id(format_mac(discovery_info.macaddress))
77  self._abort_if_unique_id_configured_abort_if_unique_id_configured(updates={CONF_HOST: self.discovered_ipdiscovered_ip})
78  name = name_short_mac(short_mac(discovery_info.macaddress))
79  self.context["title_placeholders"] = {"name": name}
80  try:
81  self.discovered_infodiscovered_info = await fetch_mac_and_title(
82  self.hass, self.discovered_ipdiscovered_ip
83  )
84  except Exception as ex: # noqa: BLE001
85  _LOGGER.debug(
86  "Unable to fetch status, falling back to manual entry", exc_info=ex
87  )
88  return await self.async_step_userasync_step_userasync_step_user()
89  return await self.async_step_confirmasync_step_confirm()
90 
91  async def async_step_confirm(
92  self, user_input: dict[str, Any] | None = None
93  ) -> ConfigFlowResult:
94  """Attempt to confirm."""
95  assert self.discovered_ipdiscovered_ip is not None
96  if user_input is not None:
97  return self.async_create_entryasync_create_entryasync_create_entry(
98  title=self.discovered_infodiscovered_info["title"],
99  data={CONF_HOST: self.discovered_ipdiscovered_ip},
100  )
101 
102  self._set_confirm_only_set_confirm_only()
103  self.context["title_placeholders"] = {"name": self.discovered_infodiscovered_info["title"]}
104  return self.async_show_formasync_show_formasync_show_form(
105  step_id="confirm",
106  description_placeholders={
107  CONF_HOST: self.discovered_ipdiscovered_ip,
108  CONF_NAME: self.discovered_infodiscovered_info["title"],
109  },
110  )
111 
112 
113 def short_mac(mac):
114  """Short version of the mac."""
115  return "".join(mac.split(":")[3:]).upper()
ConfigFlowResult async_step_confirm(self, dict[str, Any]|None user_input=None)
Definition: config_flow.py:93
ConfigFlowResult async_step_user(self, dict[str, Any]|None user_input=None)
Definition: config_flow.py:45
ConfigFlowResult async_step_dhcp(self, dhcp.DhcpServiceInfo discovery_info)
Definition: config_flow.py:73
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_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)
def fetch_mac_and_title(HomeAssistant hass, host)
Definition: config_flow.py:23