Issue #820 - improve power shedding algorithm (#821)

* Issue #820 - improve power shedding algorithm

* Fix testu

* Release

* Fix cannot turn-off a VTherm in overpowering mode

---------

Co-authored-by: Jean-Marc Collin <jean-marc.collin-extern@renault.com>
This commit is contained in:
Jean-Marc Collin
2025-01-15 07:48:45 +01:00
committed by GitHub
parent 3e96247b63
commit e71d8dba86
7 changed files with 166 additions and 14 deletions

View File

@@ -1031,6 +1031,10 @@ class BaseThermostat(ClimateEntity, RestoreEntity, Generic[T]):
return
# Remove eventual overpoering if we want to turn-off
if hvac_mode == HVACMode.OFF and self.power_manager.is_overpowering_detected:
await self.power_manager.set_overpowering(False)
self._hvac_mode = hvac_mode
# Delegate to all underlying

View File

@@ -14,6 +14,6 @@
"quality_scale": "silver",
"requirements": [],
"ssdp": [],
"version": "7.1.3",
"version": "7.1.4",
"zeroconf": []
}

View File

@@ -195,6 +195,16 @@ class UnderlyingEntity:
self._cancel_cycle()
await self.turn_off()
async def check_overpowering(self) -> bool:
"""Check that a underlying can be turned on, else
activate the overpowering state of the VTherm associated.
Returns True if the check is ok (no overpowering needed)"""
if not await self._thermostat.power_manager.check_power_available():
_LOGGER.debug("%s - overpowering is detected", self)
await self._thermostat.power_manager.set_overpowering(True)
return False
return True
class UnderlyingSwitch(UnderlyingEntity):
"""Represent a underlying switch"""
@@ -318,6 +328,10 @@ class UnderlyingSwitch(UnderlyingEntity):
"""Turn heater toggleable device on."""
self._keep_alive.cancel() # Cancel early to avoid a turn_on/turn_off race condition
_LOGGER.debug("%s - Starting underlying entity %s", self, self._entity_id)
if not await self.check_overpowering():
return False
command = SERVICE_TURN_ON if not self.is_inversed else SERVICE_TURN_OFF
domain = self._entity_id.split(".")[0]
try:
@@ -325,6 +339,7 @@ class UnderlyingSwitch(UnderlyingEntity):
data = {ATTR_ENTITY_ID: self._entity_id}
await self._hass.services.async_call(domain, command, data)
self._keep_alive.set_async_action(self._keep_alive_callback)
return True
except Exception:
self._keep_alive.cancel()
raise
@@ -414,10 +429,6 @@ class UnderlyingSwitch(UnderlyingEntity):
await self.turn_off()
return
# if await self._thermostat.power_manager.check_overpowering():
# _LOGGER.debug("%s - End of cycle (3)", self)
# return
# safety mode could have change the on_time percent
await self._thermostat.safety_manager.refresh_state()
time = self._on_time_sec
@@ -432,7 +443,8 @@ class UnderlyingSwitch(UnderlyingEntity):
time // 60,
time % 60,
)
await self.turn_on()
if not await self.turn_on():
return
else:
_LOGGER.debug("%s - No action on heater cause duration is 0", self)
self._async_cancel_cycle = self.call_later(
@@ -557,6 +569,10 @@ class UnderlyingClimate(UnderlyingEntity):
)
return False
# When turning on a climate, check that power is available
if hvac_mode in (HVACMode.HEAT, HVACMode.COOL) and not await self.check_overpowering():
return False
data = {ATTR_ENTITY_ID: self._entity_id, "hvac_mode": hvac_mode}
await self._hass.services.async_call(
CLIMATE_DOMAIN,