With 1rst implementation of VTherm TRVZB and underlying
This commit is contained in:
@@ -91,6 +91,48 @@ input_number:
|
|||||||
icon: mdi:thermostat
|
icon: mdi:thermostat
|
||||||
unit_of_measurement: °C
|
unit_of_measurement: °C
|
||||||
mode: box
|
mode: box
|
||||||
|
fake_offset_calibration1:
|
||||||
|
name: Sonoff offset calibration 1
|
||||||
|
min: -12
|
||||||
|
max: 12
|
||||||
|
icon: mdi:tune
|
||||||
|
unit_of_measurement: °C
|
||||||
|
mode: box
|
||||||
|
fake_opening_degree1:
|
||||||
|
name: Sonoff Opening degree 1
|
||||||
|
min: 0
|
||||||
|
max: 100
|
||||||
|
icon: mdi:valve-open
|
||||||
|
unit_of_measurement: "%"
|
||||||
|
mode: box
|
||||||
|
fake_closing_degree1:
|
||||||
|
name: Sonoff Closing degree 1
|
||||||
|
min: 0
|
||||||
|
max: 100
|
||||||
|
icon: mdi:valve-closed
|
||||||
|
unit_of_measurement: "%"
|
||||||
|
mode: box
|
||||||
|
fake_offset_calibration2:
|
||||||
|
name: Sonoff offset calibration 2
|
||||||
|
min: -12
|
||||||
|
max: 12
|
||||||
|
icon: mdi:tune
|
||||||
|
unit_of_measurement: °C
|
||||||
|
mode: box
|
||||||
|
fake_opening_degree2:
|
||||||
|
name: Sonoff Opening degree 2
|
||||||
|
min: 0
|
||||||
|
max: 100
|
||||||
|
icon: mdi:valve-open
|
||||||
|
unit_of_measurement: "%"
|
||||||
|
mode: box
|
||||||
|
fake_closing_degree2:
|
||||||
|
name: Sonoff Closing degree 2
|
||||||
|
min: 0
|
||||||
|
max: 100
|
||||||
|
icon: mdi:valve-closed
|
||||||
|
unit_of_measurement: "%"
|
||||||
|
mode: box
|
||||||
|
|
||||||
input_boolean:
|
input_boolean:
|
||||||
# input_boolean to simulate the windows entity. Only for development environment.
|
# input_boolean to simulate the windows entity. Only for development environment.
|
||||||
@@ -142,6 +184,12 @@ input_boolean:
|
|||||||
fake_presence_sensor1:
|
fake_presence_sensor1:
|
||||||
name: Presence Sensor 1
|
name: Presence Sensor 1
|
||||||
icon: mdi:home
|
icon: mdi:home
|
||||||
|
fake_valve_sonoff_trvzb1:
|
||||||
|
name: Valve Sonoff TRVZB1
|
||||||
|
icon: mdi:valve
|
||||||
|
fake_valve_sonoff_trvzb2:
|
||||||
|
name: Valve Sonoff TRVZB2
|
||||||
|
icon: mdi:valve
|
||||||
|
|
||||||
climate:
|
climate:
|
||||||
- platform: generic_thermostat
|
- platform: generic_thermostat
|
||||||
@@ -185,6 +233,16 @@ climate:
|
|||||||
name: Underlying thermostat9
|
name: Underlying thermostat9
|
||||||
heater: input_boolean.fake_heater_switch3
|
heater: input_boolean.fake_heater_switch3
|
||||||
target_sensor: input_number.fake_temperature_sensor1
|
target_sensor: input_number.fake_temperature_sensor1
|
||||||
|
- platform: generic_thermostat
|
||||||
|
name: Underlying Sonoff TRVZB1
|
||||||
|
heater: input_boolean.fake_valve_sonoff_trvzb1
|
||||||
|
target_sensor: input_number.fake_temperature_sensor1
|
||||||
|
ac_mode: false
|
||||||
|
- platform: generic_thermostat
|
||||||
|
name: Underlying Sonoff TRVZB2
|
||||||
|
heater: input_boolean.fake_valve_sonoff_trvzb2
|
||||||
|
target_sensor: input_number.fake_temperature_sensor1
|
||||||
|
ac_mode: false
|
||||||
|
|
||||||
input_datetime:
|
input_datetime:
|
||||||
fake_last_seen:
|
fake_last_seen:
|
||||||
@@ -238,14 +296,14 @@ switch:
|
|||||||
friendly_name: "Pilote chauffage SDB RDC"
|
friendly_name: "Pilote chauffage SDB RDC"
|
||||||
value_template: "{{ is_state_attr('switch_seche_serviettes_sdb_rdc', 'sensor_state', 'on') }}"
|
value_template: "{{ is_state_attr('switch_seche_serviettes_sdb_rdc', 'sensor_state', 'on') }}"
|
||||||
turn_on:
|
turn_on:
|
||||||
service: select.select_option
|
action: select.select_option
|
||||||
data:
|
data:
|
||||||
option: comfort
|
option: comfort
|
||||||
target:
|
target:
|
||||||
entity_id: select.seche_serviettes_sdb_rdc_cable_outlet_mode
|
entity_id: select.seche_serviettes_sdb_rdc_cable_outlet_mode
|
||||||
|
|
||||||
turn_off:
|
turn_off:
|
||||||
service: select.select_option
|
action: select.select_option
|
||||||
data:
|
data:
|
||||||
option: comfort-2
|
option: comfort-2
|
||||||
target:
|
target:
|
||||||
|
|||||||
@@ -87,10 +87,6 @@ def get_tz(hass: HomeAssistant):
|
|||||||
return dt_util.get_time_zone(hass.config.time_zone)
|
return dt_util.get_time_zone(hass.config.time_zone)
|
||||||
|
|
||||||
|
|
||||||
_LOGGER_ENERGY = logging.getLogger(
|
|
||||||
"custom_components.versatile_thermostat.energy_debug"
|
|
||||||
)
|
|
||||||
|
|
||||||
class BaseThermostat(ClimateEntity, RestoreEntity, Generic[T]):
|
class BaseThermostat(ClimateEntity, RestoreEntity, Generic[T]):
|
||||||
"""Representation of a base class for all Versatile Thermostat device."""
|
"""Representation of a base class for all Versatile Thermostat device."""
|
||||||
|
|
||||||
@@ -206,7 +202,7 @@ class BaseThermostat(ClimateEntity, RestoreEntity, Generic[T]):
|
|||||||
self._attr_translation_key = "versatile_thermostat"
|
self._attr_translation_key = "versatile_thermostat"
|
||||||
|
|
||||||
self._total_energy = None
|
self._total_energy = None
|
||||||
_LOGGER_ENERGY.debug("%s - _init_ resetting energy to None", self)
|
_LOGGER.debug("%s - _init_ resetting energy to None", self)
|
||||||
|
|
||||||
# because energy of climate is calculated in the thermostat we have to keep that here and not in underlying entity
|
# because energy of climate is calculated in the thermostat we have to keep that here and not in underlying entity
|
||||||
self._underlying_climate_start_hvac_action_date = None
|
self._underlying_climate_start_hvac_action_date = None
|
||||||
@@ -479,7 +475,7 @@ class BaseThermostat(ClimateEntity, RestoreEntity, Generic[T]):
|
|||||||
self._presence_state = None
|
self._presence_state = None
|
||||||
|
|
||||||
self._total_energy = None
|
self._total_energy = None
|
||||||
_LOGGER_ENERGY.debug("%s - post_init_ resetting energy to None", self)
|
_LOGGER.debug("%s - post_init_ resetting energy to None", self)
|
||||||
|
|
||||||
# Read the parameter from configuration.yaml if it exists
|
# Read the parameter from configuration.yaml if it exists
|
||||||
short_ema_params = DEFAULT_SHORT_EMA_PARAMS
|
short_ema_params = DEFAULT_SHORT_EMA_PARAMS
|
||||||
@@ -599,7 +595,7 @@ class BaseThermostat(ClimateEntity, RestoreEntity, Generic[T]):
|
|||||||
|
|
||||||
async def async_will_remove_from_hass(self):
|
async def async_will_remove_from_hass(self):
|
||||||
"""Try to force backup of entity"""
|
"""Try to force backup of entity"""
|
||||||
_LOGGER_ENERGY.debug(
|
_LOGGER.debug(
|
||||||
"%s - force write before remove. Energy is %s", self, self.total_energy
|
"%s - force write before remove. Energy is %s", self, self.total_energy
|
||||||
)
|
)
|
||||||
# Force dump in background
|
# Force dump in background
|
||||||
@@ -826,7 +822,7 @@ class BaseThermostat(ClimateEntity, RestoreEntity, Generic[T]):
|
|||||||
|
|
||||||
old_total_energy = old_state.attributes.get(ATTR_TOTAL_ENERGY)
|
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
|
self._total_energy = old_total_energy if old_total_energy is not None else 0
|
||||||
_LOGGER_ENERGY.debug(
|
_LOGGER.debug(
|
||||||
"%s - get_my_previous_state restored energy is %s",
|
"%s - get_my_previous_state restored energy is %s",
|
||||||
self,
|
self,
|
||||||
self._total_energy,
|
self._total_energy,
|
||||||
@@ -844,7 +840,7 @@ class BaseThermostat(ClimateEntity, RestoreEntity, Generic[T]):
|
|||||||
"No previously saved temperature, setting to %s", self._target_temp
|
"No previously saved temperature, setting to %s", self._target_temp
|
||||||
)
|
)
|
||||||
self._total_energy = 0
|
self._total_energy = 0
|
||||||
_LOGGER_ENERGY.debug(
|
_LOGGER.debug(
|
||||||
"%s - get_my_previous_state no previous state energy is %s",
|
"%s - get_my_previous_state no previous state energy is %s",
|
||||||
self,
|
self,
|
||||||
self._total_energy,
|
self._total_energy,
|
||||||
@@ -2672,7 +2668,7 @@ class BaseThermostat(ClimateEntity, RestoreEntity, Generic[T]):
|
|||||||
"max_on_percent": self._max_on_percent,
|
"max_on_percent": self._max_on_percent,
|
||||||
}
|
}
|
||||||
|
|
||||||
_LOGGER_ENERGY.debug(
|
_LOGGER.debug(
|
||||||
"%s - update_custom_attributes saved energy is %s",
|
"%s - update_custom_attributes saved energy is %s",
|
||||||
self,
|
self,
|
||||||
self.total_energy,
|
self.total_energy,
|
||||||
@@ -2681,7 +2677,7 @@ class BaseThermostat(ClimateEntity, RestoreEntity, Generic[T]):
|
|||||||
@overrides
|
@overrides
|
||||||
def async_write_ha_state(self):
|
def async_write_ha_state(self):
|
||||||
"""overrides to have log"""
|
"""overrides to have log"""
|
||||||
_LOGGER_ENERGY.debug(
|
_LOGGER.debug(
|
||||||
"%s - async_write_ha_state written state energy is %s",
|
"%s - async_write_ha_state written state energy is %s",
|
||||||
self,
|
self,
|
||||||
self._total_energy,
|
self._total_energy,
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
# pylint: disable=line-too-long, too-many-lines
|
# pylint: disable=line-too-long, too-many-lines
|
||||||
""" A climate over switch classe """
|
""" A climate over climate classe """
|
||||||
import logging
|
import logging
|
||||||
from datetime import timedelta, datetime
|
from datetime import timedelta, datetime
|
||||||
|
|
||||||
@@ -23,7 +23,7 @@ from .pi_algorithm import PITemperatureRegulator
|
|||||||
from .const import * # pylint: disable=wildcard-import, unused-wildcard-import
|
from .const import * # pylint: disable=wildcard-import, unused-wildcard-import
|
||||||
|
|
||||||
from .vtherm_api import VersatileThermostatAPI
|
from .vtherm_api import VersatileThermostatAPI
|
||||||
from .underlyings import UnderlyingClimate, UnderlyingSonoffTRVZB
|
from .underlyings import UnderlyingClimate
|
||||||
from .auto_start_stop_algorithm import (
|
from .auto_start_stop_algorithm import (
|
||||||
AutoStartStopDetectionAlgorithm,
|
AutoStartStopDetectionAlgorithm,
|
||||||
AUTO_START_STOP_ACTION_OFF,
|
AUTO_START_STOP_ACTION_OFF,
|
||||||
@@ -31,10 +31,6 @@ from .auto_start_stop_algorithm import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
_LOGGER_ENERGY = logging.getLogger(
|
|
||||||
"custom_components.versatile_thermostat.energy_debug"
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
HVAC_ACTION_ON = [ # pylint: disable=invalid-name
|
HVAC_ACTION_ON = [ # pylint: disable=invalid-name
|
||||||
HVACAction.COOLING,
|
HVACAction.COOLING,
|
||||||
@@ -104,25 +100,12 @@ class ThermostatOverClimate(BaseThermostat[UnderlyingClimate]):
|
|||||||
|
|
||||||
super().post_init(config_entry)
|
super().post_init(config_entry)
|
||||||
|
|
||||||
for idx, climate in enumerate(config_entry.get(CONF_UNDERLYING_LIST)):
|
for climate in config_entry.get(CONF_UNDERLYING_LIST):
|
||||||
if config_entry.get(CONF_SONOFF_TRZB_MODE) is True:
|
under = UnderlyingClimate(
|
||||||
offset = config_entry.get(CONF_OFFSET_CALIBRATION_LIST)[idx]
|
hass=self._hass,
|
||||||
opening = config_entry.get(CONF_OPENING_DEGREE_LIST)[idx]
|
thermostat=self,
|
||||||
closing = config_entry.get(CONF_CLOSING_DEGREE_LIST)[idx]
|
climate_entity_id=climate,
|
||||||
under = UnderlyingSonoffTRVZB(
|
)
|
||||||
hass=self._hass,
|
|
||||||
thermostat=self,
|
|
||||||
climate_entity_id=climate,
|
|
||||||
offset_calibration=offset,
|
|
||||||
opening_degree=opening,
|
|
||||||
closing_degree=closing,
|
|
||||||
)
|
|
||||||
else:
|
|
||||||
under = UnderlyingClimate(
|
|
||||||
hass=self._hass,
|
|
||||||
thermostat=self,
|
|
||||||
climate_entity_id=climate,
|
|
||||||
)
|
|
||||||
self._underlyings.append(under)
|
self._underlyings.append(under)
|
||||||
|
|
||||||
self.choose_auto_regulation_mode(
|
self.choose_auto_regulation_mode(
|
||||||
@@ -618,14 +601,14 @@ class ThermostatOverClimate(BaseThermostat[UnderlyingClimate]):
|
|||||||
|
|
||||||
if self._total_energy is None:
|
if self._total_energy is None:
|
||||||
self._total_energy = added_energy
|
self._total_energy = added_energy
|
||||||
_LOGGER_ENERGY.debug(
|
_LOGGER.debug(
|
||||||
"%s - incremente_energy set energy is %s",
|
"%s - incremente_energy set energy is %s",
|
||||||
self,
|
self,
|
||||||
self._total_energy,
|
self._total_energy,
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
self._total_energy += added_energy
|
self._total_energy += added_energy
|
||||||
_LOGGER_ENERGY.debug(
|
_LOGGER.debug(
|
||||||
"%s - incremente_energy incremented energy is %s",
|
"%s - incremente_energy incremented energy is %s",
|
||||||
self,
|
self,
|
||||||
self._total_energy,
|
self._total_energy,
|
||||||
@@ -1131,7 +1114,7 @@ class ThermostatOverClimate(BaseThermostat[UnderlyingClimate]):
|
|||||||
def current_humidity(self) -> float | None:
|
def current_humidity(self) -> float | None:
|
||||||
"""Return the humidity."""
|
"""Return the humidity."""
|
||||||
if self.underlying_entity(0):
|
if self.underlying_entity(0):
|
||||||
return self.underlying_entity(0).humidity
|
return self.underlying_entity(0).current_humidity
|
||||||
|
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,142 @@
|
|||||||
|
# pylint: disable=line-too-long, too-many-lines
|
||||||
|
""" A climate over Sonoff TRVZB classe """
|
||||||
|
|
||||||
|
import logging
|
||||||
|
|
||||||
|
from homeassistant.core import HomeAssistant
|
||||||
|
from homeassistant.components.climate import HVACMode
|
||||||
|
|
||||||
|
from .underlyings import UnderlyingSonoffTRVZB
|
||||||
|
|
||||||
|
# from .commons import NowClass, round_to_nearest
|
||||||
|
from .base_thermostat import BaseThermostat, ConfigData
|
||||||
|
from .prop_algorithm import PropAlgorithm
|
||||||
|
|
||||||
|
from .const import * # pylint: disable=wildcard-import, unused-wildcard-import
|
||||||
|
|
||||||
|
# from .vtherm_api import VersatileThermostatAPI
|
||||||
|
|
||||||
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
class ThermostatOverSonoffTRVZB(BaseThermostat[UnderlyingSonoffTRVZB]):
|
||||||
|
"""This class represent a VTherm over a Sonoff TRVZB climate"""
|
||||||
|
|
||||||
|
_entity_component_unrecorded_attributes = (
|
||||||
|
BaseThermostat._entity_component_unrecorded_attributes.union(
|
||||||
|
frozenset(
|
||||||
|
{
|
||||||
|
"is_over_climate",
|
||||||
|
"is_over_sonoff_trvzb",
|
||||||
|
"underlying_entities",
|
||||||
|
"on_time_sec",
|
||||||
|
"off_time_sec",
|
||||||
|
"cycle_min",
|
||||||
|
"function",
|
||||||
|
"tpi_coef_int",
|
||||||
|
"tpi_coef_ext",
|
||||||
|
"power_percent",
|
||||||
|
}
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
def __init__(
|
||||||
|
self, hass: HomeAssistant, unique_id: str, name: str, entry_infos: ConfigData
|
||||||
|
):
|
||||||
|
"""Initialize the ThermostatOverSonoffTRVZB class"""
|
||||||
|
_LOGGER.debug("%s - creating a ThermostatOverSonoffTRVZB VTherm", name)
|
||||||
|
super().__init__(hass, unique_id, name, entry_infos)
|
||||||
|
|
||||||
|
@overrides
|
||||||
|
def post_init(self, config_entry: ConfigData):
|
||||||
|
"""Initialize the Thermostat"""
|
||||||
|
|
||||||
|
super().post_init(config_entry)
|
||||||
|
|
||||||
|
for idx, _ in enumerate(config_entry.get(CONF_UNDERLYING_LIST)):
|
||||||
|
offset = config_entry.get(CONF_OFFSET_CALIBRATION_LIST)[idx]
|
||||||
|
opening = config_entry.get(CONF_OPENING_DEGREE_LIST)[idx]
|
||||||
|
closing = config_entry.get(CONF_CLOSING_DEGREE_LIST)[idx]
|
||||||
|
under = UnderlyingSonoffTRVZB(
|
||||||
|
hass=self._hass,
|
||||||
|
thermostat=self,
|
||||||
|
offset_calibration_entity_id=offset,
|
||||||
|
opening_degree_entity_id=opening,
|
||||||
|
closing_degree_entity_id=closing,
|
||||||
|
)
|
||||||
|
self._underlyings.append(under)
|
||||||
|
|
||||||
|
# Initialization of the TPI algo
|
||||||
|
self._prop_algorithm = PropAlgorithm(
|
||||||
|
self._proportional_function,
|
||||||
|
self._tpi_coef_int,
|
||||||
|
self._tpi_coef_ext,
|
||||||
|
self._cycle_min,
|
||||||
|
self._minimal_activation_delay,
|
||||||
|
self.name,
|
||||||
|
)
|
||||||
|
|
||||||
|
@overrides
|
||||||
|
def update_custom_attributes(self):
|
||||||
|
"""Custom attributes"""
|
||||||
|
super().update_custom_attributes()
|
||||||
|
|
||||||
|
under0: UnderlyingSonoffTRVZB = self._underlyings[0]
|
||||||
|
self._attr_extra_state_attributes["is_over_sonoff_trvzb"] = (
|
||||||
|
self.is_over_sonoff_trvzb
|
||||||
|
)
|
||||||
|
self._attr_extra_state_attributes["keep_alive_sec"] = under0.keep_alive_sec
|
||||||
|
|
||||||
|
self._attr_extra_state_attributes["underlying_entities"] = [
|
||||||
|
underlying.entity_id for underlying in self._underlyings
|
||||||
|
]
|
||||||
|
|
||||||
|
self._attr_extra_state_attributes["on_percent"] = (
|
||||||
|
self._prop_algorithm.on_percent
|
||||||
|
)
|
||||||
|
self._attr_extra_state_attributes["power_percent"] = self.power_percent
|
||||||
|
self._attr_extra_state_attributes["on_time_sec"] = (
|
||||||
|
self._prop_algorithm.on_time_sec
|
||||||
|
)
|
||||||
|
self._attr_extra_state_attributes["off_time_sec"] = (
|
||||||
|
self._prop_algorithm.off_time_sec
|
||||||
|
)
|
||||||
|
self._attr_extra_state_attributes["cycle_min"] = self._cycle_min
|
||||||
|
self._attr_extra_state_attributes["function"] = self._proportional_function
|
||||||
|
self._attr_extra_state_attributes["tpi_coef_int"] = self._tpi_coef_int
|
||||||
|
self._attr_extra_state_attributes["tpi_coef_ext"] = self._tpi_coef_ext
|
||||||
|
|
||||||
|
self.async_write_ha_state()
|
||||||
|
_LOGGER.debug(
|
||||||
|
"%s - Calling update_custom_attributes: %s",
|
||||||
|
self,
|
||||||
|
self._attr_extra_state_attributes,
|
||||||
|
)
|
||||||
|
|
||||||
|
@overrides
|
||||||
|
def recalculate(self):
|
||||||
|
"""A utility function to force the calculation of a the algo and
|
||||||
|
update the custom attributes and write the state
|
||||||
|
"""
|
||||||
|
_LOGGER.debug("%s - recalculate all", self)
|
||||||
|
self._prop_algorithm.calculate(
|
||||||
|
self._target_temp,
|
||||||
|
self._cur_temp,
|
||||||
|
self._cur_ext_temp,
|
||||||
|
self._hvac_mode or HVACMode.OFF,
|
||||||
|
)
|
||||||
|
self.update_custom_attributes()
|
||||||
|
|
||||||
|
@property
|
||||||
|
def is_over_sonoff_trvzb(self) -> bool:
|
||||||
|
"""True if the Thermostat is over_sonoff_trvzb"""
|
||||||
|
return True
|
||||||
|
|
||||||
|
@property
|
||||||
|
def power_percent(self) -> float | None:
|
||||||
|
"""Get the current on_percent value"""
|
||||||
|
if self._prop_algorithm:
|
||||||
|
return round(self._prop_algorithm.on_percent * 100, 0)
|
||||||
|
else:
|
||||||
|
return None
|
||||||
@@ -21,9 +21,6 @@ from .underlyings import UnderlyingSwitch
|
|||||||
from .prop_algorithm import PropAlgorithm
|
from .prop_algorithm import PropAlgorithm
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
_LOGGER_ENERGY = logging.getLogger(
|
|
||||||
"custom_components.versatile_thermostat.energy_debug"
|
|
||||||
)
|
|
||||||
|
|
||||||
class ThermostatOverSwitch(BaseThermostat[UnderlyingSwitch]):
|
class ThermostatOverSwitch(BaseThermostat[UnderlyingSwitch]):
|
||||||
"""Representation of a base class for a Versatile Thermostat over a switch."""
|
"""Representation of a base class for a Versatile Thermostat over a switch."""
|
||||||
@@ -190,14 +187,14 @@ class ThermostatOverSwitch(BaseThermostat[UnderlyingSwitch]):
|
|||||||
|
|
||||||
if self._total_energy is None:
|
if self._total_energy is None:
|
||||||
self._total_energy = added_energy
|
self._total_energy = added_energy
|
||||||
_LOGGER_ENERGY.debug(
|
_LOGGER.debug(
|
||||||
"%s - incremente_energy set energy is %s",
|
"%s - incremente_energy set energy is %s",
|
||||||
self,
|
self,
|
||||||
self._total_energy,
|
self._total_energy,
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
self._total_energy += added_energy
|
self._total_energy += added_energy
|
||||||
_LOGGER_ENERGY.debug(
|
_LOGGER.debug(
|
||||||
"%s - incremente_energy increment energy is %s",
|
"%s - incremente_energy increment energy is %s",
|
||||||
self,
|
self,
|
||||||
self._total_energy,
|
self._total_energy,
|
||||||
|
|||||||
@@ -25,9 +25,6 @@ from .const import (
|
|||||||
from .underlyings import UnderlyingValve
|
from .underlyings import UnderlyingValve
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
_LOGGER_ENERGY = logging.getLogger(
|
|
||||||
"custom_components.versatile_thermostat.energy_debug"
|
|
||||||
)
|
|
||||||
|
|
||||||
class ThermostatOverValve(BaseThermostat[UnderlyingValve]): # pylint: disable=abstract-method
|
class ThermostatOverValve(BaseThermostat[UnderlyingValve]): # pylint: disable=abstract-method
|
||||||
"""Representation of a class for a Versatile Thermostat over a Valve"""
|
"""Representation of a class for a Versatile Thermostat over a Valve"""
|
||||||
@@ -272,14 +269,14 @@ class ThermostatOverValve(BaseThermostat[UnderlyingValve]): # pylint: disable=a
|
|||||||
|
|
||||||
if self._total_energy is None:
|
if self._total_energy is None:
|
||||||
self._total_energy = added_energy
|
self._total_energy = added_energy
|
||||||
_LOGGER_ENERGY.debug(
|
_LOGGER.debug(
|
||||||
"%s - incremente_energy set energy is %s",
|
"%s - incremente_energy set energy is %s",
|
||||||
self,
|
self,
|
||||||
self._total_energy,
|
self._total_energy,
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
self._total_energy += added_energy
|
self._total_energy += added_energy
|
||||||
_LOGGER_ENERGY.debug(
|
_LOGGER.debug(
|
||||||
"%s - get_my_previous_state increment energy is %s",
|
"%s - get_my_previous_state increment energy is %s",
|
||||||
self,
|
self,
|
||||||
self._total_energy,
|
self._total_energy,
|
||||||
|
|||||||
@@ -53,6 +53,9 @@ class UnderlyingEntityType(StrEnum):
|
|||||||
# a valve
|
# a valve
|
||||||
VALVE = "valve"
|
VALVE = "valve"
|
||||||
|
|
||||||
|
# a Sonoff TRVZB
|
||||||
|
SONOFF_TRVZB = "sonoff_trvzb"
|
||||||
|
|
||||||
|
|
||||||
class UnderlyingEntity:
|
class UnderlyingEntity:
|
||||||
"""Represent a underlying device which could be a switch or a climate"""
|
"""Represent a underlying device which could be a switch or a climate"""
|
||||||
@@ -713,6 +716,13 @@ class UnderlyingClimate(UnderlyingEntity):
|
|||||||
return []
|
return []
|
||||||
return self._underlying_climate.hvac_modes
|
return self._underlying_climate.hvac_modes
|
||||||
|
|
||||||
|
@property
|
||||||
|
def current_humidity(self) -> float | None:
|
||||||
|
"""Get the humidity"""
|
||||||
|
if not self.is_initialized:
|
||||||
|
return None
|
||||||
|
return self._underlying_climate.current_humidity
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def fan_modes(self) -> list[str]:
|
def fan_modes(self) -> list[str]:
|
||||||
"""Get the fan_modes"""
|
"""Get the fan_modes"""
|
||||||
@@ -851,7 +861,7 @@ class UnderlyingValve(UnderlyingEntity):
|
|||||||
def __init__(
|
def __init__(
|
||||||
self, hass: HomeAssistant, thermostat: Any, valve_entity_id: str
|
self, hass: HomeAssistant, thermostat: Any, valve_entity_id: str
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Initialize the underlying switch"""
|
"""Initialize the underlying valve"""
|
||||||
|
|
||||||
super().__init__(
|
super().__init__(
|
||||||
hass=hass,
|
hass=hass,
|
||||||
@@ -988,3 +998,40 @@ class UnderlyingValve(UnderlyingEntity):
|
|||||||
def remove_entity(self):
|
def remove_entity(self):
|
||||||
"""Remove the entity after stopping its cycle"""
|
"""Remove the entity after stopping its cycle"""
|
||||||
self._cancel_cycle()
|
self._cancel_cycle()
|
||||||
|
|
||||||
|
|
||||||
|
class UnderlyingSonoffTRVZB(UnderlyingValve):
|
||||||
|
"""A specific underlying class for Sonoff TRVZB TRV"""
|
||||||
|
|
||||||
|
_offset_calibration_entity_id: str
|
||||||
|
_opening_degree_entity_id: str
|
||||||
|
_closing_degree_entity_id: str
|
||||||
|
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
hass: HomeAssistant,
|
||||||
|
thermostat: Any,
|
||||||
|
offset_calibration_entity_id: str,
|
||||||
|
opening_degree_entity_id: str,
|
||||||
|
closing_degree_entity_id: str,
|
||||||
|
) -> None:
|
||||||
|
"""Initialize the underlying Sonoff TRV"""
|
||||||
|
super().__init__(hass, thermostat, opening_degree_entity_id)
|
||||||
|
self._offset_calibration_entity_id = offset_calibration_entity_id
|
||||||
|
self._opening_degree_entity_id = opening_degree_entity_id
|
||||||
|
self._closing_degree_entity_id = closing_degree_entity_id
|
||||||
|
|
||||||
|
@property
|
||||||
|
def offset_calibration_entity_id(self) -> str:
|
||||||
|
"""The offset_calibration_entity_id"""
|
||||||
|
return self._offset_calibration_entity_id
|
||||||
|
|
||||||
|
@property
|
||||||
|
def opening_degree_entity_id(self) -> str:
|
||||||
|
"""The offset_calibration_entity_id"""
|
||||||
|
return self._opening_degree_entity_id
|
||||||
|
|
||||||
|
@property
|
||||||
|
def closing_degree_entity_id(self) -> str:
|
||||||
|
"""The offset_calibration_entity_id"""
|
||||||
|
return self._closing_degree_entity_id
|
||||||
|
|||||||
Reference in New Issue
Block a user