Co-authored-by: Jean-Marc Collin <jean-marc.collin-extern@renault.com>
This commit is contained in:
@@ -1,15 +1,13 @@
|
|||||||
// See https://aka.ms/vscode-remote/devcontainer.json for format details.
|
// See https://aka.ms/vscode-remote/devcontainer.json for format details.
|
||||||
// "image": "ghcr.io/ludeeus/devcontainer/integration:latest",
|
// "image": "ghcr.io/ludeeus/devcontainer/integration:latest",
|
||||||
{
|
{
|
||||||
"build": {
|
"build": {
|
||||||
"dockerfile": "Dockerfile"
|
"dockerfile": "Dockerfile"
|
||||||
},
|
},
|
||||||
"name": "Versatile Thermostat integration",
|
"name": "Versatile Thermostat integration",
|
||||||
"appPort": [
|
"appPort": ["8123:8123"],
|
||||||
"8123:8123"
|
// "postCreateCommand": "container install",
|
||||||
],
|
"postCreateCommand": "./container dev-setup",
|
||||||
// "postCreateCommand": "container install",
|
|
||||||
"postCreateCommand": "./container dev-setup",
|
|
||||||
|
|
||||||
"mounts": [
|
"mounts": [
|
||||||
"source=${localEnv:HOME}/.ssh,target=/home/vscode/.ssh,type=bind,consistency=cached",
|
"source=${localEnv:HOME}/.ssh,target=/home/vscode/.ssh,type=bind,consistency=cached",
|
||||||
@@ -17,52 +15,53 @@
|
|||||||
"source=${localEnv:HOME}/SugarSync/Projets/home-assistant/versatile-thermostat-ui-card/dist,target=/workspaces/versatile_thermostat/config/www/community/versatile-thermostat-ui-card,type=bind,consistency=cached"
|
"source=${localEnv:HOME}/SugarSync/Projets/home-assistant/versatile-thermostat-ui-card/dist,target=/workspaces/versatile_thermostat/config/www/community/versatile-thermostat-ui-card,type=bind,consistency=cached"
|
||||||
],
|
],
|
||||||
|
|
||||||
"customizations": {
|
"customizations": {
|
||||||
"vscode": {
|
"vscode": {
|
||||||
"extensions": [
|
"extensions": [
|
||||||
"ms-python.python",
|
"ms-python.python",
|
||||||
"ms-python.pylint",
|
"ms-python.pylint",
|
||||||
// Doesn't work (crash). Default in python is to use Jedi see Settings / Python / Default Language
|
// Doesn't work (crash). Default in python is to use Jedi see Settings / Python / Default Language
|
||||||
// "ms-python.vscode-pylance",
|
// "ms-python.vscode-pylance",
|
||||||
"ms-python.isort",
|
"ms-python.isort",
|
||||||
"ms-python.black-formatter",
|
"ms-python.black-formatter",
|
||||||
"visualstudioexptteam.vscodeintellicode",
|
"visualstudioexptteam.vscodeintellicode",
|
||||||
"redhat.vscode-yaml",
|
"redhat.vscode-yaml",
|
||||||
"github.vscode-pull-request-github",
|
"github.vscode-pull-request-github",
|
||||||
"ryanluker.vscode-coverage-gutters",
|
"ryanluker.vscode-coverage-gutters",
|
||||||
"ferrierbenjamin.fold-unfold-all-icone",
|
"ferrierbenjamin.fold-unfold-all-icone",
|
||||||
"LittleFoxTeam.vscode-python-test-adapter",
|
"LittleFoxTeam.vscode-python-test-adapter",
|
||||||
"donjayamanne.githistory",
|
"donjayamanne.githistory",
|
||||||
"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",
|
||||||
"github.vscode-github-actions",
|
"github.vscode-github-actions",
|
||||||
"azuretools.vscode-docker"
|
"azuretools.vscode-docker",
|
||||||
],
|
"huizhou.githd",
|
||||||
"settings": {
|
],
|
||||||
"files.eol": "\n",
|
"settings": {
|
||||||
"editor.tabSize": 4,
|
"files.eol": "\n",
|
||||||
"terminal.integrated.profiles.linux": {
|
"editor.tabSize": 4,
|
||||||
"bash": {
|
"terminal.integrated.profiles.linux": {
|
||||||
"path": "bash",
|
"bash": {
|
||||||
"args": []
|
"path": "bash",
|
||||||
}
|
"args": []
|
||||||
},
|
}
|
||||||
"terminal.integrated.defaultProfile.linux": "bash",
|
},
|
||||||
// "terminal.integrated.shell.linux": "/bin/bash",
|
"terminal.integrated.defaultProfile.linux": "bash",
|
||||||
"python.pythonPath": "/usr/bin/python3",
|
// "terminal.integrated.shell.linux": "/bin/bash",
|
||||||
"python.analysis.autoSearchPaths": true,
|
"python.pythonPath": "/usr/bin/python3",
|
||||||
"pylint.lintOnChange": false,
|
"python.analysis.autoSearchPaths": true,
|
||||||
"python.formatting.provider": "black",
|
"pylint.lintOnChange": false,
|
||||||
"python.formatting.blackPath": "/usr/local/py-utils/bin/black",
|
"python.formatting.provider": "black",
|
||||||
"editor.formatOnPaste": false,
|
"python.formatting.blackPath": "/usr/local/py-utils/bin/black",
|
||||||
"editor.formatOnSave": true,
|
"editor.formatOnPaste": false,
|
||||||
"editor.formatOnType": true,
|
"editor.formatOnSave": true,
|
||||||
"files.trimTrailingWhitespace": true
|
"editor.formatOnType": true,
|
||||||
// "python.experiments.optOutFrom": ["pythonTestAdapter"],
|
"files.trimTrailingWhitespace": true
|
||||||
// "python.analysis.logLevel": "Trace"
|
// "python.experiments.optOutFrom": ["pythonTestAdapter"],
|
||||||
}
|
// "python.analysis.logLevel": "Trace"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1269,7 +1269,7 @@ class BaseThermostat(ClimateEntity, RestoreEntity, Generic[T]):
|
|||||||
):
|
):
|
||||||
"""Set new preset mode."""
|
"""Set new preset mode."""
|
||||||
|
|
||||||
# Wer accept a new preset when:
|
# We accept a new preset when:
|
||||||
# 1. last_central_mode is not set,
|
# 1. last_central_mode is not set,
|
||||||
# 2. or last_central_mode is AUTO,
|
# 2. or last_central_mode is AUTO,
|
||||||
# 3. or last_central_mode is CENTRAL_MODE_FROST_PROTECTION and preset_mode is PRESET_FROST_PROTECTION (to be abel to re-set the preset_mode)
|
# 3. or last_central_mode is CENTRAL_MODE_FROST_PROTECTION and preset_mode is PRESET_FROST_PROTECTION (to be abel to re-set the preset_mode)
|
||||||
@@ -1326,6 +1326,7 @@ class BaseThermostat(ClimateEntity, RestoreEntity, Generic[T]):
|
|||||||
return
|
return
|
||||||
|
|
||||||
old_preset_mode = self._attr_preset_mode
|
old_preset_mode = self._attr_preset_mode
|
||||||
|
recalculate = True
|
||||||
if preset_mode == PRESET_NONE:
|
if preset_mode == PRESET_NONE:
|
||||||
self._attr_preset_mode = PRESET_NONE
|
self._attr_preset_mode = PRESET_NONE
|
||||||
if self._saved_target_temp:
|
if self._saved_target_temp:
|
||||||
@@ -1337,16 +1338,24 @@ class BaseThermostat(ClimateEntity, RestoreEntity, Generic[T]):
|
|||||||
if self._attr_preset_mode == PRESET_NONE:
|
if self._attr_preset_mode == PRESET_NONE:
|
||||||
self._saved_target_temp = self._target_temp
|
self._saved_target_temp = self._target_temp
|
||||||
self._attr_preset_mode = preset_mode
|
self._attr_preset_mode = preset_mode
|
||||||
await self._async_internal_set_temperature(
|
# Switch the temperature if window is not 'on'
|
||||||
self.find_preset_temp(preset_mode)
|
if self.window_state != STATE_ON:
|
||||||
)
|
await self._async_internal_set_temperature(
|
||||||
|
self.find_preset_temp(preset_mode)
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
# Window is on, so we just save the new expected temp
|
||||||
|
# so that closing the window will restore it
|
||||||
|
recalculate = False
|
||||||
|
self._saved_target_temp = self.find_preset_temp(preset_mode)
|
||||||
|
|
||||||
self.reset_last_temperature_time(old_preset_mode)
|
if recalculate:
|
||||||
|
self.reset_last_temperature_time(old_preset_mode)
|
||||||
|
|
||||||
if overwrite_saved_preset:
|
if overwrite_saved_preset:
|
||||||
self.save_preset_mode()
|
self.save_preset_mode()
|
||||||
|
|
||||||
self.recalculate()
|
self.recalculate()
|
||||||
# Notify only if there was a real change
|
# Notify only if there was a real change
|
||||||
if self._attr_preset_mode != old_preset_mode:
|
if self._attr_preset_mode != old_preset_mode:
|
||||||
self.send_event(EventType.PRESET_EVENT, {"preset": self._attr_preset_mode})
|
self.send_event(EventType.PRESET_EVENT, {"preset": self._attr_preset_mode})
|
||||||
@@ -1455,19 +1464,20 @@ class BaseThermostat(ClimateEntity, RestoreEntity, Generic[T]):
|
|||||||
_LOGGER.info("%s - Set target temp: %s", self, temperature)
|
_LOGGER.info("%s - Set target temp: %s", self, temperature)
|
||||||
if temperature is None:
|
if temperature is None:
|
||||||
return
|
return
|
||||||
await self._async_internal_set_temperature(temperature)
|
|
||||||
self._attr_preset_mode = PRESET_NONE
|
self._attr_preset_mode = PRESET_NONE
|
||||||
self.recalculate()
|
if self.window_state != STATE_ON:
|
||||||
self.reset_last_change_time_from_vtherm()
|
await self._async_internal_set_temperature(temperature)
|
||||||
await self.async_control_heating(force=True)
|
self.recalculate()
|
||||||
|
self.reset_last_change_time_from_vtherm()
|
||||||
|
await self.async_control_heating(force=True)
|
||||||
|
else:
|
||||||
|
self._saved_target_temp = temperature
|
||||||
|
|
||||||
async def _async_internal_set_temperature(self, temperature: float):
|
async def _async_internal_set_temperature(self, temperature: float):
|
||||||
"""Set the target temperature and the target temperature of underlying climate if any
|
"""Set the target temperature and the target temperature of underlying climate if any"""
|
||||||
For testing purpose you can pass an event_timestamp.
|
|
||||||
"""
|
|
||||||
if temperature:
|
if temperature:
|
||||||
self._target_temp = temperature
|
self._target_temp = temperature
|
||||||
return
|
|
||||||
|
|
||||||
def get_state_date_or_now(self, state: State) -> datetime:
|
def get_state_date_or_now(self, state: State) -> datetime:
|
||||||
"""Extract the last_changed state from State or return now if not available"""
|
"""Extract the last_changed state from State or return now if not available"""
|
||||||
|
|||||||
@@ -1762,7 +1762,7 @@ async def test_window_action_frost_temp(hass: HomeAssistant, skip_hass_states_is
|
|||||||
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_HEATER: "switch.mock_switch",
|
CONF_UNDERLYING_LIST: ["switch.mock_switch"],
|
||||||
CONF_PROP_FUNCTION: PROPORTIONAL_FUNCTION_TPI,
|
CONF_PROP_FUNCTION: PROPORTIONAL_FUNCTION_TPI,
|
||||||
CONF_TPI_COEF_INT: 0.3,
|
CONF_TPI_COEF_INT: 0.3,
|
||||||
CONF_TPI_COEF_EXT: 0.01,
|
CONF_TPI_COEF_EXT: 0.01,
|
||||||
@@ -1927,7 +1927,7 @@ async def test_window_action_frost_temp(hass: HomeAssistant, skip_hass_states_is
|
|||||||
assert entity.hvac_mode is HVACMode.HEAT
|
assert entity.hvac_mode is HVACMode.HEAT
|
||||||
# No change on preset
|
# No change on preset
|
||||||
assert entity.preset_mode is PRESET_BOOST
|
assert entity.preset_mode is PRESET_BOOST
|
||||||
# The eco temp
|
# The Boost temp
|
||||||
assert entity.target_temperature == 21
|
assert entity.target_temperature == 21
|
||||||
|
|
||||||
# Clean the entity
|
# Clean the entity
|
||||||
@@ -2091,3 +2091,223 @@ async def test_bug_66(
|
|||||||
assert entity.window_state == STATE_OFF
|
assert entity.window_state == STATE_OFF
|
||||||
assert entity.hvac_mode is HVACMode.HEAT
|
assert entity.hvac_mode is HVACMode.HEAT
|
||||||
assert entity.preset_mode is PRESET_BOOST
|
assert entity.preset_mode is PRESET_BOOST
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("expected_lingering_tasks", [True])
|
||||||
|
@pytest.mark.parametrize("expected_lingering_timers", [True])
|
||||||
|
async def test_window_action_frost_temp_preset_change(
|
||||||
|
hass: HomeAssistant, skip_hass_states_is_state
|
||||||
|
):
|
||||||
|
"""Test the Window management with the frost_temp option and change the preset during
|
||||||
|
the window is open. This should restore the new preset temperature"""
|
||||||
|
|
||||||
|
entry = MockConfigEntry(
|
||||||
|
domain=DOMAIN,
|
||||||
|
title="TheOverSwitchMockName",
|
||||||
|
unique_id="uniqueId",
|
||||||
|
data={
|
||||||
|
CONF_NAME: "TheOverSwitchMockName",
|
||||||
|
CONF_THERMOSTAT_TYPE: CONF_THERMOSTAT_SWITCH,
|
||||||
|
CONF_TEMP_SENSOR: "sensor.mock_temp_sensor",
|
||||||
|
CONF_EXTERNAL_TEMP_SENSOR: "sensor.mock_ext_temp_sensor",
|
||||||
|
CONF_CYCLE_MIN: 5,
|
||||||
|
CONF_TEMP_MIN: 15,
|
||||||
|
CONF_TEMP_MAX: 30,
|
||||||
|
CONF_USE_WINDOW_FEATURE: True,
|
||||||
|
CONF_USE_MOTION_FEATURE: False,
|
||||||
|
CONF_USE_POWER_FEATURE: False,
|
||||||
|
CONF_USE_PRESENCE_FEATURE: False,
|
||||||
|
CONF_UNDERLYING_LIST: ["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_WINDOW_ACTION: CONF_WINDOW_FROST_TEMP,
|
||||||
|
CONF_WINDOW_SENSOR: "binary_sensor.fake_window_sensor",
|
||||||
|
CONF_WINDOW_DELAY: 1,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
vtherm: BaseThermostat = await create_thermostat(
|
||||||
|
hass, entry, "climate.theoverswitchmockname"
|
||||||
|
)
|
||||||
|
assert vtherm
|
||||||
|
|
||||||
|
await set_all_climate_preset_temp(
|
||||||
|
hass, vtherm, default_temperatures, "theoverswitchmockname"
|
||||||
|
)
|
||||||
|
|
||||||
|
tz = get_tz(hass) # pylint: disable=invalid-name
|
||||||
|
now = datetime.now(tz)
|
||||||
|
|
||||||
|
await vtherm.async_set_hvac_mode(HVACMode.HEAT)
|
||||||
|
await vtherm.async_set_preset_mode(PRESET_BOOST)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
|
assert vtherm.hvac_mode is HVACMode.HEAT
|
||||||
|
assert vtherm.preset_mode is PRESET_BOOST
|
||||||
|
assert vtherm.target_temperature == 21
|
||||||
|
|
||||||
|
assert vtherm.window_state is STATE_OFF
|
||||||
|
assert vtherm.is_window_auto_enabled is False
|
||||||
|
|
||||||
|
# 1. Turn on the window sensor
|
||||||
|
now = now + timedelta(minutes=1)
|
||||||
|
vtherm._set_now(now)
|
||||||
|
with patch("homeassistant.helpers.condition.state", return_value=True):
|
||||||
|
|
||||||
|
try_function = await send_window_change_event(vtherm, True, False, now)
|
||||||
|
|
||||||
|
now = now + timedelta(minutes=2)
|
||||||
|
vtherm._set_now(now)
|
||||||
|
await try_function(None)
|
||||||
|
|
||||||
|
# VTherm should have taken the window action
|
||||||
|
assert vtherm.target_temperature == 7 # Frost
|
||||||
|
# No change
|
||||||
|
assert vtherm.preset_mode is PRESET_BOOST
|
||||||
|
assert vtherm.hvac_mode is HVACMode.HEAT
|
||||||
|
|
||||||
|
# 2. Change the preset to comfort
|
||||||
|
now = now + timedelta(minutes=1)
|
||||||
|
vtherm._set_now(now)
|
||||||
|
|
||||||
|
await vtherm.async_set_preset_mode(PRESET_COMFORT)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
|
# VTherm should have taken the new preset temperature
|
||||||
|
assert vtherm.target_temperature == 7 # frost (window is still open)
|
||||||
|
assert vtherm.preset_mode is PRESET_COMFORT
|
||||||
|
assert vtherm.hvac_mode is HVACMode.HEAT
|
||||||
|
|
||||||
|
# 3.Turn off the window sensor
|
||||||
|
now = now + timedelta(minutes=1)
|
||||||
|
vtherm._set_now(now)
|
||||||
|
with patch("homeassistant.helpers.condition.state", return_value=True):
|
||||||
|
|
||||||
|
try_function = await send_window_change_event(vtherm, False, True, now)
|
||||||
|
|
||||||
|
now = now + timedelta(minutes=2)
|
||||||
|
vtherm._set_now(now)
|
||||||
|
await try_function(None)
|
||||||
|
|
||||||
|
# VTherm should have restore the Comfort preset temperature
|
||||||
|
assert vtherm.target_temperature == 19 # restore comfort
|
||||||
|
# No change
|
||||||
|
assert vtherm.preset_mode is PRESET_COMFORT
|
||||||
|
assert vtherm.hvac_mode is HVACMode.HEAT
|
||||||
|
|
||||||
|
# Clean the entity
|
||||||
|
vtherm.remove_thermostat()
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("expected_lingering_tasks", [True])
|
||||||
|
@pytest.mark.parametrize("expected_lingering_timers", [True])
|
||||||
|
async def test_window_action_frost_temp_temp_change(
|
||||||
|
hass: HomeAssistant, skip_hass_states_is_state
|
||||||
|
):
|
||||||
|
"""Test the Window management with the frost_temp option and change the target temp during
|
||||||
|
the window is open. This should restore the new temperature"""
|
||||||
|
|
||||||
|
entry = MockConfigEntry(
|
||||||
|
domain=DOMAIN,
|
||||||
|
title="TheOverSwitchMockName",
|
||||||
|
unique_id="uniqueId",
|
||||||
|
data={
|
||||||
|
CONF_NAME: "TheOverSwitchMockName",
|
||||||
|
CONF_THERMOSTAT_TYPE: CONF_THERMOSTAT_SWITCH,
|
||||||
|
CONF_TEMP_SENSOR: "sensor.mock_temp_sensor",
|
||||||
|
CONF_EXTERNAL_TEMP_SENSOR: "sensor.mock_ext_temp_sensor",
|
||||||
|
CONF_CYCLE_MIN: 5,
|
||||||
|
CONF_TEMP_MIN: 15,
|
||||||
|
CONF_TEMP_MAX: 30,
|
||||||
|
CONF_USE_WINDOW_FEATURE: True,
|
||||||
|
CONF_USE_MOTION_FEATURE: False,
|
||||||
|
CONF_USE_POWER_FEATURE: False,
|
||||||
|
CONF_USE_PRESENCE_FEATURE: False,
|
||||||
|
CONF_UNDERLYING_LIST: ["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_WINDOW_ACTION: CONF_WINDOW_FROST_TEMP,
|
||||||
|
CONF_WINDOW_SENSOR: "binary_sensor.fake_window_sensor",
|
||||||
|
CONF_WINDOW_DELAY: 1,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
vtherm: BaseThermostat = await create_thermostat(
|
||||||
|
hass, entry, "climate.theoverswitchmockname"
|
||||||
|
)
|
||||||
|
assert vtherm
|
||||||
|
|
||||||
|
await set_all_climate_preset_temp(
|
||||||
|
hass, vtherm, default_temperatures, "theoverswitchmockname"
|
||||||
|
)
|
||||||
|
|
||||||
|
tz = get_tz(hass) # pylint: disable=invalid-name
|
||||||
|
now = datetime.now(tz)
|
||||||
|
|
||||||
|
await vtherm.async_set_hvac_mode(HVACMode.HEAT)
|
||||||
|
await vtherm.async_set_preset_mode(PRESET_BOOST)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
|
assert vtherm.hvac_mode is HVACMode.HEAT
|
||||||
|
assert vtherm.preset_mode is PRESET_BOOST
|
||||||
|
assert vtherm.target_temperature == 21
|
||||||
|
|
||||||
|
assert vtherm.window_state is STATE_OFF
|
||||||
|
assert vtherm.is_window_auto_enabled is False
|
||||||
|
|
||||||
|
# 1. Turn on the window sensor
|
||||||
|
now = now + timedelta(minutes=1)
|
||||||
|
vtherm._set_now(now)
|
||||||
|
with patch("homeassistant.helpers.condition.state", return_value=True):
|
||||||
|
|
||||||
|
try_function = await send_window_change_event(vtherm, True, False, now)
|
||||||
|
|
||||||
|
now = now + timedelta(minutes=2)
|
||||||
|
vtherm._set_now(now)
|
||||||
|
await try_function(None)
|
||||||
|
|
||||||
|
# VTherm should have taken the window action
|
||||||
|
assert vtherm.target_temperature == 7 # Frost
|
||||||
|
# No change
|
||||||
|
assert vtherm.preset_mode is PRESET_BOOST
|
||||||
|
assert vtherm.hvac_mode is HVACMode.HEAT
|
||||||
|
|
||||||
|
# 2. Change the target temperature
|
||||||
|
now = now + timedelta(minutes=1)
|
||||||
|
vtherm._set_now(now)
|
||||||
|
|
||||||
|
await vtherm.async_set_temperature(temperature=18.5)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
|
# VTherm should have taken the new preset temperature
|
||||||
|
assert vtherm.target_temperature == 7 # frost (window is still open)
|
||||||
|
assert vtherm.preset_mode is PRESET_NONE
|
||||||
|
assert vtherm.hvac_mode is HVACMode.HEAT
|
||||||
|
|
||||||
|
# 3.Turn off the window sensor
|
||||||
|
now = now + timedelta(minutes=1)
|
||||||
|
vtherm._set_now(now)
|
||||||
|
with patch("homeassistant.helpers.condition.state", return_value=True):
|
||||||
|
|
||||||
|
try_function = await send_window_change_event(vtherm, False, True, now)
|
||||||
|
|
||||||
|
now = now + timedelta(minutes=2)
|
||||||
|
vtherm._set_now(now)
|
||||||
|
await try_function(None)
|
||||||
|
|
||||||
|
# VTherm should have restore the new target temperature
|
||||||
|
assert vtherm.target_temperature == 18.5 # restore new target temperature
|
||||||
|
# No change
|
||||||
|
assert vtherm.preset_mode is PRESET_NONE
|
||||||
|
assert vtherm.hvac_mode is HVACMode.HEAT
|
||||||
|
|
||||||
|
# Clean the entity
|
||||||
|
vtherm.remove_thermostat()
|
||||||
|
|||||||
Reference in New Issue
Block a user