FIX issue #14 - delay when changing states
This commit is contained in:
@@ -455,14 +455,15 @@ class VersatileThermostat(ClimateEntity, RestoreEntity):
|
|||||||
_LOGGER.info("%s - Set hvac mode: %s", self, hvac_mode)
|
_LOGGER.info("%s - Set hvac mode: %s", self, hvac_mode)
|
||||||
if hvac_mode == HVAC_MODE_HEAT:
|
if hvac_mode == HVAC_MODE_HEAT:
|
||||||
self._hvac_mode = HVAC_MODE_HEAT
|
self._hvac_mode = HVAC_MODE_HEAT
|
||||||
await self._async_control_heating()
|
await self._async_control_heating(force=True)
|
||||||
elif hvac_mode == HVAC_MODE_COOL:
|
elif hvac_mode == HVAC_MODE_COOL:
|
||||||
self._hvac_mode = HVAC_MODE_COOL
|
self._hvac_mode = HVAC_MODE_COOL
|
||||||
await self._async_control_heating()
|
await self._async_control_heating(force=True)
|
||||||
elif hvac_mode == HVAC_MODE_OFF:
|
elif hvac_mode == HVAC_MODE_OFF:
|
||||||
self._hvac_mode = HVAC_MODE_OFF
|
self._hvac_mode = HVAC_MODE_OFF
|
||||||
if self._is_device_active:
|
if self._is_device_active:
|
||||||
await self._async_heater_turn_off()
|
await self._async_heater_turn_off()
|
||||||
|
await self._async_control_heating(force=True)
|
||||||
else:
|
else:
|
||||||
_LOGGER.error("Unrecognized hvac mode: %s", hvac_mode)
|
_LOGGER.error("Unrecognized hvac mode: %s", hvac_mode)
|
||||||
return
|
return
|
||||||
@@ -472,7 +473,7 @@ class VersatileThermostat(ClimateEntity, RestoreEntity):
|
|||||||
async def async_set_preset_mode(self, preset_mode):
|
async def async_set_preset_mode(self, preset_mode):
|
||||||
"""Set new preset mode."""
|
"""Set new preset mode."""
|
||||||
await self._async_set_preset_mode_internal(preset_mode)
|
await self._async_set_preset_mode_internal(preset_mode)
|
||||||
await self._async_control_heating()
|
await self._async_control_heating(force=True)
|
||||||
|
|
||||||
async def _async_set_preset_mode_internal(self, preset_mode, force=False):
|
async def _async_set_preset_mode_internal(self, preset_mode, force=False):
|
||||||
"""Set new preset mode."""
|
"""Set new preset mode."""
|
||||||
@@ -553,6 +554,7 @@ class VersatileThermostat(ClimateEntity, RestoreEntity):
|
|||||||
self._target_temp = temperature
|
self._target_temp = temperature
|
||||||
self._attr_preset_mode = PRESET_NONE
|
self._attr_preset_mode = PRESET_NONE
|
||||||
self.recalculate()
|
self.recalculate()
|
||||||
|
await self._async_control_heating(force=True)
|
||||||
|
|
||||||
@callback
|
@callback
|
||||||
async def entry_update_listener(
|
async def entry_update_listener(
|
||||||
@@ -638,14 +640,14 @@ class VersatileThermostat(ClimateEntity, RestoreEntity):
|
|||||||
await self.async_startup()
|
await self.async_startup()
|
||||||
|
|
||||||
# starts the cycle
|
# starts the cycle
|
||||||
if self._cycle_min:
|
# if self._cycle_min:
|
||||||
self.async_on_remove(
|
# self.async_on_remove(
|
||||||
async_track_time_interval(
|
# async_track_time_interval(
|
||||||
self.hass,
|
# self.hass,
|
||||||
self._async_control_heating,
|
# self._async_control_heating,
|
||||||
interval=timedelta(minutes=self._cycle_min),
|
# interval=timedelta(minutes=self._cycle_min),
|
||||||
)
|
# )
|
||||||
)
|
# )
|
||||||
|
|
||||||
async def async_startup(self):
|
async def async_startup(self):
|
||||||
"""Triggered on startup, used to get old state and set internal states accordingly"""
|
"""Triggered on startup, used to get old state and set internal states accordingly"""
|
||||||
@@ -869,6 +871,7 @@ class VersatileThermostat(ClimateEntity, RestoreEntity):
|
|||||||
|
|
||||||
self._async_update_temp(new_state)
|
self._async_update_temp(new_state)
|
||||||
self.recalculate()
|
self.recalculate()
|
||||||
|
await self._async_control_heating(force=False)
|
||||||
|
|
||||||
async def _async_ext_temperature_changed(self, event):
|
async def _async_ext_temperature_changed(self, event):
|
||||||
"""Handle external temperature changes."""
|
"""Handle external temperature changes."""
|
||||||
@@ -883,6 +886,7 @@ class VersatileThermostat(ClimateEntity, RestoreEntity):
|
|||||||
|
|
||||||
self._async_update_ext_temp(new_state)
|
self._async_update_ext_temp(new_state)
|
||||||
self.recalculate()
|
self.recalculate()
|
||||||
|
await self._async_control_heating(force=False)
|
||||||
|
|
||||||
@callback
|
@callback
|
||||||
async def _async_windows_changed(self, event):
|
async def _async_windows_changed(self, event):
|
||||||
@@ -992,6 +996,7 @@ class VersatileThermostat(ClimateEntity, RestoreEntity):
|
|||||||
# We do not change the preset which is kept to ACTIVITY but only the target_temperature
|
# We do not change the preset which is kept to ACTIVITY but only the target_temperature
|
||||||
self._target_temp = self._presets[new_preset]
|
self._target_temp = self._presets[new_preset]
|
||||||
self.recalculate()
|
self.recalculate()
|
||||||
|
await self._async_control_heating(force=True)
|
||||||
|
|
||||||
if self._motion_call_cancel:
|
if self._motion_call_cancel:
|
||||||
self._motion_call_cancel()
|
self._motion_call_cancel()
|
||||||
@@ -1105,6 +1110,7 @@ class VersatileThermostat(ClimateEntity, RestoreEntity):
|
|||||||
return
|
return
|
||||||
|
|
||||||
self._update_presence(new_state.state)
|
self._update_presence(new_state.state)
|
||||||
|
await self._async_control_heating(force=True)
|
||||||
|
|
||||||
def _update_presence(self, new_state):
|
def _update_presence(self, new_state):
|
||||||
_LOGGER.debug("%s - Updating presence. New state is %s", self, new_state)
|
_LOGGER.debug("%s - Updating presence. New state is %s", self, new_state)
|
||||||
@@ -1229,7 +1235,7 @@ class VersatileThermostat(ClimateEntity, RestoreEntity):
|
|||||||
self._saved_preset_mode if self._saved_preset_mode else PRESET_NONE
|
self._saved_preset_mode if self._saved_preset_mode else PRESET_NONE
|
||||||
)
|
)
|
||||||
|
|
||||||
async def _async_control_heating(self, time=None):
|
async def _async_control_heating(self, force=False, time=None):
|
||||||
"""The main function used to run the calculation at each cycle"""
|
"""The main function used to run the calculation at each cycle"""
|
||||||
|
|
||||||
overpowering: bool = await self.check_overpowering()
|
overpowering: bool = await self.check_overpowering()
|
||||||
@@ -1254,11 +1260,17 @@ class VersatileThermostat(ClimateEntity, RestoreEntity):
|
|||||||
|
|
||||||
# Cancel eventual previous cycle if any
|
# Cancel eventual previous cycle if any
|
||||||
if self._async_cancel_cycle is not None:
|
if self._async_cancel_cycle is not None:
|
||||||
_LOGGER.debug(
|
if force:
|
||||||
"%s - A previous cycle is alredy running -> waits for its end", self
|
_LOGGER.debug("%s - we force a new cycle")
|
||||||
)
|
self._async_cancel_cycle()
|
||||||
self._should_relaunch_control_heating = True
|
self._async_cancel_cycle = None
|
||||||
return
|
else:
|
||||||
|
_LOGGER.debug(
|
||||||
|
"%s - A previous cycle is alredy running and no force -> waits for its end",
|
||||||
|
self,
|
||||||
|
)
|
||||||
|
self._should_relaunch_control_heating = True
|
||||||
|
return
|
||||||
# await self._async_cancel_cycle()
|
# await self._async_cancel_cycle()
|
||||||
# self._async_cancel_cycle = None
|
# self._async_cancel_cycle = None
|
||||||
# Don't turn off if we will turn on just after
|
# Don't turn off if we will turn on just after
|
||||||
@@ -1266,39 +1278,121 @@ class VersatileThermostat(ClimateEntity, RestoreEntity):
|
|||||||
# await self._async_heater_turn_off()
|
# await self._async_heater_turn_off()
|
||||||
|
|
||||||
if self._hvac_mode == HVAC_MODE_HEAT and on_time_sec > 0:
|
if self._hvac_mode == HVAC_MODE_HEAT and on_time_sec > 0:
|
||||||
_LOGGER.info(
|
# _LOGGER.info(
|
||||||
"%s - start heating for %d min %d sec ",
|
# "%s - start heating for %d min %d sec ",
|
||||||
self,
|
# self,
|
||||||
on_time_sec // 60,
|
# on_time_sec // 60,
|
||||||
on_time_sec % 60,
|
# on_time_sec % 60,
|
||||||
)
|
# )
|
||||||
|
#
|
||||||
|
# await self._async_heater_turn_on()
|
||||||
|
|
||||||
await self._async_heater_turn_on()
|
async def _turn_on_off_later(
|
||||||
|
on: bool, time, heater_action, next_cycle_action
|
||||||
|
):
|
||||||
|
if self._async_cancel_cycle:
|
||||||
|
self._async_cancel_cycle()
|
||||||
|
self._async_cancel_cycle = None
|
||||||
|
|
||||||
async def _turn_off(_):
|
action_label = "start" if on else "stop"
|
||||||
self._async_cancel_cycle()
|
|
||||||
self._async_cancel_cycle = None
|
|
||||||
if self._should_relaunch_control_heating:
|
if self._should_relaunch_control_heating:
|
||||||
_LOGGER.debug("Don't stop cause a cycle have to be relaunch")
|
_LOGGER.debug(
|
||||||
|
"Don't %s cause a cycle have to be relaunch", action_label
|
||||||
|
)
|
||||||
self._should_relaunch_control_heating = False
|
self._should_relaunch_control_heating = False
|
||||||
await self._async_control_heating()
|
await self._async_control_heating()
|
||||||
return
|
return
|
||||||
else:
|
else:
|
||||||
_LOGGER.info(
|
_LOGGER.info(
|
||||||
"%s - stop heating for %d min %d sec",
|
"%s - %s heating for %d min %d sec",
|
||||||
self,
|
self,
|
||||||
off_time_sec // 60,
|
action_label,
|
||||||
off_time_sec % 60,
|
time // 60,
|
||||||
|
time % 60,
|
||||||
)
|
)
|
||||||
await self._async_heater_turn_off()
|
if time > 0:
|
||||||
|
await heater_action()
|
||||||
|
else:
|
||||||
|
_LOGGER.debug(
|
||||||
|
"%s - No action on heater cause duration is 0", self
|
||||||
|
)
|
||||||
self.update_custom_attributes()
|
self.update_custom_attributes()
|
||||||
|
self._async_cancel_cycle = async_call_later(
|
||||||
|
self.hass,
|
||||||
|
time,
|
||||||
|
next_cycle_action,
|
||||||
|
)
|
||||||
|
|
||||||
# Program turn off
|
async def _turn_on_later(_):
|
||||||
self._async_cancel_cycle = async_call_later(
|
await _turn_on_off_later(
|
||||||
self.hass,
|
on=True,
|
||||||
on_time_sec,
|
time=self._prop_algorithm.on_time_sec,
|
||||||
_turn_off,
|
heater_action=self._async_heater_turn_on,
|
||||||
)
|
next_cycle_action=_turn_off_later,
|
||||||
|
)
|
||||||
|
|
||||||
|
# if self._async_cancel_cycle:
|
||||||
|
# self._async_cancel_cycle()
|
||||||
|
# self._async_cancel_cycle = None
|
||||||
|
#
|
||||||
|
# if self._should_relaunch_control_heating:
|
||||||
|
# _LOGGER.debug("Don't stop cause a cycle have to be relaunch")
|
||||||
|
# self._should_relaunch_control_heating = False
|
||||||
|
# await self._async_control_heating()
|
||||||
|
# return
|
||||||
|
# else:
|
||||||
|
# _LOGGER.info(
|
||||||
|
# "%s - stop heating for %d min %d sec",
|
||||||
|
# self,
|
||||||
|
# off_time_sec // 60,
|
||||||
|
# off_time_sec % 60,
|
||||||
|
# )
|
||||||
|
# await self._async_heater_turn_off()
|
||||||
|
# self.update_custom_attributes()
|
||||||
|
# self._async_cancel_cycle = async_call_later(
|
||||||
|
# self.hass,
|
||||||
|
# off_time_sec,
|
||||||
|
# _turn_off_later,
|
||||||
|
# )
|
||||||
|
|
||||||
|
async def _turn_off_later(_):
|
||||||
|
await _turn_on_off_later(
|
||||||
|
on=False,
|
||||||
|
time=self._prop_algorithm.off_time_sec,
|
||||||
|
heater_action=self._async_heater_turn_off,
|
||||||
|
next_cycle_action=_turn_on_later,
|
||||||
|
)
|
||||||
|
|
||||||
|
# if self._async_cancel_cycle:
|
||||||
|
# self._async_cancel_cycle()
|
||||||
|
# self._async_cancel_cycle = None
|
||||||
|
#
|
||||||
|
# if self._should_relaunch_control_heating:
|
||||||
|
# _LOGGER.debug("Don't stop cause a cycle have to be relaunch")
|
||||||
|
# self._should_relaunch_control_heating = False
|
||||||
|
# await self._async_control_heating()
|
||||||
|
# return
|
||||||
|
# else:
|
||||||
|
# _LOGGER.info(
|
||||||
|
# "%s - stop heating for %d min %d sec",
|
||||||
|
# self,
|
||||||
|
# off_time_sec // 60,
|
||||||
|
# off_time_sec % 60,
|
||||||
|
# )
|
||||||
|
# await self._async_heater_turn_off()
|
||||||
|
# self.update_custom_attributes()
|
||||||
|
# self._async_cancel_cycle = async_call_later(
|
||||||
|
# self.hass,
|
||||||
|
# on_time_sec,
|
||||||
|
# _turn_on_later,
|
||||||
|
# )
|
||||||
|
await _turn_on_later(None)
|
||||||
|
# # Program turn off
|
||||||
|
# self._async_cancel_cycle = async_call_later(
|
||||||
|
# self.hass,
|
||||||
|
# on_time_sec,
|
||||||
|
# _turn_off_later,
|
||||||
|
# )
|
||||||
|
|
||||||
elif self._is_device_active:
|
elif self._is_device_active:
|
||||||
_LOGGER.info(
|
_LOGGER.info(
|
||||||
@@ -1382,6 +1476,7 @@ class VersatileThermostat(ClimateEntity, RestoreEntity):
|
|||||||
"""
|
"""
|
||||||
_LOGGER.info("%s - Calling service_set_presence, presence: %s", self, presence)
|
_LOGGER.info("%s - Calling service_set_presence, presence: %s", self, presence)
|
||||||
self._update_presence(presence)
|
self._update_presence(presence)
|
||||||
|
await self._async_control_heating(force=True)
|
||||||
|
|
||||||
async def service_set_preset_temperature(
|
async def service_set_preset_temperature(
|
||||||
self, preset, temperature=None, temperature_away=None
|
self, preset, temperature=None, temperature_away=None
|
||||||
@@ -1417,3 +1512,4 @@ class VersatileThermostat(ClimateEntity, RestoreEntity):
|
|||||||
# If the changed preset is active, change the current temperature
|
# If the changed preset is active, change the current temperature
|
||||||
if self._attr_preset_mode == preset:
|
if self._attr_preset_mode == preset:
|
||||||
await self._async_set_preset_mode_internal(preset, force=True)
|
await self._async_set_preset_mode_internal(preset, force=True)
|
||||||
|
await self._async_control_heating(force=True)
|
||||||
|
|||||||
Reference in New Issue
Block a user