* Refactor Presence Feature * Add PresenceFeatureManager ok * Python 3.13 * Fix presence test * Refactor power feature * Add Motion manager. All tests ok * Tests ok. But tests are not complete * All tests Window Feature Manager ok. * All windows tests ok * Fix all testus with feature_window_manager ok * Add test_auto_start_stop feature manager. All tests ok * Add safety feature_safety_manager Rename config attribute from security_ to safety_ * Documentation and release * Add safety manager direct tests * Typo --------- Co-authored-by: Jean-Marc Collin <jean-marc.collin-extern@renault.com>
1155 lines
42 KiB
Python
1155 lines
42 KiB
Python
""" Test the NumberEntity taht holds the temperature of a VTherm or of a Central configuration """
|
|
|
|
# pylint: disable=wildcard-import, unused-wildcard-import, protected-access, unused-argument, line-too-long, too-many-lines
|
|
|
|
# from unittest.mock import patch, call
|
|
# from datetime import datetime, timedelta
|
|
import asyncio
|
|
from homeassistant.core import HomeAssistant
|
|
from homeassistant.config_entries import ConfigEntryState
|
|
|
|
# from homeassistant.helpers.entity_component import EntityComponent
|
|
from homeassistant.components.number import DOMAIN as NUMBER_DOMAIN
|
|
|
|
from pytest_homeassistant_custom_component.common import MockConfigEntry
|
|
|
|
from custom_components.versatile_thermostat.base_thermostat import BaseThermostat
|
|
from custom_components.versatile_thermostat.thermostat_switch import (
|
|
ThermostatOverSwitch,
|
|
)
|
|
from custom_components.versatile_thermostat.const import NowClass
|
|
from custom_components.versatile_thermostat.vtherm_api import VersatileThermostatAPI
|
|
|
|
from .commons import *
|
|
|
|
|
|
@pytest.mark.parametrize("expected_lingering_tasks", [True])
|
|
@pytest.mark.parametrize("expected_lingering_timers", [True])
|
|
async def test_add_number_for_central_config(
|
|
hass: HomeAssistant, skip_hass_states_is_state
|
|
):
|
|
"""Test the construction of a central configuration and the
|
|
creation and registration of the NumberEntity which holds
|
|
the temperature initialized from config_entry"""
|
|
|
|
vtherm_api: VersatileThermostatAPI = VersatileThermostatAPI.get_vtherm_api(hass)
|
|
|
|
temps = {
|
|
"frost_temp": 10,
|
|
"eco_temp": 17.1,
|
|
"comfort_temp": 18.1,
|
|
"boost_temp": 19.1,
|
|
"eco_ac_temp": 25.1,
|
|
"comfort_ac_temp": 23.1,
|
|
"boost_ac_temp": 21.1,
|
|
"frost_away_temp": 15.1,
|
|
"eco_away_temp": 15.2,
|
|
"comfort_away_temp": 15.3,
|
|
"boost_away_temp": 15.4,
|
|
"eco_ac_away_temp": 30.5,
|
|
"comfort_ac_away_temp": 30.6,
|
|
"boost_ac_away_temp": 30.7,
|
|
}
|
|
|
|
central_config_entry = MockConfigEntry(
|
|
domain=DOMAIN,
|
|
title="TheCentralConfigMockName",
|
|
unique_id="centralConfigUniqueId",
|
|
data={
|
|
CONF_NAME: CENTRAL_CONFIG_NAME,
|
|
CONF_THERMOSTAT_TYPE: CONF_THERMOSTAT_CENTRAL_CONFIG,
|
|
CONF_EXTERNAL_TEMP_SENSOR: "sensor.mock_central_ext_temp_sensor",
|
|
CONF_TEMP_MIN: 15,
|
|
CONF_TEMP_MAX: 30,
|
|
CONF_TPI_COEF_INT: 0.5,
|
|
CONF_TPI_COEF_EXT: 0.02,
|
|
CONF_WINDOW_DELAY: 15,
|
|
CONF_WINDOW_AUTO_OPEN_THRESHOLD: 4,
|
|
CONF_WINDOW_AUTO_CLOSE_THRESHOLD: 1,
|
|
CONF_WINDOW_AUTO_MAX_DURATION: 31,
|
|
CONF_MOTION_DELAY: 31,
|
|
CONF_MOTION_OFF_DELAY: 301,
|
|
CONF_MOTION_PRESET: "boost",
|
|
CONF_NO_MOTION_PRESET: "frost",
|
|
CONF_POWER_SENSOR: "sensor.mock_central_power_sensor",
|
|
CONF_MAX_POWER_SENSOR: "sensor.mock_central_max_power_sensor",
|
|
CONF_PRESET_POWER: 14,
|
|
CONF_MINIMAL_ACTIVATION_DELAY: 11,
|
|
CONF_SAFETY_DELAY_MIN: 61,
|
|
CONF_SAFETY_MIN_ON_PERCENT: 0.5,
|
|
CONF_SAFETY_DEFAULT_ON_PERCENT: 0.2,
|
|
CONF_USE_CENTRAL_BOILER_FEATURE: False,
|
|
CONF_PROP_FUNCTION: PROPORTIONAL_FUNCTION_TPI,
|
|
}
|
|
| temps,
|
|
)
|
|
|
|
central_config_entry.add_to_hass(hass)
|
|
await hass.config_entries.async_setup(central_config_entry.entry_id)
|
|
assert central_config_entry.state is ConfigEntryState.LOADED
|
|
|
|
# We search for NumberEntities
|
|
for preset_name, value in temps.items():
|
|
temp_entity = search_entity(
|
|
hass,
|
|
"number.central_configuration_preset_" + preset_name,
|
|
NUMBER_DOMAIN,
|
|
)
|
|
assert temp_entity
|
|
assert temp_entity.state == value
|
|
|
|
# This test is dependent to translation en.json. If translations change
|
|
# this may fails
|
|
assert (
|
|
temp_entity.name.lower()
|
|
== preset_name.replace(PRESET_TEMP_SUFFIX, "")
|
|
.replace(PRESET_AC_SUFFIX, " ac")
|
|
.replace(PRESET_AWAY_SUFFIX, " away")
|
|
.lower()
|
|
)
|
|
|
|
# Find temp Number into vtherm_api
|
|
val = vtherm_api.get_temperature_number_value(
|
|
config_id=central_config_entry.entry_id, preset_name=preset_name
|
|
)
|
|
assert val == value
|
|
|
|
|
|
@pytest.mark.parametrize("expected_lingering_tasks", [True])
|
|
@pytest.mark.parametrize("expected_lingering_timers", [True])
|
|
async def test_add_number_for_central_config_without_temp(
|
|
hass: HomeAssistant, skip_hass_states_is_state
|
|
):
|
|
"""Test the construction of a central configuration and the
|
|
creation and registration of the NumberEntity which holds
|
|
the temperature not intialized from confif_entry.
|
|
In non AC_MODE the value should be initialized to the MIN"""
|
|
|
|
vtherm_api: VersatileThermostatAPI = VersatileThermostatAPI.get_vtherm_api(hass)
|
|
|
|
# Default is min Value in non AC_MODE
|
|
temps = {
|
|
"frost_temp": 15.0,
|
|
"eco_temp": 15.0,
|
|
"comfort_temp": 15.0,
|
|
"boost_temp": 15.0,
|
|
"eco_ac_temp": 15.0,
|
|
"comfort_ac_temp": 15.0,
|
|
"boost_ac_temp": 15.0,
|
|
"frost_away_temp": 15.0,
|
|
"eco_away_temp": 15.0,
|
|
"comfort_away_temp": 15.0,
|
|
"boost_away_temp": 15.0,
|
|
"eco_ac_away_temp": 15.0,
|
|
"comfort_ac_away_temp": 15.0,
|
|
"boost_ac_away_temp": 15.0,
|
|
}
|
|
|
|
central_config_entry = MockConfigEntry(
|
|
domain=DOMAIN,
|
|
title="TheCentralConfigMockName",
|
|
unique_id="centralConfigUniqueId",
|
|
data={
|
|
CONF_NAME: CENTRAL_CONFIG_NAME,
|
|
CONF_THERMOSTAT_TYPE: CONF_THERMOSTAT_CENTRAL_CONFIG,
|
|
CONF_EXTERNAL_TEMP_SENSOR: "sensor.mock_central_ext_temp_sensor",
|
|
CONF_TEMP_MIN: 15,
|
|
CONF_TEMP_MAX: 30,
|
|
CONF_TPI_COEF_INT: 0.5,
|
|
CONF_TPI_COEF_EXT: 0.02,
|
|
CONF_PROP_FUNCTION: PROPORTIONAL_FUNCTION_TPI,
|
|
CONF_WINDOW_DELAY: 15,
|
|
CONF_WINDOW_AUTO_OPEN_THRESHOLD: 4,
|
|
CONF_WINDOW_AUTO_CLOSE_THRESHOLD: 1,
|
|
CONF_WINDOW_AUTO_MAX_DURATION: 31,
|
|
CONF_MOTION_DELAY: 31,
|
|
CONF_MOTION_OFF_DELAY: 301,
|
|
CONF_MOTION_PRESET: "boost",
|
|
CONF_NO_MOTION_PRESET: "frost",
|
|
CONF_POWER_SENSOR: "sensor.mock_central_power_sensor",
|
|
CONF_MAX_POWER_SENSOR: "sensor.mock_central_max_power_sensor",
|
|
CONF_PRESET_POWER: 14,
|
|
CONF_MINIMAL_ACTIVATION_DELAY: 11,
|
|
CONF_SAFETY_DELAY_MIN: 61,
|
|
CONF_SAFETY_MIN_ON_PERCENT: 0.5,
|
|
CONF_SAFETY_DEFAULT_ON_PERCENT: 0.2,
|
|
CONF_USE_CENTRAL_BOILER_FEATURE: False,
|
|
},
|
|
# | temps,
|
|
)
|
|
|
|
central_config_entry.add_to_hass(hass)
|
|
await hass.config_entries.async_setup(central_config_entry.entry_id)
|
|
assert central_config_entry.state is ConfigEntryState.LOADED
|
|
|
|
# We search for NumberEntities
|
|
for preset_name, value in temps.items():
|
|
temp_entity = search_entity(
|
|
hass,
|
|
"number.central_configuration_preset_" + preset_name,
|
|
NUMBER_DOMAIN,
|
|
)
|
|
assert temp_entity
|
|
assert temp_entity.state == value
|
|
|
|
# This test is dependent to translation en.json. If translations change
|
|
# this may fails
|
|
assert (
|
|
temp_entity.name.lower()
|
|
== preset_name.replace(PRESET_TEMP_SUFFIX, "")
|
|
.replace(PRESET_AC_SUFFIX, " ac")
|
|
.replace(PRESET_AWAY_SUFFIX, " away")
|
|
.lower()
|
|
)
|
|
|
|
# Find temp Number into vtherm_api
|
|
val = vtherm_api.get_temperature_number_value(
|
|
config_id=central_config_entry.entry_id, preset_name=preset_name
|
|
)
|
|
assert val == value
|
|
|
|
|
|
@pytest.mark.parametrize("expected_lingering_tasks", [True])
|
|
@pytest.mark.parametrize("expected_lingering_timers", [True])
|
|
async def test_add_number_for_central_config_without_temp_ac_mode(
|
|
hass: HomeAssistant, skip_hass_states_is_state
|
|
):
|
|
"""Test the construction of a central configuration and the
|
|
creation and registration of the NumberEntity which holds
|
|
the temperature not intialized from confif_entry.
|
|
In AC_MODE the defaul value should the MAX"""
|
|
|
|
vtherm_api: VersatileThermostatAPI = VersatileThermostatAPI.get_vtherm_api(hass)
|
|
|
|
# Default is min Value in non AC_MODE
|
|
temps = {
|
|
"frost_temp": 30.0,
|
|
"eco_temp": 30.0,
|
|
"comfort_temp": 30.0,
|
|
"boost_temp": 30.0,
|
|
"eco_ac_temp": 30.0,
|
|
"comfort_ac_temp": 30.0,
|
|
"boost_ac_temp": 30.0,
|
|
"frost_away_temp": 30.0,
|
|
"eco_away_temp": 30.0,
|
|
"comfort_away_temp": 30.0,
|
|
"boost_away_temp": 30.0,
|
|
"eco_ac_away_temp": 30.0,
|
|
"comfort_ac_away_temp": 30.0,
|
|
"boost_ac_away_temp": 30.0,
|
|
}
|
|
|
|
central_config_entry = MockConfigEntry(
|
|
domain=DOMAIN,
|
|
title="TheCentralConfigMockName",
|
|
unique_id="centralConfigUniqueId",
|
|
data={
|
|
CONF_NAME: CENTRAL_CONFIG_NAME,
|
|
CONF_THERMOSTAT_TYPE: CONF_THERMOSTAT_CENTRAL_CONFIG,
|
|
CONF_EXTERNAL_TEMP_SENSOR: "sensor.mock_central_ext_temp_sensor",
|
|
CONF_TEMP_MIN: 15,
|
|
CONF_TEMP_MAX: 30,
|
|
CONF_AC_MODE: True,
|
|
CONF_TPI_COEF_INT: 0.5,
|
|
CONF_TPI_COEF_EXT: 0.02,
|
|
CONF_PROP_FUNCTION: PROPORTIONAL_FUNCTION_TPI,
|
|
CONF_WINDOW_DELAY: 15,
|
|
CONF_WINDOW_AUTO_OPEN_THRESHOLD: 4,
|
|
CONF_WINDOW_AUTO_CLOSE_THRESHOLD: 1,
|
|
CONF_WINDOW_AUTO_MAX_DURATION: 31,
|
|
CONF_MOTION_DELAY: 31,
|
|
CONF_MOTION_OFF_DELAY: 301,
|
|
CONF_MOTION_PRESET: "boost",
|
|
CONF_NO_MOTION_PRESET: "frost",
|
|
CONF_POWER_SENSOR: "sensor.mock_central_power_sensor",
|
|
CONF_MAX_POWER_SENSOR: "sensor.mock_central_max_power_sensor",
|
|
CONF_PRESET_POWER: 14,
|
|
CONF_MINIMAL_ACTIVATION_DELAY: 11,
|
|
CONF_SAFETY_DELAY_MIN: 61,
|
|
CONF_SAFETY_MIN_ON_PERCENT: 0.5,
|
|
CONF_SAFETY_DEFAULT_ON_PERCENT: 0.2,
|
|
CONF_USE_CENTRAL_BOILER_FEATURE: False,
|
|
},
|
|
# | temps,
|
|
)
|
|
|
|
central_config_entry.add_to_hass(hass)
|
|
await hass.config_entries.async_setup(central_config_entry.entry_id)
|
|
assert central_config_entry.state is ConfigEntryState.LOADED
|
|
|
|
# We search for NumberEntities
|
|
for preset_name, value in temps.items():
|
|
temp_entity = search_entity(
|
|
hass,
|
|
"number.central_configuration_preset_" + preset_name,
|
|
NUMBER_DOMAIN,
|
|
)
|
|
assert temp_entity
|
|
assert temp_entity.state == value
|
|
|
|
# This test is dependent to translation en.json. If translations change
|
|
# this may fails
|
|
assert (
|
|
temp_entity.name.lower()
|
|
== preset_name.replace(PRESET_TEMP_SUFFIX, "")
|
|
.replace(PRESET_AC_SUFFIX, " ac")
|
|
.replace(PRESET_AWAY_SUFFIX, " away")
|
|
.lower()
|
|
)
|
|
|
|
# Find temp Number into vtherm_api
|
|
val = vtherm_api.get_temperature_number_value(
|
|
config_id=central_config_entry.entry_id, preset_name=preset_name
|
|
)
|
|
assert val == value
|
|
|
|
|
|
@pytest.mark.parametrize("expected_lingering_tasks", [True])
|
|
@pytest.mark.parametrize("expected_lingering_timers", [True])
|
|
async def test_add_number_for_central_config_without_temp_restore(
|
|
hass: HomeAssistant, skip_hass_states_is_state
|
|
):
|
|
"""Test the construction of a central configuration and the
|
|
creation and registration of the NumberEntity which holds
|
|
the temperature not intialized from confif_entry"""
|
|
|
|
vtherm_api: VersatileThermostatAPI = VersatileThermostatAPI.get_vtherm_api(hass)
|
|
|
|
# Default is min Value in non AC_MODE
|
|
temps = {
|
|
"frost_temp": 23.0,
|
|
"eco_temp": 23.0,
|
|
"comfort_temp": 23.0,
|
|
"boost_temp": 23.0,
|
|
"eco_ac_temp": 23.0,
|
|
"comfort_ac_temp": 23.0,
|
|
"boost_ac_temp": 23.0,
|
|
"frost_away_temp": 23.0,
|
|
"eco_away_temp": 23.0,
|
|
"comfort_away_temp": 23.0,
|
|
"boost_away_temp": 23.0,
|
|
"eco_ac_away_temp": 23.0,
|
|
"comfort_ac_away_temp": 23.0,
|
|
"boost_ac_away_temp": 23.0,
|
|
}
|
|
|
|
central_config_entry = MockConfigEntry(
|
|
domain=DOMAIN,
|
|
title="TheCentralConfigMockName",
|
|
unique_id="centralConfigUniqueId",
|
|
data={
|
|
CONF_NAME: CENTRAL_CONFIG_NAME,
|
|
CONF_THERMOSTAT_TYPE: CONF_THERMOSTAT_CENTRAL_CONFIG,
|
|
CONF_EXTERNAL_TEMP_SENSOR: "sensor.mock_central_ext_temp_sensor",
|
|
CONF_TEMP_MIN: 15,
|
|
CONF_TEMP_MAX: 30,
|
|
CONF_AC_MODE: False,
|
|
CONF_TPI_COEF_INT: 0.5,
|
|
CONF_TPI_COEF_EXT: 0.02,
|
|
CONF_PROP_FUNCTION: PROPORTIONAL_FUNCTION_TPI,
|
|
CONF_WINDOW_DELAY: 15,
|
|
CONF_WINDOW_AUTO_OPEN_THRESHOLD: 4,
|
|
CONF_WINDOW_AUTO_CLOSE_THRESHOLD: 1,
|
|
CONF_WINDOW_AUTO_MAX_DURATION: 31,
|
|
CONF_MOTION_DELAY: 31,
|
|
CONF_MOTION_OFF_DELAY: 301,
|
|
CONF_MOTION_PRESET: "boost",
|
|
CONF_NO_MOTION_PRESET: "frost",
|
|
CONF_POWER_SENSOR: "sensor.mock_central_power_sensor",
|
|
CONF_MAX_POWER_SENSOR: "sensor.mock_central_max_power_sensor",
|
|
CONF_PRESET_POWER: 14,
|
|
CONF_MINIMAL_ACTIVATION_DELAY: 11,
|
|
CONF_SAFETY_DELAY_MIN: 61,
|
|
CONF_SAFETY_MIN_ON_PERCENT: 0.5,
|
|
CONF_SAFETY_DEFAULT_ON_PERCENT: 0.2,
|
|
CONF_USE_CENTRAL_BOILER_FEATURE: False,
|
|
},
|
|
# | temps,
|
|
)
|
|
|
|
with patch(
|
|
"homeassistant.helpers.restore_state.RestoreEntity.async_get_last_state",
|
|
return_value=State(entity_id="number.mock_valve", state="23"),
|
|
):
|
|
central_config_entry.add_to_hass(hass)
|
|
await hass.config_entries.async_setup(central_config_entry.entry_id)
|
|
|
|
assert central_config_entry.state is ConfigEntryState.LOADED
|
|
|
|
# We search for NumberEntities
|
|
for preset_name, value in temps.items():
|
|
temp_entity = search_entity(
|
|
hass,
|
|
"number.central_configuration_preset_" + preset_name,
|
|
NUMBER_DOMAIN,
|
|
)
|
|
assert temp_entity
|
|
assert temp_entity.state == value
|
|
|
|
# This test is dependent to translation en.json. If translations change
|
|
# this may fails
|
|
assert (
|
|
temp_entity.name.lower()
|
|
== preset_name.replace(PRESET_TEMP_SUFFIX, "")
|
|
.replace(PRESET_AC_SUFFIX, " ac")
|
|
.replace(PRESET_AWAY_SUFFIX, " away")
|
|
.lower()
|
|
)
|
|
|
|
# Find temp Number into vtherm_api
|
|
val = vtherm_api.get_temperature_number_value(
|
|
config_id=central_config_entry.entry_id, preset_name=preset_name
|
|
)
|
|
assert val == value
|
|
|
|
|
|
@pytest.mark.parametrize("expected_lingering_tasks", [True])
|
|
@pytest.mark.parametrize("expected_lingering_timers", [True])
|
|
async def test_add_number_for_over_switch_use_central(
|
|
hass: HomeAssistant, skip_hass_states_is_state
|
|
):
|
|
"""Test the construction of a over switch vtherm with
|
|
use central config for PRESET and PRESENCE.
|
|
It also have old temp config value which should be not used.
|
|
So it should have no Temp NumberEntity"""
|
|
|
|
vtherm_api: VersatileThermostatAPI = VersatileThermostatAPI.get_vtherm_api(hass)
|
|
|
|
temps = {
|
|
"frost_temp": 10,
|
|
"eco_temp": 17.1,
|
|
"comfort_temp": 18.1,
|
|
"boost_temp": 19.1,
|
|
"eco_ac_temp": 25.1,
|
|
"comfort_ac_temp": 23.1,
|
|
"boost_ac_temp": 21.1,
|
|
"frost_away_temp": 15.1,
|
|
"eco_away_temp": 15.2,
|
|
"comfort_away_temp": 15.3,
|
|
"boost_away_temp": 15.4,
|
|
"eco_ac_away_temp": 30.5,
|
|
"comfort_ac_away_temp": 30.6,
|
|
"boost_ac_away_temp": 30.7,
|
|
}
|
|
|
|
vtherm_entry = MockConfigEntry(
|
|
domain=DOMAIN,
|
|
title="TheCentralConfigMockName",
|
|
unique_id="centralConfigUniqueId",
|
|
data={
|
|
CONF_NAME: "TheOverSwitchVTherm",
|
|
CONF_THERMOSTAT_TYPE: CONF_THERMOSTAT_SWITCH,
|
|
CONF_EXTERNAL_TEMP_SENSOR: "sensor.mock_central_ext_temp_sensor",
|
|
CONF_TEMP_MIN: 15,
|
|
CONF_TEMP_MAX: 30,
|
|
CONF_AC_MODE: False,
|
|
CONF_TPI_COEF_INT: 0.5,
|
|
CONF_TPI_COEF_EXT: 0.02,
|
|
CONF_PROP_FUNCTION: PROPORTIONAL_FUNCTION_TPI,
|
|
CONF_USE_PRESENCE_CENTRAL_CONFIG: True,
|
|
CONF_USE_ADVANCED_CENTRAL_CONFIG: True,
|
|
CONF_USE_MAIN_CENTRAL_CONFIG: True,
|
|
CONF_USE_PRESETS_CENTRAL_CONFIG: True,
|
|
CONF_USE_WINDOW_CENTRAL_CONFIG: True,
|
|
CONF_USE_POWER_CENTRAL_CONFIG: True,
|
|
CONF_USE_MOTION_CENTRAL_CONFIG: True,
|
|
}
|
|
| temps,
|
|
)
|
|
|
|
# The restore should not be used
|
|
with patch(
|
|
"homeassistant.helpers.restore_state.RestoreEntity.async_get_last_state",
|
|
return_value=State(entity_id="number.mock_valve", state="23"),
|
|
) as mock_restore_state:
|
|
vtherm_entry.add_to_hass(hass)
|
|
await hass.config_entries.async_setup(vtherm_entry.entry_id)
|
|
|
|
assert mock_restore_state.call_count == 0
|
|
|
|
assert vtherm_entry.state is ConfigEntryState.LOADED
|
|
|
|
# We search for NumberEntities
|
|
for preset_name, _ in temps.items():
|
|
temp_entity = search_entity(
|
|
hass,
|
|
"number.central_configuration_preset_" + preset_name,
|
|
NUMBER_DOMAIN,
|
|
)
|
|
assert temp_entity is None
|
|
|
|
# Find temp Number into vtherm_api
|
|
val = vtherm_api.get_temperature_number_value(
|
|
config_id=vtherm_entry.entry_id, preset_name=preset_name
|
|
)
|
|
assert val is None
|
|
|
|
|
|
@pytest.mark.parametrize("expected_lingering_timers", [True])
|
|
async def test_add_number_for_over_switch_use_central_presence(
|
|
hass: HomeAssistant, skip_hass_states_is_state, init_central_config
|
|
):
|
|
"""Test the construction of a over switch vtherm with
|
|
use central config for PRESET and PRESENCE.
|
|
It also have old temp config value which should be not used.
|
|
So it should have no Temp NumberEntity"""
|
|
|
|
vtherm_api: VersatileThermostatAPI = VersatileThermostatAPI.get_vtherm_api(hass)
|
|
|
|
temps = {
|
|
"frost_temp": 10,
|
|
"eco_temp": 17.1,
|
|
"comfort_temp": 18.1,
|
|
"boost_temp": 19.1,
|
|
"eco_ac_temp": 25.1,
|
|
"comfort_ac_temp": 23.1,
|
|
"boost_ac_temp": 21.1,
|
|
}
|
|
temps_missing = {
|
|
"frost_away_temp": 15.1,
|
|
"eco_away_temp": 15.2,
|
|
"comfort_away_temp": 15.3,
|
|
"boost_away_temp": 15.4,
|
|
"eco_ac_away_temp": 30.5,
|
|
"comfort_ac_away_temp": 30.6,
|
|
"boost_ac_away_temp": 30.7,
|
|
}
|
|
|
|
vtherm_entry = MockConfigEntry(
|
|
domain=DOMAIN,
|
|
title="TheCentralConfigMockName",
|
|
unique_id="centralConfigUniqueId",
|
|
data={
|
|
CONF_NAME: "TheOverSwitchVTherm",
|
|
CONF_THERMOSTAT_TYPE: CONF_THERMOSTAT_SWITCH,
|
|
CONF_PROP_FUNCTION: PROPORTIONAL_FUNCTION_TPI,
|
|
CONF_TEMP_SENSOR: "sensor.mock_temp_sensor",
|
|
CONF_EXTERNAL_TEMP_SENSOR: "sensor.mock_central_ext_temp_sensor",
|
|
CONF_TEMP_MIN: 15,
|
|
CONF_TEMP_MAX: 30,
|
|
CONF_AC_MODE: True,
|
|
CONF_TPI_COEF_INT: 0.5,
|
|
CONF_TPI_COEF_EXT: 0.02,
|
|
CONF_CYCLE_MIN: 5,
|
|
CONF_HEATER: "switch.mock_switch1",
|
|
CONF_USE_PRESENCE_FEATURE: True,
|
|
CONF_USE_PRESENCE_CENTRAL_CONFIG: True,
|
|
CONF_USE_ADVANCED_CENTRAL_CONFIG: True,
|
|
CONF_USE_MAIN_CENTRAL_CONFIG: True,
|
|
CONF_USE_PRESETS_CENTRAL_CONFIG: False,
|
|
CONF_USE_WINDOW_CENTRAL_CONFIG: True,
|
|
CONF_USE_POWER_CENTRAL_CONFIG: True,
|
|
CONF_USE_MOTION_CENTRAL_CONFIG: True,
|
|
}
|
|
| temps
|
|
| temps_missing,
|
|
)
|
|
|
|
vtherm: BaseThermostat = await create_thermostat(
|
|
hass, vtherm_entry, "climate.theoverswitchvtherm"
|
|
)
|
|
|
|
assert vtherm.use_central_config_temperature is True
|
|
|
|
# 1. We search for NumberEntities
|
|
for preset_name, value in temps.items():
|
|
temp_entity = search_entity(
|
|
hass,
|
|
"number.theoverswitchvtherm_preset_" + preset_name,
|
|
NUMBER_DOMAIN,
|
|
)
|
|
assert temp_entity
|
|
assert temp_entity.state == value
|
|
|
|
# This test is dependent to translation en.json. If translations change
|
|
# this may fails
|
|
assert (
|
|
temp_entity.name.lower()
|
|
== preset_name.replace(PRESET_TEMP_SUFFIX, "")
|
|
.replace(PRESET_AC_SUFFIX, " ac")
|
|
.replace(PRESET_AWAY_SUFFIX, " away")
|
|
.lower()
|
|
)
|
|
|
|
# Find temp Number into vtherm_api
|
|
val = vtherm_api.get_temperature_number_value(
|
|
config_id=vtherm_entry.entry_id, preset_name=preset_name
|
|
)
|
|
assert val == value
|
|
|
|
# 2. We search for NumberEntities to be missing
|
|
for preset_name, value in temps_missing.items():
|
|
temp_entity = search_entity(
|
|
hass,
|
|
"number.theoverswitchvtherm_" + preset_name,
|
|
NUMBER_DOMAIN,
|
|
)
|
|
assert temp_entity is None
|
|
|
|
# Find temp Number into vtherm_api
|
|
val = vtherm_api.get_temperature_number_value(
|
|
config_id=vtherm_entry.entry_id, preset_name=preset_name
|
|
)
|
|
assert val is None
|
|
|
|
# 3. The VTherm should be initialized with all presets and correct temperature
|
|
assert vtherm
|
|
assert isinstance(vtherm, ThermostatOverSwitch)
|
|
assert vtherm.preset_modes == [
|
|
PRESET_NONE,
|
|
PRESET_FROST_PROTECTION,
|
|
PRESET_ECO,
|
|
PRESET_COMFORT,
|
|
PRESET_BOOST,
|
|
]
|
|
|
|
assert vtherm._presets == {
|
|
PRESET_FROST_PROTECTION: temps["frost_temp"],
|
|
PRESET_ECO: temps["eco_temp"],
|
|
PRESET_COMFORT: temps["comfort_temp"],
|
|
PRESET_BOOST: temps["boost_temp"],
|
|
PRESET_ECO_AC: temps["eco_ac_temp"],
|
|
PRESET_COMFORT_AC: temps["comfort_ac_temp"],
|
|
PRESET_BOOST_AC: temps["boost_ac_temp"],
|
|
}
|
|
|
|
# Preset away should be initialized with the central config
|
|
assert vtherm._presets_away == {
|
|
PRESET_FROST_PROTECTION
|
|
+ PRESET_AWAY_SUFFIX: FULL_CENTRAL_CONFIG["frost_away_temp"],
|
|
PRESET_ECO + PRESET_AWAY_SUFFIX: FULL_CENTRAL_CONFIG["eco_away_temp"],
|
|
PRESET_COMFORT + PRESET_AWAY_SUFFIX: FULL_CENTRAL_CONFIG["comfort_away_temp"],
|
|
PRESET_BOOST + PRESET_AWAY_SUFFIX: FULL_CENTRAL_CONFIG["boost_away_temp"],
|
|
PRESET_ECO_AC + PRESET_AWAY_SUFFIX: FULL_CENTRAL_CONFIG["eco_ac_away_temp"],
|
|
PRESET_COMFORT_AC
|
|
+ PRESET_AWAY_SUFFIX: FULL_CENTRAL_CONFIG["comfort_ac_away_temp"],
|
|
PRESET_BOOST_AC + PRESET_AWAY_SUFFIX: FULL_CENTRAL_CONFIG["boost_ac_away_temp"],
|
|
}
|
|
|
|
|
|
@pytest.mark.parametrize("expected_lingering_timers", [True])
|
|
async def test_add_number_for_over_switch_use_central_presets_and_restore(
|
|
hass: HomeAssistant, skip_hass_states_is_state, init_central_config
|
|
):
|
|
"""Test the construction of a over switch vtherm with
|
|
use central config for PRESET and PRESENCE.
|
|
It also have old temp config value which should be not used.
|
|
So it should have no Temp NumberEntity."""
|
|
|
|
vtherm_api: VersatileThermostatAPI = VersatileThermostatAPI.get_vtherm_api(hass)
|
|
|
|
temps = {
|
|
"frost_away_temp": 23,
|
|
"eco_away_temp": 23,
|
|
"comfort_away_temp": 23, # To test absence of preset
|
|
"boost_away_temp": 23,
|
|
}
|
|
temps_missing = {
|
|
"frost_temp": 10,
|
|
"eco_temp": 17.1,
|
|
"comfort_temp": 18.1,
|
|
"boost_temp": 19.1,
|
|
"eco_ac_temp": 25.1,
|
|
"comfort_ac_temp": 23.1,
|
|
"boost_ac_temp": 21.1,
|
|
"eco_ac_away_temp": 30.5,
|
|
"comfort_ac_away_temp": 30.6,
|
|
"boost_ac_away_temp": 30.7,
|
|
}
|
|
|
|
vtherm_entry = MockConfigEntry(
|
|
domain=DOMAIN,
|
|
title="TheCentralConfigMockName",
|
|
unique_id="centralConfigUniqueId",
|
|
data={
|
|
CONF_NAME: "TheOverSwitchVTherm",
|
|
CONF_THERMOSTAT_TYPE: CONF_THERMOSTAT_SWITCH,
|
|
CONF_TEMP_SENSOR: "sensor.mock_temp_sensor",
|
|
CONF_EXTERNAL_TEMP_SENSOR: "sensor.mock_central_ext_temp_sensor",
|
|
CONF_TEMP_MIN: 15,
|
|
CONF_TEMP_MAX: 30,
|
|
CONF_AC_MODE: False,
|
|
CONF_TPI_COEF_INT: 0.5,
|
|
CONF_TPI_COEF_EXT: 0.02,
|
|
CONF_PROP_FUNCTION: PROPORTIONAL_FUNCTION_TPI,
|
|
CONF_CYCLE_MIN: 5,
|
|
CONF_HEATER: "switch.mock_switch1",
|
|
CONF_USE_PRESENCE_FEATURE: True,
|
|
CONF_USE_PRESENCE_CENTRAL_CONFIG: False,
|
|
CONF_PRESENCE_SENSOR: "person.presence_sensor",
|
|
CONF_USE_ADVANCED_CENTRAL_CONFIG: True,
|
|
CONF_USE_MAIN_CENTRAL_CONFIG: True,
|
|
CONF_USE_PRESETS_CENTRAL_CONFIG: True,
|
|
CONF_USE_WINDOW_CENTRAL_CONFIG: True,
|
|
CONF_USE_POWER_CENTRAL_CONFIG: True,
|
|
CONF_USE_MOTION_CENTRAL_CONFIG: True,
|
|
}
|
|
| temps
|
|
| temps_missing,
|
|
)
|
|
|
|
# The restore should be used
|
|
with patch(
|
|
"homeassistant.helpers.restore_state.RestoreEntity.async_get_last_state",
|
|
return_value=State(entity_id="number.mock_valve", state="23"),
|
|
) as mock_restore_state:
|
|
vtherm: BaseThermostat = await create_thermostat(
|
|
hass, vtherm_entry, "climate.theoverswitchvtherm"
|
|
)
|
|
|
|
assert vtherm.use_central_config_temperature is True
|
|
|
|
# We should try to restore all 4 temp entities and the VTherm itself
|
|
assert mock_restore_state.call_count == 4 + 1
|
|
|
|
# 1. We search for NumberEntities
|
|
for preset_name, value in temps.items():
|
|
temp_entity = search_entity(
|
|
hass,
|
|
"number.theoverswitchvtherm_preset_" + preset_name,
|
|
NUMBER_DOMAIN,
|
|
)
|
|
assert temp_entity
|
|
assert temp_entity.state == value
|
|
|
|
# This test is dependent to translation en.json. If translations change
|
|
# this may fails
|
|
assert (
|
|
temp_entity.name.lower()
|
|
== preset_name.replace(PRESET_TEMP_SUFFIX, "")
|
|
.replace(PRESET_AC_SUFFIX, " ac")
|
|
.replace(PRESET_AWAY_SUFFIX, " away")
|
|
.lower()
|
|
)
|
|
|
|
# Find temp Number into vtherm_api
|
|
val = vtherm_api.get_temperature_number_value(
|
|
config_id=vtherm_entry.entry_id, preset_name=preset_name
|
|
)
|
|
assert val == value
|
|
|
|
# 2. We search for NumberEntities to be missing
|
|
for preset_name, value in temps_missing.items():
|
|
temp_entity = search_entity(
|
|
hass,
|
|
"number.theoverswitchvtherm_" + preset_name,
|
|
NUMBER_DOMAIN,
|
|
)
|
|
assert temp_entity is None
|
|
|
|
# Find temp Number into vtherm_api
|
|
val = vtherm_api.get_temperature_number_value(
|
|
config_id=vtherm_entry.entry_id, preset_name=preset_name
|
|
)
|
|
assert val is None
|
|
|
|
# 3. The VTherm should be initialized with all presets and correct temperature
|
|
assert vtherm
|
|
assert isinstance(vtherm, ThermostatOverSwitch)
|
|
assert vtherm.preset_modes == [
|
|
PRESET_NONE,
|
|
PRESET_FROST_PROTECTION,
|
|
PRESET_ECO,
|
|
# PRESET_COMFORT, because temp is 0
|
|
PRESET_BOOST,
|
|
]
|
|
|
|
# Preset away should be empty cause we use central config for presets
|
|
assert vtherm._presets == {
|
|
PRESET_FROST_PROTECTION: FULL_CENTRAL_CONFIG["frost_temp"],
|
|
PRESET_ECO: FULL_CENTRAL_CONFIG["eco_temp"],
|
|
PRESET_COMFORT: FULL_CENTRAL_CONFIG["comfort_temp"],
|
|
PRESET_BOOST: FULL_CENTRAL_CONFIG["boost_temp"],
|
|
}
|
|
|
|
assert vtherm._presets_away == {
|
|
PRESET_FROST_PROTECTION + PRESET_AWAY_SUFFIX: temps["frost_away_temp"],
|
|
PRESET_ECO + PRESET_AWAY_SUFFIX: temps["eco_away_temp"],
|
|
PRESET_COMFORT + PRESET_AWAY_SUFFIX: temps["comfort_away_temp"],
|
|
PRESET_BOOST + PRESET_AWAY_SUFFIX: temps["boost_away_temp"],
|
|
}
|
|
|
|
|
|
@pytest.mark.parametrize("expected_lingering_timers", [True])
|
|
async def test_change_central_config_temperature(
|
|
hass: HomeAssistant, skip_hass_states_is_state, init_central_config
|
|
):
|
|
"""Test the construction of a over valve vtherm with
|
|
use central config for PRESET and PRESENCE.
|
|
When changing the central configuration temperature, the VTherm
|
|
target temperature should change also
|
|
For the test, another Vtherm with non central conf is used to
|
|
check it is not impacted by central config temp change"""
|
|
|
|
vtherm_entry = MockConfigEntry(
|
|
domain=DOMAIN,
|
|
title="TheValveConfigMockName",
|
|
unique_id="valveConfigUniqueId",
|
|
data={
|
|
CONF_NAME: "TheOverValveVTherm",
|
|
CONF_THERMOSTAT_TYPE: CONF_THERMOSTAT_VALVE,
|
|
CONF_TEMP_SENSOR: "sensor.mock_temp_sensor",
|
|
CONF_EXTERNAL_TEMP_SENSOR: "sensor.mock_central_ext_temp_sensor",
|
|
CONF_TEMP_MIN: 15,
|
|
CONF_TEMP_MAX: 30,
|
|
CONF_TPI_COEF_INT: 0.5,
|
|
CONF_TPI_COEF_EXT: 0.02,
|
|
CONF_PROP_FUNCTION: PROPORTIONAL_FUNCTION_TPI,
|
|
CONF_CYCLE_MIN: 5,
|
|
CONF_VALVE: "switch.mock_valve",
|
|
CONF_USE_PRESENCE_FEATURE: True,
|
|
CONF_USE_PRESENCE_CENTRAL_CONFIG: True,
|
|
CONF_USE_ADVANCED_CENTRAL_CONFIG: True,
|
|
CONF_USE_MAIN_CENTRAL_CONFIG: True,
|
|
CONF_USE_PRESETS_CENTRAL_CONFIG: True,
|
|
CONF_USE_WINDOW_CENTRAL_CONFIG: True,
|
|
CONF_USE_POWER_CENTRAL_CONFIG: True,
|
|
CONF_USE_MOTION_CENTRAL_CONFIG: True,
|
|
},
|
|
)
|
|
|
|
# Their is nothing to restore so temp values should be initialized with default values
|
|
vtherm: BaseThermostat = await create_thermostat(
|
|
hass, vtherm_entry, "climate.theovervalvevtherm"
|
|
)
|
|
|
|
assert vtherm.use_central_config_temperature is True
|
|
|
|
# Creates another VTherm which is NOT binded to central configuration
|
|
vtherm2_entry = MockConfigEntry(
|
|
domain=DOMAIN,
|
|
title="TheValve2ConfigMockName",
|
|
unique_id="valve2ConfigUniqueId",
|
|
data={
|
|
CONF_NAME: "TheOverValveVTherm2",
|
|
CONF_THERMOSTAT_TYPE: CONF_THERMOSTAT_VALVE,
|
|
CONF_TEMP_SENSOR: "sensor.mock_temp_sensor",
|
|
CONF_EXTERNAL_TEMP_SENSOR: "sensor.mock_central_ext_temp_sensor",
|
|
CONF_TEMP_MIN: 15,
|
|
CONF_TEMP_MAX: 30,
|
|
CONF_TPI_COEF_INT: 0.5,
|
|
CONF_TPI_COEF_EXT: 0.02,
|
|
CONF_CYCLE_MIN: 5,
|
|
CONF_PROP_FUNCTION: PROPORTIONAL_FUNCTION_TPI,
|
|
CONF_VALVE: "switch.mock_valve",
|
|
CONF_USE_PRESENCE_FEATURE: True,
|
|
CONF_USE_PRESENCE_CENTRAL_CONFIG: False,
|
|
CONF_PRESENCE_SENSOR: "person.presence_sensor",
|
|
CONF_USE_ADVANCED_CENTRAL_CONFIG: True,
|
|
CONF_USE_MAIN_CENTRAL_CONFIG: True,
|
|
CONF_USE_PRESETS_CENTRAL_CONFIG: False,
|
|
CONF_USE_WINDOW_CENTRAL_CONFIG: True,
|
|
CONF_USE_POWER_CENTRAL_CONFIG: True,
|
|
CONF_USE_MOTION_CENTRAL_CONFIG: True,
|
|
},
|
|
)
|
|
|
|
# Their is nothing to restore so temp values should be initialized with default values
|
|
vtherm2: BaseThermostat = await create_thermostat(
|
|
hass, vtherm2_entry, "climate.theovervalvevtherm2"
|
|
)
|
|
|
|
assert vtherm2.use_central_config_temperature is False
|
|
|
|
# 1. No temp Number should be present cause central config mode
|
|
preset_name = "boost"
|
|
temp_entity = search_entity(
|
|
hass,
|
|
"number.theovervalvevtherm_" + preset_name + PRESET_TEMP_SUFFIX,
|
|
NUMBER_DOMAIN,
|
|
)
|
|
assert not temp_entity
|
|
assert (
|
|
vtherm.find_preset_temp(preset_name) == 19.1
|
|
) # 19.1 is the value of the central_config boost preset temp
|
|
|
|
assert (
|
|
vtherm2.find_preset_temp(preset_name) == 15
|
|
) # 15 is the min temp which is the default
|
|
|
|
# 2. change the central_config temp Number entity value
|
|
temp_entity = search_entity(
|
|
hass,
|
|
"number.central_configuration_preset_" + preset_name + PRESET_TEMP_SUFFIX,
|
|
NUMBER_DOMAIN,
|
|
)
|
|
|
|
assert temp_entity
|
|
assert temp_entity.value == 19.1
|
|
|
|
await temp_entity.async_set_native_value(20.3)
|
|
assert temp_entity
|
|
assert temp_entity.value == 20.3
|
|
# Wait for async job to complete
|
|
await asyncio.sleep(0.1)
|
|
|
|
assert vtherm.find_preset_temp(preset_name) == 20.3
|
|
# No change for VTherm 2
|
|
assert (
|
|
vtherm2.find_preset_temp(preset_name) == 15
|
|
) # 15 is the min temp which is the default
|
|
|
|
|
|
@pytest.mark.parametrize("expected_lingering_timers", [True])
|
|
async def test_change_vtherm_temperature(
|
|
hass: HomeAssistant, skip_hass_states_is_state, init_central_config
|
|
):
|
|
"""Test the construction of a over valve vtherm with
|
|
use central config for PRESET and PRESENCE.
|
|
When changing the central configuration temperature, the VTherm
|
|
target temperature should change also"""
|
|
|
|
vtherm_entry = MockConfigEntry(
|
|
domain=DOMAIN,
|
|
title="TheValveConfigMockName",
|
|
unique_id="valveConfigUniqueId",
|
|
data={
|
|
CONF_NAME: "TheOverValveVTherm",
|
|
CONF_THERMOSTAT_TYPE: CONF_THERMOSTAT_VALVE,
|
|
CONF_TEMP_SENSOR: "sensor.mock_temp_sensor",
|
|
CONF_EXTERNAL_TEMP_SENSOR: "sensor.mock_central_ext_temp_sensor",
|
|
CONF_TEMP_MIN: 15,
|
|
CONF_TEMP_MAX: 30,
|
|
CONF_TPI_COEF_INT: 0.5,
|
|
CONF_TPI_COEF_EXT: 0.02,
|
|
CONF_CYCLE_MIN: 5,
|
|
CONF_PROP_FUNCTION: PROPORTIONAL_FUNCTION_TPI,
|
|
CONF_VALVE: "switch.mock_valve",
|
|
CONF_USE_PRESENCE_FEATURE: True,
|
|
CONF_USE_PRESENCE_CENTRAL_CONFIG: True,
|
|
CONF_USE_ADVANCED_CENTRAL_CONFIG: True,
|
|
CONF_USE_MAIN_CENTRAL_CONFIG: True,
|
|
CONF_USE_PRESETS_CENTRAL_CONFIG: True,
|
|
CONF_USE_WINDOW_CENTRAL_CONFIG: True,
|
|
CONF_USE_POWER_CENTRAL_CONFIG: True,
|
|
CONF_USE_MOTION_CENTRAL_CONFIG: True,
|
|
},
|
|
)
|
|
|
|
# Their is nothing to restore so temp values should be initialized with default values
|
|
vtherm: BaseThermostat = await create_thermostat(
|
|
hass, vtherm_entry, "climate.theovervalvevtherm"
|
|
)
|
|
|
|
assert vtherm.use_central_config_temperature is True
|
|
|
|
# Creates another VTherm which is NOT binded to central configuration
|
|
vtherm2_entry = MockConfigEntry(
|
|
domain=DOMAIN,
|
|
title="TheValve2ConfigMockName",
|
|
unique_id="valve2ConfigUniqueId",
|
|
data={
|
|
CONF_NAME: "TheOverValveVTherm2",
|
|
CONF_THERMOSTAT_TYPE: CONF_THERMOSTAT_VALVE,
|
|
CONF_TEMP_SENSOR: "sensor.mock_temp_sensor",
|
|
CONF_EXTERNAL_TEMP_SENSOR: "sensor.mock_central_ext_temp_sensor",
|
|
CONF_TEMP_MIN: 15,
|
|
CONF_TEMP_MAX: 30,
|
|
CONF_TPI_COEF_INT: 0.5,
|
|
CONF_TPI_COEF_EXT: 0.02,
|
|
CONF_CYCLE_MIN: 5,
|
|
CONF_PROP_FUNCTION: PROPORTIONAL_FUNCTION_TPI,
|
|
CONF_VALVE: "switch.mock_valve",
|
|
CONF_USE_PRESENCE_FEATURE: True,
|
|
CONF_USE_PRESENCE_CENTRAL_CONFIG: False,
|
|
CONF_PRESENCE_SENSOR: "person.presence_sensor",
|
|
CONF_USE_ADVANCED_CENTRAL_CONFIG: True,
|
|
CONF_USE_MAIN_CENTRAL_CONFIG: True,
|
|
CONF_USE_PRESETS_CENTRAL_CONFIG: False,
|
|
CONF_USE_WINDOW_CENTRAL_CONFIG: True,
|
|
CONF_USE_POWER_CENTRAL_CONFIG: True,
|
|
CONF_USE_MOTION_CENTRAL_CONFIG: True,
|
|
},
|
|
)
|
|
|
|
# Their is nothing to restore so temp values should be initialized with default values
|
|
vtherm2: BaseThermostat = await create_thermostat(
|
|
hass, vtherm2_entry, "climate.theovervalvevtherm2"
|
|
)
|
|
|
|
assert vtherm2.use_central_config_temperature is False
|
|
|
|
# 1. No temp Number should be present cause central config mode
|
|
preset_name = "boost"
|
|
temp_entity = search_entity(
|
|
hass,
|
|
"number.theovervalvevtherm_" + preset_name + PRESET_TEMP_SUFFIX,
|
|
NUMBER_DOMAIN,
|
|
)
|
|
assert not temp_entity
|
|
assert (
|
|
vtherm.find_preset_temp(preset_name) == 19.1
|
|
) # 19.1 is the value of the central_config boost preset temp
|
|
|
|
assert (
|
|
vtherm2.find_preset_temp(preset_name) == 15
|
|
) # 15 is the min temp which is the default
|
|
|
|
# 2. change the central_config temp Number entity value
|
|
temp_entity = search_entity(
|
|
hass,
|
|
"number.central_configuration_preset_" + preset_name + PRESET_TEMP_SUFFIX,
|
|
NUMBER_DOMAIN,
|
|
)
|
|
|
|
assert temp_entity
|
|
assert temp_entity.value == 19.1
|
|
|
|
await temp_entity.async_set_native_value(20.3)
|
|
assert temp_entity
|
|
assert temp_entity.value == 20.3
|
|
# Wait for async job to complete
|
|
await asyncio.sleep(0.1)
|
|
|
|
assert vtherm.find_preset_temp(preset_name) == 20.3
|
|
# No change for VTherm 2
|
|
assert (
|
|
vtherm2.find_preset_temp(preset_name) == 15
|
|
) # 15 is the min temp which is the default
|
|
|
|
|
|
@pytest.mark.parametrize("expected_lingering_timers", [True])
|
|
async def test_change_vtherm_temperature_with_presence(
|
|
hass: HomeAssistant, skip_hass_states_is_state, init_central_config
|
|
):
|
|
"""Test the construction of a over valve vtherm with
|
|
no central config for PRESET and PRESENCE.
|
|
When changing the Vtherm temperature, the VTherm
|
|
target temperature should change but not the temp
|
|
of a second which is linked to central config
|
|
"""
|
|
|
|
vtherm_entry = MockConfigEntry(
|
|
domain=DOMAIN,
|
|
title="TheValveConfigMockName",
|
|
unique_id="valveConfigUniqueId",
|
|
data={
|
|
CONF_NAME: "TheOverValveVTherm",
|
|
CONF_THERMOSTAT_TYPE: CONF_THERMOSTAT_VALVE,
|
|
CONF_TEMP_SENSOR: "sensor.mock_temp_sensor",
|
|
CONF_EXTERNAL_TEMP_SENSOR: "sensor.mock_central_ext_temp_sensor",
|
|
CONF_TEMP_MIN: 15,
|
|
CONF_TEMP_MAX: 30,
|
|
CONF_TPI_COEF_INT: 0.5,
|
|
CONF_TPI_COEF_EXT: 0.02,
|
|
CONF_PROP_FUNCTION: PROPORTIONAL_FUNCTION_TPI,
|
|
CONF_CYCLE_MIN: 5,
|
|
CONF_AC_MODE: True,
|
|
CONF_VALVE: "switch.mock_valve",
|
|
CONF_USE_PRESENCE_FEATURE: True,
|
|
CONF_USE_PRESENCE_CENTRAL_CONFIG: False,
|
|
CONF_PRESENCE_SENSOR: "person.presence_sensor",
|
|
CONF_USE_ADVANCED_CENTRAL_CONFIG: True,
|
|
CONF_USE_MAIN_CENTRAL_CONFIG: True,
|
|
CONF_USE_PRESETS_CENTRAL_CONFIG: False,
|
|
CONF_USE_WINDOW_CENTRAL_CONFIG: True,
|
|
CONF_USE_POWER_CENTRAL_CONFIG: True,
|
|
CONF_USE_MOTION_CENTRAL_CONFIG: True,
|
|
},
|
|
)
|
|
|
|
# Their is nothing to restore so temp values should be initialized with default values
|
|
vtherm: BaseThermostat = await create_thermostat(
|
|
hass, vtherm_entry, "climate.theovervalvevtherm"
|
|
)
|
|
assert vtherm.use_central_config_temperature is False
|
|
await vtherm.async_set_hvac_mode(HVACMode.COOL)
|
|
await vtherm.async_set_preset_mode(PRESET_BOOST)
|
|
await send_presence_change_event(
|
|
vtherm, STATE_ON, STATE_OFF, NowClass.get_now(hass), True
|
|
)
|
|
assert vtherm.target_temperature == 30 # default value
|
|
|
|
# Creates another VTherm which is NOT binded to central configuration
|
|
vtherm2_entry = MockConfigEntry(
|
|
domain=DOMAIN,
|
|
title="TheValve2ConfigMockName",
|
|
unique_id="valve2ConfigUniqueId",
|
|
data={
|
|
CONF_NAME: "TheOverValveVTherm2",
|
|
CONF_THERMOSTAT_TYPE: CONF_THERMOSTAT_VALVE,
|
|
CONF_TEMP_SENSOR: "sensor.mock_temp_sensor",
|
|
CONF_EXTERNAL_TEMP_SENSOR: "sensor.mock_central_ext_temp_sensor",
|
|
CONF_TEMP_MIN: 15,
|
|
CONF_TEMP_MAX: 30,
|
|
CONF_TPI_COEF_INT: 0.5,
|
|
CONF_TPI_COEF_EXT: 0.02,
|
|
CONF_PROP_FUNCTION: PROPORTIONAL_FUNCTION_TPI,
|
|
CONF_CYCLE_MIN: 5,
|
|
CONF_VALVE: "switch.mock_valve",
|
|
CONF_USE_PRESENCE_FEATURE: True,
|
|
CONF_USE_PRESENCE_CENTRAL_CONFIG: True,
|
|
CONF_USE_ADVANCED_CENTRAL_CONFIG: True,
|
|
CONF_USE_MAIN_CENTRAL_CONFIG: True,
|
|
CONF_USE_PRESETS_CENTRAL_CONFIG: True,
|
|
CONF_USE_WINDOW_CENTRAL_CONFIG: True,
|
|
CONF_USE_POWER_CENTRAL_CONFIG: True,
|
|
CONF_USE_MOTION_CENTRAL_CONFIG: True,
|
|
},
|
|
)
|
|
|
|
# Their is nothing to restore so temp values should be initialized with default values
|
|
vtherm2: BaseThermostat = await create_thermostat(
|
|
hass, vtherm2_entry, "climate.theovervalvevtherm2"
|
|
)
|
|
assert vtherm2.use_central_config_temperature is True
|
|
|
|
# 1. Temp Number should be present cause no central config mode
|
|
preset_name = "boost"
|
|
temp_entity = search_entity(
|
|
hass,
|
|
"number.theovervalvevtherm_preset_" + preset_name + "_ac_away_temp",
|
|
NUMBER_DOMAIN,
|
|
)
|
|
assert temp_entity
|
|
assert temp_entity.state == 30 # default value in ac_mode
|
|
assert vtherm.find_preset_temp(preset_name) == 30
|
|
|
|
# 19.1 is the value of the central_config boost preset temp
|
|
assert vtherm2.find_preset_temp(preset_name) == 19.1
|
|
|
|
# 2. change the temp Number entity value for each VTherm
|
|
temp_entity = search_entity(
|
|
hass,
|
|
"number.theovervalvevtherm_preset_" + preset_name + "_ac_away_temp",
|
|
NUMBER_DOMAIN,
|
|
)
|
|
|
|
assert temp_entity
|
|
assert temp_entity.value == 30
|
|
|
|
await temp_entity.async_set_native_value(20.3)
|
|
assert temp_entity
|
|
assert temp_entity.value == 20.3
|
|
# Wait for async job to complete
|
|
await asyncio.sleep(0.1)
|
|
|
|
# 30 because I change the preset _away but someeone is present
|
|
assert vtherm.find_preset_temp(preset_name) == 30
|
|
assert vtherm.target_temperature == 30 # default value
|
|
|
|
# No change for VTherm 2
|
|
assert (
|
|
vtherm2.find_preset_temp(preset_name) == 19.1
|
|
) # 15 is the min temp which is the default
|
|
|
|
# 3. We change now the current preset temp
|
|
temp_entity = search_entity(
|
|
hass,
|
|
"number.theovervalvevtherm_preset_" + preset_name + "_ac_temp",
|
|
NUMBER_DOMAIN,
|
|
)
|
|
|
|
assert temp_entity
|
|
assert temp_entity.value == 30
|
|
|
|
await temp_entity.async_set_native_value(20.3)
|
|
assert temp_entity
|
|
assert temp_entity.value == 20.3
|
|
# Wait for async job to complete
|
|
await asyncio.sleep(0.1)
|
|
|
|
# the target should have been change
|
|
assert vtherm.find_preset_temp(preset_name) == 20.3
|
|
assert vtherm.target_temperature == 20.3 # default value
|