Add minimal_deactivation_delay (#905)
* Add minimal_deactivation_delay In some cases users may want to keep the equipment on if it will deactivate for a short time. This could help reduce wear on gas boilers. * fix(prop_algorithm): correct the log message for minimal_deactivation_delay * fix(translations): correct the translations for minimal_deactivation_delay
This commit is contained in:
@@ -38,6 +38,7 @@ async def test_tpi_calculation(
|
||||
CONF_TPI_COEF_INT: 0.3,
|
||||
CONF_TPI_COEF_EXT: 0.01,
|
||||
CONF_MINIMAL_ACTIVATION_DELAY: 30,
|
||||
CONF_MINIMAL_DEACTIVATION_DELAY: 0,
|
||||
CONF_SAFETY_DELAY_MIN: 5,
|
||||
CONF_SAFETY_MIN_ON_PERCENT: 0.3,
|
||||
# CONF_DEVICE_POWER: 100,
|
||||
@@ -159,6 +160,94 @@ async def test_tpi_calculation(
|
||||
assert tpi_algo.off_time_sec == 60
|
||||
|
||||
|
||||
@pytest.mark.parametrize("expected_lingering_tasks", [True])
|
||||
@pytest.mark.parametrize("expected_lingering_timers", [True])
|
||||
async def test_minimal_deactivation_delay(
|
||||
hass: HomeAssistant, skip_hass_states_is_state: None
|
||||
): # pylint: disable=unused-argument
|
||||
"""Test the minimal deactivation delay"""
|
||||
|
||||
entry = MockConfigEntry(
|
||||
domain=DOMAIN,
|
||||
title="TheOverSwitchMockName",
|
||||
unique_id="uniqueId",
|
||||
data={
|
||||
CONF_NAME: "TheOverSwitchMockName",
|
||||
CONF_THERMOSTAT_TYPE: CONF_THERMOSTAT_SWITCH,
|
||||
CONF_TEMP_SENSOR: "sensor.mock_temp_sensor",
|
||||
CONF_EXTERNAL_TEMP_SENSOR: "sensor.mock_ext_temp_sensor",
|
||||
CONF_CYCLE_MIN: 5,
|
||||
CONF_TEMP_MIN: 15,
|
||||
CONF_TEMP_MAX: 30,
|
||||
CONF_USE_WINDOW_FEATURE: False,
|
||||
CONF_USE_MOTION_FEATURE: False,
|
||||
CONF_USE_POWER_FEATURE: False,
|
||||
CONF_USE_PRESENCE_FEATURE: False,
|
||||
CONF_HEATER: "switch.mock_switch",
|
||||
CONF_PROP_FUNCTION: PROPORTIONAL_FUNCTION_TPI,
|
||||
CONF_TPI_COEF_INT: 0.3,
|
||||
CONF_TPI_COEF_EXT: 0.01,
|
||||
CONF_MINIMAL_ACTIVATION_DELAY: 30,
|
||||
CONF_MINIMAL_DEACTIVATION_DELAY: 60,
|
||||
CONF_SAFETY_DELAY_MIN: 5,
|
||||
CONF_SAFETY_MIN_ON_PERCENT: 0.3,
|
||||
},
|
||||
)
|
||||
|
||||
entity: BaseThermostat = await create_thermostat(
|
||||
hass, entry, "climate.theoverswitchmockname"
|
||||
)
|
||||
assert entity
|
||||
assert entity._prop_algorithm # pylint: disable=protected-access
|
||||
|
||||
tpi_algo: PropAlgorithm = entity._prop_algorithm # pylint: disable=protected-access
|
||||
assert tpi_algo
|
||||
|
||||
# off_time is less than minimal_deactivation_delay
|
||||
tpi_algo.calculate(9, 6, 10, HVACMode.HEAT)
|
||||
assert tpi_algo.on_percent == 0.89
|
||||
assert tpi_algo.calculated_on_percent == 0.89
|
||||
assert tpi_algo.on_time_sec == 300
|
||||
assert tpi_algo.off_time_sec == 0
|
||||
|
||||
# off_time is less than minimal_deactivation_delay
|
||||
tpi_algo.calculate(6, 0, 104, HVACMode.HEAT)
|
||||
assert tpi_algo.on_percent == 0.82
|
||||
assert tpi_algo.calculated_on_percent == 0.82
|
||||
assert tpi_algo.on_time_sec == 300
|
||||
assert tpi_algo.off_time_sec == 0
|
||||
|
||||
# off_time is exactly minimal_deactivation_delay
|
||||
tpi_algo.calculate(10, 8, -10, HVACMode.HEAT)
|
||||
assert tpi_algo.on_percent == 0.8
|
||||
assert tpi_algo.calculated_on_percent == 0.8
|
||||
assert tpi_algo.on_time_sec == 240
|
||||
assert tpi_algo.off_time_sec == 60 # Equal to minimal_deactivation_delay
|
||||
|
||||
# off_time is greater than minimal_deactivation_delay
|
||||
tpi_algo.calculate(10, 9, 0, HVACMode.HEAT)
|
||||
assert tpi_algo.on_percent == 0.4
|
||||
assert tpi_algo.calculated_on_percent == 0.4
|
||||
assert tpi_algo.on_time_sec == 120
|
||||
assert tpi_algo.off_time_sec == 180
|
||||
|
||||
# with safety mode
|
||||
tpi_algo.set_safety(0.2)
|
||||
tpi_algo.calculate(10, 8, -10, HVACMode.HEAT)
|
||||
assert tpi_algo.on_percent == 0.2
|
||||
assert tpi_algo.calculated_on_percent == 0.8
|
||||
assert tpi_algo.on_time_sec == 60
|
||||
assert tpi_algo.off_time_sec == 240
|
||||
tpi_algo.unset_safety()
|
||||
|
||||
# with cooling mode
|
||||
tpi_algo.calculate(10, 10, 90, HVACMode.COOL)
|
||||
assert tpi_algo.on_percent == 0.8
|
||||
assert tpi_algo.calculated_on_percent == 0.8
|
||||
assert tpi_algo.on_time_sec == 240
|
||||
assert tpi_algo.off_time_sec == 60
|
||||
|
||||
|
||||
@pytest.mark.parametrize("expected_lingering_tasks", [True])
|
||||
@pytest.mark.parametrize("expected_lingering_timers", [True])
|
||||
async def test_wrong_tpi_parameters(
|
||||
@@ -174,6 +263,7 @@ async def test_wrong_tpi_parameters(
|
||||
0.01,
|
||||
5,
|
||||
1,
|
||||
1,
|
||||
"entity_id",
|
||||
)
|
||||
# We should not be there
|
||||
@@ -190,6 +280,7 @@ async def test_wrong_tpi_parameters(
|
||||
0,
|
||||
2,
|
||||
3,
|
||||
3,
|
||||
"entity_id",
|
||||
)
|
||||
# We should not be there
|
||||
@@ -206,6 +297,7 @@ async def test_wrong_tpi_parameters(
|
||||
0,
|
||||
2,
|
||||
3,
|
||||
3,
|
||||
"entity_id",
|
||||
)
|
||||
# We should not be there
|
||||
@@ -222,6 +314,7 @@ async def test_wrong_tpi_parameters(
|
||||
None,
|
||||
2,
|
||||
3,
|
||||
3,
|
||||
"entity_id",
|
||||
)
|
||||
# We should not be there
|
||||
@@ -238,6 +331,7 @@ async def test_wrong_tpi_parameters(
|
||||
0.00001,
|
||||
None,
|
||||
3,
|
||||
3,
|
||||
"entity_id",
|
||||
)
|
||||
# We should not be there
|
||||
@@ -262,6 +356,23 @@ async def test_wrong_tpi_parameters(
|
||||
# the normal case
|
||||
pass
|
||||
|
||||
# Test minimal_activation_delay
|
||||
try:
|
||||
algo = PropAlgorithm(
|
||||
PROPORTIONAL_FUNCTION_TPI,
|
||||
0.6,
|
||||
0.00001,
|
||||
0,
|
||||
3,
|
||||
None,
|
||||
"entity_id",
|
||||
)
|
||||
# We should not be there
|
||||
assert False
|
||||
except TypeError as e:
|
||||
# the normal case
|
||||
pass
|
||||
|
||||
# Test vtherm_entity_id
|
||||
try:
|
||||
algo = PropAlgorithm(
|
||||
@@ -270,6 +381,7 @@ async def test_wrong_tpi_parameters(
|
||||
0.00001,
|
||||
0,
|
||||
12,
|
||||
12,
|
||||
None,
|
||||
)
|
||||
# We should not be there
|
||||
|
||||
Reference in New Issue
Block a user