diff --git a/custom_components/uponor/__init__.py b/custom_components/uponor/__init__.py index 24b8243..53709a1 100644 --- a/custom_components/uponor/__init__.py +++ b/custom_components/uponor/__init__.py @@ -6,12 +6,15 @@ from homeassistant.const import Platform from homeassistant.const import CONF_HOST +from homeassistant.helpers.dispatcher import async_dispatcher_send from homeassistant.helpers.event import async_track_time_interval from homeassistant.helpers.storage import Store from UponorJnap import UponorJnap +import homeassistant.util.dt as dt_util from .const import ( DOMAIN, + SIGNAL_UPONOR_STATE_UPDATE, SCAN_INTERVAL, STORAGE_KEY, STORAGE_VERSION, @@ -32,6 +35,7 @@ _LOGGER = logging.getLogger(__name__) +PLATFORMS = [Platform.CLIMATE, Platform.SWITCH] async def async_setup(hass: HomeAssistant, config: dict): hass.data.setdefault(DOMAIN, {}) @@ -59,8 +63,7 @@ def handle_set_variable(call): hass.services.async_register(DOMAIN, "set_variable", handle_set_variable) - await hass.config_entries.async_forward_entry_setup(config_entry, Platform.CLIMATE) - await hass.config_entries.async_forward_entry_setup(config_entry, Platform.SWITCH) + await hass.config_entries.async_forward_entry_setups(config_entry, PLATFORMS) async_track_time_interval(hass, state_proxy.async_update, SCAN_INTERVAL) @@ -86,6 +89,7 @@ def __init__(self, hass, host, store): self._store = store self._data = {} self._storage_data = {} + self.next_sp_from_dt = None # Thermostats config @@ -221,6 +225,7 @@ async def async_switch_to_cooling(self): await self._hass.async_add_executor_job(lambda: self._client.send_data({'sys_heat_cool_mode': '1'})) self._data['sys_heat_cool_mode'] = '1' + self._hass.async_add_job(async_dispatcher_send, self._hass, SIGNAL_UPONOR_STATE_UPDATE) async def async_switch_to_heating(self): for thermostat in self._hass.data[DOMAIN]['thermostats']: @@ -229,6 +234,7 @@ async def async_switch_to_heating(self): await self._hass.async_add_executor_job(lambda: self._client.send_data({'sys_heat_cool_mode': '0'})) self._data['sys_heat_cool_mode'] = '0' + self._hass.async_add_job(async_dispatcher_send, self._hass, SIGNAL_UPONOR_STATE_UPDATE) async def async_turn_on(self, thermostat): data = await self._store.async_load() @@ -267,6 +273,7 @@ async def async_set_away(self, is_away): data = "1" if is_away else "0" await self._hass.async_add_executor_job(lambda: self._client.send_data({var: data})) self._data[var] = data + self._hass.async_add_job(async_dispatcher_send, self._hass, SIGNAL_UPONOR_STATE_UPDATE) def is_eco(self, thermostat): if self.get_eco_setback(thermostat) == 0: @@ -280,19 +287,28 @@ def get_eco_setback(self, thermostat): var = thermostat + '_eco_offset' if var in self._data: return round(int(self._data[var]) / 18, 1) + + def get_last_update(self): + return self.next_sp_from_dt # Rest - - async def async_update(self): - self._data = await self._hass.async_add_executor_job(lambda: self._client.get_data()) - + async def async_update(self,_=None): + try: + self.next_sp_from_dt = dt_util.now() + self._data = await self._hass.async_add_executor_job(lambda: self._client.get_data()) + self._hass.async_add_job(async_dispatcher_send, self._hass, SIGNAL_UPONOR_STATE_UPDATE) + except Exception as ex: + _LOGGER.error("Uponor thermostat was unable to update: %s", ex) + def set_variable(self, var_name, var_value): _LOGGER.debug("Called set variable: name: %s, value: %s, data: %s", var_name, var_value, self._data) self._client.send_data({var_name: var_value}) self._data[var_name] = var_value + self._hass.async_add_job(async_dispatcher_send, self._hass, SIGNAL_UPONOR_STATE_UPDATE) async def set_setpoint(self, thermostat, temp): var = thermostat + '_setpoint' setpoint = int(temp * 18 + self.get_active_setback(thermostat, temp) + 320) await self._hass.async_add_executor_job(lambda: self._client.send_data({var: setpoint})) self._data[var] = setpoint + self._hass.async_add_job(async_dispatcher_send, self._hass, SIGNAL_UPONOR_STATE_UPDATE) diff --git a/custom_components/uponor/climate.py b/custom_components/uponor/climate.py index 1428c65..d476269 100644 --- a/custom_components/uponor/climate.py +++ b/custom_components/uponor/climate.py @@ -1,6 +1,8 @@ import logging from homeassistant.components.climate import ClimateEntity +from homeassistant.core import callback +from homeassistant.helpers.dispatcher import async_dispatcher_connect from homeassistant.const import ( ATTR_TEMPERATURE, @@ -17,6 +19,7 @@ from .const import ( DOMAIN, + SIGNAL_UPONOR_STATE_UPDATE, DEVICE_MANUFACTURER ) @@ -63,6 +66,22 @@ def device_info(self): def name(self): return self._name + @property + def should_poll(self): + return False + + async def async_added_to_hass(self): + async_dispatcher_connect( + self.hass, SIGNAL_UPONOR_STATE_UPDATE, self._update_callback + ) + + @callback + def _update_callback(self): + temp = self._state_proxy.get_setpoint(self._thermostat) + is_cool = self._state_proxy.is_cool_enabled() + self._is_on = not ((is_cool and temp >= self.max_temp) or (not is_cool and temp <= self.min_temp)) + self.async_schedule_update_ha_state(True) + @property def unique_id(self): return self._state_proxy.get_thermostat_id(self._thermostat) @@ -111,6 +130,7 @@ def extra_state_attributes(self): 'id': self._thermostat, 'status': self._state_proxy.get_status(self._thermostat), 'pulse_width_modulation': self._state_proxy.get_pwm(self._thermostat), + 'last_update': self._state_proxy.get_last_update(), 'eco_setback': self._state_proxy.get_eco_setback(self._thermostat), } @@ -148,19 +168,6 @@ async def async_turn_on(self): await self._state_proxy.async_turn_on(self._thermostat) self._is_on = True - # ** Actions ** - async def async_update(self): - # Update uponor (to get HC mode) and thermostat - try: -### se ha elimininado el 0 del update - await self._state_proxy.async_update() - temp = self._state_proxy.get_setpoint(self._thermostat) - is_cool = self._state_proxy.is_cool_enabled() - self._is_on = not ((is_cool and temp >= self.max_temp) or (not is_cool and temp <= self.min_temp)) - - except Exception as ex: - _LOGGER.error("Uponor thermostat was unable to update: %s", ex) - async def async_set_hvac_mode(self, hvac_mode): if hvac_mode == HVACMode.OFF and self._is_on: await self._state_proxy.async_turn_off(self._thermostat) @@ -168,12 +175,6 @@ async def async_set_hvac_mode(self, hvac_mode): if (hvac_mode == HVACMode.HEAT or hvac_mode == HVACMode.COOL) and not self._is_on: await self._state_proxy.async_turn_on(self._thermostat) self._is_on = True - - # if (hvac_mode == HVACMode.HEAT): - # await self._state_proxy.async_switch_to_heating() - # if (hvac_mode == HVACMode.COOL): - # await self._state_proxy.async_switch_to_cooling() - async def async_set_temperature(self, **kwargs): if kwargs.get(ATTR_TEMPERATURE) is None: diff --git a/custom_components/uponor/switch.py b/custom_components/uponor/switch.py index 42ca2ab..4fa85ae 100644 --- a/custom_components/uponor/switch.py +++ b/custom_components/uponor/switch.py @@ -1,8 +1,11 @@ from homeassistant.components.switch import SwitchEntity +from homeassistant.core import callback +from homeassistant.helpers.dispatcher import async_dispatcher_connect from homeassistant.const import CONF_NAME from .const import ( DOMAIN, + SIGNAL_UPONOR_STATE_UPDATE, DEVICE_MANUFACTURER ) @@ -30,9 +33,9 @@ def name(self) -> str: def icon(self): return "mdi:home-export-outline" - # @property - # def should_poll(self): - # return False + @property + def should_poll(self): + return False @property def is_on(self): @@ -43,9 +46,15 @@ async def async_turn_on(self, **kwargs): async def async_turn_off(self, **kwargs): await self._state_proxy.async_set_away(False) + + async def async_added_to_hass(self): + async_dispatcher_connect( + self.hass, SIGNAL_UPONOR_STATE_UPDATE, self._update_callback + ) - async def async_update(self): - await self._state_proxy.async_update() + @callback + def _update_callback(self): + self.async_schedule_update_ha_state(True) @property def unique_id(self): @@ -74,9 +83,9 @@ def name(self) -> str: def icon(self): return "mdi:snowflake" - # @property - # def should_poll(self): - # return False + @property + def should_poll(self): + return False @property def is_on(self): @@ -87,9 +96,15 @@ async def async_turn_on(self, **kwargs): async def async_turn_off(self, **kwargs): await self._state_proxy.async_switch_to_heating() - - async def async_update(self): - await self._state_proxy.async_update() + + async def async_added_to_hass(self): + async_dispatcher_connect( + self.hass, SIGNAL_UPONOR_STATE_UPDATE, self._update_callback + ) + + @callback + def _update_callback(self): + self.async_schedule_update_ha_state(True) @property def unique_id(self):