With central configuration testu ok
This commit is contained in:
@@ -30,7 +30,8 @@
|
|||||||
"waderyan.gitblame",
|
"waderyan.gitblame",
|
||||||
"keesschollaart.vscode-home-assistant",
|
"keesschollaart.vscode-home-assistant",
|
||||||
"vscode.markdown-math",
|
"vscode.markdown-math",
|
||||||
"yzhang.markdown-all-in-one"
|
"yzhang.markdown-all-in-one",
|
||||||
|
"ms-python.vscode-pylance"
|
||||||
],
|
],
|
||||||
// "mounts": [
|
// "mounts": [
|
||||||
// "source=${localWorkspaceFolder}/.devcontainer/configuration.yaml,target=${localWorkspaceFolder}/config/www/community/,type=bind,consistency=cached",
|
// "source=${localWorkspaceFolder}/.devcontainer/configuration.yaml,target=${localWorkspaceFolder}/config/www/community/,type=bind,consistency=cached",
|
||||||
|
|||||||
@@ -281,7 +281,7 @@ class BaseThermostat(ClimateEntity, RestoreEntity):
|
|||||||
def clean_one(cfg, schema: vol.Schema):
|
def clean_one(cfg, schema: vol.Schema):
|
||||||
"""Clean one schema"""
|
"""Clean one schema"""
|
||||||
for key, _ in schema.schema.items():
|
for key, _ in schema.schema.items():
|
||||||
if key in cfg is not None:
|
if key in cfg:
|
||||||
del cfg[key]
|
del cfg[key]
|
||||||
|
|
||||||
cfg = config_entry.copy()
|
cfg = config_entry.copy()
|
||||||
@@ -301,7 +301,7 @@ class BaseThermostat(ClimateEntity, RestoreEntity):
|
|||||||
clean_one(cfg, STEP_CENTRAL_WINDOW_DATA_SCHEMA)
|
clean_one(cfg, STEP_CENTRAL_WINDOW_DATA_SCHEMA)
|
||||||
|
|
||||||
if cfg.get(CONF_USE_MOTION_CENTRAL_CONFIG) is True:
|
if cfg.get(CONF_USE_MOTION_CENTRAL_CONFIG) is True:
|
||||||
clean_one(cfg, STEP_CENTRAL_WINDOW_DATA_SCHEMA)
|
clean_one(cfg, STEP_CENTRAL_MOTION_DATA_SCHEMA)
|
||||||
|
|
||||||
if cfg.get(CONF_USE_POWER_CENTRAL_CONFIG) is True:
|
if cfg.get(CONF_USE_POWER_CENTRAL_CONFIG) is True:
|
||||||
clean_one(cfg, STEP_CENTRAL_POWER_DATA_SCHEMA)
|
clean_one(cfg, STEP_CENTRAL_POWER_DATA_SCHEMA)
|
||||||
|
|||||||
@@ -80,6 +80,7 @@ async def async_setup_entry(
|
|||||||
async_add_entities([entity], True)
|
async_add_entities([entity], True)
|
||||||
|
|
||||||
# Add services
|
# Add services
|
||||||
|
# TODO move this to async_setup ?
|
||||||
platform = entity_platform.async_get_current_platform()
|
platform = entity_platform.async_get_current_platform()
|
||||||
platform.async_register_entity_service(
|
platform.async_register_entity_service(
|
||||||
SERVICE_SET_PRESENCE,
|
SERVICE_SET_PRESENCE,
|
||||||
|
|||||||
@@ -127,7 +127,8 @@ class VersatileThermostatBaseConfigFlow(FlowHandler):
|
|||||||
else:
|
else:
|
||||||
self._infos[config] = self._central_config is not None
|
self._infos[config] = self._central_config is not None
|
||||||
|
|
||||||
self._infos[COMES_FROM] = None
|
if COMES_FROM in self._infos:
|
||||||
|
del self._infos[COMES_FROM]
|
||||||
|
|
||||||
async def validate_input(self, data: dict) -> None:
|
async def validate_input(self, data: dict) -> None:
|
||||||
"""Validate the user input allows us to connect.
|
"""Validate the user input allows us to connect.
|
||||||
@@ -156,7 +157,7 @@ class VersatileThermostatBaseConfigFlow(FlowHandler):
|
|||||||
raise UnknownEntity(conf)
|
raise UnknownEntity(conf)
|
||||||
|
|
||||||
# Check that only one window feature is used
|
# Check that only one window feature is used
|
||||||
ws = data.get(CONF_WINDOW_SENSOR) # pylint: disable=invalid-name
|
ws = self._infos.get(CONF_WINDOW_SENSOR) # pylint: disable=invalid-name
|
||||||
waot = data.get(CONF_WINDOW_AUTO_OPEN_THRESHOLD)
|
waot = data.get(CONF_WINDOW_AUTO_OPEN_THRESHOLD)
|
||||||
wact = data.get(CONF_WINDOW_AUTO_CLOSE_THRESHOLD)
|
wact = data.get(CONF_WINDOW_AUTO_CLOSE_THRESHOLD)
|
||||||
wamd = data.get(CONF_WINDOW_AUTO_MAX_DURATION)
|
wamd = data.get(CONF_WINDOW_AUTO_MAX_DURATION)
|
||||||
@@ -315,6 +316,8 @@ class VersatileThermostatBaseConfigFlow(FlowHandler):
|
|||||||
if self._infos[CONF_THERMOSTAT_TYPE] == CONF_THERMOSTAT_CENTRAL_CONFIG:
|
if self._infos[CONF_THERMOSTAT_TYPE] == CONF_THERMOSTAT_CENTRAL_CONFIG:
|
||||||
schema = STEP_CENTRAL_TPI_DATA_SCHEMA
|
schema = STEP_CENTRAL_TPI_DATA_SCHEMA
|
||||||
next_step = self.async_step_presets
|
next_step = self.async_step_presets
|
||||||
|
elif self._infos.get(COMES_FROM) == "async_step_spec_tpi":
|
||||||
|
schema = STEP_CENTRAL_TPI_DATA_SCHEMA
|
||||||
|
|
||||||
return await self.generic_step("tpi", schema, user_input, next_step)
|
return await self.generic_step("tpi", schema, user_input, next_step)
|
||||||
|
|
||||||
@@ -323,6 +326,7 @@ class VersatileThermostatBaseConfigFlow(FlowHandler):
|
|||||||
_LOGGER.debug("Into ConfigFlow.async_step_spec_tpi user_input=%s", user_input)
|
_LOGGER.debug("Into ConfigFlow.async_step_spec_tpi user_input=%s", user_input)
|
||||||
|
|
||||||
schema = STEP_CENTRAL_TPI_DATA_SCHEMA
|
schema = STEP_CENTRAL_TPI_DATA_SCHEMA
|
||||||
|
self._infos[COMES_FROM] = "async_step_spec_tpi"
|
||||||
next_step = self.async_step_presets
|
next_step = self.async_step_presets
|
||||||
|
|
||||||
return await self.generic_step("tpi", schema, user_input, next_step)
|
return await self.generic_step("tpi", schema, user_input, next_step)
|
||||||
@@ -563,7 +567,7 @@ class VersatileThermostatBaseConfigFlow(FlowHandler):
|
|||||||
|
|
||||||
schema = STEP_CENTRAL_ADVANCED_DATA_SCHEMA
|
schema = STEP_CENTRAL_ADVANCED_DATA_SCHEMA
|
||||||
|
|
||||||
self._infos[COMES_FROM] = "async_step_spec_presence"
|
self._infos[COMES_FROM] = "async_step_spec_advanced"
|
||||||
|
|
||||||
next_step = self.async_step_advanced
|
next_step = self.async_step_advanced
|
||||||
|
|
||||||
@@ -607,7 +611,8 @@ class VersatileThermostatConfigFlow(
|
|||||||
"""Finalization of the ConfigEntry creation"""
|
"""Finalization of the ConfigEntry creation"""
|
||||||
_LOGGER.debug("ConfigFlow.async_finalize")
|
_LOGGER.debug("ConfigFlow.async_finalize")
|
||||||
# Removes temporary value
|
# Removes temporary value
|
||||||
self._infos[COMES_FROM] = None
|
if COMES_FROM in self._infos:
|
||||||
|
del self._infos[COMES_FROM]
|
||||||
return self.async_create_entry(title=self._infos[CONF_NAME], data=self._infos)
|
return self.async_create_entry(title=self._infos[CONF_NAME], data=self._infos)
|
||||||
|
|
||||||
|
|
||||||
@@ -811,7 +816,8 @@ class VersatileThermostatOptionsFlowHandler(
|
|||||||
)
|
)
|
||||||
|
|
||||||
# Removes temporary value
|
# Removes temporary value
|
||||||
self._infos[COMES_FROM] = None
|
if COMES_FROM in self._infos:
|
||||||
|
del self._infos[COMES_FROM]
|
||||||
|
|
||||||
self.hass.config_entries.async_update_entry(self.config_entry, data=self._infos)
|
self.hass.config_entries.async_update_entry(self.config_entry, data=self._infos)
|
||||||
return self.async_create_entry(title=None, data=None)
|
return self.async_create_entry(title=None, data=None)
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ class PropAlgorithm:
|
|||||||
) -> None:
|
) -> None:
|
||||||
"""Initialisation of the Proportional Algorithm"""
|
"""Initialisation of the Proportional Algorithm"""
|
||||||
_LOGGER.debug(
|
_LOGGER.debug(
|
||||||
"Creation new PropAlgorithm function_type: %s, tpi_coef_int: %s, tpi_coef_ext: %s, cycle_min:%d, minimal_activation_delay:%d",
|
"Creation new PropAlgorithm function_type: %s, tpi_coef_int: %s, tpi_coef_ext: %s, cycle_min:%d, minimal_activation_delay:%d", # pylint: disable=line-too-long
|
||||||
function_type,
|
function_type,
|
||||||
tpi_coef_int,
|
tpi_coef_int,
|
||||||
tpi_coef_ext,
|
tpi_coef_ext,
|
||||||
|
|||||||
@@ -29,6 +29,8 @@ from custom_components.versatile_thermostat.commons import ( # pylint: disable=
|
|||||||
NowClass,
|
NowClass,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
from custom_components.versatile_thermostat.vtherm_api import VersatileThermostatAPI
|
||||||
|
|
||||||
from .const import ( # pylint: disable=unused-import
|
from .const import ( # pylint: disable=unused-import
|
||||||
MOCK_TH_OVER_SWITCH_USER_CONFIG,
|
MOCK_TH_OVER_SWITCH_USER_CONFIG,
|
||||||
MOCK_TH_OVER_4SWITCH_USER_CONFIG,
|
MOCK_TH_OVER_4SWITCH_USER_CONFIG,
|
||||||
@@ -56,6 +58,7 @@ from .const import ( # pylint: disable=unused-import
|
|||||||
PRESET_ACTIVITY,
|
PRESET_ACTIVITY,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
FULL_SWITCH_CONFIG = (
|
FULL_SWITCH_CONFIG = (
|
||||||
MOCK_TH_OVER_SWITCH_USER_CONFIG
|
MOCK_TH_OVER_SWITCH_USER_CONFIG
|
||||||
| MOCK_TH_OVER_SWITCH_TYPE_CONFIG
|
| MOCK_TH_OVER_SWITCH_TYPE_CONFIG
|
||||||
@@ -114,6 +117,45 @@ FULL_4SWITCH_CONFIG = (
|
|||||||
| MOCK_ADVANCED_CONFIG
|
| MOCK_ADVANCED_CONFIG
|
||||||
)
|
)
|
||||||
|
|
||||||
|
FULL_CENTRAL_CONFIG = {
|
||||||
|
CONF_NAME: CENTRAL_CONFIG_NAME,
|
||||||
|
CONF_THERMOSTAT_TYPE: CONF_THERMOSTAT_CENTRAL_CONFIG,
|
||||||
|
CONF_EXTERNAL_TEMP_SENSOR: "sensor.mock_ext_temp_sensor",
|
||||||
|
CONF_TEMP_MIN: 15,
|
||||||
|
CONF_TEMP_MAX: 30,
|
||||||
|
CONF_TPI_COEF_INT: 0.5,
|
||||||
|
CONF_TPI_COEF_EXT: 0.02,
|
||||||
|
"frost_temp": 10,
|
||||||
|
"eco_temp": 17.1,
|
||||||
|
"comfort_temp": 0,
|
||||||
|
"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": 0,
|
||||||
|
"boost_away_temp": 15.4,
|
||||||
|
"eco_ac_away_temp": 30.5,
|
||||||
|
"comfort_ac_away_temp": 0,
|
||||||
|
"boost_ac_away_temp": 30.7,
|
||||||
|
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_power_sensor",
|
||||||
|
CONF_MAX_POWER_SENSOR: "sensor.mock_max_power_sensor",
|
||||||
|
CONF_PRESET_POWER: 14,
|
||||||
|
CONF_MINIMAL_ACTIVATION_DELAY: 11,
|
||||||
|
CONF_SECURITY_DELAY_MIN: 61,
|
||||||
|
CONF_SECURITY_MIN_ON_PERCENT: 0.5,
|
||||||
|
CONF_SECURITY_DEFAULT_ON_PERCENT: 0.2,
|
||||||
|
}
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
@@ -302,6 +344,27 @@ async def create_thermostat(
|
|||||||
return search_entity(hass, entity_id, CLIMATE_DOMAIN)
|
return search_entity(hass, entity_id, CLIMATE_DOMAIN)
|
||||||
|
|
||||||
|
|
||||||
|
async def create_central_config( # pylint: disable=dangerous-default-value
|
||||||
|
hass: HomeAssistant, entry: MockConfigEntry = FULL_CENTRAL_CONFIG
|
||||||
|
):
|
||||||
|
"""Creates a Central Configuration from entry given in argument"""
|
||||||
|
central_config_entry = MockConfigEntry(
|
||||||
|
domain=DOMAIN,
|
||||||
|
title="TheCentralConfigMockName",
|
||||||
|
unique_id="centralConfigUniqueId",
|
||||||
|
data=entry,
|
||||||
|
)
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
# Test that VTherm API find the CentralConfig
|
||||||
|
api = VersatileThermostatAPI.get_vtherm_api(hass)
|
||||||
|
central_configuration = api.find_central_configuration()
|
||||||
|
assert central_configuration is not None
|
||||||
|
|
||||||
|
|
||||||
def search_entity(hass: HomeAssistant, entity_id, domain) -> Entity:
|
def search_entity(hass: HomeAssistant, entity_id, domain) -> Entity:
|
||||||
"""Search and return the entity in the domain"""
|
"""Search and return the entity in the domain"""
|
||||||
component = hass.data[domain]
|
component = hass.data[domain]
|
||||||
@@ -311,6 +374,12 @@ def search_entity(hass: HomeAssistant, entity_id, domain) -> Entity:
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
def count_entities(hass: HomeAssistant, entity_id, domain) -> Entity:
|
||||||
|
"""Search and return the entity in the domain"""
|
||||||
|
component = hass.data[domain]
|
||||||
|
return len(list(component.entities)) if component.entities else 0
|
||||||
|
|
||||||
|
|
||||||
async def send_temperature_change_event(
|
async def send_temperature_change_event(
|
||||||
entity: BaseThermostat, new_temp, date, sleep=True
|
entity: BaseThermostat, new_temp, date, sleep=True
|
||||||
):
|
):
|
||||||
|
|||||||
@@ -6,74 +6,23 @@ from homeassistant.components.climate.const import ( # pylint: disable=unused-i
|
|||||||
PRESET_NONE,
|
PRESET_NONE,
|
||||||
PRESET_ACTIVITY,
|
PRESET_ACTIVITY,
|
||||||
)
|
)
|
||||||
from custom_components.versatile_thermostat.const import (
|
|
||||||
CONF_NAME,
|
from custom_components.versatile_thermostat.const import * # pylint: disable=wildcard-import, unused-wildcard-import
|
||||||
CONF_HEATER,
|
|
||||||
CONF_HEATER_2,
|
|
||||||
CONF_HEATER_3,
|
|
||||||
CONF_HEATER_4,
|
|
||||||
CONF_THERMOSTAT_CLIMATE,
|
|
||||||
CONF_THERMOSTAT_SWITCH,
|
|
||||||
CONF_THERMOSTAT_TYPE,
|
|
||||||
CONF_AC_MODE,
|
|
||||||
CONF_TEMP_SENSOR,
|
|
||||||
CONF_EXTERNAL_TEMP_SENSOR,
|
|
||||||
CONF_CYCLE_MIN,
|
|
||||||
CONF_TEMP_MAX,
|
|
||||||
CONF_TEMP_MIN,
|
|
||||||
CONF_PROP_FUNCTION,
|
|
||||||
PROPORTIONAL_FUNCTION_TPI,
|
|
||||||
CONF_TPI_COEF_INT,
|
|
||||||
CONF_TPI_COEF_EXT,
|
|
||||||
CONF_MINIMAL_ACTIVATION_DELAY,
|
|
||||||
CONF_SECURITY_DELAY_MIN,
|
|
||||||
CONF_SECURITY_MIN_ON_PERCENT,
|
|
||||||
CONF_SECURITY_DEFAULT_ON_PERCENT,
|
|
||||||
CONF_USE_WINDOW_FEATURE,
|
|
||||||
CONF_USE_MOTION_FEATURE,
|
|
||||||
CONF_USE_POWER_FEATURE,
|
|
||||||
CONF_USE_PRESENCE_FEATURE,
|
|
||||||
CONF_WINDOW_SENSOR,
|
|
||||||
CONF_WINDOW_DELAY,
|
|
||||||
CONF_WINDOW_AUTO_OPEN_THRESHOLD,
|
|
||||||
CONF_WINDOW_AUTO_CLOSE_THRESHOLD,
|
|
||||||
CONF_WINDOW_AUTO_MAX_DURATION,
|
|
||||||
CONF_MOTION_SENSOR,
|
|
||||||
CONF_MOTION_DELAY,
|
|
||||||
CONF_MOTION_OFF_DELAY,
|
|
||||||
CONF_MOTION_PRESET,
|
|
||||||
CONF_NO_MOTION_PRESET,
|
|
||||||
CONF_POWER_SENSOR,
|
|
||||||
CONF_MAX_POWER_SENSOR,
|
|
||||||
CONF_DEVICE_POWER,
|
|
||||||
CONF_PRESET_POWER,
|
|
||||||
CONF_PRESENCE_SENSOR,
|
|
||||||
PRESET_AWAY_SUFFIX,
|
|
||||||
CONF_CLIMATE,
|
|
||||||
CONF_AUTO_REGULATION_MODE,
|
|
||||||
CONF_AUTO_REGULATION_STRONG,
|
|
||||||
CONF_AUTO_REGULATION_NONE,
|
|
||||||
CONF_AUTO_REGULATION_DTEMP,
|
|
||||||
CONF_AUTO_REGULATION_PERIOD_MIN,
|
|
||||||
CONF_INVERSE_SWITCH,
|
|
||||||
CONF_AUTO_FAN_HIGH,
|
|
||||||
CONF_AUTO_FAN_MODE,
|
|
||||||
PRESET_FROST_PROTECTION,
|
|
||||||
)
|
|
||||||
|
|
||||||
MOCK_TH_OVER_SWITCH_USER_CONFIG = {
|
MOCK_TH_OVER_SWITCH_USER_CONFIG = {
|
||||||
CONF_NAME: "TheOverSwitchMockName",
|
|
||||||
CONF_THERMOSTAT_TYPE: CONF_THERMOSTAT_SWITCH,
|
CONF_THERMOSTAT_TYPE: CONF_THERMOSTAT_SWITCH,
|
||||||
|
}
|
||||||
|
|
||||||
|
MOCK_TH_OVER_SWITCH_MAIN_CONFIG = {
|
||||||
|
CONF_NAME: "TheOverSwitchMockName",
|
||||||
CONF_TEMP_SENSOR: "sensor.mock_temp_sensor",
|
CONF_TEMP_SENSOR: "sensor.mock_temp_sensor",
|
||||||
CONF_EXTERNAL_TEMP_SENSOR: "sensor.mock_ext_temp_sensor",
|
|
||||||
CONF_CYCLE_MIN: 5,
|
CONF_CYCLE_MIN: 5,
|
||||||
CONF_TEMP_MIN: 15,
|
|
||||||
CONF_TEMP_MAX: 30,
|
|
||||||
CONF_DEVICE_POWER: 1,
|
CONF_DEVICE_POWER: 1,
|
||||||
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_USE_MAIN_CENTRAL_CONFIG: True,
|
||||||
}
|
}
|
||||||
|
|
||||||
MOCK_TH_OVER_4SWITCH_USER_CONFIG = {
|
MOCK_TH_OVER_4SWITCH_USER_CONFIG = {
|
||||||
@@ -92,14 +41,23 @@ MOCK_TH_OVER_4SWITCH_USER_CONFIG = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
MOCK_TH_OVER_CLIMATE_USER_CONFIG = {
|
MOCK_TH_OVER_CLIMATE_USER_CONFIG = {
|
||||||
CONF_NAME: "TheOverClimateMockName",
|
|
||||||
CONF_THERMOSTAT_TYPE: CONF_THERMOSTAT_CLIMATE,
|
CONF_THERMOSTAT_TYPE: CONF_THERMOSTAT_CLIMATE,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
MOCK_TH_OVER_CLIMATE_MAIN_CONFIG = {
|
||||||
|
CONF_NAME: "TheOverClimateMockName",
|
||||||
CONF_TEMP_SENSOR: "sensor.mock_temp_sensor",
|
CONF_TEMP_SENSOR: "sensor.mock_temp_sensor",
|
||||||
CONF_EXTERNAL_TEMP_SENSOR: "sensor.mock_ext_temp_sensor",
|
|
||||||
CONF_CYCLE_MIN: 5,
|
CONF_CYCLE_MIN: 5,
|
||||||
|
CONF_DEVICE_POWER: 1,
|
||||||
|
CONF_USE_MAIN_CENTRAL_CONFIG: False
|
||||||
|
# Keep default values which are False
|
||||||
|
}
|
||||||
|
|
||||||
|
MOCK_TH_OVER_CLIMATE_CENTRAL_MAIN_CONFIG = {
|
||||||
|
CONF_EXTERNAL_TEMP_SENSOR: "sensor.mock_ext_temp_sensor",
|
||||||
CONF_TEMP_MIN: 15,
|
CONF_TEMP_MIN: 15,
|
||||||
CONF_TEMP_MAX: 30,
|
CONF_TEMP_MAX: 30,
|
||||||
CONF_DEVICE_POWER: 1
|
|
||||||
# Keep default values which are False
|
# Keep default values which are False
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -228,3 +186,14 @@ MOCK_DEFAULT_FEATURE_CONFIG = {
|
|||||||
CONF_USE_POWER_FEATURE: False,
|
CONF_USE_POWER_FEATURE: False,
|
||||||
CONF_USE_PRESENCE_FEATURE: False,
|
CONF_USE_PRESENCE_FEATURE: False,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MOCK_DEFAULT_CENTRAL_CONFIG = {
|
||||||
|
CONF_USE_MAIN_CENTRAL_CONFIG: False,
|
||||||
|
CONF_USE_TPI_CENTRAL_CONFIG: False,
|
||||||
|
CONF_USE_PRESETS_CENTRAL_CONFIG: False,
|
||||||
|
CONF_USE_WINDOW_CENTRAL_CONFIG: False,
|
||||||
|
CONF_USE_MOTION_CENTRAL_CONFIG: False,
|
||||||
|
CONF_USE_POWER_CENTRAL_CONFIG: False,
|
||||||
|
CONF_USE_PRESENCE_CENTRAL_CONFIG: False,
|
||||||
|
CONF_USE_ADVANCED_CENTRAL_CONFIG: False,
|
||||||
|
}
|
||||||
|
|||||||
400
tests/test_central_config.py
Normal file
400
tests/test_central_config.py
Normal file
@@ -0,0 +1,400 @@
|
|||||||
|
# pylint: disable=wildcard-import, unused-wildcard-import, protected-access, unused-argument, line-too-long
|
||||||
|
|
||||||
|
""" 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 HVACAction, HVACMode
|
||||||
|
from homeassistant.config_entries import ConfigEntryState
|
||||||
|
|
||||||
|
# from homeassistant.helpers.entity_component import EntityComponent
|
||||||
|
# from homeassistant.components.climate import ClimateEntity, DOMAIN as CLIMATE_DOMAIN
|
||||||
|
|
||||||
|
from pytest_homeassistant_custom_component.common import MockConfigEntry
|
||||||
|
|
||||||
|
# from custom_components.versatile_thermostat.base_thermostat import BaseThermostat
|
||||||
|
from custom_components.versatile_thermostat.thermostat_climate import (
|
||||||
|
ThermostatOverClimate,
|
||||||
|
)
|
||||||
|
|
||||||
|
from custom_components.versatile_thermostat.thermostat_switch import (
|
||||||
|
ThermostatOverSwitch,
|
||||||
|
)
|
||||||
|
|
||||||
|
from custom_components.versatile_thermostat.vtherm_api import VersatileThermostatAPI
|
||||||
|
|
||||||
|
from .commons 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_add_a_central_config(hass: HomeAssistant, skip_hass_states_is_state):
|
||||||
|
"""Tests the clean_central_config_doubon of base_thermostat"""
|
||||||
|
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,
|
||||||
|
"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,
|
||||||
|
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_SECURITY_DELAY_MIN: 61,
|
||||||
|
CONF_SECURITY_MIN_ON_PERCENT: 0.5,
|
||||||
|
CONF_SECURITY_DEFAULT_ON_PERCENT: 0.2,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
entity: ThermostatOverClimate = search_entity(
|
||||||
|
hass, "climate.thecentralconfigmockname", "climate"
|
||||||
|
)
|
||||||
|
|
||||||
|
assert entity is None
|
||||||
|
|
||||||
|
assert count_entities(hass, "climate.thecentralconfigmockname", "climate") == 0
|
||||||
|
|
||||||
|
# Test that VTherm API find the CentralConfig
|
||||||
|
api = VersatileThermostatAPI.get_vtherm_api(hass)
|
||||||
|
central_configuration = api.find_central_configuration()
|
||||||
|
assert central_configuration is not None
|
||||||
|
|
||||||
|
|
||||||
|
# @pytest.mark.parametrize("expected_lingering_tasks", [True])
|
||||||
|
# @pytest.mark.parametrize("expected_lingering_timers", [True])
|
||||||
|
async def test_minimal_over_switch_wo_central_config(
|
||||||
|
hass: HomeAssistant, skip_hass_states_is_state
|
||||||
|
):
|
||||||
|
"""Tests that a VTherm without any central_configuration is working with its own attributes"""
|
||||||
|
create_central_config(hass)
|
||||||
|
|
||||||
|
# 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_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_SECURITY_DELAY_MIN: 5,
|
||||||
|
CONF_SECURITY_MIN_ON_PERCENT: 0.3,
|
||||||
|
CONF_SECURITY_DEFAULT_ON_PERCENT: 0.1,
|
||||||
|
# CONF_WINDOW_AUTO_OPEN_THRESHOLD: 0.1,
|
||||||
|
# CONF_WINDOW_AUTO_CLOSE_THRESHOLD: 0.1,
|
||||||
|
# CONF_WINDOW_AUTO_MAX_DURATION: 0, # Should be 0 for test
|
||||||
|
CONF_INVERSE_SWITCH: True,
|
||||||
|
# CONF_USE_MAIN_CENTRAL_CONFIG: False,
|
||||||
|
# CONF_USE_TPI_CENTRAL_CONFIG: False,
|
||||||
|
# CONF_USE_WINDOW_CENTRAL_CONFIG: False,
|
||||||
|
# CONF_USE_MOTION_CENTRAL_CONFIG: False,
|
||||||
|
# CONF_USE_POWER_CENTRAL_CONFIG: False,
|
||||||
|
# CONF_USE_PRESENCE_CENTRAL_CONFIG: False,
|
||||||
|
# CONF_USE_PRESETS_CENTRAL_CONFIG: False,
|
||||||
|
# CONF_USE_ADVANCED_CENTRAL_CONFIG: False,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
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._temp_sensor_entity_id == "sensor.mock_temp_sensor"
|
||||||
|
assert entity._ext_temp_sensor_entity_id == "sensor.mock_ext_temp_sensor"
|
||||||
|
assert entity._cycle_min == 5
|
||||||
|
assert entity._attr_min_temp == 8
|
||||||
|
assert entity._attr_max_temp == 18
|
||||||
|
assert entity.preset_modes == ["none", "frost", "eco", "comfort", "boost"]
|
||||||
|
assert entity.is_window_auto_enabled is False
|
||||||
|
assert entity.nb_underlying_entities == 1
|
||||||
|
assert entity.underlying_entity_id(0) == "switch.mock_switch"
|
||||||
|
assert entity.proportional_algorithm is not None
|
||||||
|
assert entity.proportional_algorithm._tpi_coef_int == 0.3
|
||||||
|
assert entity.proportional_algorithm._tpi_coef_ext == 0.01
|
||||||
|
assert entity.proportional_algorithm._minimal_activation_delay == 30
|
||||||
|
assert entity._security_delay_min == 5
|
||||||
|
assert entity._security_min_on_percent == 0.3
|
||||||
|
assert entity._security_default_on_percent == 0.1
|
||||||
|
assert entity.is_inversed
|
||||||
|
|
||||||
|
|
||||||
|
# @pytest.mark.parametrize("expected_lingering_tasks", [True])
|
||||||
|
# @pytest.mark.parametrize("expected_lingering_timers", [True])
|
||||||
|
async def test_full_over_switch_wo_central_config(
|
||||||
|
hass: HomeAssistant, skip_hass_states_is_state
|
||||||
|
):
|
||||||
|
"""Tests that a VTherm without any central_configuration is working with its own attributes"""
|
||||||
|
await create_central_config(hass)
|
||||||
|
|
||||||
|
# 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_CYCLE_MIN: 5,
|
||||||
|
CONF_TEMP_MIN: 8,
|
||||||
|
CONF_TEMP_MAX: 18,
|
||||||
|
"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_MOTION_FEATURE: True,
|
||||||
|
CONF_USE_POWER_FEATURE: True,
|
||||||
|
CONF_USE_PRESENCE_FEATURE: True,
|
||||||
|
CONF_HEATER: "switch.mock_switch",
|
||||||
|
CONF_PROP_FUNCTION: PROPORTIONAL_FUNCTION_TPI,
|
||||||
|
CONF_INVERSE_SWITCH: False,
|
||||||
|
CONF_TPI_COEF_INT: 0.3,
|
||||||
|
CONF_TPI_COEF_EXT: 0.01,
|
||||||
|
CONF_MINIMAL_ACTIVATION_DELAY: 30,
|
||||||
|
CONF_SECURITY_DELAY_MIN: 5,
|
||||||
|
CONF_SECURITY_MIN_ON_PERCENT: 0.3,
|
||||||
|
CONF_SECURITY_DEFAULT_ON_PERCENT: 0.1,
|
||||||
|
CONF_WINDOW_SENSOR: "binary_sensor.mock_window_sensor",
|
||||||
|
CONF_WINDOW_DELAY: 30,
|
||||||
|
CONF_WINDOW_AUTO_OPEN_THRESHOLD: 3,
|
||||||
|
CONF_WINDOW_AUTO_CLOSE_THRESHOLD: 0.1,
|
||||||
|
CONF_WINDOW_AUTO_MAX_DURATION: 5,
|
||||||
|
CONF_MOTION_DELAY: 10,
|
||||||
|
CONF_MOTION_OFF_DELAY: 29,
|
||||||
|
CONF_MOTION_PRESET: "comfort",
|
||||||
|
CONF_NO_MOTION_PRESET: "eco",
|
||||||
|
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_USE_MAIN_CENTRAL_CONFIG: False,
|
||||||
|
CONF_USE_TPI_CENTRAL_CONFIG: False,
|
||||||
|
CONF_USE_WINDOW_CENTRAL_CONFIG: False,
|
||||||
|
CONF_USE_MOTION_CENTRAL_CONFIG: False,
|
||||||
|
CONF_USE_POWER_CENTRAL_CONFIG: False,
|
||||||
|
CONF_USE_PRESENCE_CENTRAL_CONFIG: False,
|
||||||
|
CONF_USE_PRESETS_CENTRAL_CONFIG: False,
|
||||||
|
CONF_USE_ADVANCED_CENTRAL_CONFIG: False,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
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._temp_sensor_entity_id == "sensor.mock_temp_sensor"
|
||||||
|
assert entity._ext_temp_sensor_entity_id == "sensor.mock_ext_temp_sensor"
|
||||||
|
assert entity._cycle_min == 5
|
||||||
|
assert entity._attr_min_temp == 8
|
||||||
|
assert entity._attr_max_temp == 18
|
||||||
|
assert entity.preset_modes == [
|
||||||
|
"none",
|
||||||
|
"frost",
|
||||||
|
"eco",
|
||||||
|
"comfort",
|
||||||
|
"boost",
|
||||||
|
"activity",
|
||||||
|
]
|
||||||
|
assert entity.nb_underlying_entities == 1
|
||||||
|
assert entity.underlying_entity_id(0) == "switch.mock_switch"
|
||||||
|
assert entity.proportional_algorithm is not None
|
||||||
|
assert entity.proportional_algorithm._tpi_coef_int == 0.3
|
||||||
|
assert entity.proportional_algorithm._tpi_coef_ext == 0.01
|
||||||
|
assert entity.proportional_algorithm._minimal_activation_delay == 30
|
||||||
|
assert entity._security_delay_min == 5
|
||||||
|
assert entity._security_min_on_percent == 0.3
|
||||||
|
assert entity._security_default_on_percent == 0.1
|
||||||
|
assert entity.is_inversed is False
|
||||||
|
|
||||||
|
assert entity.is_window_auto_enabled is True
|
||||||
|
assert entity._window_sensor_entity_id == "binary_sensor.mock_window_sensor"
|
||||||
|
assert entity._window_delay_sec == 30
|
||||||
|
assert entity._window_auto_close_threshold == 0.1
|
||||||
|
assert entity._window_auto_open_threshold == 3
|
||||||
|
assert entity._window_auto_max_duration == 5
|
||||||
|
|
||||||
|
assert entity._motion_sensor_entity_id == "binary_sensor.mock_motion_sensor"
|
||||||
|
assert entity._motion_delay_sec == 10
|
||||||
|
assert entity._motion_off_delay_sec == 29
|
||||||
|
assert entity._motion_preset == "comfort"
|
||||||
|
assert entity._no_motion_preset == "eco"
|
||||||
|
|
||||||
|
assert entity._power_sensor_entity_id == "sensor.mock_power_sensor"
|
||||||
|
assert entity._max_power_sensor_entity_id == "sensor.mock_max_power_sensor"
|
||||||
|
|
||||||
|
assert entity._presence_sensor_entity_id == "binary_sensor.mock_presence_sensor"
|
||||||
|
|
||||||
|
|
||||||
|
# @pytest.mark.parametrize("expected_lingering_tasks", [True])
|
||||||
|
# @pytest.mark.parametrize("expected_lingering_timers", [True])
|
||||||
|
async def test_full_over_switch_with_central_config(
|
||||||
|
hass: HomeAssistant, skip_hass_states_is_state
|
||||||
|
):
|
||||||
|
"""Tests that a VTherm with central_configuration is working with the central_config attributes"""
|
||||||
|
await create_central_config(hass)
|
||||||
|
|
||||||
|
# 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_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: True,
|
||||||
|
CONF_USE_PRESENCE_FEATURE: True,
|
||||||
|
CONF_HEATER: "switch.mock_switch",
|
||||||
|
CONF_PROP_FUNCTION: PROPORTIONAL_FUNCTION_TPI,
|
||||||
|
CONF_INVERSE_SWITCH: False,
|
||||||
|
CONF_TPI_COEF_INT: 0.3,
|
||||||
|
CONF_TPI_COEF_EXT: 0.01,
|
||||||
|
CONF_MINIMAL_ACTIVATION_DELAY: 30,
|
||||||
|
CONF_SECURITY_DELAY_MIN: 5,
|
||||||
|
CONF_SECURITY_MIN_ON_PERCENT: 0.3,
|
||||||
|
CONF_SECURITY_DEFAULT_ON_PERCENT: 0.1,
|
||||||
|
CONF_WINDOW_SENSOR: "binary_sensor.mock_window_sensor",
|
||||||
|
CONF_WINDOW_DELAY: 30,
|
||||||
|
CONF_WINDOW_AUTO_OPEN_THRESHOLD: 3,
|
||||||
|
CONF_WINDOW_AUTO_CLOSE_THRESHOLD: 0.1,
|
||||||
|
CONF_WINDOW_AUTO_MAX_DURATION: 5,
|
||||||
|
CONF_MOTION_DELAY: 10,
|
||||||
|
CONF_MOTION_OFF_DELAY: 29,
|
||||||
|
CONF_MOTION_PRESET: "comfort",
|
||||||
|
CONF_NO_MOTION_PRESET: "eco",
|
||||||
|
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_USE_MAIN_CENTRAL_CONFIG: True,
|
||||||
|
CONF_USE_TPI_CENTRAL_CONFIG: True,
|
||||||
|
CONF_USE_WINDOW_CENTRAL_CONFIG: True,
|
||||||
|
CONF_USE_MOTION_CENTRAL_CONFIG: True,
|
||||||
|
CONF_USE_POWER_CENTRAL_CONFIG: True,
|
||||||
|
CONF_USE_PRESENCE_CENTRAL_CONFIG: True,
|
||||||
|
CONF_USE_PRESETS_CENTRAL_CONFIG: True,
|
||||||
|
CONF_USE_ADVANCED_CENTRAL_CONFIG: True,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
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._temp_sensor_entity_id == "sensor.mock_temp_sensor"
|
||||||
|
assert entity._ext_temp_sensor_entity_id == "sensor.mock_ext_temp_sensor"
|
||||||
|
assert entity._cycle_min == 5
|
||||||
|
assert entity._attr_min_temp == 15
|
||||||
|
assert entity._attr_max_temp == 30
|
||||||
|
assert entity.preset_modes == [
|
||||||
|
"none",
|
||||||
|
"frost",
|
||||||
|
"eco",
|
||||||
|
"boost",
|
||||||
|
"activity",
|
||||||
|
]
|
||||||
|
assert entity.nb_underlying_entities == 1
|
||||||
|
assert entity.underlying_entity_id(0) == "switch.mock_switch"
|
||||||
|
assert entity.proportional_algorithm is not None
|
||||||
|
assert entity.proportional_algorithm._tpi_coef_int == 0.5
|
||||||
|
assert entity.proportional_algorithm._tpi_coef_ext == 0.02
|
||||||
|
assert entity.proportional_algorithm._minimal_activation_delay == 11
|
||||||
|
assert entity._security_delay_min == 61
|
||||||
|
assert entity._security_min_on_percent == 0.5
|
||||||
|
assert entity._security_default_on_percent == 0.2
|
||||||
|
assert entity.is_inversed is False
|
||||||
|
|
||||||
|
assert entity.is_window_auto_enabled is True
|
||||||
|
assert entity._window_sensor_entity_id == "binary_sensor.mock_window_sensor"
|
||||||
|
assert entity._window_delay_sec == 15
|
||||||
|
assert entity._window_auto_close_threshold == 1
|
||||||
|
assert entity._window_auto_open_threshold == 4
|
||||||
|
assert entity._window_auto_max_duration == 31
|
||||||
|
|
||||||
|
assert entity._motion_sensor_entity_id == "binary_sensor.mock_motion_sensor"
|
||||||
|
assert entity._motion_delay_sec == 31
|
||||||
|
assert entity._motion_off_delay_sec == 301
|
||||||
|
assert entity._motion_preset == "boost"
|
||||||
|
assert entity._no_motion_preset == "frost"
|
||||||
|
|
||||||
|
assert entity._power_sensor_entity_id == "sensor.mock_power_sensor"
|
||||||
|
assert entity._max_power_sensor_entity_id == "sensor.mock_max_power_sensor"
|
||||||
|
|
||||||
|
assert entity._presence_sensor_entity_id == "binary_sensor.mock_presence_sensor"
|
||||||
@@ -19,6 +19,7 @@ async def test_show_form(hass: HomeAssistant) -> None:
|
|||||||
# hass.data["custom_components"] = None
|
# hass.data["custom_components"] = None
|
||||||
# loader.async_get_custom_components(hass)
|
# loader.async_get_custom_components(hass)
|
||||||
# BaseThermostatAPI(hass)
|
# BaseThermostatAPI(hass)
|
||||||
|
await create_central_config(hass)
|
||||||
|
|
||||||
result = await hass.config_entries.flow.async_init(
|
result = await hass.config_entries.flow.async_init(
|
||||||
DOMAIN, context={"source": SOURCE_USER}
|
DOMAIN, context={"source": SOURCE_USER}
|
||||||
@@ -35,7 +36,8 @@ async def test_show_form(hass: HomeAssistant) -> None:
|
|||||||
async def test_user_config_flow_over_switch(
|
async def test_user_config_flow_over_switch(
|
||||||
hass: HomeAssistant, skip_hass_states_get
|
hass: HomeAssistant, skip_hass_states_get
|
||||||
): # pylint: disable=unused-argument
|
): # pylint: disable=unused-argument
|
||||||
"""Test the config flow with all thermostat_over_switch features"""
|
"""Test the config flow with all thermostat_over_switch features and central config on"""
|
||||||
|
await create_central_config(hass)
|
||||||
result = await hass.config_entries.flow.async_init(
|
result = await hass.config_entries.flow.async_init(
|
||||||
DOMAIN, context={"source": SOURCE_USER}
|
DOMAIN, context={"source": SOURCE_USER}
|
||||||
)
|
)
|
||||||
@@ -47,6 +49,14 @@ async def test_user_config_flow_over_switch(
|
|||||||
result["flow_id"], user_input=MOCK_TH_OVER_SWITCH_USER_CONFIG
|
result["flow_id"], user_input=MOCK_TH_OVER_SWITCH_USER_CONFIG
|
||||||
)
|
)
|
||||||
|
|
||||||
|
assert result["type"] == data_entry_flow.RESULT_TYPE_FORM
|
||||||
|
assert result["step_id"] == "main"
|
||||||
|
assert result["errors"] == {}
|
||||||
|
|
||||||
|
result = await hass.config_entries.flow.async_configure(
|
||||||
|
result["flow_id"], user_input=MOCK_TH_OVER_SWITCH_MAIN_CONFIG
|
||||||
|
)
|
||||||
|
|
||||||
assert result["type"] == data_entry_flow.RESULT_TYPE_FORM
|
assert result["type"] == data_entry_flow.RESULT_TYPE_FORM
|
||||||
assert result["step_id"] == "type"
|
assert result["step_id"] == "type"
|
||||||
assert result["errors"] == {}
|
assert result["errors"] == {}
|
||||||
@@ -60,7 +70,7 @@ async def test_user_config_flow_over_switch(
|
|||||||
assert result["errors"] == {}
|
assert result["errors"] == {}
|
||||||
|
|
||||||
result = await hass.config_entries.flow.async_configure(
|
result = await hass.config_entries.flow.async_configure(
|
||||||
result["flow_id"], user_input=MOCK_TH_OVER_SWITCH_TPI_CONFIG
|
result["flow_id"], user_input={CONF_USE_TPI_CENTRAL_CONFIG: True}
|
||||||
)
|
)
|
||||||
|
|
||||||
assert result["type"] == data_entry_flow.RESULT_TYPE_FORM
|
assert result["type"] == data_entry_flow.RESULT_TYPE_FORM
|
||||||
@@ -68,7 +78,7 @@ async def test_user_config_flow_over_switch(
|
|||||||
assert result["errors"] == {}
|
assert result["errors"] == {}
|
||||||
|
|
||||||
result = await hass.config_entries.flow.async_configure(
|
result = await hass.config_entries.flow.async_configure(
|
||||||
result["flow_id"], user_input=MOCK_PRESETS_CONFIG
|
result["flow_id"], user_input={CONF_USE_PRESETS_CENTRAL_CONFIG: True}
|
||||||
)
|
)
|
||||||
|
|
||||||
assert result["type"] == data_entry_flow.RESULT_TYPE_FORM
|
assert result["type"] == data_entry_flow.RESULT_TYPE_FORM
|
||||||
@@ -76,7 +86,11 @@ async def test_user_config_flow_over_switch(
|
|||||||
assert result["errors"] == {}
|
assert result["errors"] == {}
|
||||||
|
|
||||||
result = await hass.config_entries.flow.async_configure(
|
result = await hass.config_entries.flow.async_configure(
|
||||||
result["flow_id"], user_input=MOCK_WINDOW_CONFIG
|
result["flow_id"],
|
||||||
|
user_input={
|
||||||
|
CONF_WINDOW_SENSOR: "binary_sensor.window_sensor",
|
||||||
|
CONF_USE_WINDOW_CENTRAL_CONFIG: True,
|
||||||
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
assert result["type"] == data_entry_flow.RESULT_TYPE_FORM
|
assert result["type"] == data_entry_flow.RESULT_TYPE_FORM
|
||||||
@@ -84,7 +98,11 @@ async def test_user_config_flow_over_switch(
|
|||||||
assert result["errors"] == {}
|
assert result["errors"] == {}
|
||||||
|
|
||||||
result = await hass.config_entries.flow.async_configure(
|
result = await hass.config_entries.flow.async_configure(
|
||||||
result["flow_id"], user_input=MOCK_MOTION_CONFIG
|
result["flow_id"],
|
||||||
|
user_input={
|
||||||
|
CONF_MOTION_SENSOR: "input_boolean.motion_sensor",
|
||||||
|
CONF_USE_MOTION_CENTRAL_CONFIG: True,
|
||||||
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
assert result["type"] == data_entry_flow.RESULT_TYPE_FORM
|
assert result["type"] == data_entry_flow.RESULT_TYPE_FORM
|
||||||
@@ -92,7 +110,7 @@ async def test_user_config_flow_over_switch(
|
|||||||
assert result["errors"] == {}
|
assert result["errors"] == {}
|
||||||
|
|
||||||
result = await hass.config_entries.flow.async_configure(
|
result = await hass.config_entries.flow.async_configure(
|
||||||
result["flow_id"], user_input=MOCK_POWER_CONFIG
|
result["flow_id"], user_input={CONF_USE_POWER_CENTRAL_CONFIG: True}
|
||||||
)
|
)
|
||||||
|
|
||||||
assert result["type"] == data_entry_flow.RESULT_TYPE_FORM
|
assert result["type"] == data_entry_flow.RESULT_TYPE_FORM
|
||||||
@@ -100,7 +118,11 @@ async def test_user_config_flow_over_switch(
|
|||||||
assert result["errors"] == {}
|
assert result["errors"] == {}
|
||||||
|
|
||||||
result = await hass.config_entries.flow.async_configure(
|
result = await hass.config_entries.flow.async_configure(
|
||||||
result["flow_id"], user_input=MOCK_PRESENCE_CONFIG
|
result["flow_id"],
|
||||||
|
user_input={
|
||||||
|
CONF_PRESENCE_SENSOR: "person.presence_sensor",
|
||||||
|
CONF_USE_PRESENCE_CENTRAL_CONFIG: True,
|
||||||
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
assert result["type"] == data_entry_flow.RESULT_TYPE_FORM
|
assert result["type"] == data_entry_flow.RESULT_TYPE_FORM
|
||||||
@@ -108,21 +130,27 @@ async def test_user_config_flow_over_switch(
|
|||||||
assert result["errors"] == {}
|
assert result["errors"] == {}
|
||||||
|
|
||||||
result = await hass.config_entries.flow.async_configure(
|
result = await hass.config_entries.flow.async_configure(
|
||||||
result["flow_id"], user_input=MOCK_ADVANCED_CONFIG
|
result["flow_id"], user_input={CONF_USE_ADVANCED_CENTRAL_CONFIG: True}
|
||||||
)
|
)
|
||||||
|
|
||||||
assert result["type"] == data_entry_flow.RESULT_TYPE_CREATE_ENTRY
|
assert result["type"] == data_entry_flow.RESULT_TYPE_CREATE_ENTRY
|
||||||
assert (
|
assert result["data"] == (
|
||||||
result["data"]
|
MOCK_TH_OVER_SWITCH_USER_CONFIG
|
||||||
== MOCK_TH_OVER_SWITCH_USER_CONFIG
|
| MOCK_TH_OVER_SWITCH_MAIN_CONFIG
|
||||||
| MOCK_TH_OVER_SWITCH_TYPE_CONFIG
|
| MOCK_TH_OVER_SWITCH_TYPE_CONFIG
|
||||||
| MOCK_TH_OVER_SWITCH_TPI_CONFIG
|
| {CONF_WINDOW_SENSOR: "binary_sensor.window_sensor"}
|
||||||
| MOCK_PRESETS_CONFIG
|
| {CONF_MOTION_SENSOR: "input_boolean.motion_sensor"}
|
||||||
| MOCK_WINDOW_CONFIG
|
| {CONF_PRESENCE_SENSOR: "person.presence_sensor"}
|
||||||
| MOCK_MOTION_CONFIG
|
| {
|
||||||
| MOCK_POWER_CONFIG
|
CONF_USE_MAIN_CENTRAL_CONFIG: True,
|
||||||
| MOCK_PRESENCE_CONFIG
|
CONF_USE_TPI_CENTRAL_CONFIG: True,
|
||||||
| MOCK_ADVANCED_CONFIG
|
CONF_USE_PRESETS_CENTRAL_CONFIG: True,
|
||||||
|
CONF_USE_WINDOW_CENTRAL_CONFIG: True,
|
||||||
|
CONF_USE_MOTION_CENTRAL_CONFIG: True,
|
||||||
|
CONF_USE_POWER_CENTRAL_CONFIG: True,
|
||||||
|
CONF_USE_PRESENCE_CENTRAL_CONFIG: True,
|
||||||
|
CONF_USE_ADVANCED_CENTRAL_CONFIG: True,
|
||||||
|
}
|
||||||
)
|
)
|
||||||
assert result["result"]
|
assert result["result"]
|
||||||
assert result["result"].domain == DOMAIN
|
assert result["result"].domain == DOMAIN
|
||||||
@@ -137,6 +165,8 @@ async def test_user_config_flow_over_climate(
|
|||||||
hass: HomeAssistant, skip_hass_states_get
|
hass: HomeAssistant, skip_hass_states_get
|
||||||
): # pylint: disable=unused-argument
|
): # pylint: disable=unused-argument
|
||||||
"""Test the config flow with all thermostat_over_climate features and no additional features"""
|
"""Test the config flow with all thermostat_over_climate features and no additional features"""
|
||||||
|
await create_central_config(hass)
|
||||||
|
|
||||||
result = await hass.config_entries.flow.async_init(
|
result = await hass.config_entries.flow.async_init(
|
||||||
DOMAIN, context={"source": SOURCE_USER}
|
DOMAIN, context={"source": SOURCE_USER}
|
||||||
)
|
)
|
||||||
@@ -148,6 +178,22 @@ async def test_user_config_flow_over_climate(
|
|||||||
result["flow_id"], user_input=MOCK_TH_OVER_CLIMATE_USER_CONFIG
|
result["flow_id"], user_input=MOCK_TH_OVER_CLIMATE_USER_CONFIG
|
||||||
)
|
)
|
||||||
|
|
||||||
|
assert result["type"] == data_entry_flow.RESULT_TYPE_FORM
|
||||||
|
assert result["step_id"] == "main"
|
||||||
|
assert result["errors"] == {}
|
||||||
|
|
||||||
|
result = await hass.config_entries.flow.async_configure(
|
||||||
|
result["flow_id"], user_input=MOCK_TH_OVER_CLIMATE_MAIN_CONFIG
|
||||||
|
)
|
||||||
|
|
||||||
|
assert result["type"] == data_entry_flow.RESULT_TYPE_FORM
|
||||||
|
assert result["step_id"] == "main"
|
||||||
|
assert result["errors"] == {}
|
||||||
|
|
||||||
|
result = await hass.config_entries.flow.async_configure(
|
||||||
|
result["flow_id"], user_input=MOCK_TH_OVER_CLIMATE_CENTRAL_MAIN_CONFIG
|
||||||
|
)
|
||||||
|
|
||||||
assert result["type"] == data_entry_flow.RESULT_TYPE_FORM
|
assert result["type"] == data_entry_flow.RESULT_TYPE_FORM
|
||||||
assert result["step_id"] == "type"
|
assert result["step_id"] == "type"
|
||||||
assert result["errors"] == {}
|
assert result["errors"] == {}
|
||||||
@@ -160,6 +206,14 @@ async def test_user_config_flow_over_climate(
|
|||||||
assert result["step_id"] == "presets"
|
assert result["step_id"] == "presets"
|
||||||
assert result["errors"] == {}
|
assert result["errors"] == {}
|
||||||
|
|
||||||
|
result = await hass.config_entries.flow.async_configure(
|
||||||
|
result["flow_id"], user_input={CONF_USE_PRESETS_CENTRAL_CONFIG: False}
|
||||||
|
)
|
||||||
|
|
||||||
|
assert result["type"] == data_entry_flow.RESULT_TYPE_FORM
|
||||||
|
assert result["step_id"] == "presets"
|
||||||
|
assert result["errors"] == {}
|
||||||
|
|
||||||
result = await hass.config_entries.flow.async_configure(
|
result = await hass.config_entries.flow.async_configure(
|
||||||
result["flow_id"], user_input=MOCK_PRESETS_CONFIG
|
result["flow_id"], user_input=MOCK_PRESETS_CONFIG
|
||||||
)
|
)
|
||||||
@@ -168,19 +222,31 @@ async def test_user_config_flow_over_climate(
|
|||||||
assert result["step_id"] == "advanced"
|
assert result["step_id"] == "advanced"
|
||||||
assert result["errors"] == {}
|
assert result["errors"] == {}
|
||||||
|
|
||||||
|
result = await hass.config_entries.flow.async_configure(
|
||||||
|
result["flow_id"], user_input={CONF_USE_ADVANCED_CENTRAL_CONFIG: False}
|
||||||
|
)
|
||||||
|
|
||||||
|
assert result["type"] == data_entry_flow.RESULT_TYPE_FORM
|
||||||
|
assert result["step_id"] == "advanced"
|
||||||
|
assert result["errors"] == {}
|
||||||
|
|
||||||
result = await hass.config_entries.flow.async_configure(
|
result = await hass.config_entries.flow.async_configure(
|
||||||
result["flow_id"], user_input=MOCK_ADVANCED_CONFIG
|
result["flow_id"], user_input=MOCK_ADVANCED_CONFIG
|
||||||
)
|
)
|
||||||
|
|
||||||
assert result["type"] == data_entry_flow.RESULT_TYPE_CREATE_ENTRY
|
assert result["type"] == data_entry_flow.RESULT_TYPE_CREATE_ENTRY
|
||||||
assert (
|
assert result[
|
||||||
result["data"]
|
"data"
|
||||||
== MOCK_TH_OVER_CLIMATE_USER_CONFIG
|
] == MOCK_TH_OVER_CLIMATE_USER_CONFIG | MOCK_TH_OVER_CLIMATE_MAIN_CONFIG | MOCK_TH_OVER_CLIMATE_CENTRAL_MAIN_CONFIG | MOCK_TH_OVER_CLIMATE_TYPE_CONFIG | MOCK_PRESETS_CONFIG | MOCK_ADVANCED_CONFIG | MOCK_DEFAULT_FEATURE_CONFIG | {
|
||||||
| MOCK_TH_OVER_CLIMATE_TYPE_CONFIG
|
CONF_USE_MAIN_CENTRAL_CONFIG: False,
|
||||||
| MOCK_PRESETS_CONFIG
|
CONF_USE_TPI_CENTRAL_CONFIG: False,
|
||||||
| MOCK_ADVANCED_CONFIG
|
CONF_USE_PRESETS_CENTRAL_CONFIG: False,
|
||||||
| MOCK_DEFAULT_FEATURE_CONFIG
|
CONF_USE_WINDOW_CENTRAL_CONFIG: False,
|
||||||
)
|
CONF_USE_MOTION_CENTRAL_CONFIG: False,
|
||||||
|
CONF_USE_POWER_CENTRAL_CONFIG: False,
|
||||||
|
CONF_USE_PRESENCE_CENTRAL_CONFIG: False,
|
||||||
|
CONF_USE_ADVANCED_CENTRAL_CONFIG: False,
|
||||||
|
}
|
||||||
assert result["result"]
|
assert result["result"]
|
||||||
assert result["result"].domain == DOMAIN
|
assert result["result"].domain == DOMAIN
|
||||||
assert result["result"].version == 1
|
assert result["result"].version == 1
|
||||||
@@ -196,6 +262,8 @@ async def test_user_config_flow_window_auto_ok(
|
|||||||
skip_control_heating, # pylint: disable=unused-argument
|
skip_control_heating, # pylint: disable=unused-argument
|
||||||
):
|
):
|
||||||
"""Test the config flow with only window auto feature"""
|
"""Test the config flow with only window auto feature"""
|
||||||
|
await create_central_config(hass)
|
||||||
|
|
||||||
result = await hass.config_entries.flow.async_init(
|
result = await hass.config_entries.flow.async_init(
|
||||||
DOMAIN, context={"source": SOURCE_USER}
|
DOMAIN, context={"source": SOURCE_USER}
|
||||||
)
|
)
|
||||||
@@ -206,18 +274,26 @@ async def test_user_config_flow_window_auto_ok(
|
|||||||
result = await hass.config_entries.flow.async_configure(
|
result = await hass.config_entries.flow.async_configure(
|
||||||
result["flow_id"],
|
result["flow_id"],
|
||||||
user_input={
|
user_input={
|
||||||
CONF_NAME: "TheOverSwitchMockName",
|
|
||||||
CONF_THERMOSTAT_TYPE: CONF_THERMOSTAT_SWITCH,
|
CONF_THERMOSTAT_TYPE: CONF_THERMOSTAT_SWITCH,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
assert result["type"] == data_entry_flow.RESULT_TYPE_FORM
|
||||||
|
assert result["step_id"] == "main"
|
||||||
|
assert result["errors"] == {}
|
||||||
|
|
||||||
|
result = await hass.config_entries.flow.async_configure(
|
||||||
|
result["flow_id"],
|
||||||
|
user_input={
|
||||||
|
CONF_NAME: "TheOverSwitchMockName",
|
||||||
CONF_TEMP_SENSOR: "sensor.mock_temp_sensor",
|
CONF_TEMP_SENSOR: "sensor.mock_temp_sensor",
|
||||||
CONF_EXTERNAL_TEMP_SENSOR: "sensor.mock_ext_temp_sensor",
|
|
||||||
CONF_CYCLE_MIN: 5,
|
CONF_CYCLE_MIN: 5,
|
||||||
CONF_TEMP_MIN: 15,
|
|
||||||
CONF_TEMP_MAX: 30,
|
|
||||||
CONF_DEVICE_POWER: 1,
|
CONF_DEVICE_POWER: 1,
|
||||||
CONF_USE_WINDOW_FEATURE: True,
|
CONF_USE_WINDOW_FEATURE: True,
|
||||||
CONF_USE_MOTION_FEATURE: False,
|
CONF_USE_MOTION_FEATURE: False,
|
||||||
CONF_USE_POWER_FEATURE: False,
|
CONF_USE_POWER_FEATURE: False,
|
||||||
CONF_USE_PRESENCE_FEATURE: False,
|
CONF_USE_PRESENCE_FEATURE: False,
|
||||||
|
CONF_USE_MAIN_CENTRAL_CONFIG: True,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -233,6 +309,14 @@ async def test_user_config_flow_window_auto_ok(
|
|||||||
assert result["step_id"] == "tpi"
|
assert result["step_id"] == "tpi"
|
||||||
assert result["errors"] == {}
|
assert result["errors"] == {}
|
||||||
|
|
||||||
|
result = await hass.config_entries.flow.async_configure(
|
||||||
|
result["flow_id"], user_input={CONF_USE_TPI_CENTRAL_CONFIG: False}
|
||||||
|
)
|
||||||
|
|
||||||
|
assert result["type"] == data_entry_flow.RESULT_TYPE_FORM
|
||||||
|
assert result["step_id"] == "tpi"
|
||||||
|
assert result["errors"] == {}
|
||||||
|
|
||||||
result = await hass.config_entries.flow.async_configure(
|
result = await hass.config_entries.flow.async_configure(
|
||||||
result["flow_id"], user_input=MOCK_TH_OVER_SWITCH_TPI_CONFIG
|
result["flow_id"], user_input=MOCK_TH_OVER_SWITCH_TPI_CONFIG
|
||||||
)
|
)
|
||||||
@@ -242,7 +326,16 @@ async def test_user_config_flow_window_auto_ok(
|
|||||||
assert result["errors"] == {}
|
assert result["errors"] == {}
|
||||||
|
|
||||||
result = await hass.config_entries.flow.async_configure(
|
result = await hass.config_entries.flow.async_configure(
|
||||||
result["flow_id"], user_input=MOCK_PRESETS_CONFIG
|
result["flow_id"], user_input={CONF_USE_PRESETS_CENTRAL_CONFIG: True}
|
||||||
|
)
|
||||||
|
|
||||||
|
assert result["type"] == data_entry_flow.RESULT_TYPE_FORM
|
||||||
|
assert result["step_id"] == "window"
|
||||||
|
assert result["errors"] == {}
|
||||||
|
|
||||||
|
result = await hass.config_entries.flow.async_configure(
|
||||||
|
result["flow_id"],
|
||||||
|
user_input={CONF_USE_WINDOW_CENTRAL_CONFIG: False},
|
||||||
)
|
)
|
||||||
|
|
||||||
assert result["type"] == data_entry_flow.RESULT_TYPE_FORM
|
assert result["type"] == data_entry_flow.RESULT_TYPE_FORM
|
||||||
@@ -259,27 +352,34 @@ async def test_user_config_flow_window_auto_ok(
|
|||||||
assert result["errors"] == {}
|
assert result["errors"] == {}
|
||||||
|
|
||||||
result = await hass.config_entries.flow.async_configure(
|
result = await hass.config_entries.flow.async_configure(
|
||||||
result["flow_id"], user_input=MOCK_ADVANCED_CONFIG
|
result["flow_id"], user_input={CONF_USE_ADVANCED_CENTRAL_CONFIG: True}
|
||||||
)
|
)
|
||||||
|
|
||||||
assert result["type"] == data_entry_flow.RESULT_TYPE_CREATE_ENTRY
|
assert result["type"] == data_entry_flow.RESULT_TYPE_CREATE_ENTRY
|
||||||
assert (
|
assert result["data"] == {
|
||||||
result["data"]
|
CONF_THERMOSTAT_TYPE: CONF_THERMOSTAT_SWITCH,
|
||||||
== MOCK_TH_OVER_SWITCH_USER_CONFIG
|
CONF_NAME: "TheOverSwitchMockName",
|
||||||
| {
|
CONF_TEMP_SENSOR: "sensor.mock_temp_sensor",
|
||||||
CONF_USE_MOTION_FEATURE: False,
|
CONF_CYCLE_MIN: 5,
|
||||||
CONF_USE_POWER_FEATURE: False,
|
CONF_DEVICE_POWER: 1,
|
||||||
CONF_USE_PRESENCE_FEATURE: False,
|
CONF_USE_WINDOW_FEATURE: True,
|
||||||
CONF_WINDOW_DELAY: 30, # the default value is added
|
CONF_USE_MOTION_FEATURE: False,
|
||||||
CONF_USE_POWER_FEATURE: False,
|
CONF_USE_POWER_FEATURE: False,
|
||||||
CONF_USE_PRESENCE_FEATURE: False,
|
CONF_USE_PRESENCE_FEATURE: False,
|
||||||
}
|
CONF_USE_MOTION_FEATURE: False,
|
||||||
| MOCK_TH_OVER_SWITCH_TYPE_CONFIG
|
CONF_USE_POWER_FEATURE: False,
|
||||||
| MOCK_TH_OVER_SWITCH_TPI_CONFIG
|
CONF_USE_PRESENCE_FEATURE: False,
|
||||||
| MOCK_PRESETS_CONFIG
|
CONF_WINDOW_DELAY: 30, # the default value is added
|
||||||
| MOCK_WINDOW_AUTO_CONFIG
|
} | MOCK_TH_OVER_SWITCH_TYPE_CONFIG | MOCK_TH_OVER_SWITCH_TPI_CONFIG | MOCK_WINDOW_AUTO_CONFIG | {
|
||||||
| MOCK_ADVANCED_CONFIG
|
CONF_USE_MAIN_CENTRAL_CONFIG: True,
|
||||||
)
|
CONF_USE_TPI_CENTRAL_CONFIG: False,
|
||||||
|
CONF_USE_PRESETS_CENTRAL_CONFIG: True,
|
||||||
|
CONF_USE_WINDOW_CENTRAL_CONFIG: False,
|
||||||
|
CONF_USE_MOTION_CENTRAL_CONFIG: False,
|
||||||
|
CONF_USE_POWER_CENTRAL_CONFIG: False,
|
||||||
|
CONF_USE_PRESENCE_CENTRAL_CONFIG: False,
|
||||||
|
CONF_USE_ADVANCED_CENTRAL_CONFIG: True,
|
||||||
|
}
|
||||||
assert result["result"]
|
assert result["result"]
|
||||||
assert result["result"].domain == DOMAIN
|
assert result["result"].domain == DOMAIN
|
||||||
assert result["result"].version == 1
|
assert result["result"].version == 1
|
||||||
@@ -293,6 +393,9 @@ async def test_user_config_flow_window_auto_ko(
|
|||||||
hass: HomeAssistant, skip_hass_states_get # pylint: disable=unused-argument
|
hass: HomeAssistant, skip_hass_states_get # pylint: disable=unused-argument
|
||||||
):
|
):
|
||||||
"""Test the config flow with window auto and window features -> not allowed"""
|
"""Test the config flow with window auto and window features -> not allowed"""
|
||||||
|
|
||||||
|
await create_central_config(hass)
|
||||||
|
|
||||||
result = await hass.config_entries.flow.async_init(
|
result = await hass.config_entries.flow.async_init(
|
||||||
DOMAIN, context={"source": SOURCE_USER}
|
DOMAIN, context={"source": SOURCE_USER}
|
||||||
)
|
)
|
||||||
@@ -303,18 +406,26 @@ async def test_user_config_flow_window_auto_ko(
|
|||||||
result = await hass.config_entries.flow.async_configure(
|
result = await hass.config_entries.flow.async_configure(
|
||||||
result["flow_id"],
|
result["flow_id"],
|
||||||
user_input={
|
user_input={
|
||||||
CONF_NAME: "TheOverSwitchMockName",
|
|
||||||
CONF_THERMOSTAT_TYPE: CONF_THERMOSTAT_SWITCH,
|
CONF_THERMOSTAT_TYPE: CONF_THERMOSTAT_SWITCH,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
assert result["type"] == data_entry_flow.RESULT_TYPE_FORM
|
||||||
|
assert result["step_id"] == "main"
|
||||||
|
assert result["errors"] == {}
|
||||||
|
|
||||||
|
result = await hass.config_entries.flow.async_configure(
|
||||||
|
result["flow_id"],
|
||||||
|
user_input={
|
||||||
|
CONF_NAME: "TheOverSwitchMockName",
|
||||||
CONF_TEMP_SENSOR: "sensor.mock_temp_sensor",
|
CONF_TEMP_SENSOR: "sensor.mock_temp_sensor",
|
||||||
CONF_EXTERNAL_TEMP_SENSOR: "sensor.mock_ext_temp_sensor",
|
|
||||||
CONF_CYCLE_MIN: 5,
|
CONF_CYCLE_MIN: 5,
|
||||||
CONF_TEMP_MIN: 15,
|
|
||||||
CONF_TEMP_MAX: 30,
|
|
||||||
CONF_DEVICE_POWER: 1,
|
CONF_DEVICE_POWER: 1,
|
||||||
CONF_USE_WINDOW_FEATURE: True,
|
CONF_USE_WINDOW_FEATURE: True,
|
||||||
CONF_USE_MOTION_FEATURE: False,
|
CONF_USE_MOTION_FEATURE: False,
|
||||||
CONF_USE_POWER_FEATURE: False,
|
CONF_USE_POWER_FEATURE: False,
|
||||||
CONF_USE_PRESENCE_FEATURE: False,
|
CONF_USE_PRESENCE_FEATURE: False,
|
||||||
|
CONF_USE_MAIN_CENTRAL_CONFIG: True,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -330,6 +441,14 @@ async def test_user_config_flow_window_auto_ko(
|
|||||||
assert result["step_id"] == "tpi"
|
assert result["step_id"] == "tpi"
|
||||||
assert result["errors"] == {}
|
assert result["errors"] == {}
|
||||||
|
|
||||||
|
result = await hass.config_entries.flow.async_configure(
|
||||||
|
result["flow_id"], user_input={CONF_USE_TPI_CENTRAL_CONFIG: False}
|
||||||
|
)
|
||||||
|
|
||||||
|
assert result["type"] == data_entry_flow.RESULT_TYPE_FORM
|
||||||
|
assert result["step_id"] == "tpi"
|
||||||
|
assert result["errors"] == {}
|
||||||
|
|
||||||
result = await hass.config_entries.flow.async_configure(
|
result = await hass.config_entries.flow.async_configure(
|
||||||
result["flow_id"], user_input=MOCK_TH_OVER_SWITCH_TPI_CONFIG
|
result["flow_id"], user_input=MOCK_TH_OVER_SWITCH_TPI_CONFIG
|
||||||
)
|
)
|
||||||
@@ -339,7 +458,7 @@ async def test_user_config_flow_window_auto_ko(
|
|||||||
assert result["errors"] == {}
|
assert result["errors"] == {}
|
||||||
|
|
||||||
result = await hass.config_entries.flow.async_configure(
|
result = await hass.config_entries.flow.async_configure(
|
||||||
result["flow_id"], user_input=MOCK_PRESETS_CONFIG
|
result["flow_id"], user_input={CONF_USE_PRESETS_CENTRAL_CONFIG: True}
|
||||||
)
|
)
|
||||||
|
|
||||||
assert result["type"] == data_entry_flow.RESULT_TYPE_FORM
|
assert result["type"] == data_entry_flow.RESULT_TYPE_FORM
|
||||||
@@ -348,15 +467,27 @@ async def test_user_config_flow_window_auto_ko(
|
|||||||
|
|
||||||
result = await hass.config_entries.flow.async_configure(
|
result = await hass.config_entries.flow.async_configure(
|
||||||
result["flow_id"],
|
result["flow_id"],
|
||||||
user_input=MOCK_WINDOW_AUTO_CONFIG | MOCK_WINDOW_CONFIG,
|
user_input={
|
||||||
|
CONF_WINDOW_SENSOR: "binary_sensor.window_sensor",
|
||||||
|
CONF_USE_WINDOW_CENTRAL_CONFIG: False,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
assert result["type"] == data_entry_flow.RESULT_TYPE_FORM
|
||||||
|
assert result["step_id"] == "window"
|
||||||
|
assert result["errors"] == {}
|
||||||
|
|
||||||
|
result = await hass.config_entries.flow.async_configure(
|
||||||
|
result["flow_id"],
|
||||||
|
user_input=MOCK_WINDOW_AUTO_CONFIG,
|
||||||
)
|
)
|
||||||
|
|
||||||
assert result["type"] == data_entry_flow.RESULT_TYPE_FORM
|
assert result["type"] == data_entry_flow.RESULT_TYPE_FORM
|
||||||
# We should stay on window with an error
|
# We should stay on window with an error
|
||||||
assert result["step_id"] == "window"
|
|
||||||
assert result["errors"] == {
|
assert result["errors"] == {
|
||||||
"window_sensor_entity_id": "window_open_detection_method"
|
"window_sensor_entity_id": "window_open_detection_method"
|
||||||
}
|
}
|
||||||
|
assert result["step_id"] == "window"
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize("expected_lingering_tasks", [True])
|
@pytest.mark.parametrize("expected_lingering_tasks", [True])
|
||||||
@@ -368,19 +499,22 @@ async def test_user_config_flow_over_4_switches(
|
|||||||
):
|
):
|
||||||
"""Test the config flow with 4 switchs thermostat_over_switch features"""
|
"""Test the config flow with 4 switchs thermostat_over_switch features"""
|
||||||
|
|
||||||
SOURCE_CONFIG = { # pylint: disable=wildcard-import, invalid-name
|
await create_central_config(hass)
|
||||||
CONF_NAME: "TheOver4SwitchMockName",
|
|
||||||
|
SOURCE_CONFIG = {
|
||||||
CONF_THERMOSTAT_TYPE: CONF_THERMOSTAT_SWITCH,
|
CONF_THERMOSTAT_TYPE: CONF_THERMOSTAT_SWITCH,
|
||||||
|
}
|
||||||
|
|
||||||
|
MAIN_CONFIG = { # pylint: disable=wildcard-import, invalid-name
|
||||||
|
CONF_NAME: "TheOver4SwitchMockName",
|
||||||
CONF_TEMP_SENSOR: "sensor.mock_temp_sensor",
|
CONF_TEMP_SENSOR: "sensor.mock_temp_sensor",
|
||||||
CONF_EXTERNAL_TEMP_SENSOR: "sensor.mock_ext_temp_sensor",
|
|
||||||
CONF_CYCLE_MIN: 5,
|
CONF_CYCLE_MIN: 5,
|
||||||
CONF_TEMP_MIN: 15,
|
|
||||||
CONF_TEMP_MAX: 30,
|
|
||||||
CONF_DEVICE_POWER: 1,
|
CONF_DEVICE_POWER: 1,
|
||||||
CONF_USE_WINDOW_FEATURE: False,
|
CONF_USE_WINDOW_FEATURE: False,
|
||||||
CONF_USE_MOTION_FEATURE: False,
|
CONF_USE_MOTION_FEATURE: False,
|
||||||
CONF_USE_POWER_FEATURE: False,
|
CONF_USE_POWER_FEATURE: False,
|
||||||
CONF_USE_PRESENCE_FEATURE: False,
|
CONF_USE_PRESENCE_FEATURE: False,
|
||||||
|
CONF_USE_MAIN_CENTRAL_CONFIG: True,
|
||||||
}
|
}
|
||||||
|
|
||||||
TYPE_CONFIG = { # pylint: disable=wildcard-import, invalid-name
|
TYPE_CONFIG = { # pylint: disable=wildcard-import, invalid-name
|
||||||
@@ -390,6 +524,7 @@ async def test_user_config_flow_over_4_switches(
|
|||||||
CONF_HEATER_4: "switch.mock_switch4",
|
CONF_HEATER_4: "switch.mock_switch4",
|
||||||
CONF_PROP_FUNCTION: PROPORTIONAL_FUNCTION_TPI,
|
CONF_PROP_FUNCTION: PROPORTIONAL_FUNCTION_TPI,
|
||||||
CONF_AC_MODE: False,
|
CONF_AC_MODE: False,
|
||||||
|
CONF_INVERSE_SWITCH: False,
|
||||||
}
|
}
|
||||||
|
|
||||||
result = await hass.config_entries.flow.async_init(
|
result = await hass.config_entries.flow.async_init(
|
||||||
@@ -404,6 +539,15 @@ async def test_user_config_flow_over_4_switches(
|
|||||||
user_input=SOURCE_CONFIG,
|
user_input=SOURCE_CONFIG,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
assert result["type"] == data_entry_flow.RESULT_TYPE_FORM
|
||||||
|
assert result["step_id"] == "main"
|
||||||
|
assert result["errors"] == {}
|
||||||
|
|
||||||
|
result = await hass.config_entries.flow.async_configure(
|
||||||
|
result["flow_id"],
|
||||||
|
user_input=MAIN_CONFIG,
|
||||||
|
)
|
||||||
|
|
||||||
assert result["type"] == data_entry_flow.RESULT_TYPE_FORM
|
assert result["type"] == data_entry_flow.RESULT_TYPE_FORM
|
||||||
assert result["step_id"] == "type"
|
assert result["step_id"] == "type"
|
||||||
assert result["errors"] == {}
|
assert result["errors"] == {}
|
||||||
@@ -418,7 +562,7 @@ async def test_user_config_flow_over_4_switches(
|
|||||||
assert result["errors"] == {}
|
assert result["errors"] == {}
|
||||||
|
|
||||||
result = await hass.config_entries.flow.async_configure(
|
result = await hass.config_entries.flow.async_configure(
|
||||||
result["flow_id"], user_input=MOCK_TH_OVER_SWITCH_TPI_CONFIG
|
result["flow_id"], user_input={CONF_USE_TPI_CENTRAL_CONFIG: True}
|
||||||
)
|
)
|
||||||
|
|
||||||
assert result["type"] == data_entry_flow.RESULT_TYPE_FORM
|
assert result["type"] == data_entry_flow.RESULT_TYPE_FORM
|
||||||
@@ -426,7 +570,7 @@ async def test_user_config_flow_over_4_switches(
|
|||||||
assert result["errors"] == {}
|
assert result["errors"] == {}
|
||||||
|
|
||||||
result = await hass.config_entries.flow.async_configure(
|
result = await hass.config_entries.flow.async_configure(
|
||||||
result["flow_id"], user_input=MOCK_PRESETS_CONFIG
|
result["flow_id"], user_input={CONF_USE_PRESETS_CENTRAL_CONFIG: True}
|
||||||
)
|
)
|
||||||
|
|
||||||
assert result["type"] == data_entry_flow.RESULT_TYPE_FORM
|
assert result["type"] == data_entry_flow.RESULT_TYPE_FORM
|
||||||
@@ -434,15 +578,25 @@ async def test_user_config_flow_over_4_switches(
|
|||||||
assert result["errors"] == {}
|
assert result["errors"] == {}
|
||||||
|
|
||||||
result = await hass.config_entries.flow.async_configure(
|
result = await hass.config_entries.flow.async_configure(
|
||||||
result["flow_id"], user_input=MOCK_ADVANCED_CONFIG
|
result["flow_id"], user_input={CONF_USE_ADVANCED_CENTRAL_CONFIG: True}
|
||||||
)
|
)
|
||||||
|
|
||||||
assert result["type"] == data_entry_flow.RESULT_TYPE_CREATE_ENTRY
|
assert result["type"] == data_entry_flow.RESULT_TYPE_CREATE_ENTRY
|
||||||
assert result[
|
assert result["data"] == (
|
||||||
"data"
|
SOURCE_CONFIG
|
||||||
] == SOURCE_CONFIG | TYPE_CONFIG | MOCK_TH_OVER_SWITCH_TPI_CONFIG | MOCK_PRESETS_CONFIG | MOCK_ADVANCED_CONFIG | {
|
| MAIN_CONFIG
|
||||||
CONF_INVERSE_SWITCH: False
|
| TYPE_CONFIG
|
||||||
}
|
| {
|
||||||
|
CONF_USE_MAIN_CENTRAL_CONFIG: True,
|
||||||
|
CONF_USE_TPI_CENTRAL_CONFIG: True,
|
||||||
|
CONF_USE_PRESETS_CENTRAL_CONFIG: True,
|
||||||
|
CONF_USE_WINDOW_CENTRAL_CONFIG: False,
|
||||||
|
CONF_USE_MOTION_CENTRAL_CONFIG: False,
|
||||||
|
CONF_USE_POWER_CENTRAL_CONFIG: False,
|
||||||
|
CONF_USE_PRESENCE_CENTRAL_CONFIG: False,
|
||||||
|
CONF_USE_ADVANCED_CENTRAL_CONFIG: True,
|
||||||
|
}
|
||||||
|
)
|
||||||
assert result["result"]
|
assert result["result"]
|
||||||
assert result["result"].domain == DOMAIN
|
assert result["result"].domain == DOMAIN
|
||||||
assert result["result"].version == 1
|
assert result["result"].version == 1
|
||||||
|
|||||||
@@ -1,15 +1,18 @@
|
|||||||
# pylint: disable=unused-argument, line-too-long, protected-access
|
# pylint: disable=unused-argument, line-too-long, protected-access
|
||||||
""" Test the Window management """
|
""" Test the Window management """
|
||||||
import asyncio
|
# import asyncio
|
||||||
import logging
|
import logging
|
||||||
from unittest.mock import patch, call
|
from unittest.mock import patch, call
|
||||||
from datetime import datetime, timedelta
|
from datetime import datetime, timedelta
|
||||||
|
|
||||||
from custom_components.versatile_thermostat.thermostat_switch import ThermostatOverSwitch
|
from custom_components.versatile_thermostat.thermostat_switch import (
|
||||||
|
ThermostatOverSwitch,
|
||||||
|
)
|
||||||
from .commons import * # pylint: disable=wildcard-import, unused-wildcard-import
|
from .commons import * # pylint: disable=wildcard-import, unused-wildcard-import
|
||||||
|
|
||||||
logging.getLogger().setLevel(logging.DEBUG)
|
logging.getLogger().setLevel(logging.DEBUG)
|
||||||
|
|
||||||
|
|
||||||
@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_inverted_switch(hass: HomeAssistant, skip_hass_states_is_state):
|
async def test_inverted_switch(hass: HomeAssistant, skip_hass_states_is_state):
|
||||||
@@ -44,14 +47,14 @@ async def test_inverted_switch(hass: HomeAssistant, skip_hass_states_is_state):
|
|||||||
CONF_WINDOW_AUTO_OPEN_THRESHOLD: 0.1,
|
CONF_WINDOW_AUTO_OPEN_THRESHOLD: 0.1,
|
||||||
CONF_WINDOW_AUTO_CLOSE_THRESHOLD: 0.1,
|
CONF_WINDOW_AUTO_CLOSE_THRESHOLD: 0.1,
|
||||||
CONF_WINDOW_AUTO_MAX_DURATION: 0, # Should be 0 for test
|
CONF_WINDOW_AUTO_MAX_DURATION: 0, # Should be 0 for test
|
||||||
CONF_INVERSE_SWITCH: True
|
CONF_INVERSE_SWITCH: True,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
with patch(
|
with patch(
|
||||||
"homeassistant.core.ServiceRegistry.async_call"
|
"homeassistant.core.ServiceRegistry.async_call"
|
||||||
) as mock_service_call, patch(
|
) as mock_service_call, patch(
|
||||||
"homeassistant.core.StateMachine.is_state", return_value=True # switch is On
|
"homeassistant.core.StateMachine.is_state", return_value=True # switch is On
|
||||||
):
|
):
|
||||||
entity: ThermostatOverSwitch = await create_thermostat(
|
entity: ThermostatOverSwitch = await create_thermostat(
|
||||||
hass, entry, "climate.theoverswitchmockname"
|
hass, entry, "climate.theoverswitchmockname"
|
||||||
@@ -80,7 +83,7 @@ async def test_inverted_switch(hass: HomeAssistant, skip_hass_states_is_state):
|
|||||||
), patch(
|
), patch(
|
||||||
"homeassistant.core.ServiceRegistry.async_call"
|
"homeassistant.core.ServiceRegistry.async_call"
|
||||||
) as mock_service_call, patch(
|
) as mock_service_call, patch(
|
||||||
"homeassistant.core.StateMachine.is_state", return_value=True # switch is Off
|
"homeassistant.core.StateMachine.is_state", return_value=True # switch is Off
|
||||||
):
|
):
|
||||||
event_timestamp = now - timedelta(minutes=4)
|
event_timestamp = now - timedelta(minutes=4)
|
||||||
await send_temperature_change_event(entity, 19, event_timestamp)
|
await send_temperature_change_event(entity, 19, event_timestamp)
|
||||||
@@ -90,9 +93,13 @@ async def test_inverted_switch(hass: HomeAssistant, skip_hass_states_is_state):
|
|||||||
# not updated cause mocked assert entity.is_device_active is True
|
# not updated cause mocked assert entity.is_device_active is True
|
||||||
|
|
||||||
assert mock_service_call.call_count == 1
|
assert mock_service_call.call_count == 1
|
||||||
mock_service_call.assert_has_calls([
|
mock_service_call.assert_has_calls(
|
||||||
call.async_call('switch', SERVICE_TURN_OFF, {'entity_id': 'switch.mock_switch'}),
|
[
|
||||||
])
|
call.async_call(
|
||||||
|
"switch", SERVICE_TURN_OFF, {"entity_id": "switch.mock_switch"}
|
||||||
|
),
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
# 2. Make the temperature up to deactivate the switch
|
# 2. Make the temperature up to deactivate the switch
|
||||||
with patch(
|
with patch(
|
||||||
@@ -100,7 +107,8 @@ async def test_inverted_switch(hass: HomeAssistant, skip_hass_states_is_state):
|
|||||||
), patch(
|
), patch(
|
||||||
"homeassistant.core.ServiceRegistry.async_call"
|
"homeassistant.core.ServiceRegistry.async_call"
|
||||||
) as mock_service_call, patch(
|
) as mock_service_call, patch(
|
||||||
"homeassistant.core.StateMachine.is_state", return_value=False # switch is On -> it should turned off
|
"homeassistant.core.StateMachine.is_state",
|
||||||
|
return_value=False, # switch is On -> it should turned off
|
||||||
):
|
):
|
||||||
event_timestamp = now - timedelta(minutes=3)
|
event_timestamp = now - timedelta(minutes=3)
|
||||||
await send_temperature_change_event(entity, 25, event_timestamp)
|
await send_temperature_change_event(entity, 25, event_timestamp)
|
||||||
@@ -114,11 +122,13 @@ async def test_inverted_switch(hass: HomeAssistant, skip_hass_states_is_state):
|
|||||||
await entity._underlyings[0].turn_off()
|
await entity._underlyings[0].turn_off()
|
||||||
|
|
||||||
assert mock_service_call.call_count == 1
|
assert mock_service_call.call_count == 1
|
||||||
mock_service_call.assert_has_calls([
|
mock_service_call.assert_has_calls(
|
||||||
call.async_call('switch', SERVICE_TURN_ON, {'entity_id': 'switch.mock_switch'}),
|
[
|
||||||
])
|
call.async_call(
|
||||||
|
"switch", SERVICE_TURN_ON, {"entity_id": "switch.mock_switch"}
|
||||||
|
),
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
# Clean the entity
|
# Clean the entity
|
||||||
entity.remove_thermostat()
|
entity.remove_thermostat()
|
||||||
|
|||||||
Reference in New Issue
Block a user