All tests ok

This commit is contained in:
Jean-Marc Collin
2025-01-04 09:39:42 +00:00
parent 24fcb7a161
commit 0b5d937968
6 changed files with 231 additions and 136 deletions

View File

@@ -1111,3 +1111,9 @@ class SideEffects:
def add_or_update_side_effect(self, key: str, new_value: Any): def add_or_update_side_effect(self, key: str, new_value: Any):
"""Update the value of a side effect""" """Update the value of a side effect"""
self._current_side_effects[key] = new_value self._current_side_effects[key] = new_value
async def do_central_power_refresh(hass):
"""Do a central power refresh"""
await VersatileThermostatAPI.get_vtherm_api().central_power_manager.refresh_state()
return hass.async_block_till_done()

View File

@@ -1,4 +1,4 @@
# pylint: disable=wildcard-import, unused-wildcard-import, unused-argument, line-too-long # pylint: disable=wildcard-import, unused-wildcard-import, unused-argument, line-too-long, protected-access
""" Test the normal start of a Thermostat """ """ Test the normal start of a Thermostat """
from unittest.mock import patch from unittest.mock import patch
@@ -107,9 +107,16 @@ async def test_overpowering_binary_sensors(
skip_hass_states_is_state, skip_hass_states_is_state,
skip_turn_on_off_heater, skip_turn_on_off_heater,
skip_send_event, skip_send_event,
init_central_power_manager,
): ):
"""Test the overpowering binary sensors in thermostat type""" """Test the overpowering binary sensors in thermostat type"""
temps = {
"eco": 17,
"comfort": 18,
"boost": 19,
}
entry = MockConfigEntry( entry = MockConfigEntry(
domain=DOMAIN, domain=DOMAIN,
title="TheOverSwitchMockName", title="TheOverSwitchMockName",
@@ -122,9 +129,6 @@ async def test_overpowering_binary_sensors(
CONF_CYCLE_MIN: 5, CONF_CYCLE_MIN: 5,
CONF_TEMP_MIN: 15, CONF_TEMP_MIN: 15,
CONF_TEMP_MAX: 30, CONF_TEMP_MAX: 30,
"eco_temp": 17,
"comfort_temp": 18,
"boost_temp": 19,
CONF_USE_WINDOW_FEATURE: False, CONF_USE_WINDOW_FEATURE: False,
CONF_USE_MOTION_FEATURE: False, CONF_USE_MOTION_FEATURE: False,
CONF_USE_POWER_FEATURE: True, CONF_USE_POWER_FEATURE: True,
@@ -136,15 +140,13 @@ async def test_overpowering_binary_sensors(
CONF_MINIMAL_ACTIVATION_DELAY: 30, CONF_MINIMAL_ACTIVATION_DELAY: 30,
CONF_SAFETY_DELAY_MIN: 5, CONF_SAFETY_DELAY_MIN: 5,
CONF_SAFETY_MIN_ON_PERCENT: 0.3, CONF_SAFETY_MIN_ON_PERCENT: 0.3,
CONF_POWER_SENSOR: "sensor.mock_power_sensor",
CONF_MAX_POWER_SENSOR: "sensor.mock_power_max_sensor",
CONF_DEVICE_POWER: 100, CONF_DEVICE_POWER: 100,
CONF_PRESET_POWER: 12, CONF_PRESET_POWER: 12,
}, },
) )
entity: BaseThermostat = await create_thermostat( entity: BaseThermostat = await create_thermostat(
hass, entry, "climate.theoverswitchmockname" hass, entry, "climate.theoverswitchmockname", temps
) )
assert entity assert entity
@@ -153,7 +155,8 @@ async def test_overpowering_binary_sensors(
) )
assert overpowering_binary_sensor assert overpowering_binary_sensor
now: datetime = datetime.now(tz=get_tz(hass)) now: datetime = NowClass.get_now(hass)
VersatileThermostatAPI.get_vtherm_api()._set_now(now)
# Overpowering should be not set because poer have not been received # Overpowering should be not set because poer have not been received
await entity.async_set_preset_mode(PRESET_COMFORT) await entity.async_set_preset_mode(PRESET_COMFORT)
@@ -166,8 +169,20 @@ async def test_overpowering_binary_sensors(
assert overpowering_binary_sensor.state is STATE_OFF assert overpowering_binary_sensor.state is STATE_OFF
assert overpowering_binary_sensor.device_class == BinarySensorDeviceClass.POWER assert overpowering_binary_sensor.device_class == BinarySensorDeviceClass.POWER
# Send power mesurement
side_effects = SideEffects(
{
"sensor.the_power_sensor": State("sensor.the_power_sensor", 100),
"sensor.the_max_power_sensor": State("sensor.the_max_power_sensor", 150),
},
State("unknown.entity_id", "unknown"),
)
# fmt:off
with patch("homeassistant.core.StateMachine.get", side_effect=side_effects.get_side_effects()):
# fmt: on
await send_power_change_event(entity, 100, now) await send_power_change_event(entity, 100, now)
await send_max_power_change_event(entity, 150, now) await send_max_power_change_event(entity, 150, now)
assert entity.power_manager.is_overpowering_detected is True assert entity.power_manager.is_overpowering_detected is True
assert entity.power_manager.overpowering_state is STATE_ON assert entity.power_manager.overpowering_state is STATE_ON
@@ -176,6 +191,12 @@ async def test_overpowering_binary_sensors(
assert overpowering_binary_sensor.state == STATE_ON assert overpowering_binary_sensor.state == STATE_ON
# set max power to a low value # set max power to a low value
side_effects.add_or_update_side_effect("sensor.the_max_power_sensor", State("sensor.the_max_power_sensor", 201))
# fmt:off
with patch("homeassistant.core.StateMachine.get", side_effect=side_effects.get_side_effects()):
# fmt: on
now = now + timedelta(seconds=61)
VersatileThermostatAPI.get_vtherm_api()._set_now(now)
await send_max_power_change_event(entity, 201, now) await send_max_power_change_event(entity, 201, now)
assert entity.power_manager.is_overpowering_detected is False assert entity.power_manager.is_overpowering_detected is False
assert entity.power_manager.overpowering_state is STATE_OFF assert entity.power_manager.overpowering_state is STATE_OFF

View File

@@ -266,7 +266,9 @@ async def test_bug_272(
@pytest.mark.parametrize("expected_lingering_tasks", [True]) @pytest.mark.parametrize("expected_lingering_tasks", [True])
@pytest.mark.parametrize("expected_lingering_timers", [True]) @pytest.mark.parametrize("expected_lingering_timers", [True])
async def test_bug_407(hass: HomeAssistant, skip_hass_states_is_state): async def test_bug_407(
hass: HomeAssistant, skip_hass_states_is_state, init_central_power_manager
):
"""Test the followin case in power management: """Test the followin case in power management:
1. a heater is active (heating). So the power consumption takes the heater power into account. We suppose the power consumption is near the threshold, 1. a heater is active (heating). So the power consumption takes the heater power into account. We suppose the power consumption is near the threshold,
2. the user switch preset let's say from Comfort to Boost, 2. the user switch preset let's say from Comfort to Boost,
@@ -275,6 +277,12 @@ async def test_bug_407(hass: HomeAssistant, skip_hass_states_is_state):
""" """
temps = {
"eco": 17,
"comfort": 18,
"boost": 19,
}
entry = MockConfigEntry( entry = MockConfigEntry(
domain=DOMAIN, domain=DOMAIN,
title="TheOverSwitchMockName", title="TheOverSwitchMockName",
@@ -287,9 +295,6 @@ async def test_bug_407(hass: HomeAssistant, skip_hass_states_is_state):
CONF_CYCLE_MIN: 5, CONF_CYCLE_MIN: 5,
CONF_TEMP_MIN: 15, CONF_TEMP_MIN: 15,
CONF_TEMP_MAX: 30, CONF_TEMP_MAX: 30,
"eco_temp": 17,
"comfort_temp": 18,
"boost_temp": 19,
CONF_USE_WINDOW_FEATURE: False, CONF_USE_WINDOW_FEATURE: False,
CONF_USE_MOTION_FEATURE: False, CONF_USE_MOTION_FEATURE: False,
CONF_USE_POWER_FEATURE: True, CONF_USE_POWER_FEATURE: True,
@@ -301,34 +306,43 @@ async def test_bug_407(hass: HomeAssistant, skip_hass_states_is_state):
CONF_MINIMAL_ACTIVATION_DELAY: 30, CONF_MINIMAL_ACTIVATION_DELAY: 30,
CONF_SAFETY_DELAY_MIN: 5, CONF_SAFETY_DELAY_MIN: 5,
CONF_SAFETY_MIN_ON_PERCENT: 0.3, CONF_SAFETY_MIN_ON_PERCENT: 0.3,
CONF_POWER_SENSOR: "sensor.mock_power_sensor",
CONF_MAX_POWER_SENSOR: "sensor.mock_power_max_sensor",
CONF_DEVICE_POWER: 100, CONF_DEVICE_POWER: 100,
CONF_PRESET_POWER: 12, CONF_PRESET_POWER: 12,
}, },
) )
entity: ThermostatOverSwitch = await create_thermostat( entity: ThermostatOverSwitch = await create_thermostat(
hass, entry, "climate.theoverswitchmockname" hass, entry, "climate.theoverswitchmockname", temps
) )
assert entity assert entity
tpi_algo = entity._prop_algorithm tpi_algo = entity._prop_algorithm
assert tpi_algo assert tpi_algo
tz = get_tz(hass) # pylint: disable=invalid-name now: datetime = NowClass.get_now(hass)
now: datetime = datetime.now(tz=tz) VersatileThermostatAPI.get_vtherm_api()._set_now(now)
await send_temperature_change_event(entity, 16, now) await send_temperature_change_event(entity, 16, now)
await send_ext_temperature_change_event(entity, 10, now) await send_ext_temperature_change_event(entity, 10, now)
# 1. An already active heater will not switch to overpowering # 1. An already active heater will not switch to overpowering
side_effects = SideEffects(
{
"sensor.the_power_sensor": State("sensor.the_power_sensor", 100),
"sensor.the_max_power_sensor": State("sensor.the_max_power_sensor", 110),
},
State("unknown.entity_id", "unknown"),
)
with patch( with patch(
"homeassistant.core.ServiceRegistry.async_call" "homeassistant.core.ServiceRegistry.async_call"
) as mock_service_call, patch( ) as mock_service_call, patch(
"custom_components.versatile_thermostat.underlyings.UnderlyingSwitch.is_device_active", "custom_components.versatile_thermostat.underlyings.UnderlyingSwitch.is_device_active",
new_callable=PropertyMock, new_callable=PropertyMock,
return_value=True, return_value=True,
), patch(
"homeassistant.core.StateMachine.get",
side_effect=side_effects.get_side_effects(),
): ):
await entity.async_set_hvac_mode(HVACMode.HEAT) await entity.async_set_hvac_mode(HVACMode.HEAT)
await entity.async_set_preset_mode(PRESET_COMFORT) await entity.async_set_preset_mode(PRESET_COMFORT)
@@ -337,14 +351,15 @@ async def test_bug_407(hass: HomeAssistant, skip_hass_states_is_state):
assert entity.power_manager.overpowering_state is STATE_UNKNOWN assert entity.power_manager.overpowering_state is STATE_UNKNOWN
assert entity.target_temperature == 18 assert entity.target_temperature == 18
# waits that the heater starts # waits that the heater starts
await asyncio.sleep(0.1) await hass.async_block_till_done()
assert mock_service_call.call_count >= 1 assert mock_service_call.call_count >= 1
assert entity.is_device_active is True assert entity.is_device_active is True
# Send power max mesurement # Send power max mesurement
await send_max_power_change_event(entity, 110, datetime.now()) await send_max_power_change_event(entity, 110, now)
# Send power mesurement (theheater is already in the power measurement) # Send power mesurement (theheater is already in the power measurement)
await send_power_change_event(entity, 100, datetime.now()) await send_power_change_event(entity, 100, now)
# No overpowering yet # No overpowering yet
assert entity.power_manager.is_overpowering_detected is False assert entity.power_manager.is_overpowering_detected is False
# All configuration is complete and power is < power_max # All configuration is complete and power is < power_max
@@ -359,11 +374,22 @@ async def test_bug_407(hass: HomeAssistant, skip_hass_states_is_state):
"custom_components.versatile_thermostat.underlyings.UnderlyingSwitch.is_device_active", "custom_components.versatile_thermostat.underlyings.UnderlyingSwitch.is_device_active",
new_callable=PropertyMock, new_callable=PropertyMock,
return_value=True, return_value=True,
), patch(
"homeassistant.core.StateMachine.get",
side_effect=side_effects.get_side_effects(),
): ):
now = now + timedelta(seconds=61)
VersatileThermostatAPI.get_vtherm_api()._set_now(now)
# change preset to Boost # change preset to Boost
await entity.async_set_preset_mode(PRESET_BOOST) await entity.async_set_preset_mode(PRESET_BOOST)
# waits that the heater starts # waits that the heater starts
await asyncio.sleep(0.1) await asyncio.sleep(0.1)
# doesn't work for call_later
# await hass.async_block_till_done()
# simulate a refresh for central power (not necessary)
await do_central_power_refresh(hass)
assert entity.power_manager.is_overpowering_detected is False assert entity.power_manager.is_overpowering_detected is False
assert entity.hvac_mode is HVACMode.HEAT assert entity.hvac_mode is HVACMode.HEAT
@@ -379,12 +405,21 @@ async def test_bug_407(hass: HomeAssistant, skip_hass_states_is_state):
"custom_components.versatile_thermostat.underlyings.UnderlyingSwitch.is_device_active", "custom_components.versatile_thermostat.underlyings.UnderlyingSwitch.is_device_active",
new_callable=PropertyMock, new_callable=PropertyMock,
return_value=False, return_value=False,
), patch(
"homeassistant.core.StateMachine.get",
side_effect=side_effects.get_side_effects(),
): ):
now = now + timedelta(seconds=61)
VersatileThermostatAPI.get_vtherm_api()._set_now(now)
# change preset to Boost # change preset to Boost
await entity.async_set_preset_mode(PRESET_COMFORT) await entity.async_set_preset_mode(PRESET_COMFORT)
# waits that the heater starts # waits that the heater starts
await asyncio.sleep(0.1) await asyncio.sleep(0.1)
# simulate a refresh for central power (not necessary)
await do_central_power_refresh(hass)
assert entity.power_manager.is_overpowering_detected is True assert entity.power_manager.is_overpowering_detected is True
assert entity.hvac_mode is HVACMode.HEAT assert entity.hvac_mode is HVACMode.HEAT
assert entity.preset_mode is PRESET_POWER assert entity.preset_mode is PRESET_POWER

View File

@@ -188,6 +188,18 @@ async def test_full_over_switch_wo_central_config(
hass: HomeAssistant, skip_hass_states_is_state, init_vtherm_api hass: HomeAssistant, skip_hass_states_is_state, init_vtherm_api
): ):
"""Tests that a VTherm without any central_configuration is working with its own attributes""" """Tests that a VTherm without any central_configuration is working with its own attributes"""
temps = {
"frost": 10,
"eco": 17,
"comfort": 18,
"boost": 21,
"frost_away": 13,
"eco_away": 13,
"comfort_away": 13,
"boost_away": 13,
}
# Add a Switch VTherm # Add a Switch VTherm
entry = MockConfigEntry( entry = MockConfigEntry(
domain=DOMAIN, domain=DOMAIN,
@@ -202,19 +214,11 @@ async def test_full_over_switch_wo_central_config(
CONF_TEMP_MIN: 8, CONF_TEMP_MIN: 8,
CONF_TEMP_MAX: 18, CONF_TEMP_MAX: 18,
CONF_STEP_TEMPERATURE: 0.3, CONF_STEP_TEMPERATURE: 0.3,
"frost_temp": 10,
"eco_temp": 17,
"comfort_temp": 18,
"boost_temp": 21,
"frost_away_temp": 13,
"eco_away_temp": 13,
"comfort_away_temp": 13,
"boost_away_temp": 13,
CONF_USE_WINDOW_FEATURE: True, CONF_USE_WINDOW_FEATURE: True,
CONF_USE_MOTION_FEATURE: True, CONF_USE_MOTION_FEATURE: True,
CONF_USE_POWER_FEATURE: True, CONF_USE_POWER_FEATURE: True,
CONF_USE_PRESENCE_FEATURE: True, CONF_USE_PRESENCE_FEATURE: True,
CONF_HEATER: "switch.mock_switch", CONF_UNDERLYING_LIST: ["switch.mock_switch"],
CONF_PROP_FUNCTION: PROPORTIONAL_FUNCTION_TPI, CONF_PROP_FUNCTION: PROPORTIONAL_FUNCTION_TPI,
CONF_INVERSE_SWITCH: False, CONF_INVERSE_SWITCH: False,
CONF_TPI_COEF_INT: 0.3, CONF_TPI_COEF_INT: 0.3,
@@ -233,8 +237,6 @@ async def test_full_over_switch_wo_central_config(
CONF_MOTION_PRESET: "comfort", CONF_MOTION_PRESET: "comfort",
CONF_NO_MOTION_PRESET: "eco", CONF_NO_MOTION_PRESET: "eco",
CONF_MOTION_SENSOR: "binary_sensor.mock_motion_sensor", CONF_MOTION_SENSOR: "binary_sensor.mock_motion_sensor",
CONF_POWER_SENSOR: "sensor.mock_power_sensor",
CONF_MAX_POWER_SENSOR: "sensor.mock_max_power_sensor",
CONF_PRESENCE_SENSOR: "binary_sensor.mock_presence_sensor", CONF_PRESENCE_SENSOR: "binary_sensor.mock_presence_sensor",
CONF_USE_MAIN_CENTRAL_CONFIG: False, CONF_USE_MAIN_CENTRAL_CONFIG: False,
CONF_USE_TPI_CENTRAL_CONFIG: False, CONF_USE_TPI_CENTRAL_CONFIG: False,
@@ -249,7 +251,7 @@ async def test_full_over_switch_wo_central_config(
with patch("homeassistant.core.ServiceRegistry.async_call"): with patch("homeassistant.core.ServiceRegistry.async_call"):
entity: ThermostatOverSwitch = await create_thermostat( entity: ThermostatOverSwitch = await create_thermostat(
hass, entry, "climate.theoverswitchmockname" hass, entry, "climate.theoverswitchmockname", temps
) )
assert entity assert entity
assert entity.name == "TheOverSwitchMockName" assert entity.name == "TheOverSwitchMockName"
@@ -300,10 +302,13 @@ async def test_full_over_switch_wo_central_config(
assert entity.motion_manager.motion_preset == "comfort" assert entity.motion_manager.motion_preset == "comfort"
assert entity.motion_manager.no_motion_preset == "eco" assert entity.motion_manager.no_motion_preset == "eco"
assert entity.power_manager.power_sensor_entity_id == "sensor.mock_power_sensor"
assert ( assert (
entity.power_manager.max_power_sensor_entity_id VersatileThermostatAPI.get_vtherm_api().central_power_manager.power_sensor_entity_id
== "sensor.mock_max_power_sensor" is None
)
assert (
VersatileThermostatAPI.get_vtherm_api().central_power_manager.max_power_sensor_entity_id
is None
) )
assert ( assert (
@@ -317,7 +322,7 @@ async def test_full_over_switch_wo_central_config(
@pytest.mark.parametrize("expected_lingering_tasks", [True]) @pytest.mark.parametrize("expected_lingering_tasks", [True])
@pytest.mark.parametrize("expected_lingering_timers", [True]) @pytest.mark.parametrize("expected_lingering_timers", [True])
async def test_full_over_switch_with_central_config( async def test_full_over_switch_with_central_config(
hass: HomeAssistant, skip_hass_states_is_state, init_central_config hass: HomeAssistant, skip_hass_states_is_state, init_central_power_manager
): ):
"""Tests that a VTherm with central_configuration is working with the central_config attributes""" """Tests that a VTherm with central_configuration is working with the central_config attributes"""
# Add a Switch VTherm # Add a Switch VTherm
@@ -334,15 +339,11 @@ async def test_full_over_switch_with_central_config(
CONF_TEMP_MIN: 8, CONF_TEMP_MIN: 8,
CONF_TEMP_MAX: 18, CONF_TEMP_MAX: 18,
CONF_STEP_TEMPERATURE: 0.3, CONF_STEP_TEMPERATURE: 0.3,
"frost_temp": 10,
"eco_temp": 17,
"comfort_temp": 18,
"boost_temp": 21,
CONF_USE_WINDOW_FEATURE: True, CONF_USE_WINDOW_FEATURE: True,
CONF_USE_MOTION_FEATURE: True, CONF_USE_MOTION_FEATURE: True,
CONF_USE_POWER_FEATURE: True, CONF_USE_POWER_FEATURE: True,
CONF_USE_PRESENCE_FEATURE: True, CONF_USE_PRESENCE_FEATURE: True,
CONF_HEATER: "switch.mock_switch", CONF_UNDERLYING_LIST: ["switch.mock_switch"],
CONF_PROP_FUNCTION: PROPORTIONAL_FUNCTION_TPI, CONF_PROP_FUNCTION: PROPORTIONAL_FUNCTION_TPI,
CONF_INVERSE_SWITCH: False, CONF_INVERSE_SWITCH: False,
CONF_TPI_COEF_INT: 0.3, CONF_TPI_COEF_INT: 0.3,
@@ -361,8 +362,6 @@ async def test_full_over_switch_with_central_config(
CONF_MOTION_PRESET: "comfort", CONF_MOTION_PRESET: "comfort",
CONF_NO_MOTION_PRESET: "eco", CONF_NO_MOTION_PRESET: "eco",
CONF_MOTION_SENSOR: "binary_sensor.mock_motion_sensor", CONF_MOTION_SENSOR: "binary_sensor.mock_motion_sensor",
CONF_POWER_SENSOR: "sensor.mock_power_sensor",
CONF_MAX_POWER_SENSOR: "sensor.mock_max_power_sensor",
CONF_PRESENCE_SENSOR: "binary_sensor.mock_presence_sensor", CONF_PRESENCE_SENSOR: "binary_sensor.mock_presence_sensor",
CONF_USE_MAIN_CENTRAL_CONFIG: True, CONF_USE_MAIN_CENTRAL_CONFIG: True,
CONF_USE_TPI_CENTRAL_CONFIG: True, CONF_USE_TPI_CENTRAL_CONFIG: True,
@@ -426,10 +425,13 @@ async def test_full_over_switch_with_central_config(
assert entity.motion_manager.motion_preset == "boost" assert entity.motion_manager.motion_preset == "boost"
assert entity.motion_manager.no_motion_preset == "frost" assert entity.motion_manager.no_motion_preset == "frost"
assert entity.power_manager.power_sensor_entity_id == "sensor.mock_power_sensor"
assert ( assert (
entity.power_manager.max_power_sensor_entity_id VersatileThermostatAPI.get_vtherm_api().central_power_manager.power_sensor_entity_id
== "sensor.mock_max_power_sensor" == "sensor.the_power_sensor"
)
assert (
VersatileThermostatAPI.get_vtherm_api().central_power_manager.max_power_sensor_entity_id
== "sensor.the_max_power_sensor"
) )
assert ( assert (

View File

@@ -229,7 +229,7 @@ async def test_central_power_manageer_find_vtherms(
"is_overpowering_detected": False, "is_overpowering_detected": False,
}, },
], ],
{}, {"vtherm1": False},
), ),
# Simple trivial shedding # Simple trivial shedding
( (

View File

@@ -721,10 +721,14 @@ async def test_multiple_climates_underlying_changes_not_aligned(
@pytest.mark.parametrize("expected_lingering_tasks", [True]) @pytest.mark.parametrize("expected_lingering_tasks", [True])
@pytest.mark.parametrize("expected_lingering_timers", [True]) @pytest.mark.parametrize("expected_lingering_timers", [True])
async def test_multiple_switch_power_management( async def test_multiple_switch_power_management(
hass: HomeAssistant, skip_hass_states_is_state hass: HomeAssistant, skip_hass_states_is_state, init_central_power_manager
): ):
"""Test the Power management""" """Test the Power management"""
temps = {
"eco": 17,
"comfort": 18,
"boost": 19,
}
entry = MockConfigEntry( entry = MockConfigEntry(
domain=DOMAIN, domain=DOMAIN,
title="TheOverSwitchMockName", title="TheOverSwitchMockName",
@@ -737,17 +741,16 @@ async def test_multiple_switch_power_management(
CONF_CYCLE_MIN: 8, CONF_CYCLE_MIN: 8,
CONF_TEMP_MIN: 15, CONF_TEMP_MIN: 15,
CONF_TEMP_MAX: 30, CONF_TEMP_MAX: 30,
"eco_temp": 17,
"comfort_temp": 18,
"boost_temp": 19,
CONF_USE_WINDOW_FEATURE: False, CONF_USE_WINDOW_FEATURE: False,
CONF_USE_MOTION_FEATURE: False, CONF_USE_MOTION_FEATURE: False,
CONF_USE_POWER_FEATURE: True, CONF_USE_POWER_FEATURE: True,
CONF_USE_PRESENCE_FEATURE: False, CONF_USE_PRESENCE_FEATURE: False,
CONF_HEATER: "switch.mock_switch1", CONF_UNDERLYING_LIST: [
CONF_HEATER_2: "switch.mock_switch2", "switch.mock_switch1",
CONF_HEATER_3: "switch.mock_switch3", "switch.mock_switch2",
CONF_HEATER_4: "switch.mock_switch4", "switch.mock_switch3",
"switch.mock_switch4",
],
CONF_HEATER_KEEP_ALIVE: 0, CONF_HEATER_KEEP_ALIVE: 0,
CONF_MINIMAL_ACTIVATION_DELAY: 30, CONF_MINIMAL_ACTIVATION_DELAY: 30,
CONF_SAFETY_DELAY_MIN: 5, CONF_SAFETY_DELAY_MIN: 5,
@@ -755,15 +758,13 @@ async def test_multiple_switch_power_management(
CONF_PROP_FUNCTION: PROPORTIONAL_FUNCTION_TPI, CONF_PROP_FUNCTION: PROPORTIONAL_FUNCTION_TPI,
CONF_TPI_COEF_INT: 0.3, CONF_TPI_COEF_INT: 0.3,
CONF_TPI_COEF_EXT: 0.01, CONF_TPI_COEF_EXT: 0.01,
CONF_POWER_SENSOR: "sensor.mock_power_sensor",
CONF_MAX_POWER_SENSOR: "sensor.mock_power_max_sensor",
CONF_DEVICE_POWER: 100, CONF_DEVICE_POWER: 100,
CONF_PRESET_POWER: 12, CONF_PRESET_POWER: 12,
}, },
) )
entity: BaseThermostat = await create_thermostat( entity: BaseThermostat = await create_thermostat(
hass, entry, "climate.theover4switchmockname" hass, entry, "climate.theover4switchmockname", temps
) )
assert entity assert entity
assert entity.is_over_climate is False assert entity.is_over_climate is False
@@ -772,6 +773,9 @@ async def test_multiple_switch_power_management(
tpi_algo = entity._prop_algorithm tpi_algo = entity._prop_algorithm
assert tpi_algo assert tpi_algo
now: datetime = NowClass.get_now(hass)
VersatileThermostatAPI.get_vtherm_api()._set_now(now)
await entity.async_set_hvac_mode(HVACMode.HEAT) await entity.async_set_hvac_mode(HVACMode.HEAT)
await entity.async_set_preset_mode(PRESET_BOOST) await entity.async_set_preset_mode(PRESET_BOOST)
assert entity.hvac_mode is HVACMode.HEAT assert entity.hvac_mode is HVACMode.HEAT
@@ -780,8 +784,22 @@ async def test_multiple_switch_power_management(
assert entity.target_temperature == 19 assert entity.target_temperature == 19
# 1. Send power mesurement # 1. Send power mesurement
await send_power_change_event(entity, 50, datetime.now()) side_effects = SideEffects(
{
"sensor.the_power_sensor": State("sensor.the_power_sensor", 50),
"sensor.the_max_power_sensor": State("sensor.the_max_power_sensor", 300),
},
State("unknown.entity_id", "unknown"),
)
# Send power max mesurement # Send power max mesurement
# fmt:off
with patch("homeassistant.core.StateMachine.get", side_effect=side_effects.get_side_effects()):
# fmt: on
now = now + timedelta(seconds=61)
VersatileThermostatAPI.get_vtherm_api()._set_now(now)
await send_power_change_event(entity, 50, datetime.now())
await send_max_power_change_event(entity, 300, datetime.now()) await send_max_power_change_event(entity, 300, datetime.now())
assert entity.power_manager.is_overpowering_detected is False assert entity.power_manager.is_overpowering_detected is False
# All configuration is complete and power is < power_max # All configuration is complete and power is < power_max
@@ -789,6 +807,8 @@ async def test_multiple_switch_power_management(
assert entity.power_manager.overpowering_state is STATE_OFF assert entity.power_manager.overpowering_state is STATE_OFF
# 2. Send power max mesurement too low and HVACMode is on # 2. Send power max mesurement too low and HVACMode is on
side_effects.add_or_update_side_effect("sensor.the_max_power_sensor", State("sensor.the_max_power_sensor", 74))
with patch( with patch(
"custom_components.versatile_thermostat.base_thermostat.BaseThermostat.send_event" "custom_components.versatile_thermostat.base_thermostat.BaseThermostat.send_event"
) as mock_send_event, patch( ) as mock_send_event, patch(
@@ -796,6 +816,9 @@ async def test_multiple_switch_power_management(
) as mock_heater_on, patch( ) as mock_heater_on, patch(
"custom_components.versatile_thermostat.underlyings.UnderlyingSwitch.turn_off" "custom_components.versatile_thermostat.underlyings.UnderlyingSwitch.turn_off"
) as mock_heater_off: ) as mock_heater_off:
now = now + timedelta(seconds=61)
VersatileThermostatAPI.get_vtherm_api()._set_now(now)
# 100 of the device / 4 -> 25, current power 50 so max is 75 # 100 of the device / 4 -> 25, current power 50 so max is 75
await send_max_power_change_event(entity, 74, datetime.now()) await send_max_power_change_event(entity, 74, datetime.now())
assert entity.power_manager.is_overpowering_detected is True assert entity.power_manager.is_overpowering_detected is True
@@ -828,12 +851,17 @@ async def test_multiple_switch_power_management(
with patch( with patch(
"custom_components.versatile_thermostat.base_thermostat.BaseThermostat.send_event" "custom_components.versatile_thermostat.base_thermostat.BaseThermostat.send_event"
) as mock_send_event: ) as mock_send_event:
now = now + timedelta(seconds=61)
VersatileThermostatAPI.get_vtherm_api()._set_now(now)
await entity.async_set_preset_mode(PRESET_ECO) await entity.async_set_preset_mode(PRESET_ECO)
assert entity.preset_mode is PRESET_ECO assert entity.preset_mode is PRESET_ECO
# No change # No change
assert entity.power_manager.overpowering_state is STATE_ON assert entity.power_manager.overpowering_state is STATE_ON
# 4. Send hugh power max mesurement to release overpowering # 4. Send hugh power max mesurement to release overpowering
side_effects.add_or_update_side_effect("sensor.the_max_power_sensor", State("sensor.the_max_power_sensor", 150))
with patch( with patch(
"custom_components.versatile_thermostat.base_thermostat.BaseThermostat.send_event" "custom_components.versatile_thermostat.base_thermostat.BaseThermostat.send_event"
) as mock_send_event, patch( ) as mock_send_event, patch(
@@ -841,6 +869,9 @@ async def test_multiple_switch_power_management(
) as mock_heater_on, patch( ) as mock_heater_on, patch(
"custom_components.versatile_thermostat.underlyings.UnderlyingSwitch.turn_off" "custom_components.versatile_thermostat.underlyings.UnderlyingSwitch.turn_off"
) as mock_heater_off: ) as mock_heater_off:
now = now + timedelta(seconds=61)
VersatileThermostatAPI.get_vtherm_api()._set_now(now)
# 100 of the device / 4 -> 25, current power 50 so max is 75. With 150 no overheating # 100 of the device / 4 -> 25, current power 50 so max is 75. With 150 no overheating
await send_max_power_change_event(entity, 150, datetime.now()) await send_max_power_change_event(entity, 150, datetime.now())
assert entity.power_manager.is_overpowering_detected is False assert entity.power_manager.is_overpowering_detected is False