186 files
This commit is contained in:
@@ -49,6 +49,7 @@ class FeatureCentralPowerManager(BaseFeatureManager):
|
||||
self._current_power: float | None = None
|
||||
self._current_max_power: float | None = None
|
||||
self._power_temp: float | None = None
|
||||
self._power_unit_config: str | None = None
|
||||
self._cancel_calculate_shedding_call = None
|
||||
self._started_vtherm_total_power_by_id: dict[str, float] = {}
|
||||
# Not used now
|
||||
@@ -65,6 +66,7 @@ class FeatureCentralPowerManager(BaseFeatureManager):
|
||||
self._power_sensor_entity_id = entry_infos.get(CONF_POWER_SENSOR)
|
||||
self._max_power_sensor_entity_id = entry_infos.get(CONF_MAX_POWER_SENSOR)
|
||||
self._power_temp = entry_infos.get(CONF_PRESET_POWER)
|
||||
self._power_unit_config = to_internal_power_unit(entry_infos.get(CONF_POWER_UNIT))
|
||||
|
||||
self._is_configured = False
|
||||
self._current_power = None
|
||||
@@ -134,17 +136,27 @@ class FeatureCentralPowerManager(BaseFeatureManager):
|
||||
|
||||
# Retrieve current power
|
||||
new_power = get_safe_float(self._hass, self._power_sensor_entity_id)
|
||||
# Normalize to internal Watts based on sensor unit
|
||||
if new_power is not None:
|
||||
sensor_unit = self._resolve_sensor_unit(self._power_sensor_entity_id)
|
||||
new_power = self.to_watts(new_power, sensor_unit)
|
||||
|
||||
power_changed = new_power is not None and self._current_power != new_power
|
||||
if power_changed:
|
||||
self._current_power = new_power
|
||||
_LOGGER.debug("%s - New current power has been retrieved: %.3f", self, self._current_power)
|
||||
_LOGGER.debug("%s - New current power has been retrieved: %.3f (normalized to Watts)", self, self._current_power)
|
||||
|
||||
# Retrieve max power
|
||||
new_max_power = get_safe_float(self._hass, self._max_power_sensor_entity_id)
|
||||
# Normalize to internal Watts based on sensor unit
|
||||
if new_max_power is not None:
|
||||
sensor_unit = self._resolve_sensor_unit(self._max_power_sensor_entity_id)
|
||||
new_max_power = self.to_watts(new_max_power, sensor_unit)
|
||||
|
||||
max_power_changed = new_max_power is not None and self._current_max_power != new_max_power
|
||||
if max_power_changed:
|
||||
self._current_max_power = new_max_power
|
||||
_LOGGER.debug("%s - New current max power has been retrieved: %.3f", self, self._current_max_power)
|
||||
_LOGGER.debug("%s - New current max power has been retrieved: %.3f (normalized to Watts)", self, self._current_max_power)
|
||||
|
||||
# Schedule shedding calculation if there's any change
|
||||
if power_changed or max_power_changed:
|
||||
@@ -191,7 +203,7 @@ class FeatureCentralPowerManager(BaseFeatureManager):
|
||||
device_power = vtherm.power_manager.device_power
|
||||
total_power_gain += device_power
|
||||
_LOGGER.info("vtherm %s should be in overpowering state (device_power=%.2f)", vtherm.name, device_power)
|
||||
await vtherm.power_manager.set_overpowering(True, device_power)
|
||||
await vtherm.power_manager.set_overpowering(True, vtherm.power_manager.device_power)
|
||||
changed_vtherm.append(vtherm)
|
||||
|
||||
_LOGGER.debug("%s - after vtherm %s total_power_gain=%s, available_power=%s", self, vtherm.name, total_power_gain, available_power)
|
||||
@@ -245,6 +257,17 @@ class FeatureCentralPowerManager(BaseFeatureManager):
|
||||
await vtherm.update_states(force=True)
|
||||
self._last_shedding_date = self._vtherm_api.now
|
||||
|
||||
# Additionally, clean up any VTherms that are in overpowering state but shouldn't be
|
||||
# This handles cases where is_device_active changed after a VTherm was put in overpowering
|
||||
if available_power >= 0:
|
||||
all_vtherms = self.get_climate_components_entities()
|
||||
for vtherm in all_vtherms:
|
||||
if vtherm.power_manager.overpowering_state != STATE_OFF and vtherm.power_manager.is_configured:
|
||||
# Check if this VTherm was already processed in the unshedding loop
|
||||
if vtherm not in vtherms_sorted:
|
||||
_LOGGER.debug("%s - Cleaning up vtherm %s from overpowering state (not in active list but has positive available power)", self, vtherm.name)
|
||||
await vtherm.power_manager.set_overpowering(False)
|
||||
|
||||
# calculate a state as true if one of the VTherm is in shedding
|
||||
self._state = any(vtherm.power_manager.is_overpowering_detected for vtherm in vtherms_sorted)
|
||||
_LOGGER.debug("%s - -------- End of calculate_shedding", self)
|
||||
@@ -325,14 +348,43 @@ class FeatureCentralPowerManager(BaseFeatureManager):
|
||||
|
||||
@property
|
||||
def current_power(self) -> float | None:
|
||||
"""Return the current power from sensor"""
|
||||
"""Return the current power from sensor (normalized in Watts)"""
|
||||
|
||||
return self._current_power
|
||||
|
||||
@property
|
||||
def current_max_power(self) -> float | None:
|
||||
"""Return the current power from sensor"""
|
||||
"""Return the current max power from sensor (normalized in Watts)"""
|
||||
|
||||
return self._current_max_power
|
||||
|
||||
def _resolve_sensor_unit(self, entity_id: str | None) -> str:
|
||||
"""Resolve the power unit to use for a sensor.
|
||||
Uses the user configured unit when set, else the sensor own
|
||||
unit_of_measurement attribute, else falls back to Watts."""
|
||||
if self._power_unit_config in (POWER_UNIT_WATT, POWER_UNIT_KILO_WATT):
|
||||
return self._power_unit_config
|
||||
|
||||
if entity_id is not None and (state := self._hass.states.get(entity_id)) is not None:
|
||||
unit = to_internal_power_unit(state.attributes.get("unit_of_measurement"))
|
||||
if unit in (POWER_UNIT_WATT, POWER_UNIT_KILO_WATT):
|
||||
return unit
|
||||
|
||||
return POWER_UNIT_WATT
|
||||
|
||||
@property
|
||||
def power_unit(self) -> str:
|
||||
"""Return the resolved central power unit ("W" or "kW")"""
|
||||
return to_legal_power_unit(self._resolve_sensor_unit(self._power_sensor_entity_id))
|
||||
|
||||
def to_watts(self, power: float | None, unit: str | None) -> float | None:
|
||||
"""Convert a power value to Watts"""
|
||||
return power_to_watts(power, unit)
|
||||
|
||||
def from_watts(self, power_w: float | None, target_unit: str | None) -> float | None:
|
||||
"""Convert a Watts value to the target power unit"""
|
||||
return power_from_watts(power_w, target_unit)
|
||||
|
||||
@property
|
||||
def power_temperature(self) -> float | None:
|
||||
"""Return the power temperature"""
|
||||
|
||||
Reference in New Issue
Block a user