Skip to content

Commit

Permalink
Issue #121 - loop when underlying is slow
Browse files Browse the repository at this point in the history
  • Loading branch information
Jean-Marc Collin committed Oct 14, 2023
1 parent fcdd93b commit 0372337
Showing 1 changed file with 24 additions and 3 deletions.
27 changes: 24 additions & 3 deletions custom_components/versatile_thermostat/climate.py
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,7 @@ class VersatileThermostat(ClimateEntity, RestoreEntity):
_presence_state: bool
_window_auto_state: bool
_underlyings: list[UnderlyingEntity]
_last_change_time: datetime

def __init__(self, hass: HomeAssistant, unique_id, name, entry_infos) -> None:
"""Initialize the thermostat."""
Expand Down Expand Up @@ -284,6 +285,8 @@ def __init__(self, hass: HomeAssistant, unique_id, name, entry_infos) -> None:

self._current_tz = dt_util.get_time_zone(self._hass.config.time_zone)

self._last_change_time = None

self._underlyings = []

self.post_init(entry_infos)
Expand Down Expand Up @@ -778,6 +781,8 @@ async def _async_startup_internal(*_):
else:
self.hass.create_task(self._async_control_heating())

self.reset_last_change_time()

await self.get_my_previous_state()

if self.hass.state == CoreState.running:
Expand Down Expand Up @@ -1233,6 +1238,8 @@ async def async_set_hvac_mode(self, hvac_mode, need_control_heating=True):
# Ensure we update the current operation after changing the mode
self.reset_last_temperature_time()

self.reset_last_change_time()

self.update_custom_attributes()
self.async_write_ha_state()
self.send_event(EventType.HVAC_MODE_EVENT, {"hvac_mode": self._hvac_mode})
Expand Down Expand Up @@ -1288,6 +1295,11 @@ async def _async_set_preset_mode_internal(self, preset_mode, force=False):
self.recalculate()
self.send_event(EventType.PRESET_EVENT, {"preset": self._attr_preset_mode})

def reset_last_change_time(self, old_preset_mode=None):
"""Reset to now the last change time"""
self._last_change_time = datetime.now(tz=self._current_tz)
_LOGGER.warning("%s - last_change_time is now %s", self, self._last_change_time)

def reset_last_temperature_time(self, old_preset_mode=None):
"""Reset to now the last temperature time if conditions are satisfied"""
if (
Expand Down Expand Up @@ -1363,6 +1375,7 @@ async def async_set_temperature(self, **kwargs):
await self._async_internal_set_temperature(temperature)
self._attr_preset_mode = PRESET_NONE
self.recalculate()
self.reset_last_change_time()
await self._async_control_heating(force=True)

async def _async_internal_set_temperature(self, temperature):
Expand Down Expand Up @@ -1606,6 +1619,11 @@ async def _async_climate_changed(self, event):
else None
)

old_state_date_changed = old_state.last_changed
old_state_date_updated = old_state.last_updated
new_state_date_changed = new_state.last_changed
new_state_date_updated = new_state.last_updated

# Issue 99 - some AC turn hvac_mode=cool and hvac_action=idle when sending a HVACMode_OFF command
# Issue 114 - Remove this because hvac_mode is now managed by local _hvac_mode and use idle action as is
#if self._hvac_mode == HVACMode.OFF and new_hvac_action == HVACAction.IDLE:
Expand All @@ -1621,6 +1639,8 @@ async def _async_climate_changed(self, event):
old_hvac_action,
)

_LOGGER.warning("%s - last_change_time=%s old_state_date_changed=%s old_state_date_updated=%s new_state_date_changed=%s new_state_date_updated=%s", self, self._last_change_time, old_state_date_changed, old_state_date_updated, new_state_date_changed, new_state_date_updated)

if new_hvac_mode in [
HVACMode.OFF,
HVACMode.HEAT,
Expand All @@ -1633,7 +1653,7 @@ async def _async_climate_changed(self, event):
] and self._hvac_mode != new_hvac_mode:
changes = True
self._hvac_mode = new_hvac_mode
# Do not try to update all underlying state, else we will have a loop
# Update all underlyings state
if self._is_over_climate:
for under in self._underlyings:
await under.set_hvac_mode(new_hvac_mode)
Expand Down Expand Up @@ -1681,8 +1701,9 @@ async def _async_climate_changed(self, event):
# try to manage new target temperature set if state
_LOGGER.debug("Do temperature check. temperature is %s, new_state.attributes is %s", self.target_temperature, new_state.attributes)
if self._is_over_climate and new_state.attributes and (new_target_temp := new_state.attributes.get("temperature")) and new_target_temp != self.target_temperature:
_LOGGER.info("%s - Target temp have change to %s", self, new_target_temp)
await self.async_set_temperature(temperature = new_target_temp)
_LOGGER.warning("%s - Target temp have change to %s", self, new_target_temp)
# TODO temporary removes the temperature changes for test
# await self.async_set_temperature(temperature = new_target_temp)
changes = True

if changes:
Expand Down

0 comments on commit 0372337

Please sign in to comment.