1 """Component to embed Aqualink devices."""
3 from __future__
import annotations
5 from collections.abc
import Awaitable, Callable, Coroutine
6 from datetime
import datetime
7 from functools
import wraps
9 from typing
import Any, Concatenate
12 from iaqualink.client
import AqualinkClient
13 from iaqualink.device
import (
20 from iaqualink.exception
import AqualinkServiceException
35 from .const
import DOMAIN, UPDATE_INTERVAL
36 from .entity
import AqualinkEntity
38 _LOGGER = logging.getLogger(__name__)
40 ATTR_CONFIG =
"config"
44 Platform.BINARY_SENSOR,
53 """Set up Aqualink from a config entry."""
54 username = entry.data[CONF_USERNAME]
55 password = entry.data[CONF_PASSWORD]
57 hass.data.setdefault(DOMAIN, {})
60 binary_sensors = hass.data[DOMAIN][BINARY_SENSOR_DOMAIN] = []
61 climates = hass.data[DOMAIN][CLIMATE_DOMAIN] = []
62 lights = hass.data[DOMAIN][LIGHT_DOMAIN] = []
63 sensors = hass.data[DOMAIN][SENSOR_DOMAIN] = []
64 switches = hass.data[DOMAIN][SWITCH_DOMAIN] = []
66 aqualink = AqualinkClient(username, password, httpx_client=
get_async_client(hass))
68 await aqualink.login()
69 except AqualinkServiceException
as login_exception:
70 _LOGGER.error(
"Failed to login: %s", login_exception)
71 await aqualink.close()
73 except (TimeoutError, httpx.HTTPError)
as aio_exception:
74 await aqualink.close()
76 f
"Error while attempting login: {aio_exception}"
80 systems = await aqualink.get_systems()
81 except AqualinkServiceException
as svc_exception:
82 await aqualink.close()
84 f
"Error while attempting to retrieve systems list: {svc_exception}"
87 systems =
list(systems.values())
89 _LOGGER.error(
"No systems detected or supported")
90 await aqualink.close()
93 for system
in systems:
95 devices = await system.get_devices()
96 except AqualinkServiceException
as svc_exception:
97 await aqualink.close()
99 f
"Error while attempting to retrieve devices list: {svc_exception}"
102 for dev
in devices.values():
103 if isinstance(dev, AqualinkThermostat):
105 elif isinstance(dev, AqualinkLight):
107 elif isinstance(dev, AqualinkSwitch):
109 elif isinstance(dev, AqualinkBinarySensor):
110 binary_sensors += [dev]
111 elif isinstance(dev, AqualinkSensor):
116 _LOGGER.debug(
"Got %s binary sensors: %s", len(binary_sensors), binary_sensors)
117 platforms.append(Platform.BINARY_SENSOR)
119 _LOGGER.debug(
"Got %s climates: %s", len(climates), climates)
120 platforms.append(Platform.CLIMATE)
122 _LOGGER.debug(
"Got %s lights: %s", len(lights), lights)
123 platforms.append(Platform.LIGHT)
125 _LOGGER.debug(
"Got %s sensors: %s", len(sensors), sensors)
126 platforms.append(Platform.SENSOR)
128 _LOGGER.debug(
"Got %s switches: %s", len(switches), switches)
129 platforms.append(Platform.SWITCH)
131 hass.data[DOMAIN][
"client"] = aqualink
133 await hass.config_entries.async_forward_entry_setups(entry, platforms)
135 async
def _async_systems_update(_: datetime) ->
None:
136 """Refresh internal state for all systems."""
137 for system
in systems:
141 await system.update()
142 except (AqualinkServiceException, httpx.HTTPError)
as svc_exception:
145 "Failed to refresh system %s state: %s",
149 await system.aqualink.close()
153 _LOGGER.warning(
"System %s reconnected to iAqualink", system.serial)
157 entry.async_on_unload(
165 """Unload a config entry."""
166 aqualink = hass.data[DOMAIN][
"client"]
167 await aqualink.close()
169 platforms_to_unload = [
170 platform
for platform
in PLATFORMS
if platform
in hass.data[DOMAIN]
173 del hass.data[DOMAIN]
175 return await hass.config_entries.async_unload_platforms(entry, platforms_to_unload)
178 def refresh_system[_AqualinkEntityT: AqualinkEntity, **_P](
179 func: Callable[Concatenate[_AqualinkEntityT, _P], Awaitable[Any]],
180 ) -> Callable[Concatenate[_AqualinkEntityT, _P], Coroutine[Any, Any,
None]]:
181 """Force update all entities after state change."""
185 self: _AqualinkEntityT, *args: _P.args, **kwargs: _P.kwargs
187 """Call decorated function and send update signal to all entities."""
188 await func(self, *args, **kwargs)
bool async_unload_entry(HomeAssistant hass, ConfigEntry entry)
bool async_setup_entry(HomeAssistant hass, ConfigEntry entry)
None async_dispatcher_send(HomeAssistant hass, str signal, *Any args)
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)
httpx.AsyncClient get_async_client(HomeAssistant hass, bool verify_ssl=True)