* 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
1069 lines
41 KiB
Python
1069 lines
41 KiB
Python
# pylint: disable=wildcard-import, unused-wildcard-import, protected-access, unused-argument, line-too-long, too-many-lines
|
|
|
|
""" Test the central_configuration """
|
|
from unittest.mock import patch, call
|
|
|
|
from datetime import datetime, timedelta
|
|
|
|
from homeassistant.core import HomeAssistant
|
|
|
|
from homeassistant.components.climate import HVACMode
|
|
|
|
# from homeassistant.helpers.entity_component import EntityComponent
|
|
from homeassistant.components.select import DOMAIN as SELECT_DOMAIN
|
|
|
|
from pytest_homeassistant_custom_component.common import MockConfigEntry
|
|
|
|
from custom_components.versatile_thermostat.thermostat_switch import (
|
|
ThermostatOverSwitch,
|
|
)
|
|
|
|
from .commons import * # pylint: disable=wildcard-import, unused-wildcard-import
|
|
from .const import * # pylint: disable=wildcard-import, unused-wildcard-import
|
|
|
|
|
|
# @pytest.mark.parametrize("expected_lingering_tasks", [True])
|
|
@pytest.mark.parametrize("expected_lingering_timers", [True])
|
|
async def test_config_with_central_mode_true(
|
|
hass: HomeAssistant, skip_hass_states_is_state
|
|
):
|
|
"""A config with central_mode True"""
|
|
|
|
# Add a Switch VTherm
|
|
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_USE_CENTRAL_MODE: True,
|
|
CONF_CYCLE_MIN: 5,
|
|
CONF_TEMP_MIN: 8,
|
|
CONF_TEMP_MAX: 18,
|
|
"frost_temp": 10,
|
|
"eco_temp": 17,
|
|
"comfort_temp": 18,
|
|
"boost_temp": 21,
|
|
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: 0,
|
|
CONF_SAFETY_DELAY_MIN: 5,
|
|
CONF_SAFETY_MIN_ON_PERCENT: 0.3,
|
|
CONF_SAFETY_DEFAULT_ON_PERCENT: 0.1,
|
|
},
|
|
)
|
|
|
|
with patch("homeassistant.core.ServiceRegistry.async_call"):
|
|
entity: ThermostatOverSwitch = await create_thermostat(
|
|
hass, entry, "climate.theoverswitchmockname"
|
|
)
|
|
assert entity
|
|
assert entity.name == "TheOverSwitchMockName"
|
|
assert entity.is_over_switch
|
|
assert entity.is_controlled_by_central_mode
|
|
assert entity.last_central_mode is None # cause no central config exists
|
|
|
|
|
|
@pytest.mark.parametrize("expected_lingering_timers", [True])
|
|
async def test_config_with_central_mode_false(
|
|
hass: HomeAssistant, skip_hass_states_is_state
|
|
):
|
|
"""A config with central_mode False"""
|
|
|
|
# Add a Climate VTherm
|
|
entry = MockConfigEntry(
|
|
domain=DOMAIN,
|
|
title="TheOverClimateMockName",
|
|
unique_id="uniqueId",
|
|
data={
|
|
CONF_NAME: "TheOverClimateMockName",
|
|
CONF_THERMOSTAT_TYPE: CONF_THERMOSTAT_CLIMATE,
|
|
CONF_TEMP_SENSOR: "sensor.mock_temp_sensor",
|
|
CONF_EXTERNAL_TEMP_SENSOR: "sensor.mock_ext_temp_sensor",
|
|
CONF_USE_CENTRAL_MODE: False,
|
|
CONF_CYCLE_MIN: 5,
|
|
CONF_TEMP_MIN: 8,
|
|
CONF_TEMP_MAX: 18,
|
|
"frost_temp": 10,
|
|
"eco_temp": 17,
|
|
"comfort_temp": 18,
|
|
"boost_temp": 21,
|
|
CONF_USE_WINDOW_FEATURE: False,
|
|
CONF_USE_MOTION_FEATURE: False,
|
|
CONF_USE_POWER_FEATURE: False,
|
|
CONF_USE_PRESENCE_FEATURE: False,
|
|
CONF_CLIMATE: "climate.mock_climate",
|
|
CONF_MINIMAL_ACTIVATION_DELAY: 30,
|
|
CONF_MINIMAL_DEACTIVATION_DELAY: 0,
|
|
CONF_SAFETY_DELAY_MIN: 5,
|
|
CONF_SAFETY_MIN_ON_PERCENT: 0.3,
|
|
CONF_SAFETY_DEFAULT_ON_PERCENT: 0.1,
|
|
},
|
|
)
|
|
|
|
with patch("homeassistant.core.ServiceRegistry.async_call"):
|
|
entity: ThermostatOverSwitch = await create_thermostat(
|
|
hass, entry, "climate.theoverclimatemockname"
|
|
)
|
|
assert entity
|
|
assert entity.name == "TheOverClimateMockName"
|
|
assert entity.is_over_climate
|
|
assert entity.is_controlled_by_central_mode is False
|
|
assert entity.last_central_mode is None # cause no central config exists
|
|
|
|
|
|
@pytest.mark.parametrize("expected_lingering_timers", [True])
|
|
async def test_config_with_central_mode_none(
|
|
hass: HomeAssistant, skip_hass_states_is_state
|
|
):
|
|
"""A config with central_mode is None"""
|
|
|
|
# Add a Switch VTherm
|
|
entry = MockConfigEntry(
|
|
domain=DOMAIN,
|
|
title="TheOverValveMockName",
|
|
unique_id="uniqueId",
|
|
data={
|
|
CONF_NAME: "TheOverValveMockName",
|
|
CONF_THERMOSTAT_TYPE: CONF_THERMOSTAT_VALVE,
|
|
CONF_TEMP_SENSOR: "sensor.mock_temp_sensor",
|
|
CONF_EXTERNAL_TEMP_SENSOR: "sensor.mock_ext_temp_sensor",
|
|
CONF_USE_CENTRAL_MODE: True,
|
|
CONF_CYCLE_MIN: 5,
|
|
CONF_TEMP_MIN: 8,
|
|
CONF_TEMP_MAX: 18,
|
|
"frost_temp": 10,
|
|
"eco_temp": 17,
|
|
"comfort_temp": 18,
|
|
"boost_temp": 21,
|
|
CONF_USE_WINDOW_FEATURE: False,
|
|
CONF_USE_MOTION_FEATURE: False,
|
|
CONF_USE_POWER_FEATURE: False,
|
|
CONF_USE_PRESENCE_FEATURE: False,
|
|
CONF_VALVE: "number.mock_valve",
|
|
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: 0,
|
|
CONF_SAFETY_DELAY_MIN: 5,
|
|
CONF_SAFETY_MIN_ON_PERCENT: 0.3,
|
|
CONF_SAFETY_DEFAULT_ON_PERCENT: 0.1,
|
|
},
|
|
)
|
|
|
|
with patch("homeassistant.core.ServiceRegistry.async_call"):
|
|
entity: ThermostatOverSwitch = await create_thermostat(
|
|
hass, entry, "climate.theovervalvemockname"
|
|
)
|
|
assert entity
|
|
assert entity.name == "TheOverValveMockName"
|
|
assert entity.is_over_valve
|
|
assert entity.is_controlled_by_central_mode
|
|
assert entity.last_central_mode is None # cause no central config exists
|
|
|
|
|
|
@pytest.mark.parametrize("expected_lingering_tasks", [True])
|
|
@pytest.mark.parametrize("expected_lingering_timers", [True])
|
|
async def test_switch_change_central_mode_true(
|
|
hass: HomeAssistant, skip_hass_states_is_state, init_central_config
|
|
):
|
|
"""test that changes with over_switch config with central_mode True are
|
|
taken into account"""
|
|
|
|
# Add a Switch VTherm
|
|
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_USE_CENTRAL_MODE: True,
|
|
CONF_CYCLE_MIN: 5,
|
|
CONF_TEMP_MIN: 8,
|
|
CONF_TEMP_MAX: 18,
|
|
"frost_temp": 10,
|
|
"eco_temp": 17,
|
|
"comfort_temp": 18,
|
|
"boost_temp": 21,
|
|
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: 0,
|
|
CONF_SAFETY_DELAY_MIN: 5,
|
|
CONF_SAFETY_MIN_ON_PERCENT: 0.3,
|
|
CONF_SAFETY_DEFAULT_ON_PERCENT: 0.1,
|
|
},
|
|
)
|
|
|
|
# 1 initialize entity and find select entity
|
|
with patch("homeassistant.core.ServiceRegistry.async_call"):
|
|
entity: ThermostatOverSwitch = await create_thermostat(
|
|
hass, entry, "climate.theoverswitchmockname"
|
|
)
|
|
assert entity
|
|
assert entity.is_controlled_by_central_mode
|
|
assert entity.last_central_mode is None
|
|
|
|
# Find the select entity
|
|
select_entity = search_entity(hass, "select.central_mode", SELECT_DOMAIN)
|
|
|
|
assert select_entity
|
|
assert select_entity.current_option == CENTRAL_MODE_AUTO
|
|
assert select_entity.options == CENTRAL_MODES
|
|
|
|
# start entity
|
|
await entity.async_set_hvac_mode(HVACMode.HEAT)
|
|
await entity.async_set_preset_mode(PRESET_BOOST)
|
|
|
|
assert entity.hvac_mode == HVACMode.HEAT
|
|
assert entity.preset_mode == PRESET_BOOST
|
|
|
|
# 2 change central_mode to STOPPED
|
|
with patch("homeassistant.core.ServiceRegistry.async_call"):
|
|
await select_entity.async_select_option(CENTRAL_MODE_STOPPED)
|
|
|
|
assert entity.last_central_mode is CENTRAL_MODE_STOPPED
|
|
assert entity.hvac_mode == HVACMode.OFF
|
|
assert entity.preset_mode == PRESET_BOOST
|
|
|
|
# 3 change back central_mode to AUTO
|
|
with patch("homeassistant.core.ServiceRegistry.async_call"):
|
|
await entity.async_set_preset_mode(PRESET_COMFORT)
|
|
assert entity.preset_mode == PRESET_COMFORT
|
|
|
|
await select_entity.async_select_option(CENTRAL_MODE_AUTO)
|
|
|
|
# hvac_mode should be restored as before the STOP and preset should be restored with the last choosen preset (COMFORT here)
|
|
assert entity.last_central_mode is CENTRAL_MODE_AUTO
|
|
assert entity.hvac_mode == HVACMode.HEAT
|
|
assert entity.preset_mode == PRESET_COMFORT
|
|
|
|
# 4 change central_mode to COOL_ONLY
|
|
with patch("homeassistant.core.ServiceRegistry.async_call"):
|
|
await select_entity.async_select_option(CENTRAL_MODE_COOL_ONLY)
|
|
|
|
# hvac_mode should be set to OFF because there is no COOL mode for this VTherm
|
|
assert entity.last_central_mode is CENTRAL_MODE_COOL_ONLY
|
|
assert entity.hvac_mode == HVACMode.OFF
|
|
assert entity.preset_mode == PRESET_COMFORT
|
|
|
|
# 5 change back central_mode to AUTO
|
|
with patch("homeassistant.core.ServiceRegistry.async_call"):
|
|
await select_entity.async_select_option(CENTRAL_MODE_AUTO)
|
|
|
|
# hvac_mode should be restored to HEAT
|
|
assert entity.last_central_mode is CENTRAL_MODE_AUTO
|
|
assert entity.hvac_mode == HVACMode.HEAT
|
|
assert entity.preset_mode == PRESET_COMFORT
|
|
|
|
# 6 change central_mode to HEAT_ONLY
|
|
with patch("homeassistant.core.ServiceRegistry.async_call"):
|
|
await select_entity.async_select_option(CENTRAL_MODE_HEAT_ONLY)
|
|
|
|
# hvac_mode should stay in HEAT mode
|
|
assert entity.last_central_mode is CENTRAL_MODE_HEAT_ONLY
|
|
assert entity.hvac_mode == HVACMode.HEAT
|
|
# No change
|
|
assert entity.preset_mode == PRESET_COMFORT
|
|
|
|
# 7 change back central_mode to AUTO
|
|
with patch("homeassistant.core.ServiceRegistry.async_call"):
|
|
await select_entity.async_select_option(CENTRAL_MODE_AUTO)
|
|
|
|
# hvac_mode should be restored to HEAT
|
|
assert entity.last_central_mode is CENTRAL_MODE_AUTO
|
|
assert entity.hvac_mode == HVACMode.HEAT
|
|
assert entity.preset_mode == PRESET_COMFORT
|
|
|
|
# 8 change central_mode to FROST_PROTECTION
|
|
with patch("homeassistant.core.ServiceRegistry.async_call"):
|
|
await select_entity.async_select_option(CENTRAL_MODE_FROST_PROTECTION)
|
|
|
|
# hvac_mode should stay in HEAT mode
|
|
assert entity.last_central_mode is CENTRAL_MODE_FROST_PROTECTION
|
|
assert entity.hvac_mode == HVACMode.HEAT
|
|
# change to Frost
|
|
assert entity.preset_mode == PRESET_FROST_PROTECTION
|
|
|
|
# 9 change back central_mode to AUTO
|
|
with patch("homeassistant.core.ServiceRegistry.async_call"):
|
|
await select_entity.async_select_option(CENTRAL_MODE_AUTO)
|
|
|
|
# hvac_mode should be restored to HEAT
|
|
assert entity.last_central_mode is CENTRAL_MODE_AUTO
|
|
assert entity.hvac_mode == HVACMode.HEAT
|
|
# preset restored to COMFORT
|
|
assert entity.preset_mode == PRESET_COMFORT
|
|
|
|
|
|
@pytest.mark.parametrize("expected_lingering_tasks", [True])
|
|
@pytest.mark.parametrize("expected_lingering_timers", [True])
|
|
async def test_switch_ac_change_central_mode_true(
|
|
hass: HomeAssistant, skip_hass_states_is_state, init_central_config
|
|
):
|
|
"""test that changes with over_switch config with central_mode True are
|
|
taken into account"""
|
|
|
|
# Add a Switch VTherm
|
|
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_USE_CENTRAL_MODE: True,
|
|
CONF_CYCLE_MIN: 5,
|
|
CONF_TEMP_MIN: 8,
|
|
CONF_TEMP_MAX: 18,
|
|
"frost_temp": 10,
|
|
"eco_temp": 17,
|
|
"comfort_temp": 18,
|
|
"boost_temp": 21,
|
|
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: 0,
|
|
CONF_SAFETY_DELAY_MIN: 5,
|
|
CONF_SAFETY_MIN_ON_PERCENT: 0.3,
|
|
CONF_SAFETY_DEFAULT_ON_PERCENT: 0.1,
|
|
CONF_AC_MODE: True,
|
|
},
|
|
)
|
|
|
|
# 1 initialize entity and find select entity
|
|
with patch("homeassistant.core.ServiceRegistry.async_call"):
|
|
entity: ThermostatOverSwitch = await create_thermostat(
|
|
hass, entry, "climate.theoverswitchmockname"
|
|
)
|
|
assert entity
|
|
assert entity.is_controlled_by_central_mode
|
|
assert entity.ac_mode is True
|
|
assert entity.hvac_modes == [HVACMode.HEAT, HVACMode.COOL, HVACMode.OFF]
|
|
|
|
# Find the select entity
|
|
select_entity = search_entity(hass, "select.central_mode", SELECT_DOMAIN)
|
|
|
|
assert select_entity
|
|
assert select_entity.current_option == CENTRAL_MODE_AUTO
|
|
assert select_entity.options == CENTRAL_MODES
|
|
|
|
# start entity in cooling mode
|
|
await entity.async_set_hvac_mode(HVACMode.COOL)
|
|
await entity.async_set_preset_mode(PRESET_BOOST)
|
|
|
|
assert entity.hvac_mode == HVACMode.COOL
|
|
assert entity.preset_mode == PRESET_BOOST
|
|
|
|
# 2 change central_mode to STOPPED
|
|
with patch("homeassistant.core.ServiceRegistry.async_call"):
|
|
await select_entity.async_select_option(CENTRAL_MODE_STOPPED)
|
|
|
|
assert entity.hvac_mode == HVACMode.OFF
|
|
assert entity.preset_mode == PRESET_BOOST
|
|
|
|
# 3 change back central_mode to AUTO
|
|
with patch("homeassistant.core.ServiceRegistry.async_call"):
|
|
await entity.async_set_preset_mode(PRESET_COMFORT)
|
|
assert entity.preset_mode == PRESET_COMFORT
|
|
|
|
await select_entity.async_select_option(CENTRAL_MODE_AUTO)
|
|
|
|
# hvac_mode should be restored as before the STOP and preset should be restored with the last choosen preset (COMFORT here)
|
|
assert entity.hvac_mode == HVACMode.COOL
|
|
assert entity.preset_mode == PRESET_COMFORT
|
|
|
|
# 4 change central_mode to COOL_ONLY
|
|
with patch("homeassistant.core.ServiceRegistry.async_call"):
|
|
await select_entity.async_select_option(CENTRAL_MODE_COOL_ONLY)
|
|
|
|
# hvac_mode should be set to OFF because there is no COOL mode for this VTherm
|
|
assert entity.hvac_mode == HVACMode.COOL
|
|
assert entity.preset_mode == PRESET_COMFORT
|
|
|
|
# 5 change back central_mode to AUTO
|
|
with patch("homeassistant.core.ServiceRegistry.async_call"):
|
|
await select_entity.async_select_option(CENTRAL_MODE_AUTO)
|
|
|
|
# hvac_mode should be restored to HEAT
|
|
assert entity.hvac_mode == HVACMode.COOL
|
|
assert entity.preset_mode == PRESET_COMFORT
|
|
|
|
# 6 change central_mode to HEAT_ONLY
|
|
with patch("homeassistant.core.ServiceRegistry.async_call"):
|
|
await select_entity.async_select_option(CENTRAL_MODE_HEAT_ONLY)
|
|
|
|
# hvac_mode should stay in HEAT mode
|
|
assert entity.hvac_mode == HVACMode.HEAT
|
|
# No change
|
|
assert entity.preset_mode == PRESET_COMFORT
|
|
|
|
# 7 change back central_mode to AUTO
|
|
with patch("homeassistant.core.ServiceRegistry.async_call"):
|
|
await select_entity.async_select_option(CENTRAL_MODE_AUTO)
|
|
|
|
# hvac_mode should be restored to COOL
|
|
assert entity.hvac_mode == HVACMode.COOL
|
|
assert entity.preset_mode == PRESET_COMFORT
|
|
|
|
# 8 change central_mode to FROST_PROTECTION
|
|
with patch("homeassistant.core.ServiceRegistry.async_call"):
|
|
await select_entity.async_select_option(CENTRAL_MODE_FROST_PROTECTION)
|
|
|
|
# hvac_mode should stay in COOL mode
|
|
assert entity.hvac_mode == HVACMode.HEAT
|
|
# change to Frost
|
|
assert entity.preset_mode == PRESET_FROST_PROTECTION
|
|
|
|
# 9 change back central_mode to AUTO
|
|
with patch("homeassistant.core.ServiceRegistry.async_call"):
|
|
await select_entity.async_select_option(CENTRAL_MODE_AUTO)
|
|
|
|
# hvac_mode should be restored to COOL
|
|
assert entity.hvac_mode == HVACMode.COOL
|
|
# preset restored to COMFORT
|
|
assert entity.preset_mode == PRESET_COMFORT
|
|
|
|
|
|
@pytest.mark.parametrize("expected_lingering_tasks", [True])
|
|
@pytest.mark.parametrize("expected_lingering_timers", [True])
|
|
async def test_climate_ac_change_central_mode_false(
|
|
hass: HomeAssistant, skip_hass_states_is_state, init_central_config
|
|
):
|
|
"""test that changes with over_climate config with central_mode False are
|
|
not taken into account"""
|
|
|
|
fake_underlying_climate = MockClimate(hass, "mockUniqueId", "MockClimateName", {})
|
|
|
|
# Add a Climate VTherm
|
|
entry = MockConfigEntry(
|
|
domain=DOMAIN,
|
|
title="TheOverClimateMockName",
|
|
unique_id="uniqueId",
|
|
data={
|
|
CONF_NAME: "TheOverClimateMockName",
|
|
CONF_THERMOSTAT_TYPE: CONF_THERMOSTAT_CLIMATE,
|
|
CONF_TEMP_SENSOR: "sensor.mock_temp_sensor",
|
|
CONF_EXTERNAL_TEMP_SENSOR: "sensor.mock_ext_temp_sensor",
|
|
CONF_USE_CENTRAL_MODE: False,
|
|
CONF_CYCLE_MIN: 5,
|
|
CONF_TEMP_MIN: 8,
|
|
CONF_TEMP_MAX: 18,
|
|
"frost_temp": 10,
|
|
"eco_temp": 17,
|
|
"comfort_temp": 18,
|
|
"boost_temp": 21,
|
|
CONF_USE_WINDOW_FEATURE: False,
|
|
CONF_USE_MOTION_FEATURE: False,
|
|
CONF_USE_POWER_FEATURE: False,
|
|
CONF_USE_PRESENCE_FEATURE: False,
|
|
CONF_CLIMATE: "climate.mock_climate",
|
|
CONF_MINIMAL_ACTIVATION_DELAY: 30,
|
|
CONF_MINIMAL_DEACTIVATION_DELAY: 0,
|
|
CONF_SAFETY_DELAY_MIN: 5,
|
|
CONF_SAFETY_MIN_ON_PERCENT: 0.3,
|
|
CONF_SAFETY_DEFAULT_ON_PERCENT: 0.1,
|
|
},
|
|
)
|
|
|
|
with patch("homeassistant.core.ServiceRegistry.async_call"), patch(
|
|
"custom_components.versatile_thermostat.underlyings.UnderlyingClimate.find_underlying_climate",
|
|
return_value=fake_underlying_climate,
|
|
):
|
|
entity: ThermostatOverSwitch = await create_thermostat(
|
|
hass, entry, "climate.theoverclimatemockname"
|
|
)
|
|
assert entity
|
|
assert entity.name == "TheOverClimateMockName"
|
|
assert entity.is_over_climate
|
|
assert entity.is_controlled_by_central_mode is False
|
|
assert entity.hvac_modes == [HVACMode.OFF, HVACMode.COOL, HVACMode.HEAT]
|
|
|
|
# Find the select entity
|
|
select_entity = search_entity(hass, "select.central_mode", SELECT_DOMAIN)
|
|
|
|
assert select_entity
|
|
assert select_entity.current_option == CENTRAL_MODE_AUTO
|
|
assert select_entity.options == CENTRAL_MODES
|
|
|
|
# start entity in Heating mode
|
|
await entity.async_set_hvac_mode(HVACMode.HEAT)
|
|
await entity.async_set_preset_mode(PRESET_BOOST)
|
|
|
|
assert entity.hvac_mode == HVACMode.HEAT
|
|
assert entity.preset_mode == PRESET_BOOST
|
|
|
|
# 2 change central_mode to STOPPED
|
|
with patch("homeassistant.core.ServiceRegistry.async_call"):
|
|
await select_entity.async_select_option(CENTRAL_MODE_STOPPED)
|
|
|
|
# No change
|
|
assert entity.hvac_mode == HVACMode.HEAT
|
|
assert entity.preset_mode == PRESET_BOOST
|
|
|
|
# 3 change back central_mode to AUTO
|
|
with patch("homeassistant.core.ServiceRegistry.async_call"):
|
|
await entity.async_set_preset_mode(PRESET_COMFORT)
|
|
assert entity.preset_mode == PRESET_COMFORT
|
|
|
|
await select_entity.async_select_option(CENTRAL_MODE_AUTO)
|
|
|
|
# No change
|
|
assert entity.hvac_mode == HVACMode.HEAT
|
|
assert entity.preset_mode == PRESET_COMFORT
|
|
|
|
# 4 change central_mode to COOL_ONLY
|
|
with patch("homeassistant.core.ServiceRegistry.async_call"):
|
|
await select_entity.async_select_option(CENTRAL_MODE_COOL_ONLY)
|
|
|
|
# No change
|
|
assert entity.hvac_mode == HVACMode.HEAT
|
|
assert entity.preset_mode == PRESET_COMFORT
|
|
|
|
# 5 change back central_mode to AUTO
|
|
with patch("homeassistant.core.ServiceRegistry.async_call"):
|
|
await select_entity.async_select_option(CENTRAL_MODE_AUTO)
|
|
|
|
# No change
|
|
assert entity.hvac_mode == HVACMode.HEAT
|
|
assert entity.preset_mode == PRESET_COMFORT
|
|
|
|
# 6 change central_mode to HEAT_ONLY
|
|
with patch("homeassistant.core.ServiceRegistry.async_call"):
|
|
await select_entity.async_select_option(CENTRAL_MODE_HEAT_ONLY)
|
|
|
|
# No change
|
|
assert entity.hvac_mode == HVACMode.HEAT
|
|
assert entity.preset_mode == PRESET_COMFORT
|
|
|
|
# 7 change back central_mode to AUTO
|
|
with patch("homeassistant.core.ServiceRegistry.async_call"):
|
|
await select_entity.async_select_option(CENTRAL_MODE_AUTO)
|
|
|
|
# No change
|
|
assert entity.hvac_mode == HVACMode.HEAT
|
|
assert entity.preset_mode == PRESET_COMFORT
|
|
|
|
# 8 change central_mode to FROST_PROTECTION
|
|
with patch("homeassistant.core.ServiceRegistry.async_call"):
|
|
await select_entity.async_select_option(CENTRAL_MODE_FROST_PROTECTION)
|
|
|
|
# No change
|
|
assert entity.hvac_mode == HVACMode.HEAT
|
|
assert entity.preset_mode == PRESET_COMFORT
|
|
|
|
# 9 change back central_mode to AUTO
|
|
with patch("homeassistant.core.ServiceRegistry.async_call"):
|
|
await select_entity.async_select_option(CENTRAL_MODE_AUTO)
|
|
|
|
# No change
|
|
assert entity.hvac_mode == HVACMode.HEAT
|
|
assert entity.preset_mode == PRESET_COMFORT
|
|
|
|
|
|
@pytest.mark.parametrize("expected_lingering_tasks", [True])
|
|
@pytest.mark.parametrize("expected_lingering_timers", [True])
|
|
async def test_climate_ac_only_change_central_mode_true(
|
|
hass: HomeAssistant, skip_hass_states_is_state, init_central_config
|
|
):
|
|
"""test that changes with over_climate with AC only config with central_mode True are
|
|
taken into account
|
|
Test also switching from central_mode without coming to AUTO each time"""
|
|
|
|
fake_underlying_climate = MockClimate(
|
|
hass,
|
|
"mockUniqueId",
|
|
"MockClimateName",
|
|
entry_infos={},
|
|
hvac_modes=[HVACMode.OFF, HVACMode.COOL],
|
|
)
|
|
|
|
# Add a Climate VTherm
|
|
entry = MockConfigEntry(
|
|
domain=DOMAIN,
|
|
title="TheOverClimateMockName",
|
|
unique_id="uniqueId",
|
|
data={
|
|
CONF_NAME: "TheOverClimateMockName",
|
|
CONF_THERMOSTAT_TYPE: CONF_THERMOSTAT_CLIMATE,
|
|
CONF_TEMP_SENSOR: "sensor.mock_temp_sensor",
|
|
CONF_EXTERNAL_TEMP_SENSOR: "sensor.mock_ext_temp_sensor",
|
|
CONF_USE_CENTRAL_MODE: True,
|
|
CONF_CYCLE_MIN: 5,
|
|
CONF_TEMP_MIN: 8,
|
|
CONF_TEMP_MAX: 18,
|
|
"frost_temp": 10,
|
|
"eco_temp": 17,
|
|
"comfort_temp": 18,
|
|
"boost_temp": 21,
|
|
CONF_USE_WINDOW_FEATURE: False,
|
|
CONF_USE_MOTION_FEATURE: False,
|
|
CONF_USE_POWER_FEATURE: False,
|
|
CONF_USE_PRESENCE_FEATURE: False,
|
|
CONF_CLIMATE: "climate.mock_climate",
|
|
CONF_MINIMAL_ACTIVATION_DELAY: 30,
|
|
CONF_MINIMAL_DEACTIVATION_DELAY: 0,
|
|
CONF_SAFETY_DELAY_MIN: 5,
|
|
CONF_SAFETY_MIN_ON_PERCENT: 0.3,
|
|
CONF_SAFETY_DEFAULT_ON_PERCENT: 0.1,
|
|
},
|
|
)
|
|
|
|
# 1. set hvac_mode to COOL and preet ECO
|
|
with patch("homeassistant.core.ServiceRegistry.async_call"), patch(
|
|
"custom_components.versatile_thermostat.underlyings.UnderlyingClimate.find_underlying_climate",
|
|
return_value=fake_underlying_climate,
|
|
):
|
|
entity: ThermostatOverSwitch = await create_thermostat(
|
|
hass, entry, "climate.theoverclimatemockname"
|
|
)
|
|
assert entity
|
|
assert entity.name == "TheOverClimateMockName"
|
|
assert entity.is_over_climate
|
|
assert entity.is_controlled_by_central_mode is True
|
|
assert entity.hvac_modes == [HVACMode.OFF, HVACMode.COOL]
|
|
|
|
# Find the select entity
|
|
select_entity = search_entity(hass, "select.central_mode", SELECT_DOMAIN)
|
|
|
|
assert select_entity
|
|
assert select_entity.current_option == CENTRAL_MODE_AUTO
|
|
assert select_entity.options == CENTRAL_MODES
|
|
|
|
# start entity in Cooling mode
|
|
await entity.async_set_hvac_mode(HVACMode.COOL)
|
|
await entity.async_set_preset_mode(PRESET_ECO)
|
|
|
|
assert entity.hvac_mode == HVACMode.COOL
|
|
assert entity.preset_mode == PRESET_ECO
|
|
|
|
# 2 change central_mode to STOPPED
|
|
with patch("homeassistant.core.ServiceRegistry.async_call"):
|
|
await select_entity.async_select_option(CENTRAL_MODE_STOPPED)
|
|
|
|
# No change
|
|
assert entity.hvac_mode == HVACMode.OFF
|
|
assert entity.preset_mode == PRESET_ECO
|
|
|
|
# 3 change central_mode to HEAT ONLY after switching to COMFORT preset
|
|
with patch("homeassistant.core.ServiceRegistry.async_call"):
|
|
await entity.async_set_preset_mode(PRESET_COMFORT)
|
|
assert entity.preset_mode == PRESET_COMFORT
|
|
|
|
await select_entity.async_select_option(CENTRAL_MODE_HEAT_ONLY)
|
|
|
|
# Stay in OFF because HEAT is not permitted
|
|
assert entity.hvac_mode == HVACMode.OFF
|
|
assert entity.preset_mode == PRESET_COMFORT
|
|
|
|
# 4 change central_mode to COOL_ONLY
|
|
with patch("homeassistant.core.ServiceRegistry.async_call"):
|
|
await select_entity.async_select_option(CENTRAL_MODE_COOL_ONLY)
|
|
|
|
# switch back to COOL restoring the preset
|
|
assert entity.hvac_mode == HVACMode.COOL
|
|
assert entity.preset_mode == PRESET_COMFORT
|
|
|
|
# 5 change back central_mode to AUTO
|
|
with patch("homeassistant.core.ServiceRegistry.async_call"):
|
|
await select_entity.async_select_option(CENTRAL_MODE_AUTO)
|
|
|
|
# No change
|
|
assert entity.hvac_mode == HVACMode.COOL
|
|
assert entity.preset_mode == PRESET_COMFORT
|
|
|
|
# 6 change central_mode to FROST_PROTECTION
|
|
with patch("homeassistant.core.ServiceRegistry.async_call"):
|
|
await select_entity.async_select_option(CENTRAL_MODE_FROST_PROTECTION)
|
|
|
|
# No change
|
|
assert entity.hvac_mode == HVACMode.OFF
|
|
assert entity.preset_mode == PRESET_COMFORT
|
|
|
|
# 7 change back central_mode to AUTO
|
|
with patch("homeassistant.core.ServiceRegistry.async_call"):
|
|
await select_entity.async_select_option(CENTRAL_MODE_AUTO)
|
|
|
|
# No change
|
|
assert entity.hvac_mode == HVACMode.COOL
|
|
assert entity.preset_mode == PRESET_COMFORT
|
|
|
|
# 8 change central_mode to FROST_PROTECTION
|
|
with patch("homeassistant.core.ServiceRegistry.async_call"):
|
|
await select_entity.async_select_option(CENTRAL_MODE_FROST_PROTECTION)
|
|
|
|
# No change
|
|
assert entity.hvac_mode == HVACMode.OFF
|
|
assert entity.preset_mode == PRESET_COMFORT
|
|
|
|
# 9 change back central_mode to COOL_ONLY
|
|
with patch("homeassistant.core.ServiceRegistry.async_call"):
|
|
await select_entity.async_select_option(CENTRAL_MODE_COOL_ONLY)
|
|
|
|
# No change
|
|
assert entity.hvac_mode == HVACMode.COOL
|
|
assert entity.preset_mode == PRESET_COMFORT
|
|
|
|
await entity.async_set_preset_mode(PRESET_ECO)
|
|
# 10 change back central_mode to HEAT_ONLY
|
|
with patch("homeassistant.core.ServiceRegistry.async_call"):
|
|
await select_entity.async_select_option(CENTRAL_MODE_HEAT_ONLY)
|
|
|
|
# Shutdown cause no HEAT
|
|
assert entity.hvac_mode == HVACMode.OFF
|
|
assert entity.preset_mode == PRESET_ECO
|
|
|
|
# 11 change back central_mode to AUTO
|
|
with patch("homeassistant.core.ServiceRegistry.async_call"):
|
|
await select_entity.async_select_option(CENTRAL_MODE_AUTO)
|
|
|
|
# No change
|
|
assert entity.hvac_mode == HVACMode.COOL
|
|
assert entity.preset_mode == PRESET_ECO
|
|
|
|
|
|
@pytest.mark.parametrize("expected_lingering_tasks", [True])
|
|
@pytest.mark.parametrize("expected_lingering_timers", [True])
|
|
async def test_switch_change_central_mode_true_with_window(
|
|
hass: HomeAssistant, skip_hass_states_is_state, init_central_config
|
|
):
|
|
"""test that changes with over_switch config with central_mode True are
|
|
taken into account"""
|
|
|
|
# Add a Switch VTherm
|
|
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_USE_CENTRAL_MODE: True,
|
|
CONF_CYCLE_MIN: 5,
|
|
CONF_TEMP_MIN: 8,
|
|
CONF_TEMP_MAX: 18,
|
|
"frost_temp": 10,
|
|
"eco_temp": 17,
|
|
"comfort_temp": 18,
|
|
"boost_temp": 21,
|
|
CONF_USE_WINDOW_FEATURE: True,
|
|
CONF_USE_MOTION_FEATURE: True,
|
|
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: 0,
|
|
CONF_SAFETY_DELAY_MIN: 5,
|
|
CONF_SAFETY_MIN_ON_PERCENT: 0.3,
|
|
CONF_SAFETY_DEFAULT_ON_PERCENT: 0.1,
|
|
CONF_WINDOW_SENSOR: "binary_sensor.window_sensor",
|
|
CONF_WINDOW_DELAY: 0, # To be not obliged to wait
|
|
CONF_MOTION_SENSOR: "input_boolean.motion_sensor",
|
|
CONF_MOTION_DELAY: 10,
|
|
CONF_MOTION_OFF_DELAY: 30,
|
|
CONF_MOTION_PRESET: PRESET_BOOST,
|
|
CONF_NO_MOTION_PRESET: PRESET_ECO,
|
|
},
|
|
)
|
|
|
|
tz = get_tz(hass) # pylint: disable=invalid-name
|
|
event_timestamp = datetime.now(tz)
|
|
|
|
# 1 initialize entity and find select entity
|
|
with patch("homeassistant.core.ServiceRegistry.async_call"):
|
|
entity: ThermostatOverSwitch = await create_thermostat(
|
|
hass, entry, "climate.theoverswitchmockname"
|
|
)
|
|
assert entity
|
|
assert entity.is_controlled_by_central_mode
|
|
assert entity.last_central_mode is None
|
|
|
|
# Find the select entity
|
|
select_entity = search_entity(hass, "select.central_mode", SELECT_DOMAIN)
|
|
|
|
assert select_entity
|
|
assert select_entity.current_option == CENTRAL_MODE_AUTO
|
|
assert select_entity.options == CENTRAL_MODES
|
|
|
|
# start entity
|
|
await entity.async_set_hvac_mode(HVACMode.HEAT)
|
|
await entity.async_set_preset_mode(PRESET_ACTIVITY)
|
|
|
|
assert entity.hvac_mode == HVACMode.HEAT
|
|
assert entity.preset_mode == PRESET_ACTIVITY
|
|
assert entity.window_state is STATE_UNKNOWN
|
|
|
|
# 2 Open the window
|
|
with patch(
|
|
"custom_components.versatile_thermostat.base_thermostat.BaseThermostat.send_event"
|
|
) as mock_send_event, patch(
|
|
"homeassistant.helpers.condition.state", return_value=True
|
|
):
|
|
event_timestamp = event_timestamp + timedelta(minutes=1)
|
|
try_function = await send_window_change_event(
|
|
entity, True, False, event_timestamp
|
|
)
|
|
|
|
await try_function(None)
|
|
|
|
assert mock_send_event.call_count == 1
|
|
mock_send_event.assert_has_calls(
|
|
[call.send_event(EventType.HVAC_MODE_EVENT, {"hvac_mode": HVACMode.OFF})]
|
|
)
|
|
|
|
assert entity.hvac_mode == HVACMode.OFF
|
|
assert entity.preset_mode == PRESET_ACTIVITY
|
|
assert entity._saved_hvac_mode == HVACMode.HEAT
|
|
assert entity._saved_preset_mode == PRESET_ACTIVITY
|
|
assert entity.window_state is STATE_ON
|
|
|
|
# 3 Change central_mode to STOPPED
|
|
with patch("homeassistant.core.ServiceRegistry.async_call"):
|
|
event_timestamp = event_timestamp + timedelta(minutes=1)
|
|
entity._set_now(event_timestamp)
|
|
|
|
await select_entity.async_select_option(CENTRAL_MODE_STOPPED)
|
|
|
|
assert entity.last_central_mode is CENTRAL_MODE_STOPPED
|
|
# No change
|
|
assert entity.hvac_mode == HVACMode.OFF
|
|
assert entity.preset_mode == PRESET_ACTIVITY
|
|
assert entity._saved_hvac_mode == HVACMode.HEAT
|
|
assert entity._saved_preset_mode == PRESET_ACTIVITY
|
|
|
|
# 4 Close the window
|
|
with patch(
|
|
"custom_components.versatile_thermostat.base_thermostat.BaseThermostat.send_event"
|
|
) as mock_send_event, patch(
|
|
"homeassistant.helpers.condition.state", return_value=True
|
|
):
|
|
event_timestamp = event_timestamp + timedelta(minutes=1)
|
|
try_function = await send_window_change_event(
|
|
entity, False, True, event_timestamp
|
|
)
|
|
|
|
await try_function(None)
|
|
|
|
# No hvac_mode change cause the central mode is STOPPED
|
|
assert mock_send_event.call_count == 0
|
|
|
|
# We should stay off because central is STOPPED
|
|
assert entity.hvac_mode == HVACMode.OFF
|
|
assert entity.preset_mode == PRESET_ACTIVITY
|
|
assert entity._saved_hvac_mode == HVACMode.HEAT
|
|
assert entity._saved_preset_mode == PRESET_ACTIVITY
|
|
assert entity.window_state is STATE_OFF
|
|
|
|
# 5 Back to Auto
|
|
with patch(
|
|
"custom_components.versatile_thermostat.base_thermostat.BaseThermostat.send_event"
|
|
) as mock_send_event:
|
|
event_timestamp = event_timestamp + timedelta(minutes=1)
|
|
|
|
await select_entity.async_select_option(CENTRAL_MODE_AUTO)
|
|
|
|
assert mock_send_event.call_count == 1
|
|
mock_send_event.assert_has_calls(
|
|
[call.send_event(EventType.HVAC_MODE_EVENT, {"hvac_mode": HVACMode.HEAT})]
|
|
)
|
|
|
|
# We should switch back to HEAT
|
|
assert entity.hvac_mode == HVACMode.HEAT
|
|
assert entity.preset_mode == PRESET_ACTIVITY
|
|
assert entity._saved_hvac_mode == HVACMode.HEAT
|
|
assert entity._saved_preset_mode == PRESET_ACTIVITY
|
|
assert entity.window_state is STATE_OFF
|
|
|
|
|
|
@pytest.mark.parametrize("expected_lingering_tasks", [True])
|
|
@pytest.mark.parametrize("expected_lingering_timers", [True])
|
|
async def test_switch_change_central_mode_true_with_cool_only_and_window(
|
|
hass: HomeAssistant, skip_hass_states_is_state, init_central_config
|
|
):
|
|
"""test that changes with over_switch config with central_mode True are
|
|
taken into account"""
|
|
|
|
# Add a Switch VTherm
|
|
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_USE_CENTRAL_MODE: True,
|
|
CONF_CYCLE_MIN: 5,
|
|
CONF_TEMP_MIN: 8,
|
|
CONF_TEMP_MAX: 18,
|
|
"frost_temp": 10,
|
|
"eco_temp": 17,
|
|
"comfort_temp": 18,
|
|
"boost_temp": 21,
|
|
CONF_USE_WINDOW_FEATURE: True,
|
|
CONF_USE_MOTION_FEATURE: True,
|
|
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: 0,
|
|
CONF_SAFETY_DELAY_MIN: 5,
|
|
CONF_SAFETY_MIN_ON_PERCENT: 0.3,
|
|
CONF_SAFETY_DEFAULT_ON_PERCENT: 0.1,
|
|
CONF_WINDOW_SENSOR: "binary_sensor.window_sensor",
|
|
CONF_WINDOW_DELAY: 0, # To be not obliged to wait
|
|
CONF_MOTION_SENSOR: "input_boolean.motion_sensor",
|
|
CONF_MOTION_DELAY: 10,
|
|
CONF_MOTION_OFF_DELAY: 30,
|
|
CONF_MOTION_PRESET: PRESET_BOOST,
|
|
CONF_NO_MOTION_PRESET: PRESET_ECO,
|
|
},
|
|
)
|
|
|
|
tz = get_tz(hass) # pylint: disable=invalid-name
|
|
event_timestamp = datetime.now(tz)
|
|
|
|
# 1 initialize entity and find select entity
|
|
with patch("homeassistant.core.ServiceRegistry.async_call"):
|
|
entity: ThermostatOverSwitch = await create_thermostat(
|
|
hass, entry, "climate.theoverswitchmockname"
|
|
)
|
|
assert entity
|
|
assert entity.is_controlled_by_central_mode
|
|
assert entity.last_central_mode is None
|
|
|
|
# Find the select entity
|
|
select_entity = search_entity(hass, "select.central_mode", SELECT_DOMAIN)
|
|
|
|
assert select_entity
|
|
assert select_entity.current_option == CENTRAL_MODE_AUTO
|
|
assert select_entity.options == CENTRAL_MODES
|
|
|
|
# start entity
|
|
await entity.async_set_hvac_mode(HVACMode.HEAT)
|
|
await entity.async_set_preset_mode(PRESET_ACTIVITY)
|
|
|
|
assert entity.hvac_mode == HVACMode.HEAT
|
|
assert entity.preset_mode == PRESET_ACTIVITY
|
|
assert entity.window_state is STATE_UNKNOWN
|
|
|
|
# 2 Change central_mode to COOL_ONLY
|
|
with patch("homeassistant.core.ServiceRegistry.async_call"):
|
|
event_timestamp = event_timestamp + timedelta(minutes=1)
|
|
entity._set_now(event_timestamp)
|
|
|
|
await select_entity.async_select_option(CENTRAL_MODE_COOL_ONLY)
|
|
|
|
assert entity.last_central_mode is CENTRAL_MODE_COOL_ONLY
|
|
assert entity.hvac_mode is HVACMode.OFF
|
|
assert entity.hvac_off_reason == HVAC_OFF_REASON_MANUAL
|
|
await entity.async_set_preset_mode(PRESET_ACTIVITY)
|
|
assert entity._saved_hvac_mode == HVACMode.HEAT
|
|
assert entity._saved_preset_mode == PRESET_ACTIVITY
|
|
|
|
# 3 Open the window
|
|
with patch(
|
|
"custom_components.versatile_thermostat.base_thermostat.BaseThermostat.send_event"
|
|
) as mock_send_event, patch(
|
|
"homeassistant.helpers.condition.state", return_value=True
|
|
):
|
|
event_timestamp = event_timestamp + timedelta(minutes=1)
|
|
try_function = await send_window_change_event(
|
|
entity, True, False, event_timestamp
|
|
)
|
|
|
|
await try_function(None)
|
|
|
|
# The VTherm is already off -> window detection is ignored
|
|
assert mock_send_event.call_count == 0
|
|
# mock_send_event.assert_has_calls(
|
|
# [call.send_event(EventType.HVAC_MODE_EVENT, {"hvac_mode": HVACMode.OFF})]
|
|
# )
|
|
|
|
assert entity.hvac_mode == HVACMode.OFF
|
|
assert entity.hvac_off_reason == HVAC_OFF_REASON_MANUAL
|
|
assert entity.preset_mode == PRESET_ACTIVITY
|
|
assert entity._saved_hvac_mode == HVACMode.HEAT
|
|
assert entity._saved_preset_mode == PRESET_ACTIVITY
|
|
assert entity.window_state is STATE_ON
|
|
|
|
# 4 Change central_mode to AUTO
|
|
with patch("homeassistant.core.ServiceRegistry.async_call"):
|
|
event_timestamp = event_timestamp + timedelta(minutes=1)
|
|
entity._set_now(event_timestamp)
|
|
|
|
await select_entity.async_select_option(CENTRAL_MODE_AUTO)
|
|
|
|
assert entity.last_central_mode is CENTRAL_MODE_AUTO
|
|
# No change
|
|
assert entity.hvac_mode == HVACMode.OFF
|
|
# We have to a reason of WINDOW_DETECTION
|
|
assert entity.hvac_off_reason == HVAC_OFF_REASON_WINDOW_DETECTION
|
|
assert entity.preset_mode == PRESET_ACTIVITY
|
|
assert entity._saved_hvac_mode == HVACMode.HEAT
|
|
assert entity._saved_preset_mode == PRESET_ACTIVITY
|
|
|
|
# 5 Close the window
|
|
with patch(
|
|
"custom_components.versatile_thermostat.base_thermostat.BaseThermostat.send_event"
|
|
) as mock_send_event, patch(
|
|
"homeassistant.helpers.condition.state", return_value=True
|
|
):
|
|
event_timestamp = event_timestamp + timedelta(minutes=1)
|
|
try_function = await send_window_change_event(
|
|
entity, False, True, event_timestamp
|
|
)
|
|
|
|
await try_function(None)
|
|
|
|
# hvac_mode change to HEAT
|
|
assert mock_send_event.call_count == 1
|
|
mock_send_event.assert_has_calls(
|
|
[call.send_event(EventType.HVAC_MODE_EVENT, {"hvac_mode": HVACMode.HEAT})]
|
|
)
|
|
|
|
# We should stay off because central is STOPPED
|
|
assert entity.hvac_mode == HVACMode.HEAT
|
|
assert entity.hvac_off_reason is None
|
|
assert entity.preset_mode == PRESET_ACTIVITY
|
|
assert entity._saved_hvac_mode == HVACMode.HEAT
|
|
assert entity._saved_preset_mode == PRESET_ACTIVITY
|
|
assert entity.window_state is STATE_OFF
|