From f167914951c93f26f9f4305380150166215cccbd Mon Sep 17 00:00:00 2001 From: Florent Thoumie Date: Mon, 9 Sep 2019 11:06:06 -0700 Subject: [PATCH] Move iaqualink update from climate to component (#26505) * Move iaqualink update from climate to component * Typing fix --- .../components/iaqualink/__init__.py | 50 ++++++++++++++++++- homeassistant/components/iaqualink/climate.py | 16 ++---- homeassistant/components/iaqualink/const.py | 3 ++ 3 files changed, 56 insertions(+), 13 deletions(-) diff --git a/homeassistant/components/iaqualink/__init__.py b/homeassistant/components/iaqualink/__init__.py index 3f171715c57..95c6f6895fc 100644 --- a/homeassistant/components/iaqualink/__init__.py +++ b/homeassistant/components/iaqualink/__init__.py @@ -1,5 +1,6 @@ """Component to embed Aqualink devices.""" import asyncio +from functools import wraps import logging from aiohttp import CookieJar @@ -11,11 +12,18 @@ from homeassistant import config_entries from homeassistant.components.climate import DOMAIN as CLIMATE_DOMAIN from homeassistant.config_entries import ConfigEntry from homeassistant.const import CONF_PASSWORD, CONF_USERNAME +from homeassistant.core import callback from homeassistant.helpers.aiohttp_client import async_create_clientsession +from homeassistant.helpers.dispatcher import ( + async_dispatcher_connect, + async_dispatcher_send, +) +from homeassistant.helpers.entity import Entity +from homeassistant.helpers.event import async_track_time_interval import homeassistant.helpers.config_validation as cv from homeassistant.helpers.typing import ConfigType, HomeAssistantType -from .const import DOMAIN +from .const import DOMAIN, UPDATE_INTERVAL _LOGGER = logging.getLogger(__name__) @@ -86,6 +94,13 @@ async def async_setup_entry(hass: HomeAssistantType, entry: ConfigEntry) -> None _LOGGER.debug("Got %s climates: %s", len(climates), climates) hass.async_create_task(forward_setup(entry, CLIMATE_DOMAIN)) + async def _async_systems_update(now): + """Refresh internal state for all systems.""" + await systems[0].update() + async_dispatcher_send(hass, DOMAIN) + + async_track_time_interval(hass, _async_systems_update, UPDATE_INTERVAL) + return True @@ -101,3 +116,36 @@ async def async_unload_entry(hass: HomeAssistantType, entry: ConfigEntry) -> boo hass.data[DOMAIN].clear() return all(await asyncio.gather(*tasks)) + + +def refresh_system(func): + """Force update all entities after state change.""" + + @wraps(func) + async def wrapper(self, *args, **kwargs): + """Call decorated function and send update signal to all entities.""" + await func(self, *args, **kwargs) + async_dispatcher_send(self.hass, DOMAIN) + + return wrapper + + +class AqualinkEntity(Entity): + """Abstract class for all Aqualink platforms.""" + + async def async_added_to_hass(self) -> None: + """Set up a listener when this entity is added to HA.""" + async_dispatcher_connect(self.hass, DOMAIN, self._update_callback) + + @callback + def _update_callback(self) -> None: + self.async_schedule_update_ha_state(force_refresh=True) + + @property + def should_poll(self) -> bool: + """Return False as entities shouldn't be polled. + + Entities are checked periodically as the integration runs periodic + updates on a timer. + """ + return False diff --git a/homeassistant/components/iaqualink/climate.py b/homeassistant/components/iaqualink/climate.py index 0a30517623d..321c54329a2 100644 --- a/homeassistant/components/iaqualink/climate.py +++ b/homeassistant/components/iaqualink/climate.py @@ -27,6 +27,7 @@ from homeassistant.config_entries import ConfigEntry from homeassistant.const import ATTR_TEMPERATURE, TEMP_CELSIUS, TEMP_FAHRENHEIT from homeassistant.helpers.typing import HomeAssistantType +from . import AqualinkEntity, refresh_system from .const import DOMAIN as AQUALINK_DOMAIN, CLIMATE_SUPPORTED_MODES _LOGGER = logging.getLogger(__name__) @@ -44,7 +45,7 @@ async def async_setup_entry( async_add_entities(devs, True) -class HassAqualinkThermostat(ClimateDevice): +class HassAqualinkThermostat(ClimateDevice, AqualinkEntity): """Representation of a thermostat.""" def __init__(self, dev: AqualinkThermostat): @@ -56,17 +57,6 @@ class HassAqualinkThermostat(ClimateDevice): """Return the name of the thermostat.""" return self.dev.label.split(" ")[0] - async def async_update(self) -> None: - """Update the internal state of the thermostat. - - The API update() command refreshes the state of all devices so we - only update if this is the main thermostat to avoid unnecessary - calls. - """ - if self.name != "Pool": - return - await self.dev.system.update() - @property def supported_features(self) -> int: """Return the list of supported features.""" @@ -91,6 +81,7 @@ class HassAqualinkThermostat(ClimateDevice): return HVAC_MODE_HEAT return HVAC_MODE_OFF + @refresh_system async def async_set_hvac_mode(self, hvac_mode: str) -> None: """Turn the underlying heater switch on or off.""" if hvac_mode == HVAC_MODE_HEAT: @@ -126,6 +117,7 @@ class HassAqualinkThermostat(ClimateDevice): """Return the current target temperature.""" return float(self.dev.state) + @refresh_system async def async_set_temperature(self, **kwargs) -> None: """Set new target temperature.""" await self.dev.set_temperature(int(kwargs[ATTR_TEMPERATURE])) diff --git a/homeassistant/components/iaqualink/const.py b/homeassistant/components/iaqualink/const.py index ebdcd365194..219eb912994 100644 --- a/homeassistant/components/iaqualink/const.py +++ b/homeassistant/components/iaqualink/const.py @@ -1,5 +1,8 @@ """Constants for the the iaqualink component.""" +from datetime import timedelta + from homeassistant.components.climate.const import HVAC_MODE_HEAT, HVAC_MODE_OFF DOMAIN = "iaqualink" CLIMATE_SUPPORTED_MODES = [HVAC_MODE_HEAT, HVAC_MODE_OFF] +UPDATE_INTERVAL = timedelta(seconds=30)