Home Assistant Unofficial Reference 2024.12.1
config_flow.py
Go to the documentation of this file.
1 """Config flow for the Daikin platform."""
2 
3 from __future__ import annotations
4 
5 import asyncio
6 import logging
7 from typing import Any
8 from uuid import uuid4
9 
10 from aiohttp import ClientError, web_exceptions
11 from pydaikin.daikin_base import Appliance
12 from pydaikin.discovery import Discovery
13 from pydaikin.exceptions import DaikinException
14 from pydaikin.factory import DaikinFactory
15 import voluptuous as vol
16 
17 from homeassistant.components import zeroconf
18 from homeassistant.config_entries import ConfigFlow, ConfigFlowResult
19 from homeassistant.const import CONF_API_KEY, CONF_HOST, CONF_PASSWORD, CONF_UUID
20 from homeassistant.helpers.aiohttp_client import async_get_clientsession
21 
22 from .const import DOMAIN, KEY_MAC, TIMEOUT
23 
24 _LOGGER = logging.getLogger(__name__)
25 
26 
27 class FlowHandler(ConfigFlow, domain=DOMAIN):
28  """Handle a config flow."""
29 
30  VERSION = 1
31 
32  def __init__(self) -> None:
33  """Initialize the Daikin config flow."""
34  self.hosthost: str | None = None
35 
36  @property
37  def schema(self) -> vol.Schema:
38  """Return current schema."""
39  return vol.Schema(
40  {
41  vol.Required(CONF_HOST, default=self.hosthost): str,
42  vol.Optional(CONF_API_KEY): str,
43  vol.Optional(CONF_PASSWORD): str,
44  }
45  )
46 
47  async def _create_entry(
48  self,
49  host: str,
50  mac: str,
51  key: str | None = None,
52  uuid: str | None = None,
53  password: str | None = None,
54  ) -> ConfigFlowResult:
55  """Register new entry."""
56  if not self.unique_idunique_id:
57  await self.async_set_unique_idasync_set_unique_id(mac)
58  self._abort_if_unique_id_configured_abort_if_unique_id_configured()
59 
60  return self.async_create_entryasync_create_entryasync_create_entry(
61  title=host,
62  data={
63  CONF_HOST: host,
64  KEY_MAC: mac,
65  CONF_API_KEY: key,
66  CONF_UUID: uuid,
67  CONF_PASSWORD: password,
68  },
69  )
70 
71  async def _create_device(
72  self, host: str, key: str | None = None, password: str | None = None
73  ) -> ConfigFlowResult:
74  """Create device."""
75  # BRP07Cxx devices needs uuid together with key
76  if key:
77  uuid = str(uuid4())
78  else:
79  uuid = None
80  key = None
81 
82  if not password:
83  password = None
84 
85  try:
86  async with asyncio.timeout(TIMEOUT):
87  device: Appliance = await DaikinFactory(
88  host,
89  async_get_clientsession(self.hass),
90  key=key,
91  uuid=uuid,
92  password=password,
93  )
94  except (TimeoutError, ClientError):
95  self.hosthost = None
96  return self.async_show_formasync_show_formasync_show_form(
97  step_id="user",
98  data_schema=self.schemaschema,
99  errors={"base": "cannot_connect"},
100  )
101  except web_exceptions.HTTPForbidden:
102  return self.async_show_formasync_show_formasync_show_form(
103  step_id="user",
104  data_schema=self.schemaschema,
105  errors={"base": "invalid_auth"},
106  )
107  except DaikinException as daikin_exp:
108  _LOGGER.error(daikin_exp)
109  return self.async_show_formasync_show_formasync_show_form(
110  step_id="user",
111  data_schema=self.schemaschema,
112  errors={"base": "unknown"},
113  )
114  except Exception:
115  _LOGGER.exception("Unexpected error creating device")
116  return self.async_show_formasync_show_formasync_show_form(
117  step_id="user",
118  data_schema=self.schemaschema,
119  errors={"base": "unknown"},
120  )
121 
122  mac = device.mac
123  return await self._create_entry_create_entry(host, mac, key, uuid, password)
124 
125  async def async_step_user(
126  self, user_input: dict[str, Any] | None = None
127  ) -> ConfigFlowResult:
128  """User initiated config flow."""
129  if user_input is None:
130  return self.async_show_formasync_show_formasync_show_form(step_id="user", data_schema=self.schemaschema)
131  if user_input.get(CONF_API_KEY) and user_input.get(CONF_PASSWORD):
132  self.hosthost = user_input[CONF_HOST]
133  return self.async_show_formasync_show_formasync_show_form(
134  step_id="user",
135  data_schema=self.schemaschema,
136  errors={"base": "api_password"},
137  )
138  return await self._create_device_create_device(
139  user_input[CONF_HOST],
140  user_input.get(CONF_API_KEY),
141  user_input.get(CONF_PASSWORD),
142  )
143 
145  self, discovery_info: zeroconf.ZeroconfServiceInfo
146  ) -> ConfigFlowResult:
147  """Prepare configuration for a discovered Daikin device."""
148  _LOGGER.debug("Zeroconf user_input: %s", discovery_info)
149  devices = Discovery().poll(ip=discovery_info.host)
150  if not devices:
151  _LOGGER.debug(
152  (
153  "Could not find MAC-address for %s, make sure the required UDP"
154  " ports are open (see integration documentation)"
155  ),
156  discovery_info.host,
157  )
158  return self.async_abortasync_abortasync_abort(reason="cannot_connect")
159  await self.async_set_unique_idasync_set_unique_id(next(iter(devices))[KEY_MAC])
160  self._abort_if_unique_id_configured_abort_if_unique_id_configured()
161  self.hosthost = discovery_info.host
162  return await self.async_step_userasync_step_userasync_step_user()
ConfigFlowResult async_step_user(self, dict[str, Any]|None user_input=None)
Definition: config_flow.py:127
ConfigFlowResult async_step_zeroconf(self, zeroconf.ZeroconfServiceInfo discovery_info)
Definition: config_flow.py:146
ConfigFlowResult _create_device(self, str host, str|None key=None, str|None password=None)
Definition: config_flow.py:73
ConfigFlowResult _create_entry(self, str host, str mac, str|None key=None, str|None uuid=None, str|None password=None)
Definition: config_flow.py:54
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)
str
_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)
aiohttp.ClientSession async_get_clientsession(HomeAssistant hass, bool verify_ssl=True, socket.AddressFamily family=socket.AF_UNSPEC, ssl_util.SSLCipherList ssl_cipher=ssl_util.SSLCipherList.PYTHON_DEFAULT)