Files
HomeAssistantVS/custom_components/versatile_thermostat/opening_degree_algorithm.py
T
2026-06-16 10:33:21 -04:00

72 lines
2.7 KiB
Python

""" This class aims to calculate the opening/closing degree of a valve.
See: https://github.com/jmcollin78/versatile_thermostat/issues/1220 """
import logging
from vtherm_api.log_collector import get_vtherm_logger
_LOGGER = get_vtherm_logger(__name__)
class OpeningClosingDegreeCalculation:
"""Class to calculate the opening/closing degree of a valve."""
@staticmethod
def calculate_opening_closing_degree(
brut_valve_open_percent: float,
min_opening_degree: float,
max_closing_degree: float,
max_opening_degree: float,
opening_threshold: float
) -> float:
"""
Calculate the opening/closing degree based on parameters. See explanation on README
Args:
brut_valve_open_percent: Raw valve opening percentage (0-100)
min_opening_degree: Minimum opening degree
max_closing_degree: Maximum closing degree
max_opening_degree: Maximum opening degree
opening_threshold: Opening threshold
Returns:
float: The calculated opening degree
float: The calculated closing degree
"""
_LOGGER.debug(
"Calculate opening/closing degree - Input: brut_valve_open_percent=%.2f, min_opening_degree=%.2f, max_closing_degree=%.2f",
brut_valve_open_percent,
min_opening_degree,
max_closing_degree
)
# for direct test. Already done in underlyings.py
if min_opening_degree >= max_opening_degree:
min_opening_degree = opening_threshold
# clamp the brut_valve_open_percent to be within 0 and 100
brut_valve_open_percent = max(0, min(100, brut_valve_open_percent))
# normalize to 0-1 range
bvop = brut_valve_open_percent / 100.0
min_od = min_opening_degree / 100.0
max_cd = max_closing_degree / 100.0
max_od = max_opening_degree / 100.0
ot = opening_threshold / 100.0
# if heating need is >= opening_threshold (and heating is > 0) -> open and calculate with interpolation,
if bvop >= ot and bvop > 0:
# interpolation is just here to normalize the max opening which can be != 100. Some TRV has a max which not 100
slope = (max_od - min_od) / (1 - ot)
calculated_degree = min_od + slope * (bvop - ot)
else:
calculated_degree = 1 - max_cd
# set to base 100
calculated_degree = round(calculated_degree * 100)
_LOGGER.debug(
"Calculate opening/closing degree - Output: calculated_degree=%.2f %%",
calculated_degree,
)
return calculated_degree, 100 - calculated_degree