Home Assistant Unofficial Reference 2024.12.1
__init__.py
Go to the documentation of this file.
1 """Support for EQ3 devices."""
2 
3 import asyncio
4 import logging
5 from typing import TYPE_CHECKING
6 
7 from eq3btsmart import Thermostat
8 from eq3btsmart.exceptions import Eq3Exception
9 from eq3btsmart.thermostat_config import ThermostatConfig
10 
11 from homeassistant.components import bluetooth
12 from homeassistant.config_entries import ConfigEntry
13 from homeassistant.const import Platform
14 from homeassistant.core import HomeAssistant
15 from homeassistant.exceptions import ConfigEntryNotReady
16 from homeassistant.helpers.dispatcher import async_dispatcher_send
17 
18 from .const import SIGNAL_THERMOSTAT_CONNECTED, SIGNAL_THERMOSTAT_DISCONNECTED
19 from .models import Eq3Config, Eq3ConfigEntryData
20 
21 PLATFORMS = [
22  Platform.BINARY_SENSOR,
23  Platform.CLIMATE,
24  Platform.NUMBER,
25  Platform.SENSOR,
26  Platform.SWITCH,
27 ]
28 
29 _LOGGER = logging.getLogger(__name__)
30 
31 
32 type Eq3ConfigEntry = ConfigEntry[Eq3ConfigEntryData]
33 
34 
35 async def async_setup_entry(hass: HomeAssistant, entry: Eq3ConfigEntry) -> bool:
36  """Handle config entry setup."""
37 
38  mac_address: str | None = entry.unique_id
39 
40  if TYPE_CHECKING:
41  assert mac_address is not None
42 
43  eq3_config = Eq3Config(
44  mac_address=mac_address,
45  )
46 
47  device = bluetooth.async_ble_device_from_address(
48  hass, mac_address.upper(), connectable=True
49  )
50 
51  if device is None:
52  raise ConfigEntryNotReady(
53  f"[{eq3_config.mac_address}] Device could not be found"
54  )
55 
56  thermostat = Thermostat(
57  thermostat_config=ThermostatConfig(
58  mac_address=mac_address,
59  ),
60  ble_device=device,
61  )
62 
63  entry.runtime_data = Eq3ConfigEntryData(
64  eq3_config=eq3_config, thermostat=thermostat
65  )
66  entry.async_on_unload(entry.add_update_listener(update_listener))
67  await hass.config_entries.async_forward_entry_setups(entry, PLATFORMS)
68  entry.async_create_background_task(
69  hass, _async_run_thermostat(hass, entry), entry.entry_id
70  )
71 
72  return True
73 
74 
75 async def async_unload_entry(hass: HomeAssistant, entry: Eq3ConfigEntry) -> bool:
76  """Handle config entry unload."""
77 
78  if unload_ok := await hass.config_entries.async_unload_platforms(entry, PLATFORMS):
79  await entry.runtime_data.thermostat.async_disconnect()
80 
81  return unload_ok
82 
83 
84 async def update_listener(hass: HomeAssistant, entry: Eq3ConfigEntry) -> None:
85  """Handle config entry update."""
86 
87  await hass.config_entries.async_reload(entry.entry_id)
88 
89 
90 async def _async_run_thermostat(hass: HomeAssistant, entry: Eq3ConfigEntry) -> None:
91  """Run the thermostat."""
92 
93  thermostat = entry.runtime_data.thermostat
94  mac_address = entry.runtime_data.eq3_config.mac_address
95  scan_interval = entry.runtime_data.eq3_config.scan_interval
96 
97  await _async_reconnect_thermostat(hass, entry)
98 
99  while True:
100  try:
101  await thermostat.async_get_status()
102  except Eq3Exception as e:
103  if not thermostat.is_connected:
104  _LOGGER.error(
105  "[%s] eQ-3 device disconnected",
106  mac_address,
107  )
109  hass,
110  f"{SIGNAL_THERMOSTAT_DISCONNECTED}_{mac_address}",
111  )
112  await _async_reconnect_thermostat(hass, entry)
113  continue
114 
115  _LOGGER.error(
116  "[%s] Error updating eQ-3 device: %s",
117  mac_address,
118  e,
119  )
120 
121  await asyncio.sleep(scan_interval)
122 
123 
125  hass: HomeAssistant, entry: Eq3ConfigEntry
126 ) -> None:
127  """Reconnect the thermostat."""
128 
129  thermostat = entry.runtime_data.thermostat
130  mac_address = entry.runtime_data.eq3_config.mac_address
131  scan_interval = entry.runtime_data.eq3_config.scan_interval
132 
133  while True:
134  try:
135  await thermostat.async_connect()
136  except Eq3Exception:
137  await asyncio.sleep(scan_interval)
138  continue
139 
140  _LOGGER.debug(
141  "[%s] eQ-3 device connected",
142  mac_address,
143  )
144 
146  hass,
147  f"{SIGNAL_THERMOSTAT_CONNECTED}_{mac_address}",
148  )
149 
150  return
None _async_reconnect_thermostat(HomeAssistant hass, Eq3ConfigEntry entry)
Definition: __init__.py:126
None _async_run_thermostat(HomeAssistant hass, Eq3ConfigEntry entry)
Definition: __init__.py:90
bool async_setup_entry(HomeAssistant hass, Eq3ConfigEntry entry)
Definition: __init__.py:35
bool async_unload_entry(HomeAssistant hass, Eq3ConfigEntry entry)
Definition: __init__.py:75
None update_listener(HomeAssistant hass, Eq3ConfigEntry entry)
Definition: __init__.py:84
None async_dispatcher_send(HomeAssistant hass, str signal, *Any args)
Definition: dispatcher.py:193