Home Assistant Unofficial Reference 2024.12.1
__init__.py
Go to the documentation of this file.
1 """Support for the (unofficial) Tado API."""
2 
3 from datetime import timedelta
4 import logging
5 
6 import requests.exceptions
7 
8 from homeassistant.config_entries import ConfigEntry
9 from homeassistant.const import CONF_PASSWORD, CONF_USERNAME, Platform
10 from homeassistant.core import HomeAssistant, callback
11 from homeassistant.exceptions import ConfigEntryNotReady
12 from homeassistant.helpers import config_validation as cv
13 from homeassistant.helpers.event import async_track_time_interval
14 from homeassistant.helpers.typing import ConfigType
15 
16 from .const import (
17  CONF_FALLBACK,
18  CONST_OVERLAY_MANUAL,
19  CONST_OVERLAY_TADO_DEFAULT,
20  CONST_OVERLAY_TADO_MODE,
21  CONST_OVERLAY_TADO_OPTIONS,
22  DOMAIN,
23 )
24 from .services import setup_services
25 from .tado_connector import TadoConnector
26 
27 _LOGGER = logging.getLogger(__name__)
28 
29 
30 PLATFORMS = [
31  Platform.BINARY_SENSOR,
32  Platform.CLIMATE,
33  Platform.DEVICE_TRACKER,
34  Platform.SENSOR,
35  Platform.WATER_HEATER,
36 ]
37 
38 MIN_TIME_BETWEEN_UPDATES = timedelta(minutes=4)
39 SCAN_INTERVAL = timedelta(minutes=5)
40 SCAN_MOBILE_DEVICE_INTERVAL = timedelta(seconds=30)
41 
42 CONFIG_SCHEMA = cv.config_entry_only_config_schema(DOMAIN)
43 
44 
45 async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
46  """Set up Tado."""
47 
48  setup_services(hass)
49 
50  return True
51 
52 
53 type TadoConfigEntry = ConfigEntry[TadoConnector]
54 
55 
56 async def async_setup_entry(hass: HomeAssistant, entry: TadoConfigEntry) -> bool:
57  """Set up Tado from a config entry."""
58 
60 
61  username = entry.data[CONF_USERNAME]
62  password = entry.data[CONF_PASSWORD]
63  fallback = entry.options.get(CONF_FALLBACK, CONST_OVERLAY_TADO_DEFAULT)
64 
65  tadoconnector = TadoConnector(hass, username, password, fallback)
66 
67  try:
68  await hass.async_add_executor_job(tadoconnector.setup)
69  except KeyError:
70  _LOGGER.error("Failed to login to tado")
71  return False
72  except RuntimeError as exc:
73  _LOGGER.error("Failed to setup tado: %s", exc)
74  return False
75  except requests.exceptions.Timeout as ex:
76  raise ConfigEntryNotReady from ex
77  except requests.exceptions.HTTPError as ex:
78  if ex.response.status_code > 400 and ex.response.status_code < 500:
79  _LOGGER.error("Failed to login to tado: %s", ex)
80  return False
81  raise ConfigEntryNotReady from ex
82 
83  # Do first update
84  await hass.async_add_executor_job(tadoconnector.update)
85 
86  # Poll for updates in the background
87  entry.async_on_unload(
89  hass,
90  lambda now: tadoconnector.update(),
91  SCAN_INTERVAL,
92  )
93  )
94 
95  entry.async_on_unload(
97  hass,
98  lambda now: tadoconnector.update_mobile_devices(),
99  SCAN_MOBILE_DEVICE_INTERVAL,
100  )
101  )
102 
103  entry.async_on_unload(entry.add_update_listener(_async_update_listener))
104 
105  entry.runtime_data = tadoconnector
106 
107  await hass.config_entries.async_forward_entry_setups(entry, PLATFORMS)
108 
109  return True
110 
111 
112 @callback
113 def _async_import_options_from_data_if_missing(hass: HomeAssistant, entry: ConfigEntry):
114  options = dict(entry.options)
115  if CONF_FALLBACK not in options:
116  options[CONF_FALLBACK] = entry.data.get(
117  CONF_FALLBACK, CONST_OVERLAY_TADO_DEFAULT
118  )
119  hass.config_entries.async_update_entry(entry, options=options)
120 
121  if options[CONF_FALLBACK] not in CONST_OVERLAY_TADO_OPTIONS:
122  if options[CONF_FALLBACK]:
123  options[CONF_FALLBACK] = CONST_OVERLAY_TADO_MODE
124  else:
125  options[CONF_FALLBACK] = CONST_OVERLAY_MANUAL
126  hass.config_entries.async_update_entry(entry, options=options)
127 
128 
129 async def _async_update_listener(hass: HomeAssistant, entry: ConfigEntry) -> None:
130  """Handle options update."""
131  await hass.config_entries.async_reload(entry.entry_id)
132 
133 
134 async def async_unload_entry(hass: HomeAssistant, entry: TadoConfigEntry) -> bool:
135  """Unload a config entry."""
136  return await hass.config_entries.async_unload_platforms(entry, PLATFORMS)
bool async_unload_entry(HomeAssistant hass, TadoConfigEntry entry)
Definition: __init__.py:134
None _async_update_listener(HomeAssistant hass, ConfigEntry entry)
Definition: __init__.py:129
def _async_import_options_from_data_if_missing(HomeAssistant hass, ConfigEntry entry)
Definition: __init__.py:113
bool async_setup(HomeAssistant hass, ConfigType config)
Definition: __init__.py:45
bool async_setup_entry(HomeAssistant hass, TadoConfigEntry entry)
Definition: __init__.py:56
CALLBACK_TYPE async_track_time_interval(HomeAssistant hass, Callable[[datetime], Coroutine[Any, Any, None]|None] action, timedelta interval, *str|None name=None, bool|None cancel_on_shutdown=None)
Definition: event.py:1679