Removes Valve update trigger to avoid loops
This commit is contained in:
@@ -91,173 +91,10 @@ class ThermostatOverValve(BaseThermostat):
|
|||||||
@callback
|
@callback
|
||||||
async def _async_valve_changed(self, event):
|
async def _async_valve_changed(self, event):
|
||||||
"""Handle unerdlying valve state changes.
|
"""Handle unerdlying valve state changes.
|
||||||
This method takes the underlying values and update the VTherm with them.
|
This method just log the change. It changes nothing to avoid loops.
|
||||||
To avoid loops (issues #121 #101 #95 #99), we discard the event if it is received
|
|
||||||
less than 10 sec after the last command. What we want here is to take the values
|
|
||||||
from underlyings ONLY if someone have change directly on the underlying and not
|
|
||||||
as a return of the command. The only thing we take all the time is the HVACAction
|
|
||||||
which is important for feedaback and which cannot generates loops.
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
async def end_climate_changed(changes):
|
|
||||||
"""To end the event management"""
|
|
||||||
if changes:
|
|
||||||
self.async_write_ha_state()
|
|
||||||
self.update_custom_attributes()
|
|
||||||
await self.async_control_heating()
|
|
||||||
|
|
||||||
new_state = event.data.get("new_state")
|
new_state = event.data.get("new_state")
|
||||||
_LOGGER.debug("%s - _async_climate_changed new_state is %s", self, new_state)
|
_LOGGER.debug("%s - _async_valve_changed new_state is %s", self, new_state.state)
|
||||||
if not new_state:
|
|
||||||
return
|
|
||||||
|
|
||||||
changes = False
|
|
||||||
new_hvac_mode = new_state.state
|
|
||||||
|
|
||||||
old_state = event.data.get("old_state")
|
|
||||||
old_hvac_action = (
|
|
||||||
old_state.attributes.get("hvac_action")
|
|
||||||
if old_state and old_state.attributes
|
|
||||||
else None
|
|
||||||
)
|
|
||||||
new_hvac_action = (
|
|
||||||
new_state.attributes.get("hvac_action")
|
|
||||||
if new_state and new_state.attributes
|
|
||||||
else None
|
|
||||||
)
|
|
||||||
|
|
||||||
old_state_date_changed = (
|
|
||||||
old_state.last_changed if old_state and old_state.last_changed else None
|
|
||||||
)
|
|
||||||
old_state_date_updated = (
|
|
||||||
old_state.last_updated if old_state and old_state.last_updated else None
|
|
||||||
)
|
|
||||||
new_state_date_changed = (
|
|
||||||
new_state.last_changed if new_state and new_state.last_changed else None
|
|
||||||
)
|
|
||||||
new_state_date_updated = (
|
|
||||||
new_state.last_updated if new_state and new_state.last_updated else None
|
|
||||||
)
|
|
||||||
|
|
||||||
# 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:
|
|
||||||
# _LOGGER.debug("The underlying switch to idle instead of OFF. We will consider it as OFF")
|
|
||||||
# new_hvac_mode = HVACMode.OFF
|
|
||||||
|
|
||||||
_LOGGER.info(
|
|
||||||
"%s - Underlying climate changed. Event.new_hvac_mode is %s, current_hvac_mode=%s, new_hvac_action=%s, old_hvac_action=%s",
|
|
||||||
self,
|
|
||||||
new_hvac_mode,
|
|
||||||
self._hvac_mode,
|
|
||||||
new_hvac_action,
|
|
||||||
old_hvac_action,
|
|
||||||
)
|
|
||||||
|
|
||||||
_LOGGER.debug(
|
|
||||||
"%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,
|
|
||||||
)
|
|
||||||
|
|
||||||
# Interpretation of hvac action
|
|
||||||
HVAC_ACTION_ON = [ # pylint: disable=invalid-name
|
|
||||||
HVACAction.COOLING,
|
|
||||||
HVACAction.DRYING,
|
|
||||||
HVACAction.FAN,
|
|
||||||
HVACAction.HEATING,
|
|
||||||
]
|
|
||||||
if old_hvac_action not in HVAC_ACTION_ON and new_hvac_action in HVAC_ACTION_ON:
|
|
||||||
self._underlying_climate_start_hvac_action_date = (
|
|
||||||
self.get_last_updated_date_or_now(new_state)
|
|
||||||
)
|
|
||||||
_LOGGER.info(
|
|
||||||
"%s - underlying just switch ON. Set power and energy start date %s",
|
|
||||||
self,
|
|
||||||
self._underlying_climate_start_hvac_action_date.isoformat(),
|
|
||||||
)
|
|
||||||
changes = True
|
|
||||||
|
|
||||||
if old_hvac_action in HVAC_ACTION_ON and new_hvac_action not in HVAC_ACTION_ON:
|
|
||||||
stop_power_date = self.get_last_updated_date_or_now(new_state)
|
|
||||||
if self._underlying_climate_start_hvac_action_date:
|
|
||||||
delta = (
|
|
||||||
stop_power_date - self._underlying_climate_start_hvac_action_date
|
|
||||||
)
|
|
||||||
self._underlying_climate_delta_t = delta.total_seconds() / 3600.0
|
|
||||||
|
|
||||||
# increment energy at the end of the cycle
|
|
||||||
self.incremente_energy()
|
|
||||||
|
|
||||||
self._underlying_climate_start_hvac_action_date = None
|
|
||||||
|
|
||||||
_LOGGER.info(
|
|
||||||
"%s - underlying just switch OFF at %s. delta_h=%.3f h",
|
|
||||||
self,
|
|
||||||
stop_power_date.isoformat(),
|
|
||||||
self._underlying_climate_delta_t,
|
|
||||||
)
|
|
||||||
changes = True
|
|
||||||
|
|
||||||
# Issue #120 - Some TRV are chaning target temperature a very long time (6 sec) after the change.
|
|
||||||
# In that case a loop is possible if a user change multiple times during this 6 sec.
|
|
||||||
if new_state_date_updated and self._last_change_time:
|
|
||||||
delta = (new_state_date_updated - self._last_change_time).total_seconds()
|
|
||||||
if delta < 10:
|
|
||||||
_LOGGER.info(
|
|
||||||
"%s - underlying event is received less than 10 sec after command. Forget it to avoid loop",
|
|
||||||
self,
|
|
||||||
)
|
|
||||||
await end_climate_changed(changes)
|
|
||||||
return
|
|
||||||
|
|
||||||
if (
|
|
||||||
new_hvac_mode
|
|
||||||
in [
|
|
||||||
HVACMode.OFF,
|
|
||||||
HVACMode.HEAT,
|
|
||||||
HVACMode.COOL,
|
|
||||||
HVACMode.HEAT_COOL,
|
|
||||||
HVACMode.DRY,
|
|
||||||
HVACMode.AUTO,
|
|
||||||
HVACMode.FAN_ONLY,
|
|
||||||
None,
|
|
||||||
]
|
|
||||||
and self._hvac_mode != new_hvac_mode
|
|
||||||
):
|
|
||||||
changes = True
|
|
||||||
self._hvac_mode = new_hvac_mode
|
|
||||||
# Update all underlyings state
|
|
||||||
if self.is_over_climate:
|
|
||||||
for under in self._underlyings:
|
|
||||||
await under.set_hvac_mode(new_hvac_mode)
|
|
||||||
|
|
||||||
if not changes:
|
|
||||||
# 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 in underlying have change to %s",
|
|
||||||
self,
|
|
||||||
new_target_temp,
|
|
||||||
)
|
|
||||||
await self.async_set_temperature(temperature=new_target_temp)
|
|
||||||
changes = True
|
|
||||||
|
|
||||||
await end_climate_changed(changes)
|
|
||||||
|
|
||||||
def update_custom_attributes(self):
|
def update_custom_attributes(self):
|
||||||
""" Custom attributes """
|
""" Custom attributes """
|
||||||
|
|||||||
Reference in New Issue
Block a user