Home Assistant Unofficial Reference 2024.12.1
config_flow.py
Go to the documentation of this file.
1 """Config flow to configure ecobee."""
2 
3 from typing import Any
4 
5 from pyecobee import (
6  ECOBEE_API_KEY,
7  ECOBEE_CONFIG_FILENAME,
8  ECOBEE_REFRESH_TOKEN,
9  Ecobee,
10 )
11 import voluptuous as vol
12 
13 from homeassistant.config_entries import ConfigFlow, ConfigFlowResult
14 from homeassistant.const import CONF_API_KEY
15 from homeassistant.exceptions import HomeAssistantError
16 from homeassistant.util.json import load_json_object
17 
18 from .const import _LOGGER, CONF_REFRESH_TOKEN, DATA_ECOBEE_CONFIG, DOMAIN
19 
20 
21 class EcobeeFlowHandler(ConfigFlow, domain=DOMAIN):
22  """Handle an ecobee config flow."""
23 
24  VERSION = 1
25 
26  _ecobee: Ecobee
27 
28  async def async_step_user(
29  self, user_input: dict[str, Any] | None = None
30  ) -> ConfigFlowResult:
31  """Handle a flow initiated by the user."""
32  errors = {}
33  stored_api_key = (
34  self.hass.data[DATA_ECOBEE_CONFIG].get(CONF_API_KEY)
35  if DATA_ECOBEE_CONFIG in self.hass.data
36  else ""
37  )
38 
39  if user_input is not None:
40  # Use the user-supplied API key to attempt to obtain a PIN from ecobee.
41  self._ecobee_ecobee = Ecobee(config={ECOBEE_API_KEY: user_input[CONF_API_KEY]})
42 
43  if await self.hass.async_add_executor_job(self._ecobee_ecobee.request_pin):
44  # We have a PIN; move to the next step of the flow.
45  return await self.async_step_authorizeasync_step_authorize()
46  errors["base"] = "pin_request_failed"
47 
48  return self.async_show_formasync_show_formasync_show_form(
49  step_id="user",
50  data_schema=vol.Schema(
51  {vol.Required(CONF_API_KEY, default=stored_api_key): str}
52  ),
53  errors=errors,
54  )
55 
57  self, user_input: dict[str, Any] | None = None
58  ) -> ConfigFlowResult:
59  """Present the user with the PIN so that the app can be authorized on ecobee.com."""
60  errors = {}
61 
62  if user_input is not None:
63  # Attempt to obtain tokens from ecobee and finish the flow.
64  if await self.hass.async_add_executor_job(self._ecobee_ecobee.request_tokens):
65  # Refresh token obtained; create the config entry.
66  config = {
67  CONF_API_KEY: self._ecobee_ecobee.api_key,
68  CONF_REFRESH_TOKEN: self._ecobee_ecobee.refresh_token,
69  }
70  return self.async_create_entryasync_create_entryasync_create_entry(title=DOMAIN, data=config)
71  errors["base"] = "token_request_failed"
72 
73  return self.async_show_formasync_show_formasync_show_form(
74  step_id="authorize",
75  errors=errors,
76  description_placeholders={"pin": self._ecobee_ecobee.pin},
77  )
78 
79  async def async_step_import(self, import_data: None) -> ConfigFlowResult:
80  """Import ecobee config from configuration.yaml.
81 
82  Triggered by async_setup only if a config entry doesn't already exist.
83  If ecobee.conf exists, we will attempt to validate the credentials
84  and create an entry if valid. Otherwise, we will delegate to the user
85  step so that the user can continue the config flow.
86  """
87  try:
88  legacy_config = await self.hass.async_add_executor_job(
89  load_json_object, self.hass.config.path(ECOBEE_CONFIG_FILENAME)
90  )
91  config = {
92  ECOBEE_API_KEY: legacy_config[ECOBEE_API_KEY],
93  ECOBEE_REFRESH_TOKEN: legacy_config[ECOBEE_REFRESH_TOKEN],
94  }
95  except (HomeAssistantError, KeyError):
96  _LOGGER.debug(
97  "No valid ecobee.conf configuration found for import, delegating to"
98  " user step"
99  )
100  return await self.async_step_userasync_step_userasync_step_user(
101  user_input={
102  CONF_API_KEY: self.hass.data[DATA_ECOBEE_CONFIG].get(CONF_API_KEY)
103  }
104  )
105 
106  ecobee = Ecobee(config=config)
107  if await self.hass.async_add_executor_job(ecobee.refresh_tokens):
108  # Credentials found and validated; create the entry.
109  _LOGGER.debug(
110  "Valid ecobee configuration found for import, creating configuration"
111  " entry"
112  )
113  return self.async_create_entryasync_create_entryasync_create_entry(
114  title=DOMAIN,
115  data={
116  CONF_API_KEY: ecobee.api_key,
117  CONF_REFRESH_TOKEN: ecobee.refresh_token,
118  },
119  )
120  return await self.async_step_userasync_step_userasync_step_user(
121  user_input={
122  CONF_API_KEY: self.hass.data[DATA_ECOBEE_CONFIG].get(CONF_API_KEY)
123  }
124  )
ConfigFlowResult async_step_import(self, None import_data)
Definition: config_flow.py:79
ConfigFlowResult async_step_user(self, dict[str, Any]|None user_input=None)
Definition: config_flow.py:30
ConfigFlowResult async_step_authorize(self, dict[str, Any]|None user_input=None)
Definition: config_flow.py:58
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)
web.Response get(self, web.Request request, str config_key)
Definition: view.py:88