Compare commits

...

2 Commits

Author SHA1 Message Date
Jean-Marc Collin 8b88ed5c9c Add tests for over switch AC mode 2023-10-21 17:18:56 +00:00
Jean-Marc Collin c0d422a916 Change port 2023-10-21 13:42:44 +00:00
12 changed files with 237 additions and 44 deletions
+7 -4
View File
@@ -60,6 +60,9 @@ input_boolean:
fake_heater_switch1: fake_heater_switch1:
name: Heater 1 name: Heater 1
icon: mdi:radiator icon: mdi:radiator
fake_heater_ac1:
name: Air contionner 1
icon: mdi:air-conditioner
fake_heater_4switch1: fake_heater_4switch1:
name: Heater (multiswitch1) name: Heater (multiswitch1)
icon: mdi:radiator icon: mdi:radiator
@@ -114,22 +117,22 @@ climate:
name: Underlying thermostat 4-1 name: Underlying thermostat 4-1
heater: input_boolean.fake_heater_4climate1 heater: input_boolean.fake_heater_4climate1
target_sensor: input_number.fake_temperature_sensor1 target_sensor: input_number.fake_temperature_sensor1
ac_mode: true ac_mode: false
- platform: generic_thermostat - platform: generic_thermostat
name: Underlying thermostat 4-2 name: Underlying thermostat 4-2
heater: input_boolean.fake_heater_4climate2 heater: input_boolean.fake_heater_4climate2
target_sensor: input_number.fake_temperature_sensor1 target_sensor: input_number.fake_temperature_sensor1
ac_mode: true ac_mode: false
- platform: generic_thermostat - platform: generic_thermostat
name: Underlying thermostat 4-3 name: Underlying thermostat 4-3
heater: input_boolean.fake_heater_4climate3 heater: input_boolean.fake_heater_4climate3
target_sensor: input_number.fake_temperature_sensor1 target_sensor: input_number.fake_temperature_sensor1
ac_mode: true ac_mode: false
- platform: generic_thermostat - platform: generic_thermostat
name: Underlying thermostat 4-4 name: Underlying thermostat 4-4
heater: input_boolean.fake_heater_4climate4 heater: input_boolean.fake_heater_4climate4
target_sensor: input_number.fake_temperature_sensor1 target_sensor: input_number.fake_temperature_sensor1
ac_mode: true ac_mode: false
- platform: generic_thermostat - platform: generic_thermostat
name: Underlying thermostat9 name: Underlying thermostat9
heater: input_boolean.fake_heater_switch3 heater: input_boolean.fake_heater_switch3
+1 -1
View File
@@ -4,7 +4,7 @@
"image": "mcr.microsoft.com/devcontainers/python:1-3.11-bullseye", "image": "mcr.microsoft.com/devcontainers/python:1-3.11-bullseye",
"name": "Versatile Thermostat integration", "name": "Versatile Thermostat integration",
"appPort": [ "appPort": [
"9123:8123" "8123:8123"
], ],
// "postCreateCommand": "container install", // "postCreateCommand": "container install",
"postCreateCommand": "./container dev-setup", "postCreateCommand": "./container dev-setup",
+1 -1
View File
@@ -14,7 +14,7 @@
"python.testing.pytestEnabled": true, "python.testing.pytestEnabled": true,
"python.analysis.extraPaths": [ "python.analysis.extraPaths": [
// "/home/vscode/core", // "/home/vscode/core",
"/workspaces/custom_components/versatile_thermostat" "/workspaces/versatile_thermostat/custom_components/versatile_thermostat"
], ],
"python.formatting.provider": "none" "python.formatting.provider": "none"
} }
+2 -2
View File
@@ -2,13 +2,13 @@
"version": "2.0.0", "version": "2.0.0",
"tasks": [ "tasks": [
{ {
"label": "Run Home Assistant on port 9123", "label": "Run Home Assistant on port 8123",
"type": "shell", "type": "shell",
"command": "./container start", "command": "./container start",
"problemMatcher": [] "problemMatcher": []
}, },
{ {
"label": "Restart Home Assistant on port 9123", "label": "Restart Home Assistant on port 8123",
"type": "shell", "type": "shell",
"command": "./container restart", "command": "./container restart",
"problemMatcher": [] "problemMatcher": []
@@ -428,7 +428,7 @@ class VersatileThermostat(ClimateEntity, RestoreEntity):
self._presence_on = self._presence_sensor_entity_id is not None self._presence_on = self._presence_sensor_entity_id is not None
if self._ac_mode: if self._ac_mode:
self._hvac_list = [HVACMode.HEAT, HVACMode.COOL, HVACMode.OFF] self._hvac_list = [HVACMode.COOL, HVACMode.OFF]
else: else:
self._hvac_list = [HVACMode.HEAT, HVACMode.OFF] self._hvac_list = [HVACMode.HEAT, HVACMode.OFF]
@@ -919,6 +919,11 @@ class VersatileThermostat(ClimateEntity, RestoreEntity):
return self._hvac_list return self._hvac_list
@property
def ac_mode(self) -> bool:
""" Get the ac_mode of the Themostat"""
return self._ac_mode
@property @property
def fan_mode(self) -> str | None: def fan_mode(self) -> str | None:
"""Return the fan setting. """Return the fan setting.
@@ -1345,8 +1350,8 @@ class VersatileThermostat(ClimateEntity, RestoreEntity):
if preset_mode == PRESET_POWER: if preset_mode == PRESET_POWER:
return self._power_temp return self._power_temp
else: else:
# Select _ac presets if in COOL Mode # Select _ac presets if in COOL Mode (or over_switch with _ac_mode)
if self._ac_mode and self._hvac_mode == HVACMode.COOL: if self._ac_mode and (self._hvac_mode == HVACMode.COOL or not self._is_over_climate):
preset_mode = preset_mode + PRESET_AC_SUFFIX preset_mode = preset_mode + PRESET_AC_SUFFIX
if self._presence_on is False or self._presence_state in [ if self._presence_on is False or self._presence_state in [
@@ -1974,25 +1979,25 @@ class VersatileThermostat(ClimateEntity, RestoreEntity):
if self._attr_preset_mode not in [PRESET_BOOST, PRESET_COMFORT, PRESET_ECO]: if self._attr_preset_mode not in [PRESET_BOOST, PRESET_COMFORT, PRESET_ECO]:
return return
# Change temperature with preset named _way # Change temperature with preset named _away
new_temp = None # new_temp = None
if new_state == STATE_ON or new_state == STATE_HOME: #if new_state == STATE_ON or new_state == STATE_HOME:
new_temp = self._presets[self._attr_preset_mode] # new_temp = self._presets[self._attr_preset_mode]
_LOGGER.info( # _LOGGER.info(
"%s - Someone is back home. Restoring temperature to %.2f", # "%s - Someone is back home. Restoring temperature to %.2f",
self, # self,
new_temp, # new_temp,
) # )
else: #else:
new_temp = self._presets_away[ # new_temp = self._presets_away[
self.get_preset_away_name(self._attr_preset_mode) # self.get_preset_away_name(self._attr_preset_mode)
] # ]
_LOGGER.info( # _LOGGER.info(
"%s - No one is at home. Apply temperature %.2f", # "%s - No one is at home. Apply temperature %.2f",
self, # self,
new_temp, # new_temp,
) # )
new_temp = self.find_preset_temp(self.preset_mode)
if new_temp is not None: if new_temp is not None:
_LOGGER.debug( _LOGGER.debug(
"%s - presence change in temperature mode new_temp will be: %.2f", "%s - presence change in temperature mode new_temp will be: %.2f",
@@ -2503,6 +2508,7 @@ class VersatileThermostat(ClimateEntity, RestoreEntity):
"target_temp": self.target_temperature, "target_temp": self.target_temperature,
"current_temp": self._cur_temp, "current_temp": self._cur_temp,
"ext_current_temperature": self._cur_ext_temp, "ext_current_temperature": self._cur_ext_temp,
"ac_mode": self._ac_mode,
"current_power": self._current_power, "current_power": self._current_power,
"current_power_max": self._current_power_max, "current_power_max": self._current_power_max,
"saved_preset_mode": self._saved_preset_mode, "saved_preset_mode": self._saved_preset_mode,
@@ -245,6 +245,7 @@ class VersatileThermostatBaseConfigFlow(FlowHandler):
vol.Optional(CONF_CLIMATE_4): selector.EntitySelector( vol.Optional(CONF_CLIMATE_4): selector.EntitySelector(
selector.EntitySelectorConfig(domain=CLIMATE_DOMAIN), selector.EntitySelectorConfig(domain=CLIMATE_DOMAIN),
), ),
vol.Optional(CONF_AC_MODE, default=False): cv.boolean,
} }
) )
@@ -1,12 +1,12 @@
""" Underlying entities classes """ """ Underlying entities classes """
import logging import logging
from typing import Any from typing import Any
from enum import StrEnum
from homeassistant.const import ATTR_ENTITY_ID, STATE_ON, UnitOfTemperature from homeassistant.const import ATTR_ENTITY_ID, STATE_ON, UnitOfTemperature
from homeassistant.exceptions import ServiceNotFound from homeassistant.exceptions import ServiceNotFound
from enum import StrEnum
from homeassistant.core import HomeAssistant, DOMAIN as HA_DOMAIN, CALLBACK_TYPE from homeassistant.core import HomeAssistant, DOMAIN as HA_DOMAIN, CALLBACK_TYPE
from homeassistant.components.climate import ( from homeassistant.components.climate import (
ClimateEntity, ClimateEntity,
+6 -5
View File
@@ -11,11 +11,12 @@ if [[ ! -d "${PWD}/config" ]]; then
mkdir -p "${PWD}/config" mkdir -p "${PWD}/config"
# Add defaults configuration # Add defaults configuration
hass --config "${PWD}/config" --script ensure_config hass --config "${PWD}/config" --script ensure_config
# Overwrite configuration.yaml if provided fi
if [ -f ${PWD}/.devcontainer/configuration.yaml ]; then
rm -f ${PWD}/config/configuration.yaml # Overwrite configuration.yaml if provided
ln -s ${PWD}/.devcontainer/configuration.yaml ${PWD}/config/configuration.yaml if [ -f ${PWD}/.devcontainer/configuration.yaml ]; then
fi rm -f ${PWD}/config/configuration.yaml
ln -s ${PWD}/.devcontainer/configuration.yaml ${PWD}/config/configuration.yaml
fi fi
# Set the path to custom_components # Set the path to custom_components
+22 -5
View File
@@ -5,7 +5,7 @@ from unittest.mock import patch, MagicMock
import pytest # pylint: disable=unused-import import pytest # pylint: disable=unused-import
from homeassistant.core import HomeAssistant, Event, EVENT_STATE_CHANGED, State from homeassistant.core import HomeAssistant, Event, EVENT_STATE_CHANGED, State
from homeassistant.const import UnitOfTemperature, STATE_ON, STATE_OFF from homeassistant.const import UnitOfTemperature, STATE_ON, STATE_OFF, ATTR_TEMPERATURE
from homeassistant.config_entries import ConfigEntryState from homeassistant.config_entries import ConfigEntryState
from homeassistant.util import dt as dt_util from homeassistant.util import dt as dt_util
@@ -29,14 +29,17 @@ from .const import ( # pylint: disable=unused-import
MOCK_TH_OVER_4SWITCH_USER_CONFIG, MOCK_TH_OVER_4SWITCH_USER_CONFIG,
MOCK_TH_OVER_CLIMATE_USER_CONFIG, MOCK_TH_OVER_CLIMATE_USER_CONFIG,
MOCK_TH_OVER_SWITCH_TYPE_CONFIG, MOCK_TH_OVER_SWITCH_TYPE_CONFIG,
MOCK_TH_OVER_SWITCH_AC_TYPE_CONFIG,
MOCK_TH_OVER_4SWITCH_TYPE_CONFIG, MOCK_TH_OVER_4SWITCH_TYPE_CONFIG,
MOCK_TH_OVER_CLIMATE_TYPE_CONFIG, MOCK_TH_OVER_CLIMATE_TYPE_CONFIG,
MOCK_TH_OVER_SWITCH_TPI_CONFIG, MOCK_TH_OVER_SWITCH_TPI_CONFIG,
MOCK_PRESETS_CONFIG, MOCK_PRESETS_CONFIG,
MOCK_PRESETS_AC_CONFIG,
MOCK_WINDOW_CONFIG, MOCK_WINDOW_CONFIG,
MOCK_MOTION_CONFIG, MOCK_MOTION_CONFIG,
MOCK_POWER_CONFIG, MOCK_POWER_CONFIG,
MOCK_PRESENCE_CONFIG, MOCK_PRESENCE_CONFIG,
MOCK_PRESENCE_AC_CONFIG,
MOCK_ADVANCED_CONFIG, MOCK_ADVANCED_CONFIG,
# MOCK_DEFAULT_FEATURE_CONFIG, # MOCK_DEFAULT_FEATURE_CONFIG,
PRESET_BOOST, PRESET_BOOST,
@@ -58,6 +61,19 @@ FULL_SWITCH_CONFIG = (
| MOCK_ADVANCED_CONFIG | MOCK_ADVANCED_CONFIG
) )
FULL_SWITCH_AC_CONFIG = (
MOCK_TH_OVER_SWITCH_USER_CONFIG
| MOCK_TH_OVER_SWITCH_AC_TYPE_CONFIG
| MOCK_TH_OVER_SWITCH_TPI_CONFIG
| MOCK_PRESETS_AC_CONFIG
| MOCK_WINDOW_CONFIG
| MOCK_MOTION_CONFIG
| MOCK_POWER_CONFIG
| MOCK_PRESENCE_AC_CONFIG
| MOCK_ADVANCED_CONFIG
)
PARTIAL_CLIMATE_CONFIG = ( PARTIAL_CLIMATE_CONFIG = (
MOCK_TH_OVER_CLIMATE_USER_CONFIG MOCK_TH_OVER_CLIMATE_USER_CONFIG
| MOCK_TH_OVER_CLIMATE_TYPE_CONFIG | MOCK_TH_OVER_CLIMATE_TYPE_CONFIG
@@ -83,7 +99,7 @@ _LOGGER = logging.getLogger(__name__)
class MockClimate(ClimateEntity): class MockClimate(ClimateEntity):
"""A Mock Climate class used for Underlying climate mode""" """A Mock Climate class used for Underlying climate mode"""
def __init__(self, hass: HomeAssistant, unique_id, name, entry_infos, hvac_mode:HVACMode = HVACMode.OFF) -> None: def __init__(self, hass: HomeAssistant, unique_id, name, entry_infos, hvac_mode:HVACMode = HVACMode.OFF) -> None: # pylint: disable=unused-argument
"""Initialize the thermostat.""" """Initialize the thermostat."""
super().__init__() super().__init__()
@@ -101,12 +117,13 @@ class MockClimate(ClimateEntity):
self._attr_target_temperature = 20 self._attr_target_temperature = 20
self._attr_current_temperature = 15 self._attr_current_temperature = 15
def set_temperature(self, temperature): def set_temperature(self, **kwargs):
""" Set the target temperature""" """ Set the target temperature"""
temperature = kwargs.get(ATTR_TEMPERATURE)
self._attr_target_temperature = temperature self._attr_target_temperature = temperature
self.async_write_ha_state() self.async_write_ha_state()
def async_set_hvac_mode(self, hvac_mode): async def async_set_hvac_mode(self, hvac_mode):
""" The hvac mode""" """ The hvac mode"""
self._attr_hvac_mode = hvac_mode self._attr_hvac_mode = hvac_mode
self.async_write_ha_state() self.async_write_ha_state()
@@ -114,7 +131,7 @@ class MockClimate(ClimateEntity):
class MockUnavailableClimate(ClimateEntity): class MockUnavailableClimate(ClimateEntity):
"""A Mock Climate class used for Underlying climate mode""" """A Mock Climate class used for Underlying climate mode"""
def __init__(self, hass: HomeAssistant, unique_id, name, entry_infos) -> None: def __init__(self, hass: HomeAssistant, unique_id, name, entry_infos) -> None: # pylint: disable=unused-argument
"""Initialize the thermostat.""" """Initialize the thermostat."""
super().__init__() super().__init__()
+26 -1
View File
@@ -51,7 +51,6 @@ from custom_components.versatile_thermostat.const import (
PRESET_AWAY_SUFFIX, PRESET_AWAY_SUFFIX,
CONF_CLIMATE, CONF_CLIMATE,
) )
MOCK_TH_OVER_SWITCH_USER_CONFIG = { MOCK_TH_OVER_SWITCH_USER_CONFIG = {
CONF_NAME: "TheOverSwitchMockName", CONF_NAME: "TheOverSwitchMockName",
CONF_THERMOSTAT_TYPE: CONF_THERMOSTAT_SWITCH, CONF_THERMOSTAT_TYPE: CONF_THERMOSTAT_SWITCH,
@@ -100,6 +99,12 @@ MOCK_TH_OVER_SWITCH_TYPE_CONFIG = {
CONF_AC_MODE: False, CONF_AC_MODE: False,
} }
MOCK_TH_OVER_SWITCH_AC_TYPE_CONFIG = {
CONF_HEATER: "switch.mock_air_conditioner",
CONF_PROP_FUNCTION: PROPORTIONAL_FUNCTION_TPI,
CONF_AC_MODE: True,
}
MOCK_TH_OVER_4SWITCH_TYPE_CONFIG = { MOCK_TH_OVER_4SWITCH_TYPE_CONFIG = {
CONF_HEATER: "switch.mock_4switch0", CONF_HEATER: "switch.mock_4switch0",
CONF_HEATER_2: "switch.mock_4switch1", CONF_HEATER_2: "switch.mock_4switch1",
@@ -116,6 +121,7 @@ MOCK_TH_OVER_SWITCH_TPI_CONFIG = {
MOCK_TH_OVER_CLIMATE_TYPE_CONFIG = { MOCK_TH_OVER_CLIMATE_TYPE_CONFIG = {
CONF_CLIMATE: "climate.mock_climate", CONF_CLIMATE: "climate.mock_climate",
CONF_AC_MODE: False,
} }
MOCK_PRESETS_CONFIG = { MOCK_PRESETS_CONFIG = {
@@ -124,6 +130,15 @@ MOCK_PRESETS_CONFIG = {
PRESET_BOOST + "_temp": 18, PRESET_BOOST + "_temp": 18,
} }
MOCK_PRESETS_AC_CONFIG = {
PRESET_ECO + "_temp": 17,
PRESET_COMFORT + "_temp": 19,
PRESET_BOOST + "_temp": 20,
PRESET_ECO + "_ac_temp": 25,
PRESET_COMFORT + "_ac_temp": 23,
PRESET_BOOST + "_ac_temp": 21,
}
MOCK_WINDOW_CONFIG = { MOCK_WINDOW_CONFIG = {
CONF_WINDOW_SENSOR: "binary_sensor.window_sensor", CONF_WINDOW_SENSOR: "binary_sensor.window_sensor",
CONF_WINDOW_DELAY: 10, CONF_WINDOW_DELAY: 10,
@@ -156,6 +171,16 @@ MOCK_PRESENCE_CONFIG = {
PRESET_BOOST + PRESET_AWAY_SUFFIX + "_temp": 18, PRESET_BOOST + PRESET_AWAY_SUFFIX + "_temp": 18,
} }
MOCK_PRESENCE_AC_CONFIG = {
CONF_PRESENCE_SENSOR: "person.presence_sensor",
PRESET_ECO + PRESET_AWAY_SUFFIX + "_temp": 16,
PRESET_COMFORT + PRESET_AWAY_SUFFIX + "_temp": 17,
PRESET_BOOST + PRESET_AWAY_SUFFIX + "_temp": 18,
PRESET_ECO + "_ac" + PRESET_AWAY_SUFFIX + "_temp": 27,
PRESET_COMFORT + "_ac" + PRESET_AWAY_SUFFIX + "_temp": 26,
PRESET_BOOST + "_ac" + PRESET_AWAY_SUFFIX + "_temp": 25,
}
MOCK_ADVANCED_CONFIG = { MOCK_ADVANCED_CONFIG = {
CONF_MINIMAL_ACTIVATION_DELAY: 10, CONF_MINIMAL_ACTIVATION_DELAY: 10,
CONF_SECURITY_DELAY_MIN: 5, CONF_SECURITY_DELAY_MIN: 5,
+2 -2
View File
@@ -1,10 +1,10 @@
""" Test the Window management """ """ Test the Window management """
import asyncio import asyncio
from datetime import datetime, timedelta
import logging
from unittest.mock import patch, call, PropertyMock from unittest.mock import patch, call, PropertyMock
from .commons import * # pylint: disable=wildcard-import, unused-wildcard-import from .commons import * # pylint: disable=wildcard-import, unused-wildcard-import
from datetime import datetime, timedelta
import logging
logging.getLogger().setLevel(logging.DEBUG) logging.getLogger().setLevel(logging.DEBUG)
+140
View File
@@ -0,0 +1,140 @@
""" Test the normal start of a Switch AC Thermostat """
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.climate import VersatileThermostat
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_over_switch_ac_full_start(hass: HomeAssistant, skip_hass_states_is_state): # pylint: disable=unused-argument
"""Test the normal full start of a thermostat in thermostat_over_switch type"""
entry = MockConfigEntry(
domain=DOMAIN,
title="TheOverSwitchACMockName",
unique_id="uniqueId",
data=FULL_SWITCH_AC_CONFIG,
)
tz = get_tz(hass) # pylint: disable=invalid-name
now: datetime = datetime.now(tz=tz)
with patch(
"custom_components.versatile_thermostat.climate.VersatileThermostat.send_event"
) as mock_send_event:
entry.add_to_hass(hass)
await hass.config_entries.async_setup(entry.entry_id)
assert entry.state is ConfigEntryState.LOADED
def find_my_entity(entity_id) -> ClimateEntity:
"""Find my new entity"""
component: EntityComponent[ClimateEntity] = hass.data[CLIMATE_DOMAIN]
for entity in component.entities:
if entity.entity_id == entity_id:
return entity
# The name is in the CONF and not the title of the entry
entity: VersatileThermostat = find_my_entity("climate.theoverswitchmockname")
assert entity
assert entity.name == "TheOverSwitchMockName"
assert entity._is_over_climate is False # pylint: disable=protected-access
assert entity.ac_mode is True
assert entity.hvac_action is HVACAction.OFF
assert entity.hvac_mode is HVACMode.OFF
assert entity.hvac_modes == [HVACMode.COOL, HVACMode.OFF]
assert entity.target_temperature == entity.max_temp
assert entity.preset_modes == [
PRESET_NONE,
PRESET_ECO,
PRESET_COMFORT,
PRESET_BOOST,
PRESET_ACTIVITY,
]
assert entity.preset_mode is PRESET_NONE
assert entity._security_state is False # pylint: disable=protected-access
assert entity._window_state is None # pylint: disable=protected-access
assert entity._motion_state is None # pylint: disable=protected-access
assert entity._presence_state is None # pylint: disable=protected-access
assert entity._prop_algorithm is not None # pylint: disable=protected-access
# should have been called with EventType.PRESET_EVENT and EventType.HVAC_MODE_EVENT
assert mock_send_event.call_count == 2
mock_send_event.assert_has_calls(
[
call.send_event(EventType.PRESET_EVENT, {"preset": PRESET_NONE}),
call.send_event(
EventType.HVAC_MODE_EVENT,
{"hvac_mode": HVACMode.OFF},
),
]
)
# Select a hvacmode, presence and preset
await entity.async_set_hvac_mode(HVACMode.COOL)
assert entity.hvac_mode is HVACMode.COOL
event_timestamp = now - timedelta(minutes=4)
await send_presence_change_event(entity, True, False, event_timestamp)
assert entity._presence_state == STATE_ON # pylint: disable=protected-access
await entity.async_set_hvac_mode(HVACMode.COOL)
assert entity.hvac_mode is HVACMode.COOL
await entity.async_set_preset_mode(PRESET_COMFORT)
assert entity.preset_mode is PRESET_COMFORT
assert entity.target_temperature == 23
# switch to Eco
await entity.async_set_preset_mode(PRESET_ECO)
assert entity.preset_mode is PRESET_ECO
assert entity.target_temperature == 25
# Unset the presence
event_timestamp = now - timedelta(minutes=3)
await send_presence_change_event(entity, False, True, event_timestamp)
assert entity._presence_state == STATE_OFF # pylint: disable=protected-access
assert entity.target_temperature == 27 # eco_ac_away
# Open a window
with patch(
"homeassistant.helpers.condition.state", return_value=True
):
event_timestamp = now - timedelta(minutes=2)
try_condition = await send_window_change_event(entity, True, False, event_timestamp)
# Confirme the window event
await try_condition(None)
assert entity.hvac_mode is HVACMode.OFF
assert entity.hvac_action is HVACAction.OFF
assert entity.target_temperature == 27 # eco_ac_away
# Close a window
with patch(
"homeassistant.helpers.condition.state", return_value=True
):
event_timestamp = now - timedelta(minutes=2)
try_condition = await send_window_change_event(entity, False, True, event_timestamp)
# Confirme the window event
await try_condition(None)
assert entity.hvac_mode is HVACMode.COOL
assert (entity.hvac_action is HVACAction.OFF or entity.hvac_action is HVACAction.IDLE)
assert entity.target_temperature == 27 # eco_ac_away