Skip to content

Commit

Permalink
[MERGE]
Browse files Browse the repository at this point in the history
  • Loading branch information
KartoffelToby committed Dec 27, 2023
2 parents c2f2a65 + 5675cf7 commit 5458055
Show file tree
Hide file tree
Showing 14 changed files with 383 additions and 396 deletions.
14 changes: 7 additions & 7 deletions custom_components/better_thermostat/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,13 @@
from homeassistant.config_entries import ConfigEntry
import voluptuous as vol

from .const import (
CONF_FIX_CALIBRATION,
from .utils.const import (
CONF_CALIBRATION_MODE,
CONF_HEATER,
CONF_NO_SYSTEM_MODE_OFF,
CONF_WINDOW_TIMEOUT,
CONF_WINDOW_TIMEOUT_AFTER,
CalibrationMode
)

_LOGGER = logging.getLogger(__name__)
Expand Down Expand Up @@ -57,7 +57,7 @@ async def async_migrate_entry(hass, config_entry: ConfigEntry):
if config_entry.version == 1:
new = {**config_entry.data}
for trv in new[CONF_HEATER]:
trv["advanced"].update({CONF_FIX_CALIBRATION: False})
trv["advanced"].update({CalibrationMode.AGGRESIVE_CALIBRATION: False})
config_entry.version = 2
hass.config_entries.async_update_entry(config_entry, data=new)

Expand All @@ -71,12 +71,12 @@ async def async_migrate_entry(hass, config_entry: ConfigEntry):
new = {**config_entry.data}
for trv in new[CONF_HEATER]:
if (
CONF_FIX_CALIBRATION in trv["advanced"]
and trv["advanced"][CONF_FIX_CALIBRATION]
CalibrationMode.AGGRESIVE_CALIBRATION in trv["advanced"]
and trv["advanced"][CalibrationMode.AGGRESIVE_CALIBRATION]
):
trv["advanced"].update({CONF_CALIBRATION_MODE: CONF_FIX_CALIBRATION})
trv["advanced"].update({CONF_CALIBRATION_MODE: CalibrationMode.AGGRESIVE_CALIBRATION})
else:
trv["advanced"].update({CONF_CALIBRATION_MODE: "default"})
trv["advanced"].update({CONF_CALIBRATION_MODE: CalibrationMode.DEFAULT})
config_entry.version = 4
hass.config_entries.async_update_entry(config_entry, data=new)

Expand Down
226 changes: 226 additions & 0 deletions custom_components/better_thermostat/calibration.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,226 @@
"""Helper functions for the Better Thermostat component."""
import logging
from typing import Union

from homeassistant.components.climate.const import HVACAction

from custom_components.better_thermostat.utils.const import (
CalibrationMode,
CONF_PROTECT_OVERHEATING,
)

from custom_components.better_thermostat.utils.helpers import (
convert_to_float,
round_down_to_half_degree,
round_by_steps,
heating_power_valve_position
)

from custom_components.better_thermostat.model_fixes.model_quirks import (
fix_local_calibration,
fix_target_temperature_calibration,
)

_LOGGER = logging.getLogger(__name__)


def calculate_calibration_local(self, entity_id) -> Union[float, None]:
"""Calculate local delta to adjust the setpoint of the TRV based on the air temperature of the external sensor.
This calibration is for devices with local calibration option, it syncs the current temperature of the TRV to the target temperature of
the external sensor.
Parameters
----------
self :
self instance of better_thermostat
Returns
-------
float
new local calibration delta
"""
_context = "_calculate_calibration_local()"

if None in (self.cur_temp, self.bt_target_temp):
return None

_cur_trv_temp_s = self.real_trvs[entity_id]["current_temperature"]
_calibration_steps = self.real_trvs[entity_id]["local_calibration_steps"]
_cur_external_temp = self.cur_temp
_cur_target_temp = self.bt_target_temp

_cur_trv_temp_f = convert_to_float(
str(_cur_trv_temp_s), self.name, _context
)

_current_trv_calibration = convert_to_float(
str(self.real_trvs[entity_id]["last_calibration"]), self.name, _context
)

if None in (_current_trv_calibration, _cur_external_temp, _cur_trv_temp_f, _calibration_steps):
_LOGGER.warning(
f"better thermostat {self.name}: {entity_id} Could not calculate local calibration in {_context}:"
f" trv_calibration: {_current_trv_calibration}, trv_temp: {_cur_trv_temp_f}, external_temp: {_cur_external_temp}"
f" calibration_steps: {_calibration_steps}"
)
return None

_new_trv_calibration = (_cur_external_temp - _cur_trv_temp_f) + _current_trv_calibration

_calibration_mode = self.real_trvs[entity_id]["advanced"].get(
"calibration_mode", CalibrationMode.DEFAULT
)

if _calibration_mode == CalibrationMode.AGGRESIVE_CALIBRATION:
if self.attr_hvac_action == HVACAction.HEATING:
if _new_trv_calibration > -2.5:
_new_trv_calibration -= 2.5

if _calibration_mode == CalibrationMode.HEATING_POWER_CALIBRATION:
if self.attr_hvac_action == HVACAction.HEATING:
_valve_position = heating_power_valve_position(self, entity_id)
_new_trv_calibration = _current_trv_calibration - (
(self.real_trvs[entity_id]["local_calibration_min"] + _cur_trv_temp_f)
* _valve_position
)

# Respecting tolerance in all calibration modes, delaying heat
if self.attr_hvac_action == HVACAction.IDLE:
if _new_trv_calibration < 0.0:
_new_trv_calibration += self.tolerance

_new_trv_calibration = fix_local_calibration(
self, entity_id, _new_trv_calibration
)

_overheating_protection = self.real_trvs[entity_id]["advanced"].get(
CONF_PROTECT_OVERHEATING, False
)

if _overheating_protection is True:
if _cur_external_temp >= _cur_target_temp:
_new_trv_calibration += (_cur_external_temp - _cur_target_temp) * 10.0

# Adjust based on the steps allowed by the local calibration entity
_new_trv_calibration = round_by_steps(
_new_trv_calibration,
_calibration_steps
)

# Compare against min/max
if _new_trv_calibration > float(
self.real_trvs[entity_id]["local_calibration_max"]
):
_new_trv_calibration = float(
self.real_trvs[entity_id]["local_calibration_max"]
)
elif _new_trv_calibration < float(
self.real_trvs[entity_id]["local_calibration_min"]
):
_new_trv_calibration = float(
self.real_trvs[entity_id]["local_calibration_min"]
)

_new_trv_calibration = convert_to_float(
str(_new_trv_calibration), self.name, _context
)

_logmsg = "better_thermostat %s: %s - new local calibration: %s | external_temp: %s, "\
"trv_temp: %s, calibration: %s"

_LOGGER.debug(
_logmsg,
self.name,
entity_id,
_new_trv_calibration,
_cur_external_temp,
_cur_trv_temp_f,
_current_trv_calibration
)

return _new_trv_calibration

def calculate_calibration_setpoint(self, entity_id) -> Union[float, None]:
"""Calculate new setpoint for the TRV based on its own temperature measurement and the air temperature of the external sensor.
This calibration is for devices with no local calibration option, it syncs the target temperature of the TRV to a new target
temperature based on the current temperature of the external sensor.
Parameters
----------
self :
self instance of better_thermostat
Returns
-------
float
new target temp with calibration
"""
if None in (self.cur_temp, self.bt_target_temp):
return None

_cur_trv_temp_s = self.real_trvs[entity_id]["current_temperature"]

_cur_external_temp = self.cur_temp
_cur_target_temp = self.bt_target_temp

if None in (_cur_target_temp, _cur_external_temp, _cur_trv_temp_s):
return None

_calibrated_setpoint = (_cur_target_temp - _cur_external_temp) + _cur_trv_temp_s

_calibration_mode = self.real_trvs[entity_id]["advanced"].get(
"calibration_mode", CalibrationMode.DEFAULT
)

if _calibration_mode == CalibrationMode.AGGRESIVE_CALIBRATION:
if self.attr_hvac_action == HVACAction.HEATING:
if _calibrated_setpoint - _cur_trv_temp_s < 2.5:
_calibrated_setpoint += 2.5

if _calibration_mode == CalibrationMode.HEATING_POWER_CALIBRATION:
if self.attr_hvac_action == HVACAction.HEATING:
valve_position = heating_power_valve_position(self, entity_id)
_calibrated_setpoint = _cur_trv_temp_s + (
(self.real_trvs[entity_id]["max_temp"] - _cur_trv_temp_s) * valve_position
)

if self.attr_hvac_action == HVACAction.IDLE:
if _calibrated_setpoint - _cur_trv_temp_s > 0.0:
_calibrated_setpoint -= self.tolerance

_calibrated_setpoint = fix_target_temperature_calibration(
self, entity_id, _calibrated_setpoint
)

_overheating_protection = self.real_trvs[entity_id]["advanced"].get(
CONF_PROTECT_OVERHEATING, False
)

if _overheating_protection is True:
if _cur_external_temp >= _cur_target_temp:
_calibrated_setpoint -= (_cur_external_temp - _cur_target_temp) * 10.0

_calibrated_setpoint = round_down_to_half_degree(_calibrated_setpoint)

# check if new setpoint is inside the TRV's range, else set to min or max
if _calibrated_setpoint < self.real_trvs[entity_id]["min_temp"]:
_calibrated_setpoint = self.real_trvs[entity_id]["min_temp"]
if _calibrated_setpoint > self.real_trvs[entity_id]["max_temp"]:
_calibrated_setpoint = self.real_trvs[entity_id]["max_temp"]

_logmsg = "better_thermostat %s: %s - new setpoint calibration: %s | external_temp: %s, "\
"target_temp: %s, trv_temp: %s"

_LOGGER.debug(
_logmsg,
self.name,
entity_id,
_calibrated_setpoint,
_cur_external_temp,
_cur_target_temp,
_cur_trv_temp_s
)

return _calibrated_setpoint
14 changes: 8 additions & 6 deletions custom_components/better_thermostat/climate.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,16 @@
from .utils.watcher import check_all_entities

from .utils.weather import check_ambient_air_temperature, check_weather
from .utils.bridge import (
from .adapters.delegate import (
get_current_offset,
get_offset_steps,
get_min_offset,
get_max_offset,
init,
load_adapter,
)

from .utils.model_quirks import load_model_quirks
from .model_fixes.model_quirks import load_model_quirks

from .utils.helpers import convert_to_float, find_battery_entity, get_hvac_bt_mode
from homeassistant.helpers import entity_platform
Expand Down Expand Up @@ -56,7 +57,7 @@

from homeassistant.components.group.util import reduce_attribute

from .const import (
from .utils.const import (
ATTR_STATE_BATTERIES,
ATTR_STATE_CALL_FOR_HEAT,
ATTR_STATE_ERRORS,
Expand Down Expand Up @@ -286,8 +287,6 @@ def __init__(
self.heating_end_temp = None
self.heating_end_timestamp = None
self._async_unsub_state_changed = None
self.old_external_temp = 0
self.old_internal_temp = 0
self.all_entities = []
self.devices_states = {}
self.devices_errors = []
Expand Down Expand Up @@ -587,7 +586,7 @@ async def startup(self):
self.bt_min_temp = reduce_attribute(states, ATTR_MIN_TEMP, reduce=max)
self.bt_max_temp = reduce_attribute(states, ATTR_MAX_TEMP, reduce=min)

if self.bt_target_temp_step == 0.0:
if self.bt_target_temp_step == 0.0:
self.bt_target_temp_step = reduce_attribute(
states, ATTR_TARGET_TEMP_STEP, reduce=max
)
Expand Down Expand Up @@ -787,6 +786,9 @@ async def startup(self):
self.real_trvs[trv]["local_calibration_max"] = await get_max_offset(
self, trv
)
self.real_trvs[trv][
"local_calibration_steps"
] = await get_offset_steps(self, trv)
else:
self.real_trvs[trv]["last_calibration"] = 0

Expand Down
6 changes: 3 additions & 3 deletions custom_components/better_thermostat/config_flow.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,11 @@
from homeassistant.helpers import config_validation as cv


from .utils.bridge import load_adapter
from .adapters.delegate import load_adapter

from .utils.helpers import get_device_model, get_trv_intigration

from .const import (
from .utils.const import (
CONF_COOLER,
CONF_PROTECT_OVERHEATING,
CONF_CALIBRATION,
Expand Down Expand Up @@ -90,7 +90,7 @@
options=[
selector.SelectOptionDict(value=CalibrationMode.DEFAULT, label="Normal"),
selector.SelectOptionDict(
value=CalibrationMode.FIX_CALIBRATION, label="Agressive"
value=CalibrationMode.AGGRESIVE_CALIBRATION, label="Agressive"
),
selector.SelectOptionDict(
value=CalibrationMode.HEATING_POWER_CALIBRATION, label="AI Time Based"
Expand Down
4 changes: 2 additions & 2 deletions custom_components/better_thermostat/diagnostics.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@
from homeassistant.config_entries import ConfigEntry
from homeassistant.core import HomeAssistant

from .utils.bridge import load_adapter
from .adapters.delegate import load_adapter

from .const import CONF_HEATER, CONF_SENSOR, CONF_SENSOR_WINDOW
from .utils.const import CONF_HEATER, CONF_SENSOR, CONF_SENSOR_WINDOW


async def async_get_config_entry_diagnostics(
Expand Down
2 changes: 1 addition & 1 deletion custom_components/better_thermostat/events/temperature.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import logging

from custom_components.better_thermostat.const import CONF_HOMATICIP
from custom_components.better_thermostat.utils.const import CONF_HOMATICIP
from ..utils.helpers import convert_to_float
from datetime import datetime

Expand Down
Loading

0 comments on commit 5458055

Please sign in to comment.