Home Assistant Unofficial Reference 2024.12.1
__init__.py
Go to the documentation of this file.
1 """Support for ecobee."""
2 
3 from datetime import timedelta
4 
5 from pyecobee import ECOBEE_API_KEY, ECOBEE_REFRESH_TOKEN, Ecobee, ExpiredTokenError
6 import voluptuous as vol
7 
8 from homeassistant.config_entries import SOURCE_IMPORT, ConfigEntry
9 from homeassistant.const import CONF_API_KEY
10 from homeassistant.core import HomeAssistant
11 from homeassistant.helpers import config_validation as cv
12 from homeassistant.helpers.typing import ConfigType
13 from homeassistant.util import Throttle
14 
15 from .const import (
16  _LOGGER,
17  CONF_REFRESH_TOKEN,
18  DATA_ECOBEE_CONFIG,
19  DATA_HASS_CONFIG,
20  DOMAIN,
21  PLATFORMS,
22 )
23 
24 MIN_TIME_BETWEEN_UPDATES = timedelta(seconds=180)
25 
26 CONFIG_SCHEMA = vol.Schema(
27  {DOMAIN: vol.Schema({vol.Optional(CONF_API_KEY): cv.string})}, extra=vol.ALLOW_EXTRA
28 )
29 
30 
31 async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
32  """Ecobee uses config flow for configuration.
33 
34  But, an "ecobee:" entry in configuration.yaml will trigger an import flow
35  if a config entry doesn't already exist. If ecobee.conf exists, the import
36  flow will attempt to import it and create a config entry, to assist users
37  migrating from the old ecobee integration. Otherwise, the user will have to
38  continue setting up the integration via the config flow.
39  """
40 
41  hass.data[DATA_ECOBEE_CONFIG] = config.get(DOMAIN, {})
42  hass.data[DATA_HASS_CONFIG] = config
43 
44  if not hass.config_entries.async_entries(DOMAIN) and hass.data[DATA_ECOBEE_CONFIG]:
45  # No config entry exists and configuration.yaml config exists, trigger the import flow.
46  hass.async_create_task(
47  hass.config_entries.flow.async_init(
48  DOMAIN, context={"source": SOURCE_IMPORT}
49  )
50  )
51 
52  return True
53 
54 
55 async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
56  """Set up ecobee via a config entry."""
57  api_key = entry.data[CONF_API_KEY]
58  refresh_token = entry.data[CONF_REFRESH_TOKEN]
59 
60  data = EcobeeData(hass, entry, api_key=api_key, refresh_token=refresh_token)
61 
62  if not await data.refresh():
63  return False
64 
65  await data.update()
66 
67  if data.ecobee.thermostats is None:
68  _LOGGER.error("No ecobee devices found to set up")
69  return False
70 
71  hass.data[DOMAIN] = data
72 
73  await hass.config_entries.async_forward_entry_setups(entry, PLATFORMS)
74 
75  return True
76 
77 
78 class EcobeeData:
79  """Handle getting the latest data from ecobee.com so platforms can use it.
80 
81  Also handle refreshing tokens and updating config entry with refreshed tokens.
82  """
83 
84  def __init__(
85  self, hass: HomeAssistant, entry: ConfigEntry, api_key: str, refresh_token: str
86  ) -> None:
87  """Initialize the Ecobee data object."""
88  self._hass_hass = hass
89  self.entryentry = entry
90  self.ecobeeecobee = Ecobee(
91  config={ECOBEE_API_KEY: api_key, ECOBEE_REFRESH_TOKEN: refresh_token}
92  )
93 
94  @Throttle(MIN_TIME_BETWEEN_UPDATES)
95  async def update(self):
96  """Get the latest data from ecobee.com."""
97  try:
98  await self._hass_hass.async_add_executor_job(self.ecobeeecobee.update)
99  _LOGGER.debug("Updating ecobee")
100  except ExpiredTokenError:
101  _LOGGER.debug("Refreshing expired ecobee tokens")
102  await self.refreshrefresh()
103 
104  async def refresh(self) -> bool:
105  """Refresh ecobee tokens and update config entry."""
106  _LOGGER.debug("Refreshing ecobee tokens and updating config entry")
107  if await self._hass_hass.async_add_executor_job(self.ecobeeecobee.refresh_tokens):
108  self._hass_hass.config_entries.async_update_entry(
109  self.entryentry,
110  data={
111  CONF_API_KEY: self.ecobeeecobee.config[ECOBEE_API_KEY],
112  CONF_REFRESH_TOKEN: self.ecobeeecobee.config[ECOBEE_REFRESH_TOKEN],
113  },
114  )
115  return True
116  _LOGGER.error("Error refreshing ecobee tokens")
117  return False
118 
119 
120 async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
121  """Unload the config entry and platforms."""
122  unload_ok = await hass.config_entries.async_unload_platforms(entry, PLATFORMS)
123  if unload_ok:
124  hass.data.pop(DOMAIN)
125  return unload_ok
None __init__(self, HomeAssistant hass, ConfigEntry entry, str api_key, str refresh_token)
Definition: __init__.py:86
bool async_unload_entry(HomeAssistant hass, ConfigEntry entry)
Definition: __init__.py:120
bool async_setup(HomeAssistant hass, ConfigType config)
Definition: __init__.py:31
bool async_setup_entry(HomeAssistant hass, ConfigEntry entry)
Definition: __init__.py:55