186 files
This commit is contained in:
@@ -334,6 +334,17 @@ async def async_migrate_entry(hass: HomeAssistant, config_entry: ConfigEntry):
|
||||
new.pop("auto_tpi_keep_ext_learning", None)
|
||||
new.pop("auto_tpi_continuous_learning", None)
|
||||
|
||||
if version <= 203:
|
||||
# Freeze the power unit to preserve the unit previously displayed by the sensors.
|
||||
# Only set it when absent to respect an already configured value.
|
||||
if CONF_POWER_UNIT not in new:
|
||||
if thermostat_type == CONF_THERMOSTAT_CENTRAL_CONFIG:
|
||||
new[CONF_POWER_UNIT] = POWER_UNIT_AUTO
|
||||
else:
|
||||
device_power = get_safe_float_value(new.get(CONF_DEVICE_POWER))
|
||||
# Reproduce the historical THRESHOLD_WATT_KILO heuristic
|
||||
new[CONF_POWER_UNIT] = POWER_UNIT_WATT if device_power is not None and device_power > THRESHOLD_POWER_WATT_KILO else POWER_UNIT_KILO_WATT
|
||||
|
||||
# Update the config entry with migrated data
|
||||
hass.config_entries.async_update_entry(
|
||||
config_entry,
|
||||
|
||||
@@ -2572,6 +2572,17 @@ class AutoTpiManager:
|
||||
_LOGGER.debug("%s - Auto TPI: Captured end of ON temp: %.1f", self._name, self.state.last_on_temp_in)
|
||||
self._timer_capture_remove_callback = None
|
||||
|
||||
def _cancel_capture_timer(self) -> None:
|
||||
"""Cancel the pending end-of-ON temperature capture."""
|
||||
if self._timer_capture_remove_callback:
|
||||
self._timer_capture_remove_callback()
|
||||
self._timer_capture_remove_callback = None
|
||||
|
||||
def shutdown(self) -> None:
|
||||
"""Stop transient cycle activity owned by the manager."""
|
||||
self._cancel_capture_timer()
|
||||
self.state.cycle_active = False
|
||||
|
||||
def update_realized_power(self, realized_percent: float):
|
||||
"""Update the power actually applied to the underlyings.
|
||||
|
||||
@@ -2603,9 +2614,7 @@ class AutoTpiManager:
|
||||
# You could add specific logic here if needed (stats, etc)
|
||||
|
||||
# Cancel any pending capture timer
|
||||
if self._timer_capture_remove_callback:
|
||||
self._timer_capture_remove_callback()
|
||||
self._timer_capture_remove_callback = None
|
||||
self._cancel_capture_timer()
|
||||
|
||||
self.state.cycle_active = True
|
||||
|
||||
@@ -2789,6 +2798,8 @@ class AutoTpiManager:
|
||||
|
||||
async def on_cycle_completed(self, e_eff: float = None, **_kw) -> None:
|
||||
"""Called when a TPI cycle completes."""
|
||||
self._cancel_capture_timer()
|
||||
|
||||
# Validation logic (moved from old _tick)
|
||||
now = dt_util.now()
|
||||
|
||||
|
||||
@@ -82,6 +82,15 @@ class VersatileThermostatBaseEntity(Entity):
|
||||
async def async_added_to_hass(self):
|
||||
"""Listen to my climate state change"""
|
||||
|
||||
@callback
|
||||
def cancel_pending_climate_lookup():
|
||||
"""Cancel a pending climate lookup retry."""
|
||||
if self._cancel_call:
|
||||
self._cancel_call()
|
||||
self._cancel_call = None
|
||||
|
||||
self.async_on_remove(cancel_pending_climate_lookup)
|
||||
|
||||
# Check delay condition
|
||||
async def try_find_climate(_):
|
||||
_LOGGER.debug(
|
||||
@@ -89,9 +98,7 @@ class VersatileThermostatBaseEntity(Entity):
|
||||
)
|
||||
mcl = self.my_climate
|
||||
if mcl:
|
||||
if self._cancel_call:
|
||||
self._cancel_call()
|
||||
self._cancel_call = None
|
||||
cancel_pending_climate_lookup()
|
||||
self.async_on_remove(
|
||||
async_track_state_change_event(
|
||||
self.hass,
|
||||
|
||||
@@ -152,6 +152,7 @@ class BaseThermostat(ClimateEntity, RestoreEntity, Generic[T]):
|
||||
self._attr_translation_key = "versatile_thermostat"
|
||||
|
||||
self._total_energy = None
|
||||
self._energy_unit_needs_persistence = False
|
||||
_LOGGER.debug("%s - _init_ resetting energy to None", self)
|
||||
|
||||
# Because energy of climate is calculated in the thermostat we have to keep
|
||||
@@ -289,12 +290,13 @@ class BaseThermostat(ClimateEntity, RestoreEntity, Generic[T]):
|
||||
) -> dict[str, Any]:
|
||||
"""Removes all values from config with are concerned by central_config"""
|
||||
|
||||
def clean_one(cfg, schema: vol.Schema):
|
||||
def clean_one(cfg, schema: vol.Schema, excluded_keys: set[str] | None = None):
|
||||
"""Clean one schema"""
|
||||
excluded_keys = excluded_keys or set()
|
||||
for marker in schema.schema:
|
||||
# Extract the actual key from Voluptuous Marker objects
|
||||
key = marker.schema if hasattr(marker, 'schema') else marker
|
||||
if key in cfg:
|
||||
if key in cfg and key not in excluded_keys:
|
||||
del cfg[key]
|
||||
|
||||
cfg = config_entry.copy()
|
||||
@@ -313,7 +315,14 @@ class BaseThermostat(ClimateEntity, RestoreEntity, Generic[T]):
|
||||
clean_one(cfg, STEP_CENTRAL_MOTION_DATA_SCHEMA)
|
||||
|
||||
if cfg.get(CONF_USE_POWER_CENTRAL_CONFIG) is True:
|
||||
clean_one(cfg, STEP_CENTRAL_POWER_DATA_SCHEMA)
|
||||
# The central unit may be ``auto``. It only controls how the
|
||||
# central input sensors are read; each VTherm keeps its own
|
||||
# display unit (W or kW) for its power and energy sensors.
|
||||
clean_one(
|
||||
cfg,
|
||||
STEP_CENTRAL_POWER_DATA_SCHEMA,
|
||||
{CONF_POWER_UNIT},
|
||||
)
|
||||
|
||||
if cfg.get(CONF_USE_PRESENCE_CENTRAL_CONFIG) is True:
|
||||
clean_one(cfg, STEP_CENTRAL_PRESENCE_DATA_SCHEMA)
|
||||
@@ -411,6 +420,7 @@ class BaseThermostat(ClimateEntity, RestoreEntity, Generic[T]):
|
||||
self._last_ext_temperature_measure = self.now
|
||||
|
||||
self._total_energy = None
|
||||
self._energy_unit_needs_persistence = False
|
||||
_LOGGER.debug("%s - post_init_ resetting energy to None", self)
|
||||
|
||||
# Read the parameter from configuration.yaml if it exists
|
||||
@@ -633,6 +643,7 @@ class BaseThermostat(ClimateEntity, RestoreEntity, Generic[T]):
|
||||
# need_write_state = True
|
||||
|
||||
await self.update_states(force=True)
|
||||
self._persist_energy_unit_if_needed()
|
||||
self.recalculate()
|
||||
|
||||
# check initial state should be done after the current state has been calculated and so after the manager has been updated
|
||||
@@ -646,8 +657,24 @@ class BaseThermostat(ClimateEntity, RestoreEntity, Generic[T]):
|
||||
restored
|
||||
"""
|
||||
|
||||
def _persist_energy_unit_if_needed(self) -> None:
|
||||
"""Persist restored energy in the current power unit when it changed."""
|
||||
if not self._energy_unit_needs_persistence:
|
||||
return
|
||||
|
||||
_LOGGER.info(
|
||||
"%s - Rewriting restored energy from its previous unit to %s",
|
||||
self,
|
||||
self.power_manager.power_unit,
|
||||
)
|
||||
self.update_custom_attributes()
|
||||
self.async_write_ha_state()
|
||||
self._energy_unit_needs_persistence = False
|
||||
|
||||
async def get_my_previous_state(self):
|
||||
"""Try to get my previous state"""
|
||||
self._energy_unit_needs_persistence = False
|
||||
|
||||
# Check If we have an old state
|
||||
old_state = await self.async_get_last_state()
|
||||
_LOGGER.debug(
|
||||
@@ -703,7 +730,38 @@ class BaseThermostat(ClimateEntity, RestoreEntity, Generic[T]):
|
||||
if old_total_energy is None:
|
||||
# Fallback to root level for backward compatibility
|
||||
old_total_energy = old_state.attributes.get(ATTR_TOTAL_ENERGY)
|
||||
self._total_energy = old_total_energy if old_total_energy is not None else 0
|
||||
# Energy is stored in the unit associated with the configured power unit.
|
||||
# Legacy states did not record that unit, so use their persisted
|
||||
# configuration before falling back to the migrated current one.
|
||||
if old_total_energy is not None:
|
||||
stored_unit = specific_states.get(ATTR_TOTAL_ENERGY_UNIT)
|
||||
if stored_unit is None:
|
||||
stored_unit = old_state.attributes.get("configuration", {}).get(
|
||||
CONF_POWER_UNIT,
|
||||
self.power_manager.power_unit,
|
||||
)
|
||||
current_unit = to_internal_power_unit(self.power_manager.power_unit) or POWER_UNIT_WATT
|
||||
stored_unit = to_internal_power_unit(stored_unit)
|
||||
has_invalid_stored_unit = stored_unit not in (POWER_UNIT_WATT, POWER_UNIT_KILO_WATT)
|
||||
if has_invalid_stored_unit:
|
||||
_LOGGER.warning(
|
||||
"%s - Restored energy has an unsupported unit %s. Using %s",
|
||||
self,
|
||||
stored_unit,
|
||||
self.power_manager.power_unit,
|
||||
)
|
||||
stored_unit = current_unit
|
||||
self._energy_unit_needs_persistence = has_invalid_stored_unit or stored_unit != current_unit
|
||||
if self._energy_unit_needs_persistence:
|
||||
_LOGGER.info(
|
||||
"%s - Restored energy unit %s differs from configured unit %s",
|
||||
self,
|
||||
to_legal_power_unit(stored_unit),
|
||||
self.power_manager.power_unit,
|
||||
)
|
||||
self._total_energy = power_to_watts(old_total_energy, stored_unit) if old_total_energy else 0
|
||||
else:
|
||||
self._total_energy = 0
|
||||
_LOGGER.debug(
|
||||
"%s - get_my_previous_state restored energy is %s",
|
||||
self,
|
||||
@@ -1947,7 +2005,11 @@ class BaseThermostat(ClimateEntity, RestoreEntity, Generic[T]):
|
||||
"temperature_slope": round(self.last_temperature_slope or 0, 3),
|
||||
"hvac_off_reason": self.hvac_off_reason,
|
||||
"hvac_mode_reason": self.hvac_mode_reason,
|
||||
ATTR_TOTAL_ENERGY: self.total_energy,
|
||||
ATTR_TOTAL_ENERGY: self.power_manager.from_watts(
|
||||
self.total_energy,
|
||||
self.power_manager.power_unit,
|
||||
),
|
||||
ATTR_TOTAL_ENERGY_UNIT: self.power_manager.power_unit,
|
||||
"last_change_time_from_vtherm": (
|
||||
self._last_change_time_from_vtherm.astimezone(self._current_tz).isoformat() if self._last_change_time_from_vtherm is not None else None
|
||||
),
|
||||
@@ -1969,6 +2031,7 @@ class BaseThermostat(ClimateEntity, RestoreEntity, Generic[T]):
|
||||
"max_on_percent": self._max_on_percent,
|
||||
"have_valve_regulation": self.have_valve_regulation,
|
||||
"cycle_min": self._cycle_min,
|
||||
CONF_POWER_UNIT: self.power_manager.power_unit,
|
||||
},
|
||||
"preset_temperatures": {
|
||||
"frost_temp": self._presets.get(VThermPreset.FROST, 0),
|
||||
|
||||
@@ -470,8 +470,9 @@ class CentralBoilerBinarySensor(BinarySensorEntity):
|
||||
"""Update the custom extra attributes for the entity"""
|
||||
self._attr_extra_state_attributes = {"central_boiler_state": STATE_ON if self._attr_is_on else STATE_OFF}
|
||||
api: VersatileThermostatAPI = VersatileThermostatAPI.get_vtherm_api()
|
||||
cb_manager = api.central_boiler_manager
|
||||
cb_manager.add_custom_attributes(self._attr_extra_state_attributes)
|
||||
if api is None:
|
||||
return
|
||||
api.central_boiler_manager.add_custom_attributes(self._attr_extra_state_attributes)
|
||||
|
||||
def __str__(self):
|
||||
return f"VersatileThermostat-{self.name}"
|
||||
|
||||
@@ -139,6 +139,13 @@ STEP_MAIN_DATA_SCHEMA = vol.Schema( # pylint: disable=invalid-name
|
||||
vol.Required(CONF_CYCLE_MIN, default=5): selector.NumberSelector(selector.NumberSelectorConfig(min=1, max=1000, step=1, mode=selector.NumberSelectorMode.BOX)),
|
||||
|
||||
vol.Optional(CONF_DEVICE_POWER, default="1"): vol.Coerce(float),
|
||||
vol.Optional(CONF_POWER_UNIT, default=POWER_UNIT_WATT): selector.SelectSelector(
|
||||
selector.SelectSelectorConfig(
|
||||
options=CONF_POWER_UNITS,
|
||||
translation_key="power_unit",
|
||||
mode="dropdown",
|
||||
)
|
||||
),
|
||||
vol.Required(CONF_USE_MAIN_CENTRAL_CONFIG, default=True): cv.boolean,
|
||||
vol.Optional(CONF_USE_CENTRAL_MODE, default=True): cv.boolean,
|
||||
vol.Required(CONF_USED_BY_CENTRAL_BOILER, default=False): cv.boolean,
|
||||
@@ -430,6 +437,13 @@ STEP_CENTRAL_POWER_DATA_SCHEMA = vol.Schema( # pylint: disable=invalid-name
|
||||
vol.Required(CONF_MAX_POWER_SENSOR): selector.EntitySelector(
|
||||
selector.EntitySelectorConfig(domain=[SENSOR_DOMAIN, INPUT_NUMBER_DOMAIN]),
|
||||
),
|
||||
vol.Optional(CONF_POWER_UNIT, default=POWER_UNIT_AUTO): selector.SelectSelector(
|
||||
selector.SelectSelectorConfig(
|
||||
options=CONF_CENTRAL_POWER_UNITS,
|
||||
translation_key="central_power_unit",
|
||||
mode="dropdown",
|
||||
)
|
||||
),
|
||||
vol.Optional(CONF_PRESET_POWER, default="13"): vol.Coerce(float),
|
||||
}
|
||||
)
|
||||
|
||||
@@ -8,7 +8,7 @@ from typing import Literal
|
||||
from datetime import datetime
|
||||
|
||||
from enum import Enum
|
||||
from homeassistant.const import STATE_UNKNOWN, STATE_UNAVAILABLE
|
||||
from homeassistant.const import STATE_UNKNOWN, STATE_UNAVAILABLE, UnitOfPower
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.const import CONF_NAME, Platform
|
||||
|
||||
@@ -41,7 +41,7 @@ from .vtherm_state import VThermState # pylint: disable=unused-import
|
||||
_LOGGER = get_vtherm_logger(__name__)
|
||||
|
||||
CONFIG_VERSION = 2
|
||||
CONFIG_MINOR_VERSION = 3
|
||||
CONFIG_MINOR_VERSION = 4
|
||||
|
||||
DEVICE_MANUFACTURER = "JMCOLLIN"
|
||||
DEVICE_MODEL = "Versatile Thermostat"
|
||||
@@ -70,6 +70,21 @@ CONF_MAX_POWER_SENSOR = "max_power_sensor_entity_id"
|
||||
CONF_WINDOW_SENSOR = "window_sensor_entity_id"
|
||||
CONF_MOTION_SENSOR = "motion_sensor_entity_id"
|
||||
CONF_DEVICE_POWER = "device_power"
|
||||
CONF_POWER_UNIT = "power_unit"
|
||||
|
||||
# Power unit values used by configuration selector translation keys.
|
||||
# Convert them to Home Assistant's "W" / "kW" values only at entity boundaries.
|
||||
POWER_UNIT_WATT = "w"
|
||||
POWER_UNIT_KILO_WATT = "kw"
|
||||
POWER_UNIT_MEGA_WATT = "mw"
|
||||
POWER_UNIT_AUTO = "auto"
|
||||
|
||||
# Selector options
|
||||
CONF_POWER_UNITS = [POWER_UNIT_WATT, POWER_UNIT_KILO_WATT]
|
||||
CONF_CENTRAL_POWER_UNITS = [POWER_UNIT_WATT, POWER_UNIT_KILO_WATT, POWER_UNIT_AUTO]
|
||||
|
||||
# Threshold used by the legacy unit heuristic and by the config migration
|
||||
THRESHOLD_POWER_WATT_KILO = 100
|
||||
CONF_CYCLE_MIN = "cycle_min"
|
||||
CONF_PROP_FUNCTION = "proportional_function"
|
||||
CONF_WINDOW_DELAY = "window_delay"
|
||||
@@ -360,6 +375,7 @@ ALL_CONF = (
|
||||
CONF_MOTION_PRESET,
|
||||
CONF_NO_MOTION_PRESET,
|
||||
CONF_DEVICE_POWER,
|
||||
CONF_POWER_UNIT,
|
||||
CONF_CYCLE_MIN,
|
||||
CONF_PROP_FUNCTION,
|
||||
CONF_TPI_COEF_INT,
|
||||
@@ -520,6 +536,7 @@ DEFAULT_HEATING_FAILURE_DETECTION_DELAY = 15 # 15 minutes
|
||||
DEFAULT_TEMPERATURE_CHANGE_TOLERANCE = 0.5 # 0.5°C
|
||||
|
||||
ATTR_TOTAL_ENERGY = "total_energy"
|
||||
ATTR_TOTAL_ENERGY_UNIT = "total_energy_unit"
|
||||
ATTR_MEAN_POWER_CYCLE = "mean_cycle_power"
|
||||
|
||||
AUTO_FAN_DTEMP_THRESHOLD = 2
|
||||
@@ -649,6 +666,54 @@ def get_safe_float_value(value):
|
||||
return None
|
||||
|
||||
|
||||
def power_to_watts(value: float | None, unit: str | None) -> float | None:
|
||||
"""Normalize a power (or energy) magnitude to Watts (or Watt-hours).
|
||||
The conversion accepts internal selector keys and Home Assistant units."""
|
||||
|
||||
if value is None:
|
||||
return None
|
||||
if to_internal_power_unit(unit) == POWER_UNIT_KILO_WATT:
|
||||
return value * 1000.0
|
||||
return value
|
||||
|
||||
|
||||
def power_from_watts(value_w: float | None, unit: str | None) -> float | None:
|
||||
"""Convert a Watts (or Watt-hours) magnitude to the target power unit.
|
||||
|
||||
The conversion accepts internal selector keys and Home Assistant units.
|
||||
"""
|
||||
|
||||
if value_w is None:
|
||||
return None
|
||||
if to_internal_power_unit(unit) == POWER_UNIT_KILO_WATT:
|
||||
return value_w / 1000.0
|
||||
return value_w
|
||||
|
||||
|
||||
def to_internal_power_unit(power_unit: str | None) -> str | None:
|
||||
"""Map a selector key or Home Assistant power unit to its internal key."""
|
||||
power_unit_mapping = {
|
||||
POWER_UNIT_WATT: POWER_UNIT_WATT,
|
||||
UnitOfPower.WATT: POWER_UNIT_WATT,
|
||||
POWER_UNIT_KILO_WATT: POWER_UNIT_KILO_WATT,
|
||||
UnitOfPower.KILO_WATT: POWER_UNIT_KILO_WATT,
|
||||
POWER_UNIT_MEGA_WATT: POWER_UNIT_MEGA_WATT,
|
||||
UnitOfPower.MEGA_WATT: POWER_UNIT_MEGA_WATT,
|
||||
}
|
||||
return power_unit_mapping.get(power_unit, power_unit)
|
||||
|
||||
|
||||
def to_legal_power_unit(power_unit: str) -> str:
|
||||
"""Map the power unit from the thermostat to Home Assistant's expected unit."""
|
||||
power_unit_mapping: dict[str, str] = {
|
||||
POWER_UNIT_WATT: UnitOfPower.WATT,
|
||||
POWER_UNIT_KILO_WATT: UnitOfPower.KILO_WATT,
|
||||
POWER_UNIT_MEGA_WATT: UnitOfPower.MEGA_WATT,
|
||||
}
|
||||
internal_power_unit = to_internal_power_unit(power_unit) or power_unit
|
||||
return power_unit_mapping.get(internal_power_unit, power_unit)
|
||||
|
||||
|
||||
class UnknownEntity(HomeAssistantError):
|
||||
"""Error to indicate there is an unknown entity_id given."""
|
||||
|
||||
|
||||
@@ -158,6 +158,24 @@ class CycleScheduler:
|
||||
UnderlyingEntityType.VALVE_REGULATION,
|
||||
)
|
||||
|
||||
def _resolve_valve_on_percent(
|
||||
self,
|
||||
on_percent: float,
|
||||
force: bool = False,
|
||||
) -> float:
|
||||
"""Return the valve command retained by the thermostat."""
|
||||
requested = max(0.0, min(1.0, float(on_percent)))
|
||||
resolver = getattr(
|
||||
type(self._thermostat),
|
||||
"apply_valve_command_percent",
|
||||
None,
|
||||
)
|
||||
if resolver is None:
|
||||
return requested
|
||||
|
||||
retained = resolver(self._thermostat, requested, force=force)
|
||||
return max(0.0, min(1.0, float(retained)))
|
||||
|
||||
def register_cycle_start_callback(self, callback: Callable):
|
||||
"""Register a callback to be called at the start of each master cycle.
|
||||
|
||||
@@ -232,6 +250,9 @@ class CycleScheduler:
|
||||
force: If True, cancel any running cycle and restart immediately.
|
||||
_from_cycle_end: Internal flag — True when called from _on_master_cycle_end.
|
||||
"""
|
||||
if self._is_valve_mode:
|
||||
on_percent = self._resolve_valve_on_percent(on_percent, force=force)
|
||||
|
||||
cycle_min = self._cycle_duration_sec / 60
|
||||
on_time_sec, off_time_sec, _ = calculate_cycle_times(
|
||||
on_percent,
|
||||
@@ -239,7 +260,15 @@ class CycleScheduler:
|
||||
self.min_activation_delay,
|
||||
self.min_deactivation_delay,
|
||||
)
|
||||
realized_on_percent = on_time_sec / self._cycle_duration_sec if self._cycle_duration_sec > 0 else 0.0
|
||||
# A valve applies the retained position directly. Converting it back
|
||||
# from integer cycle seconds would quantize it a second time and feed a
|
||||
# different command into the next automatic cycle restart.
|
||||
if self._is_valve_mode:
|
||||
realized_on_percent = on_percent
|
||||
elif self._cycle_duration_sec > 0:
|
||||
realized_on_percent = on_time_sec / self._cycle_duration_sec
|
||||
else:
|
||||
realized_on_percent = 0.0
|
||||
|
||||
# Always update thermostat timing attributes immediately so sensors
|
||||
# reflect the latest computed value, even when the cycle returns early.
|
||||
@@ -336,6 +365,7 @@ class CycleScheduler:
|
||||
if not self._is_valve_mode:
|
||||
return
|
||||
|
||||
on_percent = self._resolve_valve_on_percent(on_percent)
|
||||
cycle_min = self._cycle_duration_sec / 60
|
||||
on_time_sec, off_time_sec, _ = calculate_cycle_times(
|
||||
on_percent,
|
||||
@@ -343,7 +373,9 @@ class CycleScheduler:
|
||||
self.min_activation_delay,
|
||||
self.min_deactivation_delay,
|
||||
)
|
||||
realized_on_percent = on_time_sec / self._cycle_duration_sec if self._cycle_duration_sec > 0 else 0.0
|
||||
# Valve mode is direct-position control: cycle seconds are diagnostic
|
||||
# timing data, not the source of the applied valve percentage.
|
||||
realized_on_percent = on_percent
|
||||
|
||||
self._thermostat._on_time_sec = on_time_sec
|
||||
self._thermostat._off_time_sec = off_time_sec
|
||||
|
||||
@@ -401,7 +401,16 @@ class FeatureCentralBoilerManager(BaseFeatureManager):
|
||||
total_power = self.total_power_active_for_boiler
|
||||
power_threshold = self.total_power_active_for_boiler_threshold
|
||||
|
||||
return total_power >= power_threshold
|
||||
total_power_watts = power_to_watts(
|
||||
total_power,
|
||||
self._total_power_active_entity.native_unit_of_measurement,
|
||||
)
|
||||
power_threshold_watts = power_to_watts(
|
||||
power_threshold,
|
||||
self._total_power_active_threshold_number_entity.native_unit_of_measurement,
|
||||
)
|
||||
|
||||
return total_power_watts >= power_threshold_watts
|
||||
|
||||
def _get_all_boiler_entity_ids(self, force=False) -> list[str]:
|
||||
"""Returns the list of all VTherm entity ids which have an influence
|
||||
|
||||
@@ -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"""
|
||||
|
||||
@@ -9,6 +9,7 @@ from homeassistant.const import (
|
||||
STATE_OFF,
|
||||
STATE_UNAVAILABLE,
|
||||
STATE_UNKNOWN,
|
||||
UnitOfEnergy,
|
||||
)
|
||||
|
||||
from homeassistant.core import (
|
||||
@@ -43,6 +44,7 @@ class FeaturePowerManager(BaseFeatureManager):
|
||||
self._overpowering_state: str | None = None
|
||||
self._is_configured: bool = False
|
||||
self._device_power: float = 0
|
||||
self._power_unit: str = POWER_UNIT_WATT
|
||||
self._use_power_feature: bool = False
|
||||
|
||||
@overrides
|
||||
@@ -52,7 +54,19 @@ class FeaturePowerManager(BaseFeatureManager):
|
||||
# Power management
|
||||
self._power_temp = entry_infos.get(CONF_PRESET_POWER)
|
||||
|
||||
self._device_power = entry_infos.get(CONF_DEVICE_POWER) or 0
|
||||
configured_power_unit = to_internal_power_unit(entry_infos.get(CONF_POWER_UNIT))
|
||||
if configured_power_unit not in (POWER_UNIT_WATT, POWER_UNIT_KILO_WATT):
|
||||
_LOGGER.warning(
|
||||
"%s - Unsupported power unit %s. Falling back to W",
|
||||
self,
|
||||
entry_infos.get(CONF_POWER_UNIT),
|
||||
)
|
||||
self._power_unit = POWER_UNIT_WATT
|
||||
else:
|
||||
self._power_unit = configured_power_unit
|
||||
# Normalize device_power to internal Watts based on configured unit
|
||||
raw_device_power = entry_infos.get(CONF_DEVICE_POWER)
|
||||
self._device_power = (power_to_watts(raw_device_power, self._power_unit) or 0.0) if raw_device_power else 0.0
|
||||
self._use_power_feature = entry_infos.get(CONF_USE_POWER_FEATURE, False)
|
||||
self._is_configured = False
|
||||
|
||||
@@ -92,26 +106,35 @@ class FeaturePowerManager(BaseFeatureManager):
|
||||
}
|
||||
)
|
||||
if self._is_configured:
|
||||
central = vtherm_api.central_power_manager
|
||||
power_unit = self.power_unit
|
||||
central_power_unit = central.power_unit
|
||||
extra_state_attributes.update(
|
||||
{
|
||||
"power_manager": {
|
||||
"power_sensor_entity_id": vtherm_api.central_power_manager.power_sensor_entity_id,
|
||||
"max_power_sensor_entity_id": vtherm_api.central_power_manager.max_power_sensor_entity_id,
|
||||
"power_sensor_entity_id": central.power_sensor_entity_id,
|
||||
"max_power_sensor_entity_id": central.max_power_sensor_entity_id,
|
||||
"overpowering_state": self.overpowering_state,
|
||||
"device_power": self._device_power,
|
||||
"device_power": self.from_watts(self._device_power, power_unit),
|
||||
"power_temp": self._power_temp,
|
||||
"current_power": vtherm_api.central_power_manager.current_power,
|
||||
"current_max_power": vtherm_api.central_power_manager.current_max_power,
|
||||
"mean_cycle_power": self.mean_cycle_power,
|
||||
"current_power": central.from_watts(central.current_power, central_power_unit),
|
||||
"current_max_power": central.from_watts(central.current_max_power, central_power_unit),
|
||||
"mean_cycle_power": self.from_watts(self.mean_cycle_power, power_unit),
|
||||
"power_unit": power_unit,
|
||||
"energy_unit": self.energy_unit,
|
||||
"central_power_unit": central_power_unit,
|
||||
}
|
||||
}
|
||||
)
|
||||
else:
|
||||
power_unit = self.power_unit
|
||||
extra_state_attributes.update(
|
||||
{
|
||||
"power_manager": {
|
||||
"device_power": self._device_power,
|
||||
"mean_cycle_power": self.mean_cycle_power,
|
||||
"device_power": self.from_watts(self._device_power, power_unit),
|
||||
"mean_cycle_power": self.from_watts(self.mean_cycle_power, power_unit),
|
||||
"power_unit": power_unit,
|
||||
"energy_unit": self.energy_unit,
|
||||
}
|
||||
}
|
||||
)
|
||||
@@ -135,9 +158,7 @@ class FeaturePowerManager(BaseFeatureManager):
|
||||
current_power = vtherm_api.central_power_manager.current_power
|
||||
current_max_power = vtherm_api.central_power_manager.current_max_power
|
||||
started_vtherm_total_power = vtherm_api.central_power_manager.started_vtherm_total_power
|
||||
current_started_power = vtherm_api.central_power_manager.get_started_vtherm_power(
|
||||
effective_reservation_key
|
||||
)
|
||||
current_started_power = vtherm_api.central_power_manager.get_started_vtherm_power(effective_reservation_key)
|
||||
if (
|
||||
current_power is None
|
||||
or current_max_power is None
|
||||
@@ -334,9 +355,20 @@ class FeaturePowerManager(BaseFeatureManager):
|
||||
|
||||
@property
|
||||
def device_power(self) -> float:
|
||||
"""Return the device power"""
|
||||
"""Return the device power (normalized in Watts)"""
|
||||
|
||||
return self._device_power
|
||||
|
||||
@property
|
||||
def power_unit(self) -> str:
|
||||
"""Return the configured power unit of the VTherm ("W" or "kW")"""
|
||||
return to_legal_power_unit(self._power_unit)
|
||||
|
||||
@property
|
||||
def energy_unit(self) -> str:
|
||||
"""Return the energy unit matching the configured power unit"""
|
||||
return UnitOfEnergy.WATT_HOUR if self._power_unit == POWER_UNIT_WATT else UnitOfEnergy.KILO_WATT_HOUR
|
||||
|
||||
@property
|
||||
def mean_cycle_power(self) -> float | None:
|
||||
"""Returns the mean power consumption during the cycle"""
|
||||
@@ -359,5 +391,13 @@ class FeaturePowerManager(BaseFeatureManager):
|
||||
"""Return a stable fallback key for temporary power reservations."""
|
||||
return getattr(self._vtherm, "entity_id", None) or self._vtherm.name
|
||||
|
||||
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)
|
||||
|
||||
def __str__(self):
|
||||
return f"PowerManager-{self.name}"
|
||||
|
||||
@@ -28,8 +28,9 @@ class FeatureRepairIncorrectStateManager(BaseFeatureManager):
|
||||
On each control heating cycle, if the feature is enabled, it compares
|
||||
the desired state (should_device_be_active) with the actual state
|
||||
(is_device_active) for each underlying entity. If they differ, it
|
||||
re-emits the desired command. The number of consecutive repairs is
|
||||
capped at REPAIR_MAX_ATTEMPTS to prevent infinite loops.
|
||||
re-emits the desired command. After REPAIR_MAX_ATTEMPTS consecutive
|
||||
repairs, repairs are paused for REPAIR_MAX_ATTEMPTS - 1 cycles and then
|
||||
retried, to prevent infinite loops.
|
||||
|
||||
The feature only activates at least REPAIR_MIN_DELAY_AFTER_INIT_SEC
|
||||
seconds after VTherm has become fully operational (is_ready).
|
||||
@@ -105,21 +106,24 @@ class FeatureRepairIncorrectStateManager(BaseFeatureManager):
|
||||
if elapsed < REPAIR_MIN_DELAY_AFTER_INIT_SEC:
|
||||
return False
|
||||
|
||||
# Stop if the maximum consecutive repair count is reached
|
||||
# Pause repairs if the maximum consecutive repair count is reached.
|
||||
# The pause lasts REPAIR_MAX_ATTEMPTS - 1 cycles, then repairs are retried.
|
||||
if self._consecutive_repair_count >= REPAIR_MAX_ATTEMPTS:
|
||||
_LOGGER.error(
|
||||
"%s - RepairIncorrectStateManager: maximum repair attempts (%d) " "reached. Stopped attempting repairs to avoid infinite loop.",
|
||||
self._vtherm.name,
|
||||
REPAIR_MAX_ATTEMPTS,
|
||||
)
|
||||
self._consecutive_repair_count += 1
|
||||
if self._consecutive_repair_count >= 2 * REPAIR_MAX_ATTEMPTS:
|
||||
_LOGGER.info(
|
||||
"%s - RepairIncorrectStateManager: consecutive repair count has doubled the max attempts, resetting the counter to allow new repair attempts.",
|
||||
"%s - RepairIncorrectStateManager: repair pause is over, resetting the counter and retrying repairs.",
|
||||
self._vtherm.name,
|
||||
)
|
||||
self._consecutive_repair_count = 0
|
||||
else:
|
||||
_LOGGER.error(
|
||||
"%s - RepairIncorrectStateManager: maximum consecutive repair attempts (%d) reached. Repairs are paused (skipped cycle %d/%d) and will be retried afterwards.",
|
||||
self._vtherm.name,
|
||||
REPAIR_MAX_ATTEMPTS,
|
||||
self._consecutive_repair_count - REPAIR_MAX_ATTEMPTS,
|
||||
REPAIR_MAX_ATTEMPTS - 1,
|
||||
)
|
||||
return False
|
||||
|
||||
repaired = False
|
||||
|
||||
@@ -22,6 +22,6 @@
|
||||
"vtherm_api>=0.4.0"
|
||||
],
|
||||
"ssdp": [],
|
||||
"version": "10.2.0",
|
||||
"version": "10.3.0",
|
||||
"zeroconf": []
|
||||
}
|
||||
|
||||
@@ -45,6 +45,9 @@ from .const import (
|
||||
CONF_USE_CENTRAL_BOILER_FEATURE,
|
||||
overrides,
|
||||
CONF_USE_MAIN_CENTRAL_CONFIG,
|
||||
POWER_UNIT_WATT,
|
||||
power_from_watts,
|
||||
power_to_watts,
|
||||
)
|
||||
|
||||
from .vtherm_preset import VThermPreset, VThermPresetWithAC, VThermPresetWithAway, VThermPresetWithACAway, PRESET_TEMP_SUFFIX, PRESET_AWAY_SUFFIX
|
||||
@@ -251,6 +254,11 @@ class ActivateBoilerPowerThresholdNumber(NumberEntity, RestoreEntity): # pylint
|
||||
def icon(self) -> str | None:
|
||||
return "mdi:water-boiler-auto"
|
||||
|
||||
@property
|
||||
def native_unit_of_measurement(self) -> str | None:
|
||||
"""Return the unit used by the central boiler power sensor."""
|
||||
return VersatileThermostatAPI.get_vtherm_api(self._hass).central_power_manager.power_unit
|
||||
|
||||
@property
|
||||
def device_info(self) -> DeviceInfo:
|
||||
"""Return the device info."""
|
||||
@@ -272,7 +280,12 @@ class ActivateBoilerPowerThresholdNumber(NumberEntity, RestoreEntity): # pylint
|
||||
old_state: CoreState = await self.async_get_last_state()
|
||||
_LOGGER.debug("%s - Calling async_added_to_hass old_state is %s", self, old_state)
|
||||
if old_state is not None:
|
||||
self._attr_value = self._attr_native_value = float(old_state.state)
|
||||
stored_unit = old_state.attributes.get("unit_of_measurement", POWER_UNIT_WATT)
|
||||
restored_watts = power_to_watts(float(old_state.state), stored_unit)
|
||||
self._attr_value = self._attr_native_value = power_from_watts(
|
||||
restored_watts,
|
||||
self.native_unit_of_measurement,
|
||||
)
|
||||
|
||||
@overrides
|
||||
def set_native_value(self, value: float) -> None:
|
||||
|
||||
@@ -220,6 +220,7 @@ class TPIHandler:
|
||||
"""Cleanup on removal."""
|
||||
t = self._thermostat
|
||||
if self._auto_tpi_manager:
|
||||
self._auto_tpi_manager.shutdown()
|
||||
t.hass.async_create_task(self._auto_tpi_manager.async_save_data())
|
||||
|
||||
def on_scheduler_ready(self, scheduler) -> None:
|
||||
|
||||
@@ -9,8 +9,6 @@ from homeassistant.core import HomeAssistant, callback, Event, State
|
||||
|
||||
from homeassistant.const import (
|
||||
UnitOfTime,
|
||||
UnitOfPower,
|
||||
UnitOfEnergy,
|
||||
PERCENTAGE,
|
||||
)
|
||||
|
||||
@@ -59,8 +57,6 @@ from .const import (
|
||||
overrides,
|
||||
)
|
||||
|
||||
THRESHOLD_WATT_KILO = 100
|
||||
|
||||
_LOGGER = get_vtherm_logger(__name__)
|
||||
|
||||
|
||||
@@ -166,15 +162,18 @@ class EnergySensor(VersatileThermostatBaseEntity, SensorEntity):
|
||||
"""Called when my climate have change"""
|
||||
# _LOGGER.debug("%s - climate state change", self._attr_unique_id)
|
||||
|
||||
energy = self.my_climate.total_energy
|
||||
if energy is None:
|
||||
energy_wh = self.my_climate.total_energy
|
||||
if energy_wh is None:
|
||||
return
|
||||
|
||||
if math.isnan(energy) or math.isinf(energy):
|
||||
if math.isnan(energy_wh) or math.isinf(energy_wh):
|
||||
raise ValueError(f"Sensor has illegal state {self.my_climate.total_energy}")
|
||||
|
||||
# Convert from internal Wh to display unit (Wh or kWh)
|
||||
displayed_energy = self.my_climate.power_manager.from_watts(energy_wh, self.my_climate.power_manager.power_unit)
|
||||
|
||||
old_state = self._attr_native_value
|
||||
self._attr_native_value = round(energy, self.suggested_display_precision)
|
||||
self._attr_native_value = round(displayed_energy, self.suggested_display_precision)
|
||||
if old_state != self._attr_native_value:
|
||||
self.async_write_ha_state()
|
||||
return
|
||||
@@ -200,10 +199,7 @@ class EnergySensor(VersatileThermostatBaseEntity, SensorEntity):
|
||||
if not self.my_climate:
|
||||
return None
|
||||
|
||||
if self.my_climate.power_manager.device_power > THRESHOLD_WATT_KILO:
|
||||
return UnitOfEnergy.WATT_HOUR
|
||||
else:
|
||||
return UnitOfEnergy.KILO_WATT_HOUR
|
||||
return self.my_climate.power_manager.energy_unit
|
||||
|
||||
@property
|
||||
def suggested_display_precision(self) -> int | None:
|
||||
@@ -233,12 +229,17 @@ class MeanPowerSensor(VersatileThermostatBaseEntity, SensorEntity):
|
||||
raise ValueError(f"Sensor has illegal state {mean_cycle_power}")
|
||||
|
||||
mean_cycle_power = float(mean_cycle_power)
|
||||
# Convert from internal Watts to display unit
|
||||
displayed_power = self.my_climate.power_manager.from_watts(mean_cycle_power, self.my_climate.power_manager.power_unit)
|
||||
|
||||
old_state = self._attr_native_value
|
||||
self._attr_native_value = round(
|
||||
mean_cycle_power,
|
||||
self.suggested_display_precision,
|
||||
)
|
||||
if displayed_power is None:
|
||||
self._attr_native_value = None
|
||||
else:
|
||||
self._attr_native_value = round(
|
||||
displayed_power,
|
||||
self.suggested_display_precision,
|
||||
)
|
||||
if old_state != self._attr_native_value:
|
||||
self.async_write_ha_state()
|
||||
return
|
||||
@@ -260,13 +261,10 @@ class MeanPowerSensor(VersatileThermostatBaseEntity, SensorEntity):
|
||||
if not self.my_climate:
|
||||
return None
|
||||
|
||||
if self.my_climate.power_manager.device_power > THRESHOLD_WATT_KILO:
|
||||
return UnitOfPower.WATT
|
||||
else:
|
||||
return UnitOfPower.KILO_WATT
|
||||
return self.my_climate.power_manager.power_unit
|
||||
|
||||
@property
|
||||
def suggested_display_precision(self) -> int | None:
|
||||
def suggested_display_precision(self) -> int:
|
||||
"""Return the suggested number of decimal digits for display."""
|
||||
return 3
|
||||
|
||||
@@ -969,6 +967,10 @@ class TotalPowerActiveDeviceForBoilerSensor(NbActiveDeviceForBoilerSensor):
|
||||
def device_class(self) -> SensorDeviceClass | None:
|
||||
return SensorDeviceClass.POWER
|
||||
|
||||
@property
|
||||
def native_unit_of_measurement(self) -> str | None:
|
||||
return VersatileThermostatAPI.get_vtherm_api(self._hass).central_power_manager.power_unit
|
||||
|
||||
@property
|
||||
def suggested_display_precision(self) -> int | None:
|
||||
"""Return the suggested number of decimal digits for display."""
|
||||
@@ -1074,7 +1076,11 @@ class TotalPowerActiveDeviceForBoilerSensor(NbActiveDeviceForBoilerSensor):
|
||||
|
||||
total_active_power += mean_cycle_power
|
||||
|
||||
self._attr_native_value = total_active_power
|
||||
central_power_manager = VersatileThermostatAPI.get_vtherm_api(self._hass).central_power_manager
|
||||
self._attr_native_value = central_power_manager.from_watts(
|
||||
total_active_power,
|
||||
central_power_manager.power_unit,
|
||||
)
|
||||
self._attr_active_device_ids = active_device_ids
|
||||
|
||||
self.async_write_ha_state()
|
||||
|
||||
@@ -69,6 +69,7 @@
|
||||
"temp_max": "Maximum temperature allowed",
|
||||
"step_temperature": "Temperature step",
|
||||
"device_power": "Device power",
|
||||
"power_unit": "Power unit (for device_power)",
|
||||
"use_central_mode": "Enable the control by central entity (requires central config). Check to enable the control of the VTherm with the select central_mode entities.",
|
||||
"use_main_central_config": "Use additional central main configuration. Check to use the central main configuration (outdoor temperature, min, max, step, ...).",
|
||||
"used_by_controls_central_boiler": "Used by central boiler. Check if this VTherm should have control on the central boiler"
|
||||
@@ -80,7 +81,8 @@
|
||||
"step_temperature": "Temperature step for setting the target temperature",
|
||||
"temperature_sensor_entity_id": "Room temperature sensor entity id",
|
||||
"last_seen_temperature_sensor_entity_id": "Last seen room temperature sensor entity id. Should be datetime sensor",
|
||||
"external_temperature_sensor_entity_id": "Outdoor temperature sensor entity id. Not used if central configuration is selected"
|
||||
"external_temperature_sensor_entity_id": "Outdoor temperature sensor entity id. Not used if central configuration is selected",
|
||||
"power_unit": "Unit for device power consumption"
|
||||
}
|
||||
},
|
||||
"features": {
|
||||
@@ -208,16 +210,18 @@
|
||||
},
|
||||
"power": {
|
||||
"title": "Power management",
|
||||
"description": "Power management attributes.\nGives the power and max power sensor of your home.\nSpecify the power consumption of the heater when on.\nAll sensors and device power should use the same unit (kW or W)",
|
||||
"description": "Power management attributes.\nSelect W or kW for each VTherm device power, and W, kW, or Auto for the central configuration.\nValues are normalized internally, so W and kW can be mixed safely.",
|
||||
"data": {
|
||||
"power_sensor_entity_id": "Power",
|
||||
"max_power_sensor_entity_id": "Max power",
|
||||
"power_unit": "Central power unit",
|
||||
"power_temp": "Shedding temperature",
|
||||
"use_power_central_config": "Use central power configuration"
|
||||
},
|
||||
"data_description": {
|
||||
"power_sensor_entity_id": "Power sensor entity id",
|
||||
"max_power_sensor_entity_id": "Max power sensor entity id",
|
||||
"power_unit": "Select power unit or Auto to detect from sensor",
|
||||
"power_temp": "Temperature for Power shedding",
|
||||
"use_power_central_config": "Check to use the central power configuration. Uncheck to use a specific power configuration for this VTherm"
|
||||
}
|
||||
@@ -594,7 +598,7 @@
|
||||
},
|
||||
"power": {
|
||||
"title": "Power - {name}",
|
||||
"description": "Power management attributes.\nGives the power and max power sensor of your home.\nSpecify the power consumption of the heater when on.\nAll sensors and device power should use the same unit (kW or W)",
|
||||
"description": "Power management attributes.\nSelect W or kW for each VTherm device power, and W, kW, or Auto for the central configuration.\nValues are normalized internally, so W and kW can be mixed safely.",
|
||||
"data": {
|
||||
"power_sensor_entity_id": "Power",
|
||||
"max_power_sensor_entity_id": "Max power",
|
||||
@@ -844,6 +848,19 @@
|
||||
"discovery": "Discovery",
|
||||
"fine_tuning": "Fine Tuning"
|
||||
}
|
||||
},
|
||||
"power_unit": {
|
||||
"options": {
|
||||
"w": "Watts (W)",
|
||||
"kw": "Kilowatts (kW)"
|
||||
}
|
||||
},
|
||||
"central_power_unit": {
|
||||
"options": {
|
||||
"w": "Watts (W)",
|
||||
"kw": "Kilowatts (kW)",
|
||||
"auto": "Auto (detect from sensor)"
|
||||
}
|
||||
}
|
||||
},
|
||||
"entity": {
|
||||
|
||||
@@ -212,8 +212,29 @@ class ThermostatOverValve(ThermostatProp[UnderlyingValve]): # pylint: disable=a
|
||||
# Temperature not yet available; preserve the current valve position.
|
||||
return
|
||||
|
||||
self.apply_valve_command_percent(current_on_percent, force=True)
|
||||
|
||||
def apply_valve_command_percent(
|
||||
self,
|
||||
on_percent: float,
|
||||
force: bool = False,
|
||||
) -> float:
|
||||
"""Accept a requested valve command and return the retained ratio.
|
||||
|
||||
This is the single conversion point between a proportional algorithm's
|
||||
continuous output and the integer command exposed by the thermostat.
|
||||
"""
|
||||
self.stop_recalculate_later()
|
||||
|
||||
if self._auto_regulation_period_min is None or self._auto_regulation_dpercent is None:
|
||||
_LOGGER.warning(
|
||||
"%s - auto_regulation_period_min or auto_regulation_dpercent is not set. Keeping current valve command.",
|
||||
self,
|
||||
)
|
||||
return self.valve_open_percent / 100.0
|
||||
|
||||
new_valve_percent = round(
|
||||
max(0, min(current_on_percent, 1)) * 100
|
||||
max(0, min(on_percent, 1)) * 100
|
||||
)
|
||||
|
||||
# Issue 533 - don't filter with dtemp if valve should be close. Else it will never close
|
||||
@@ -233,11 +254,23 @@ class ThermostatOverValve(ThermostatProp[UnderlyingValve]): # pylint: disable=a
|
||||
dpercent,
|
||||
)
|
||||
|
||||
return
|
||||
return self.valve_open_percent / 100.0
|
||||
|
||||
if self._valve_open_percent == new_valve_percent:
|
||||
_LOGGER.debug("%s - no change in valve_open_percent.", self)
|
||||
return
|
||||
return self.valve_open_percent / 100.0
|
||||
|
||||
now = self.now
|
||||
if self._last_calculation_timestamp is not None:
|
||||
period = (now - self._last_calculation_timestamp).total_seconds() / 60
|
||||
if not force and period < self._auto_regulation_period_min:
|
||||
_LOGGER.info(
|
||||
"%s - do not apply valve command because regulation_period (%d) is not exceeded",
|
||||
self,
|
||||
period,
|
||||
)
|
||||
self.do_recalculate_later()
|
||||
return self.valve_open_percent / 100.0
|
||||
|
||||
self._valve_open_percent = new_valve_percent
|
||||
|
||||
@@ -249,6 +282,7 @@ class ThermostatOverValve(ThermostatProp[UnderlyingValve]): # pylint: disable=a
|
||||
# self.calculate_hvac_action()
|
||||
self.update_custom_attributes()
|
||||
self.async_write_ha_state()
|
||||
return self.valve_open_percent / 100.0
|
||||
|
||||
def do_recalculate_later(self):
|
||||
"""A utility function to set the valve open percent later on all underlyings"""
|
||||
|
||||
@@ -69,6 +69,7 @@
|
||||
"temp_max": "Maximální povolená teplota",
|
||||
"step_temperature": "Krok teploty",
|
||||
"device_power": "Výkon zařízení",
|
||||
"power_unit": "Jednotka výkonu (pro výkon zařízení)",
|
||||
"use_central_mode": "Povolit řízení centrální entitou (vyžaduje centrální konfiguraci). Zaškrtněte pro povolení řízení VTherm pomocí entit select central_mode.",
|
||||
"use_main_central_config": "Použít dodatečnou centrální hlavní konfiguraci. Zaškrtněte pro použití centrální hlavní konfigurace (venkovní teplota, min, max, krok, ...).",
|
||||
"used_by_controls_central_boiler": "Používán centrálním kotlem. Zaškrtněte, pokud má tento VTherm řídit centrální kotel"
|
||||
@@ -80,7 +81,8 @@
|
||||
"step_temperature": "Krok teploty pro nastavení cílové teploty",
|
||||
"temperature_sensor_entity_id": "ID entity senzoru teploty místnosti",
|
||||
"last_seen_temperature_sensor_entity_id": "ID entity posledního času měření teploty místnosti. Měl by být datetime senzor",
|
||||
"external_temperature_sensor_entity_id": "ID entity senzoru venkovní teploty. Nepoužívá se, pokud je zvolena centrální konfigurace"
|
||||
"external_temperature_sensor_entity_id": "ID entity senzoru venkovní teploty. Nepoužívá se, pokud je zvolena centrální konfigurace",
|
||||
"power_unit": "Jednotka spotřeby výkonu zařízení"
|
||||
}
|
||||
},
|
||||
"features": {
|
||||
@@ -208,16 +210,18 @@
|
||||
},
|
||||
"power": {
|
||||
"title": "Správa výkonu",
|
||||
"description": "Atributy správy výkonu.\nUdává výkon a maximální výkonový senzor vašeho domova.\nUveďte spotřebu energie ohřívače při zapnutí.\nVšechny senzory a výkon zařízení by měly používat stejnou jednotku (kW nebo W) [](https://github.com/jmcollin78/versatile_thermostat/blob/main/documentation/cs/feature-power.md)",
|
||||
"description": "Atributy správy výkonu.\nPro výkon zařízení každého VTherm vyberte W nebo kW a pro centralizovanou konfiguraci W, kW nebo Automaticky.\nHodnoty jsou interně normalizovány, takže lze bezpečně kombinovat W a kW. [](https://github.com/jmcollin78/versatile_thermostat/blob/main/documentation/cs/feature-power.md)",
|
||||
"data": {
|
||||
"power_sensor_entity_id": "Výkon",
|
||||
"max_power_sensor_entity_id": "Maximální výkon",
|
||||
"power_unit": "Jednotka centrálního výkonu",
|
||||
"power_temp": "Teplota odlehčení",
|
||||
"use_power_central_config": "Použít centrální konfiguraci výkonu"
|
||||
},
|
||||
"data_description": {
|
||||
"power_sensor_entity_id": "ID entity senzoru výkonu",
|
||||
"max_power_sensor_entity_id": "ID entity senzoru maximálního výkonu",
|
||||
"power_unit": "Vyberte jednotku výkonu nebo Automaticky k automatické detekci ze senzoru",
|
||||
"power_temp": "Teplota pro odlehčení výkonu",
|
||||
"use_power_central_config": "Zaškrtněte pro použití centrální konfigurace výkonu. Odškrtněte pro použití specifické konfigurace výkonu pro tento VTherm"
|
||||
}
|
||||
@@ -844,6 +848,19 @@
|
||||
"discovery": "Objev",
|
||||
"fine_tuning": "Jemné ladění"
|
||||
}
|
||||
},
|
||||
"power_unit": {
|
||||
"options": {
|
||||
"w": "Watty (W)",
|
||||
"kw": "Kilowatty (kW)"
|
||||
}
|
||||
},
|
||||
"central_power_unit": {
|
||||
"options": {
|
||||
"w": "Watty (W)",
|
||||
"kw": "Kilowatty (kW)",
|
||||
"auto": "Automaticky (automatická detekce ze senzoru)"
|
||||
}
|
||||
}
|
||||
},
|
||||
"entity": {
|
||||
@@ -1046,4 +1063,4 @@
|
||||
"message": "Automatické učení TPI pro {name} bylo zastaveno kvůli 3 po sobě jdoucím selháním. Důvod: {reason}. Zkontrolujte prosím svou konfiguraci."
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -69,6 +69,7 @@
|
||||
"temp_max": "Zulässige Höchsttemperatur",
|
||||
"step_temperature": "Temperaturschritte",
|
||||
"device_power": "Geräteleistung",
|
||||
"power_unit": "Leistungseinheit (für Geräteleistung)",
|
||||
"use_central_mode": "Kontrolle durch zentrale Stelle zulassen (zentrale Konfiguration erforderlich). Aktivieren, um die Steuerung des VTherm mit den ausgewählten Zentralmodus-Entities zu aktivieren.",
|
||||
"use_main_central_config": "Zusätzliche zentrale Konfiguration verwenden. Anwählen, wenn eine zusätzliche zentrale Konfiguration verwendet werden soll (Außentemperatur, Min, Max, Stufe, ...).",
|
||||
"used_by_controls_central_boiler": "Zentralheizung verwenden. Wenn angewählt, steuert dieses VTherm den zentralen Heizkessel."
|
||||
@@ -80,7 +81,8 @@
|
||||
"step_temperature": "Temperaturschritt für die Einstellung der Zieltemperatur",
|
||||
"temperature_sensor_entity_id": "Entity-ID des Raumtemperatursensor",
|
||||
"last_seen_temperature_sensor_entity_id": "Entity-ID des Sensors, der das Datum und die Uhrzeit der letzten Datenübermittlung vom Temperatursensors angibt. Der Status muss im Format Datum Uhrzeit angegeben werden (z. B.: 2024-03-31T17:07:03+00:00).",
|
||||
"external_temperature_sensor_entity_id": "Außentemperatursensor Entity-ID. Wird nicht verwendet, wenn zentrale Konfiguration gewählt wurde."
|
||||
"external_temperature_sensor_entity_id": "Außentemperatursensor Entity-ID. Wird nicht verwendet, wenn zentrale Konfiguration gewählt wurde.",
|
||||
"power_unit": "Leistungsverbrauchseinheit des Geräts"
|
||||
}
|
||||
},
|
||||
"features": {
|
||||
@@ -208,16 +210,18 @@
|
||||
},
|
||||
"power": {
|
||||
"title": "Powermanagement",
|
||||
"description": "Wählt automatisch die Voreinstellung 'power', wenn der Energieverbrauch ein Maximum überschreitet.\nGibt die Entity-IDs der Sensoren an, die die Gesamtleistung und die maximal zulässige Leistung messen.\nGib anschließend die Leistung des Geräts an.\nAlle Sensoren und die Geräteleistung sollten die gleiche Einheit verwenden (kW oder W).",
|
||||
"description": "Attribute für das Powermanagement.\nWählen Sie W oder kW für die Leistung jedes VTherm sowie W, kW oder Automatisch für die zentrale Konfiguration.\nDie Werte werden intern normalisiert, daher können W und kW sicher gemischt werden.",
|
||||
"data": {
|
||||
"power_sensor_entity_id": "Gesamtleistungssensor (Entity-ID)",
|
||||
"max_power_sensor_entity_id": "Sensor für maximale Leistung (Entity-ID)",
|
||||
"power_unit": "Zentrale Leistungseinheit",
|
||||
"power_temp": "Temperatur bei Lastabwurf",
|
||||
"use_power_central_config": "Zentrales Powermanagement verwenden"
|
||||
},
|
||||
"data_description": {
|
||||
"power_sensor_entity_id": "Entity-ID des Gesamtleistungssensors der Wohnung/des Hauses",
|
||||
"max_power_sensor_entity_id": "Entity-ID des Maximalleistungssensors vor Lastabwurf",
|
||||
"power_unit": "Wählen Sie die Leistungseinheit oder Automatisch, um sie automatisch vom Sensor zu erkennen",
|
||||
"power_temp": "Zieltemperatur bei Leistungsreduzierung",
|
||||
"use_power_central_config": "Aktivieren, zur Verwendung des zentralen Powermanagements. Deaktivieren, um eine spezifische Leistungskonfiguration für dieses VTherm zu verwenden."
|
||||
}
|
||||
@@ -703,7 +707,7 @@
|
||||
"heater_cooling_time": "Abkühlzeit (min)",
|
||||
"auto_tpi_aggressiveness": "Aggressivität",
|
||||
"auto_tpi_enable_advanced_settings": "Erweiterte Einstellungen aktivieren",
|
||||
"auto_tpi_continuous_kext": "Kontinuierliches Kext-lernen"
|
||||
"auto_tpi_continuous_kext": "Kontinuierliches Kext-lernen"
|
||||
},
|
||||
"data_description": {
|
||||
"auto_tpi_learning_type": "Wähle 'Erkundung' für den ersten Start (gewichteter Durchschnitt, Gewicht 1) oder 'Feinabstimmung' für kontinuierliche Anpassungen (EWMA, Alpha 0,08).",
|
||||
@@ -736,7 +740,7 @@
|
||||
"data_description": {
|
||||
"auto_tpi_ema_alpha": "Glättungsfaktor (0-1). Höher = schnellere Anpassung",
|
||||
"auto_tpi_ema_decay_rate": "Rate, mit der Alpha im Laufe der Zeit abnimmt (Stabilisierung)",
|
||||
"auto_tpi_continuous_kext_alpha": "Glättungsfaktor für kontinuierliches Kext-Lernen (Alpha). Standardwert 0,04 (Anpassungszeit von ca. 3–5 Tagen)."
|
||||
"auto_tpi_continuous_kext_alpha": "Glättungsfaktor für kontinuierliches Kext-Lernen (Alpha). Standardwert 0,04 (Anpassungszeit von ca. 3–5 Tagen)."
|
||||
}
|
||||
},
|
||||
"heating_failure_detection": {
|
||||
@@ -844,6 +848,19 @@
|
||||
"discovery": "Erkundung",
|
||||
"fine_tuning": "Feinjustierung"
|
||||
}
|
||||
},
|
||||
"power_unit": {
|
||||
"options": {
|
||||
"w": "Watt (W)",
|
||||
"kw": "Kilowatt (kW)"
|
||||
}
|
||||
},
|
||||
"central_power_unit": {
|
||||
"options": {
|
||||
"w": "Watt (W)",
|
||||
"kw": "Kilowatt (kW)",
|
||||
"auto": "Automatisch (automatische Erkennung vom Sensor)"
|
||||
}
|
||||
}
|
||||
},
|
||||
"entity": {
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
"temp_min": "Ελάχιστη επιτρεπτή θερμοκρασία",
|
||||
"temp_max": "Μέγιστη επιτρεπτή θερμοκρασία",
|
||||
"device_power": "Ισχύς συσκευής",
|
||||
"power_unit": "Μονάδα ισχύος (για την ισχύ της συσκευής)",
|
||||
"use_window_feature": "Χρήση ανίχνευσης παραθύρου",
|
||||
"use_motion_feature": "Χρήση ανίχνευσης κίνησης",
|
||||
"use_power_feature": "Χρήση διαχείρισης ισχύος",
|
||||
@@ -27,7 +28,16 @@
|
||||
"step_temperature": "Temperature step for setting the target temperature",
|
||||
"temperature_sensor_entity_id": "Room temperature sensor entity id",
|
||||
"last_seen_temperature_sensor_entity_id": "Last seen room temperature sensor entity id. Should be datetime sensor",
|
||||
"external_temperature_sensor_entity_id": "Outdoor temperature sensor entity id. Not used if central configuration is selected"
|
||||
"external_temperature_sensor_entity_id": "Outdoor temperature sensor entity id. Not used if central configuration is selected",
|
||||
"power_unit": "Μονάδα κατανάλωσης ισχύος της συσκευής"
|
||||
}
|
||||
},
|
||||
"main": {
|
||||
"data": {
|
||||
"power_unit": "Μονάδα ισχύος (για την ισχύ της συσκευής)"
|
||||
},
|
||||
"data_description": {
|
||||
"power_unit": "Μονάδα κατανάλωσης ισχύος της συσκευής"
|
||||
}
|
||||
},
|
||||
"lock": {
|
||||
@@ -151,11 +161,15 @@
|
||||
},
|
||||
"power": {
|
||||
"title": "Διαχείριση Ενέργειας",
|
||||
"description": "Χαρακτηριστικά διαχείρισης ενέργειας.\nΔίνει τον αισθητήρα ενέργειας και τον μέγιστο αισθητήρα ενέργειας του σπιτιού σας.\nΣτη συνέχεια καθορίστε την κατανάλωση ενέργειας του θερμαντήρα όταν είναι ενεργοποιημένος.\nΌλοι οι αισθητήρες και η ισχύς της συσκευής πρέπει να έχουν την ίδια μονάδα (kW ή W).\nΑφήστε το αντίστοιχο entity_id κενό αν δεν χρησιμοποιείται.",
|
||||
"description": "Χαρακτηριστικά διαχείρισης ισχύος.\nΕπιλέξτε W ή kW για την ισχύ συσκευής κάθε VTherm και W, kW ή Αυτόματα για την κεντρική διαμόρφωση.\nΟι τιμές κανονικοποιούνται εσωτερικά, επομένως οι μονάδες W και kW μπορούν να συνδυαστούν με ασφάλεια.",
|
||||
"data": {
|
||||
"power_sensor_entity_id": "Ταυτότητα οντότητας αισθητήρα ενέργειας",
|
||||
"max_power_sensor_entity_id": "Ταυτότητα οντότητας αισθητήρα μέγιστης ενέργειας",
|
||||
"power_unit": "Κεντρική μονάδα ισχύος",
|
||||
"power_temp": "Θερμοκρασία για Αποβολή Ενέργειας"
|
||||
},
|
||||
"data_description": {
|
||||
"power_unit": "Επιλέξτε μονάδα ισχύος ή Αυτόματα για αυτόματη ανίχνευση από τον αισθητήρα"
|
||||
}
|
||||
},
|
||||
"presence": {
|
||||
@@ -560,6 +574,19 @@
|
||||
"auto_fan_high": "High",
|
||||
"auto_fan_turbo": "Turbo"
|
||||
}
|
||||
},
|
||||
"power_unit": {
|
||||
"options": {
|
||||
"w": "Watt (W)",
|
||||
"kw": "Kilowatt (kW)"
|
||||
}
|
||||
},
|
||||
"central_power_unit": {
|
||||
"options": {
|
||||
"w": "Watt (W)",
|
||||
"kw": "Kilowatt (kW)",
|
||||
"auto": "Αυτόματη (αυτόματη ανίχνευση από τον αισθητήρα)"
|
||||
}
|
||||
}
|
||||
},
|
||||
"entity": {
|
||||
|
||||
@@ -69,6 +69,7 @@
|
||||
"temp_max": "Maximum temperature allowed",
|
||||
"step_temperature": "Temperature step",
|
||||
"device_power": "Device power",
|
||||
"power_unit": "Power unit (for device power)",
|
||||
"use_central_mode": "Enable the control by central entity (requires central config). Check to enable the control of the VTherm with the select central_mode entities.",
|
||||
"use_main_central_config": "Use additional central main configuration. Check to use the central main configuration (outdoor temperature, min, max, step, ...).",
|
||||
"used_by_controls_central_boiler": "Used by central boiler. Check if this VTherm should have control on the central boiler"
|
||||
@@ -80,7 +81,8 @@
|
||||
"step_temperature": "Temperature step for setting the target temperature",
|
||||
"temperature_sensor_entity_id": "Room temperature sensor entity id",
|
||||
"last_seen_temperature_sensor_entity_id": "Last seen room temperature sensor entity id. Should be datetime sensor",
|
||||
"external_temperature_sensor_entity_id": "Outdoor temperature sensor entity id. Not used if central configuration is selected"
|
||||
"external_temperature_sensor_entity_id": "Outdoor temperature sensor entity id. Not used if central configuration is selected",
|
||||
"power_unit": "Device power consumption unit"
|
||||
}
|
||||
},
|
||||
"features": {
|
||||
@@ -208,16 +210,18 @@
|
||||
},
|
||||
"power": {
|
||||
"title": "Power management",
|
||||
"description": "Power management attributes.\nGives the power and max power sensor of your home.\nSpecify the power consumption of the heater when on.\nAll sensors and device power should use the same unit (kW or W)",
|
||||
"description": "Power management attributes.\nSelect W or kW for each VTherm device power, and W, kW, or Auto for the central configuration.\nValues are normalized internally, so W and kW can be mixed safely.",
|
||||
"data": {
|
||||
"power_sensor_entity_id": "Power",
|
||||
"max_power_sensor_entity_id": "Max power",
|
||||
"power_unit": "Central power unit",
|
||||
"power_temp": "Shedding temperature",
|
||||
"use_power_central_config": "Use central power configuration"
|
||||
},
|
||||
"data_description": {
|
||||
"power_sensor_entity_id": "Power sensor entity id",
|
||||
"max_power_sensor_entity_id": "Max power sensor entity id",
|
||||
"power_unit": "Select the power unit or Auto to auto-detect from the sensor",
|
||||
"power_temp": "Temperature for Power shedding",
|
||||
"use_power_central_config": "Check to use the central power configuration. Uncheck to use a specific power configuration for this VTherm"
|
||||
}
|
||||
@@ -844,6 +848,19 @@
|
||||
"discovery": "Discovery",
|
||||
"fine_tuning": "Fine Tuning"
|
||||
}
|
||||
},
|
||||
"power_unit": {
|
||||
"options": {
|
||||
"w": "Watts (W)",
|
||||
"kw": "Kilowatts (kW)"
|
||||
}
|
||||
},
|
||||
"central_power_unit": {
|
||||
"options": {
|
||||
"w": "Watts (W)",
|
||||
"kw": "Kilowatts (kW)",
|
||||
"auto": "Auto (auto-detect from sensor)"
|
||||
}
|
||||
}
|
||||
},
|
||||
"entity": {
|
||||
|
||||
@@ -70,6 +70,7 @@
|
||||
"temp_max": "Température maximale permise",
|
||||
"step_temperature": "Pas de température",
|
||||
"device_power": "Puissance de l'équipement",
|
||||
"power_unit": "Unité de puissance (pour puissance équipement)",
|
||||
"use_central_mode": "Autoriser le controle par une entity centrale ('nécessite une config. centrale`). Cochez pour autoriser le contrôle du VTherm par la liste déroulante 'central_mode' de l'entité configuration centrale.",
|
||||
"use_main_central_config": "Utiliser la configuration centrale supplémentaire. Cochez pour utiliser la configuration centrale supplémentaire (température externe, min, max, pas, ...)",
|
||||
"used_by_controls_central_boiler": "Utilisé par la chaudière centrale. Cochez si ce VTherm doit contrôler la chaudière centrale."
|
||||
@@ -81,7 +82,8 @@
|
||||
"step_temperature": "Pas de température pour le réglage de la température cible",
|
||||
"temperature_sensor_entity_id": "Id d'entité du capteur de température",
|
||||
"last_seen_temperature_sensor_entity_id": "Id d'entité du capteur donnant la date et heure de dernière vue capteur de température. L'état doit être au format date heure (ex: 2024-03-31T17:07:03+00:00)",
|
||||
"external_temperature_sensor_entity_id": "Entity id du capteur de température extérieure. Non utilisé si une configuration centrale est définie"
|
||||
"external_temperature_sensor_entity_id": "Entity id du capteur de température extérieure. Non utilisé si une configuration centrale est définie",
|
||||
"power_unit": "Unité de consommation de puissance de l'équipement"
|
||||
}
|
||||
},
|
||||
"features": {
|
||||
@@ -209,16 +211,18 @@
|
||||
},
|
||||
"power": {
|
||||
"title": "Gestion de la puissance",
|
||||
"description": "Sélectionne automatiquement le preset 'power' si la puissance consommée est supérieure à un maximum.\nDonnez les entity id des capteurs qui mesurent la puissance totale et la puissance max autorisée.\nEnsuite donnez la puissance de l'équipement.\nTous les capteurs et la puissance consommée par l'équipement doivent avoir la même unité de mesure (kW ou W)",
|
||||
"description": "Attributs de gestion de la puissance.\nSélectionnez W ou kW pour la puissance de chaque VTherm, et W, kW ou Auto pour la configuration centralisée.\nLes valeurs sont normalisées en interne : les valeurs en W et en kW peuvent donc être mélangées en toute sécurité.",
|
||||
"data": {
|
||||
"power_sensor_entity_id": "Capteur de puissance totale (entity id)",
|
||||
"max_power_sensor_entity_id": "Capteur de puissance Max (entity id)",
|
||||
"power_unit": "Unité de puissance centrale",
|
||||
"power_temp": "Température si délestaqe",
|
||||
"use_power_central_config": "Utiliser la configuration centrale de la puissance"
|
||||
},
|
||||
"data_description": {
|
||||
"power_sensor_entity_id": "Entity id du capteur de puissance totale du logement",
|
||||
"max_power_sensor_entity_id": "Entity id du capteur de puissance Max autorisée avant délestage",
|
||||
"power_unit": "Sélectionnez l'unité de puissance ou Auto pour la détecter automatiquement depuis le capteur",
|
||||
"power_temp": "Température cible si délestaqe",
|
||||
"use_power_central_config": "Cochez pour utiliser la configuration centrale de la puissance. Décochez et saisissez les attributs pour utiliser une configuration spécifique de la puissance"
|
||||
}
|
||||
@@ -846,6 +850,19 @@
|
||||
"discovery": "Découverte",
|
||||
"fine_tuning": "Ajustement fin"
|
||||
}
|
||||
},
|
||||
"power_unit": {
|
||||
"options": {
|
||||
"w": "Watts (W)",
|
||||
"kw": "Kilowatts (kW)"
|
||||
}
|
||||
},
|
||||
"central_power_unit": {
|
||||
"options": {
|
||||
"w": "Watts (W)",
|
||||
"kw": "Kilowatts (kW)",
|
||||
"auto": "Auto (détection depuis le capteur)"
|
||||
}
|
||||
}
|
||||
},
|
||||
"entity": {
|
||||
|
||||
@@ -70,6 +70,7 @@
|
||||
"temp_max": "Temperatura massima permessa",
|
||||
"step_temperature": "Passi di temperatura",
|
||||
"device_power": "Potenza del dispositivo",
|
||||
"power_unit": "Unità di potenza (per potenza del dispositivo)",
|
||||
"use_central_mode": "Abilita il controllo tramite entità centrale (richiede configurazione centralizzata). Seleziona per abilitare il controllo di VTherm con le entità central_mode selezionate.",
|
||||
"use_main_central_config": "Utilizzare configurazione principale centralizzata aggiuntiva. Selezionare per utilizzare la configurazione principale centrale (temperatura esterna, min, max, passo, ...).",
|
||||
"used_by_controls_central_boiler": "Utilizzato dalla caldaia centralizzata. Selezionare se questo VTherm deve avere il controllo sulla caldaia centralizzata."
|
||||
@@ -81,7 +82,8 @@
|
||||
"step_temperature": "Passo di temperatura per l'impostazione della temperatura target",
|
||||
"temperature_sensor_entity_id": "Entity id del sensore di temperatura ambiente",
|
||||
"last_seen_temperature_sensor_entity_id": "Ultima visualizzazione entity id del sensore di temperatura ambiente. Dovrebbe essere il sensore data e ora",
|
||||
"external_temperature_sensor_entity_id": "Entity id del sensore di temperatura esterna. Non utilizzato se è selezionata la configurazione centralizzata"
|
||||
"external_temperature_sensor_entity_id": "Entity id del sensore di temperatura esterna. Non utilizzato se è selezionata la configurazione centralizzata",
|
||||
"power_unit": "Unità di consumo di potenza del dispositivo"
|
||||
}
|
||||
},
|
||||
"features": {
|
||||
@@ -209,16 +211,18 @@
|
||||
},
|
||||
"power": {
|
||||
"title": "Gestione energetica",
|
||||
"description": "Attributi di gestione dell'eneregia elettrica.\nIndica la potenza e il sensore della potenza massima della tua abitazione.\nSpecifica il consumo energetico del riscaldatore quando è acceso.\nTutti i sensori e l'alimentazione dei dispositivi devono utilizzare la stessa unità di misura (kW o W)",
|
||||
"description": "Attributi di gestione della potenza.\nSelezionare W o kW per la potenza del dispositivo di ogni VTherm e W, kW o Auto per la configurazione centralizzata.\nI valori sono normalizzati internamente, quindi W e kW possono essere combinati in sicurezza.",
|
||||
"data": {
|
||||
"power_sensor_entity_id": "Potenza",
|
||||
"max_power_sensor_entity_id": "Potenza massima",
|
||||
"power_unit": "Unità di potenza centralizzata",
|
||||
"power_temp": "Distribuzione Temperatura",
|
||||
"use_power_central_config": "Utilizzare configurazione centralizzata della potenza"
|
||||
},
|
||||
"data_description": {
|
||||
"power_sensor_entity_id": "Entity id del sensore di potenza",
|
||||
"max_power_sensor_entity_id": "Entity id del ensore della potenza massima",
|
||||
"power_unit": "Selezionare l'unità di potenza o Auto per rilevare automaticamente dal sensore",
|
||||
"power_temp": "Temperature per la distribuzione della potenza",
|
||||
"use_power_central_config": "Selezionare per utilizzare la configurazione centralizzata della potenza. Deselezionare per utilizzare una configurazione specifica per questo VTherm."
|
||||
}
|
||||
@@ -846,6 +850,19 @@
|
||||
"discovery": "Discovery",
|
||||
"fine_tuning": "Fine Tuning"
|
||||
}
|
||||
},
|
||||
"power_unit": {
|
||||
"options": {
|
||||
"w": "Watt (W)",
|
||||
"kw": "Chilowatt (kW)"
|
||||
}
|
||||
},
|
||||
"central_power_unit": {
|
||||
"options": {
|
||||
"w": "Watt (W)",
|
||||
"kw": "Chilowatt (kW)",
|
||||
"auto": "Auto (rilevamento automatico dal sensore)"
|
||||
}
|
||||
}
|
||||
},
|
||||
"entity": {
|
||||
@@ -1048,4 +1065,4 @@
|
||||
"message": "L'apprendimento automatico TPI per {name} è stato interrotto a causa di 3 errori consecutivi. Motivo: {reason}. Controllare la configurazione."
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -66,6 +66,7 @@
|
||||
"temp_max": "Maksymalna temperatura dopuszczalna",
|
||||
"step_temperature": "Krok temperatury",
|
||||
"device_power": "Moc urządzenia",
|
||||
"power_unit": "Jednostka mocy (dla mocy urządzenia)",
|
||||
"use_central_mode": "Załączenie sterowania przez encję centralną (wymaga konfiguracji centralnej). Zaznacz, aby załączyć sterowanie termostatu wybranymi encjami.",
|
||||
"use_main_central_config": "Użyj dodatkowej konfiguracji centralnej. Zaznacz, aby korzystać z podstawowej konfiguracji centralnej (temperatura zewnętrzna, min, max, krok, itp.).",
|
||||
"used_by_controls_central_boiler": "Używane przez kocioł centralny. Zaznacz, jeśli termostat ma sterować kotłem centralnym."
|
||||
@@ -77,7 +78,8 @@
|
||||
"step_temperature": "Krok temperatury do ustawiania temperatury docelowej",
|
||||
"temperature_sensor_entity_id": "Identyfikator encji sensora temperatury pomieszczenia",
|
||||
"last_seen_temperature_sensor_entity_id": "Czas ostatniego odczytu temperatury pomieszczenia. Powinien być sensorem typu 'data/czas'",
|
||||
"external_temperature_sensor_entity_id": "Identyfikator encji sensora temperatury zewnętrznej. Nie będzie używany, gdy wybrano konfigurację centralną"
|
||||
"external_temperature_sensor_entity_id": "Identyfikator encji sensora temperatury zewnętrznej. Nie będzie używany, gdy wybrano konfigurację centralną",
|
||||
"power_unit": "Jednostka zużycia mocy urządzenia"
|
||||
}
|
||||
},
|
||||
"features": {
|
||||
@@ -205,16 +207,18 @@
|
||||
},
|
||||
"power": {
|
||||
"title": "Energia",
|
||||
"description": "Atrybuty zarządzania energią.\nWskazują moc i maksymalną moc sensora.\nOkreślają pobór mocy grzejnika, gdy jest włączony.\nWszystkie sensory i urządzenia powinny mieć tę samą jednostkę mocy (kW lub W).",
|
||||
"description": "Atrybuty zarządzania mocą.\nDla mocy urządzenia każdego VTherm wybierz W lub kW, a dla konfiguracji centralnej W, kW lub Automatycznie.\nWartości są wewnętrznie normalizowane, dlatego można bezpiecznie łączyć W i kW.",
|
||||
"data": {
|
||||
"power_sensor_entity_id": "Moc",
|
||||
"max_power_sensor_entity_id": "Moc maksymalna",
|
||||
"power_unit": "Centralna jednostka mocy",
|
||||
"power_temp": "Temperatura progowa redukująca zużycie energii",
|
||||
"use_power_central_config": "Użyj centralnej konfiguracji energii"
|
||||
},
|
||||
"data_description": {
|
||||
"power_sensor_entity_id": "Identyfikator encji sensora energii",
|
||||
"max_power_sensor_entity_id": "Identyfikator encji sensora energii maksymalnej",
|
||||
"power_unit": "Wybierz jednostkę mocy lub Automatycznie, aby automatycznie wykryć z sensora",
|
||||
"power_temp": "Temperatura progowa redukująca zużycie energii",
|
||||
"use_power_central_config": "Wybierz, aby użyć centralnej konfiguracji energii. Wyłącz wybór, aby użyć konfiguracji energii dedykowanej dla tego termostatu"
|
||||
}
|
||||
@@ -779,6 +783,19 @@
|
||||
"average": "Średnia",
|
||||
"ema": "Zmienna Średnia Wykładnicza (EMA)"
|
||||
}
|
||||
},
|
||||
"power_unit": {
|
||||
"options": {
|
||||
"w": "Waty (W)",
|
||||
"kw": "Kilowaty (kW)"
|
||||
}
|
||||
},
|
||||
"central_power_unit": {
|
||||
"options": {
|
||||
"w": "Waty (W)",
|
||||
"kw": "Kilowaty (kW)",
|
||||
"auto": "Automatycznie (wykrywanie z czujnika)"
|
||||
}
|
||||
}
|
||||
},
|
||||
"entity": {
|
||||
|
||||
@@ -63,6 +63,7 @@
|
||||
"temp_max": "Максимальная допустимая температура",
|
||||
"step_temperature": "Шаг температуры",
|
||||
"device_power": "Мощность устройства",
|
||||
"power_unit": "Единица мощности (для мощности устройства)",
|
||||
"use_central_mode": "Включить управление через центральную сущность (требует центральной конфигурации). Отметьте для управления VTherm через сущности центральной конфигурации.",
|
||||
"use_main_central_config": "Использовать дополнительную центральную конфигурацию. Отметьте для использования центральной конфигурации (уличная температура, мин, макс, шаг, ...).",
|
||||
"used_by_controls_central_boiler": "Используется центральным котлом. Отметьте, если этот VTherm должен управлять центральным котлом"
|
||||
@@ -74,7 +75,8 @@
|
||||
"step_temperature": "Шаг температуры для установки целевой температуры",
|
||||
"temperature_sensor_entity_id": "ID датчика температуры в помещении",
|
||||
"last_seen_temperature_sensor_entity_id": "ID датчика времени последнего измерения температуры. Должен быть датчиком datetime",
|
||||
"external_temperature_sensor_entity_id": "ID датчика уличной температуры. Не используется, если выбрана центральная конфигурация"
|
||||
"external_temperature_sensor_entity_id": "ID датчика уличной температуры. Не используется, если выбрана центральная конфигурация",
|
||||
"power_unit": "Единица потребления мощности устройства"
|
||||
}
|
||||
},
|
||||
"features": {
|
||||
@@ -200,16 +202,18 @@
|
||||
},
|
||||
"power": {
|
||||
"title": "Управление питанием",
|
||||
"description": "Атрибуты управления питанием.\nУказывает датчики мощности и максимальной мощности вашего дома.\nУкажите потребляемую мощность обогревателя при включении.\nВсе датчики и мощность устройства должны использовать одинаковые единицы измерения (кВт или Вт)",
|
||||
"description": "Атрибуты управления мощностью.\nВыберите Вт или кВт для мощности устройства каждого VTherm, а для центральной конфигурации — Вт, кВт или Авто.\nЗначения нормализуются внутри системы, поэтому Вт и кВт можно безопасно комбинировать.",
|
||||
"data": {
|
||||
"power_sensor_entity_id": "Мощность",
|
||||
"max_power_sensor_entity_id": "Максимальная мощность",
|
||||
"power_unit": "Центральная единица мощности",
|
||||
"power_temp": "Температура снижения мощности",
|
||||
"use_power_central_config": "Использовать центральную конфигурацию питания"
|
||||
},
|
||||
"data_description": {
|
||||
"power_sensor_entity_id": "ID датчика мощности",
|
||||
"max_power_sensor_entity_id": "ID датчика максимальной мощности",
|
||||
"power_unit": "Выберите единицу мощности или Автоматически для автоматического обнаружения из датчика",
|
||||
"power_temp": "Температура для снижения мощности",
|
||||
"use_power_central_config": "Отметьте для использования центральной конфигурации питания. Снимите для использования специфичной конфигурации питания для этого VTherm"
|
||||
}
|
||||
@@ -726,6 +730,19 @@
|
||||
"auto_start_stop_medium": "Среднее обнаружение",
|
||||
"auto_start_stop_fast": "Быстрое обнаружение"
|
||||
}
|
||||
},
|
||||
"power_unit": {
|
||||
"options": {
|
||||
"w": "Ватты (W)",
|
||||
"kw": "Киловатты (kW)"
|
||||
}
|
||||
},
|
||||
"central_power_unit": {
|
||||
"options": {
|
||||
"w": "Ватты (W)",
|
||||
"kw": "Киловатты (kW)",
|
||||
"auto": "Автоматически (автоматическое обнаружение из датчика)"
|
||||
}
|
||||
}
|
||||
},
|
||||
"entity": {
|
||||
|
||||
@@ -64,6 +64,7 @@
|
||||
"temp_max": "Maximálna povolená teplota",
|
||||
"step_temperature": "Krok teploty",
|
||||
"device_power": "Napájanie zariadenia",
|
||||
"power_unit": "Jednotka výkonu (pre napájanie zariadenia)",
|
||||
"use_central_mode": "Povoliť ovládanie centrálnou entitou (potrebná centrálna konfigurácia)",
|
||||
"use_main_central_config": "Použite dodatočnú centrálnu hlavnú konfiguráciu. Začiarknite, ak chcete použiť centrálnu hlavnú konfiguráciu (vonkajšia teplota, min, max, krok, ...).",
|
||||
"used_by_controls_central_boiler": "Používa sa centrálnym kotlom. Skontrolujte, či má mať tento VTherm ovládanie na centrálnom kotli"
|
||||
@@ -75,7 +76,8 @@
|
||||
"step_temperature": "Krok teploty na nastavenie cieľovej teploty",
|
||||
"temperature_sensor_entity_id": "ID entity snímača izbovej teploty",
|
||||
"last_seen_temperature_sensor_entity_id": "Naposledy videný snímač izbovej teploty ID entity. Mal by to byť snímač dátumu a času",
|
||||
"external_temperature_sensor_entity_id": "ID entity snímača vonkajšej teploty. Nepoužíva sa, ak je zvolená centrálna konfigurácia"
|
||||
"external_temperature_sensor_entity_id": "ID entity snímača vonkajšej teploty. Nepoužíva sa, ak je zvolená centrálna konfigurácia",
|
||||
"power_unit": "Jednotka spotreby výkonu zariadenia"
|
||||
}
|
||||
},
|
||||
"features": {
|
||||
@@ -207,16 +209,18 @@
|
||||
},
|
||||
"power": {
|
||||
"title": "Správa napájania",
|
||||
"description": "Atribúty správy napájania.\nPoskytuje senzor výkonu a maximálneho výkonu vášho domova.\nPotom zadajte spotrebu energie ohrievača, keď je zapnutý.\nVšetky senzory a výkon zariadenia by mali mať rovnakú jednotku (kW alebo W).\nPonechajte zodpovedajúce entity_id prázdne ak sa nepoužíva.",
|
||||
"description": "Atribúty správy výkonu.\nPre výkon zariadenia každého VTherm vyberte W alebo kW a pre centrálnu konfiguráciu W, kW alebo Automaticky.\nHodnoty sú interne normalizované, takže W a kW možno bezpečne kombinovať.",
|
||||
"data": {
|
||||
"power_sensor_entity_id": "ID entity snímača výkonu",
|
||||
"max_power_sensor_entity_id": "ID entity snímača maximálneho výkonu",
|
||||
"power_unit": "Centrálna jednotka výkonu",
|
||||
"power_temp": "Teplota pre zníženie výkonu",
|
||||
"use_power_central_config": "Použite centrálnu konfiguráciu napájania"
|
||||
},
|
||||
"data_description": {
|
||||
"power_sensor_entity_id": "ID entity snímača výkonu",
|
||||
"max_power_sensor_entity_id": "ID entity snímača maximálneho výkonu",
|
||||
"power_unit": "Vyberte jednotku výkonu alebo Automaticky pre automatické rozpoznanie zo senzora",
|
||||
"power_temp": "Teplota pre zníženie výkonu",
|
||||
"use_power_central_config": "Začiarknite, ak chcete použiť konfiguráciu centrálneho napájania. Zrušte začiarknutie, ak chcete použiť špecifickú konfiguráciu napájania pre tento VTherm"
|
||||
}
|
||||
@@ -699,6 +703,19 @@
|
||||
"comfort": "Komfort",
|
||||
"boost": "Boost"
|
||||
}
|
||||
},
|
||||
"power_unit": {
|
||||
"options": {
|
||||
"w": "Watt (W)",
|
||||
"kw": "Kilowatt (kW)"
|
||||
}
|
||||
},
|
||||
"central_power_unit": {
|
||||
"options": {
|
||||
"w": "Watt (W)",
|
||||
"kw": "Kilowatt (kW)",
|
||||
"auto": "Automaticky (automatická detekcia zo senzoru)"
|
||||
}
|
||||
}
|
||||
},
|
||||
"entity": {
|
||||
|
||||
@@ -69,6 +69,7 @@
|
||||
"temp_max": "允许的最高温度",
|
||||
"step_temperature": "温度步进",
|
||||
"device_power": "设备功率",
|
||||
"power_unit": "功率单位(用于设备功率)",
|
||||
"use_central_mode": "启用中央实体控制(需要中央配置)。勾选后可使用 central_mode 选择实体控制此 VTherm。",
|
||||
"use_main_central_config": "使用额外的中央主配置。勾选后使用中央主配置(室外温度、最小值、最大值、步进等)。",
|
||||
"used_by_controls_central_boiler": "用于中央锅炉。勾选后,此 VTherm 可以控制中央锅炉"
|
||||
@@ -80,7 +81,8 @@
|
||||
"step_temperature": "设置目标温度的温度步长",
|
||||
"temperature_sensor_entity_id": "室温传感器实体 ID",
|
||||
"last_seen_temperature_sensor_entity_id": "室温传感器最后更新时间实体 ID。应为 datetime 传感器",
|
||||
"external_temperature_sensor_entity_id": "室外温度传感器实体 ID。如果选择中央配置则不使用"
|
||||
"external_temperature_sensor_entity_id": "室外温度传感器实体 ID。如果选择中央配置则不使用",
|
||||
"power_unit": "设备功率消耗单位"
|
||||
}
|
||||
},
|
||||
"features": {
|
||||
@@ -208,16 +210,18 @@
|
||||
},
|
||||
"power": {
|
||||
"title": "功率管理",
|
||||
"description": "电源管理属性。\n提供您家的功率和最大功率传感器。\n指定加热器开启时的功耗。\n所有传感器和设备功率应使用相同的单位(kW 或 W)",
|
||||
"description": "功率管理属性。\n为每个 VTherm 的设备功率选择 W 或 kW,并为中央配置选择 W、kW 或自动。\n数值会在内部标准化,因此可以安全地混用 W 和 kW。",
|
||||
"data": {
|
||||
"power_sensor_entity_id": "功率",
|
||||
"max_power_sensor_entity_id": "最大功率",
|
||||
"power_unit": "中央功率单位",
|
||||
"power_temp": "削峰温度",
|
||||
"use_power_central_config": "采用集中电源配置"
|
||||
},
|
||||
"data_description": {
|
||||
"power_sensor_entity_id": "功率传感器实体 ID",
|
||||
"max_power_sensor_entity_id": "最大功率传感器实体 ID",
|
||||
"power_unit": "选择功率单位,或选择自动以从传感器自动检测",
|
||||
"power_temp": "削峰温度",
|
||||
"use_power_central_config": "勾选使用中央电源配置。取消选中为此 VTherm 使用特定电源配置"
|
||||
}
|
||||
@@ -455,6 +459,7 @@
|
||||
"temp_max": "允许的最高温度",
|
||||
"step_temperature": "温度步进",
|
||||
"device_power": "设备功率",
|
||||
"power_unit": "功率单位(用于设备功率)",
|
||||
"use_central_mode": "启用中央实体控制(需要中央配置)。勾选后可使用 central_mode 选择实体控制此 VTherm。",
|
||||
"use_main_central_config": "使用额外的中央主配置。勾选后使用中央主配置(室外温度、最小值、最大值、步进等)。",
|
||||
"used_by_controls_central_boiler": "用于中央锅炉。勾选后,此 VTherm 可以控制中央锅炉"
|
||||
@@ -466,7 +471,8 @@
|
||||
"step_temperature": "设置目标温度的温度步长",
|
||||
"temperature_sensor_entity_id": "室温传感器实体 ID",
|
||||
"last_seen_temperature_sensor_entity_id": "室温传感器最后更新时间实体 ID。应为 datetime 传感器",
|
||||
"external_temperature_sensor_entity_id": "室外温度传感器实体 ID。如果选择中央配置则不使用"
|
||||
"external_temperature_sensor_entity_id": "室外温度传感器实体 ID。如果选择中央配置则不使用",
|
||||
"power_unit": "设备功率消耗单位"
|
||||
}
|
||||
},
|
||||
"features": {
|
||||
@@ -844,6 +850,19 @@
|
||||
"discovery": "发现",
|
||||
"fine_tuning": "微调"
|
||||
}
|
||||
},
|
||||
"power_unit": {
|
||||
"options": {
|
||||
"w": "瓦特 (W)",
|
||||
"kw": "千瓦 (kW)"
|
||||
}
|
||||
},
|
||||
"central_power_unit": {
|
||||
"options": {
|
||||
"w": "瓦特 (W)",
|
||||
"kw": "千瓦 (kW)",
|
||||
"auto": "自动 (从传感器自动检测)"
|
||||
}
|
||||
}
|
||||
},
|
||||
"entity": {
|
||||
@@ -1046,4 +1065,4 @@
|
||||
"message": "由于连续 3 次失败,{name} 的自动 TPI 学习已停止。原因:{reason}。请检查您的配置。"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -85,7 +85,7 @@ class UnderlyingStateManager:
|
||||
entity_id,
|
||||
)
|
||||
return state
|
||||
_LOGGER.error("UnderlyingStateManager - Requested state for unknown entity_id: %s", entity_id)
|
||||
_LOGGER.warning("UnderlyingStateManager - Requested state for unknown entity_id: %s", entity_id)
|
||||
return None
|
||||
return self._states[idx]
|
||||
|
||||
|
||||
@@ -622,7 +622,13 @@ class UnderlyingClimate(UnderlyingEntity):
|
||||
if hvac_mode in (VThermHvacMode_HEAT, VThermHvacMode_COOL):
|
||||
|
||||
async def callback_resend_temp(_):
|
||||
await self.set_temperature(self._thermostat.target_temperature, None, None)
|
||||
temperature = self.last_sent_temperature
|
||||
if temperature is None:
|
||||
temperature = getattr(self._thermostat, "regulated_target_temperature", None)
|
||||
if temperature is None:
|
||||
temperature = self._thermostat.target_temperature
|
||||
if temperature is not None:
|
||||
await self.set_temperature(temperature, None, None)
|
||||
|
||||
if self._cancel_set_temperature_later:
|
||||
self._cancel_set_temperature_later()
|
||||
@@ -1130,6 +1136,13 @@ class UnderlyingClimate(UnderlyingEntity):
|
||||
if str(hvac_mode) == str(under_hvac_mode):
|
||||
return False
|
||||
|
||||
if self._thermostat.now < self._last_command_sent_datetime + timedelta(seconds=resend_delay_sec):
|
||||
_LOGGER.debug(
|
||||
"%s - Skipping climate state repair while waiting for the last command to be applied",
|
||||
self,
|
||||
)
|
||||
return False
|
||||
|
||||
await self.set_hvac_mode(hvac_mode)
|
||||
return True
|
||||
|
||||
|
||||
Reference in New Issue
Block a user