257 files

This commit is contained in:
Home Assistant Version Control committed 2026-10-02 16:06:24 +00:00
1 parent 7c55603942
commit c29f5cc088
258 files changed
+24621 -3136

No files matched your search

@@ -593,6 +593,7 @@ class UnderlyingClimate(UnderlyingEntity):
async def set_hvac_mode(self, hvac_mode: VThermHvacMode) -> bool:
"""Set the HVACmode of the underlying climate. Returns true if something have change"""
hvac_mode = self._thermostat.get_underlying_hvac_mode(hvac_mode)
state = self._state_manager.get_state(self._entity_id)
if state is None:
return False
@@ -609,6 +610,13 @@ class UnderlyingClimate(UnderlyingEntity):
if hvac_mode in (VThermHvacMode_HEAT, VThermHvacMode_COOL) and not await self.check_overpowering():
return False
# Always cancel a pending delayed temperature resend, whatever the new mode is.
# Otherwise a HEAT -> OFF sequence within resend_delay_sec would send a set_temperature
# to an underlying that is now off, which turns some devices (e.g. Sonoff TRVZB) back on.
if self._cancel_set_temperature_later:
self._cancel_set_temperature_later()
self._cancel_set_temperature_later = None
await super().set_hvac_mode(hvac_mode)
data = {ATTR_ENTITY_ID: self._entity_id, "hvac_mode": to_legacy_ha_hvac_mode(hvac_mode)}
@@ -630,8 +638,6 @@ class UnderlyingClimate(UnderlyingEntity):
if temperature is not None:
await self.set_temperature(temperature, None, None)
if self._cancel_set_temperature_later:
self._cancel_set_temperature_later()
self._cancel_set_temperature_later = async_call_later(self._hass, resend_delay_sec, callback_resend_temp)
return True
@@ -1177,6 +1183,7 @@ class UnderlyingValve(UnderlyingEntity):
max_opening_degree: int | None = None,
max_closing_degree: int = 100,
opening_threshold: int = 0,
has_valve_control: bool = False,
) -> None:
"""Initialize the underlying valve"""
@@ -1188,6 +1195,7 @@ class UnderlyingValve(UnderlyingEntity):
)
self._hvac_mode = None
self._percent_open: int | None = None # self._thermostat.valve_open_percent
self._raw_percent_open: float | None = None
self._min_open: float | None = None
self._max_open: float | None = None
self._last_sent_temperature = None
@@ -1196,6 +1204,7 @@ class UnderlyingValve(UnderlyingEntity):
self._max_opening_degree = max_opening_degree
self._max_closing_degree = max_closing_degree
self._opening_threshold = opening_threshold
self._has_valve_control = has_valve_control
def init_valve_state_min_max_open(self):
"""Initialize the min and max open percent"""
@@ -1224,6 +1233,11 @@ class UnderlyingValve(UnderlyingEntity):
self.init_valve_state_min_max_open()
raw_percent = self._thermostat.valve_open_percent
if self._has_valve_control and isinstance(raw_percent, (int, float)):
self._raw_percent_open = raw_percent
self._percent_open = self._get_controlled_percent(raw_percent)
should_device_be_active = self.should_device_be_active
is_device_active = self.is_device_active
@@ -1244,7 +1258,9 @@ class UnderlyingValve(UnderlyingEntity):
self._last_sent_opening_value or 9999,
self._entity_id,
)
await self.send_percent_open(fixed_value=self._min_open)
self._percent_open = self._get_controlled_percent(0)
self._raw_percent_open = 0
await self.send_percent_open()
async def send_percent_open(self, fixed_value: int = None):
"""Send the percent open to the underlying valve"""
@@ -1259,6 +1275,7 @@ class UnderlyingValve(UnderlyingEntity):
# Issue 341
is_active = self.is_device_active
self._percent_open = self._get_controlled_percent(0)
self._raw_percent_open = 0
if is_active:
await self.send_percent_open()
@@ -1284,10 +1301,14 @@ class UnderlyingValve(UnderlyingEntity):
@property
def should_device_be_active(self) -> bool:
"""If the toggleable device is currently active."""
try:
if not self._has_valve_control:
return self._percent_open > (self._min_open or 0) if isinstance(self._percent_open, (int, float)) else False
except Exception: # pylint: disable=broad-exception-caught
return False
return (
self._raw_percent_open > 0 and self._raw_percent_open >= self._opening_threshold
if isinstance(self._raw_percent_open, (int, float))
else False
)
@property
def is_device_active(self) -> bool | None:
@@ -1295,7 +1316,7 @@ class UnderlyingValve(UnderlyingEntity):
if (current_opening := self.current_valve_opening) is None:
return None
return current_opening > (self._min_open or 0)
return current_opening > max(100 - self._max_closing_degree, self._min_open or 0)
@overrides
def clamp_sent_value(self, value) -> float:
@@ -1322,7 +1343,9 @@ class UnderlyingValve(UnderlyingEntity):
async def set_valve_open_percent(self):
"""Update the valve open percent"""
caped_val = self._get_controlled_percent(self._thermostat.valve_open_percent)
raw_percent = self._thermostat.valve_open_percent
self._raw_percent_open = raw_percent
caped_val = self._get_controlled_percent(raw_percent)
if self._percent_open == caped_val:
# No changes
return
@@ -1449,6 +1472,11 @@ class UnderlyingValveRegulation(UnderlyingValve):
# Initialize valve state and min max opening
self.init_valve_state_min_max_open()
if self._thermostat.is_sleeping:
self._percent_open = 100
await self.send_percent_open()
return
hvac_mode = self._thermostat.vtherm_hvac_mode
device_valve_opening = self.current_valve_opening # the real opening value