Add testus and change date timestamp.
This commit is contained in:
@@ -8,6 +8,7 @@ from datetime import timedelta, datetime
|
||||
|
||||
import voluptuous as vol
|
||||
|
||||
from homeassistant.util import dt as dt_util
|
||||
from homeassistant.core import (
|
||||
HomeAssistant,
|
||||
callback,
|
||||
@@ -261,6 +262,8 @@ class VersatileThermostat(ClimateEntity, RestoreEntity):
|
||||
|
||||
self._total_energy = None
|
||||
|
||||
self._current_tz = dt_util.get_time_zone(self._hass.config.time_zone)
|
||||
|
||||
self.post_init(entry_infos)
|
||||
|
||||
def post_init(self, entry_infos):
|
||||
@@ -1014,6 +1017,16 @@ class VersatileThermostat(ClimateEntity, RestoreEntity):
|
||||
"""Get the overpowering_state"""
|
||||
return self._overpowering_state
|
||||
|
||||
@property
|
||||
def window_state(self) -> bool | None:
|
||||
"""Get the window_state"""
|
||||
return self._window_state
|
||||
|
||||
@property
|
||||
def motion_state(self) -> bool | None:
|
||||
"""Get the motion_state"""
|
||||
return self._motion_state
|
||||
|
||||
def turn_aux_heat_on(self) -> None:
|
||||
"""Turn auxiliary heater on."""
|
||||
if self._is_over_climate and self._underlying_climate:
|
||||
@@ -1321,6 +1334,7 @@ class VersatileThermostat(ClimateEntity, RestoreEntity):
|
||||
_LOGGER.debug(
|
||||
"Window delay condition is not satisfied. Ignore window event"
|
||||
)
|
||||
self._window_state = old_state.state
|
||||
return
|
||||
|
||||
_LOGGER.debug("%s - Window delay condition is satisfied", self)
|
||||
@@ -1349,6 +1363,8 @@ class VersatileThermostat(ClimateEntity, RestoreEntity):
|
||||
self._window_call_cancel = async_call_later(
|
||||
self.hass, timedelta(seconds=self._window_delay_sec), try_window_condition
|
||||
)
|
||||
# For testing purpose we need to access the inner function
|
||||
return try_window_condition
|
||||
|
||||
@callback
|
||||
async def _async_motion_changed(self, event):
|
||||
@@ -1704,7 +1720,9 @@ class VersatileThermostat(ClimateEntity, RestoreEntity):
|
||||
"""
|
||||
|
||||
if not self._pmax_on:
|
||||
_LOGGER.debug("%s - power not configured. check_overpowering not available")
|
||||
_LOGGER.debug(
|
||||
"%s - power not configured. check_overpowering not available", self
|
||||
)
|
||||
return False
|
||||
|
||||
if (
|
||||
@@ -1712,7 +1730,9 @@ class VersatileThermostat(ClimateEntity, RestoreEntity):
|
||||
or self._device_power is None
|
||||
or self._current_power_max is None
|
||||
):
|
||||
_LOGGER.warning("%s - power not valued. check_overpowering not available")
|
||||
_LOGGER.warning(
|
||||
"%s - power not valued. check_overpowering not available", self
|
||||
)
|
||||
return False
|
||||
|
||||
_LOGGER.debug(
|
||||
@@ -1773,12 +1793,12 @@ class VersatileThermostat(ClimateEntity, RestoreEntity):
|
||||
|
||||
async def check_security(self) -> bool:
|
||||
"""Check if last temperature date is too long"""
|
||||
now = datetime.now()
|
||||
now = datetime.now(self._current_tz)
|
||||
delta_temp = (
|
||||
now - self._last_temperature_mesure.replace(tzinfo=None)
|
||||
now - self._last_temperature_mesure.replace(tzinfo=self._current_tz)
|
||||
).total_seconds() / 60.0
|
||||
delta_ext_temp = (
|
||||
now - self._last_ext_temperature_mesure.replace(tzinfo=None)
|
||||
now - self._last_ext_temperature_mesure.replace(tzinfo=self._current_tz)
|
||||
).total_seconds() / 60.0
|
||||
|
||||
mode_cond = self._is_over_climate or self._hvac_mode != HVACMode.OFF
|
||||
@@ -1839,8 +1859,12 @@ class VersatileThermostat(ClimateEntity, RestoreEntity):
|
||||
self.send_event(
|
||||
EventType.TEMPERATURE_EVENT,
|
||||
{
|
||||
"last_temperature_mesure": self._last_temperature_mesure.isoformat(),
|
||||
"last_ext_temperature_mesure": self._last_ext_temperature_mesure.isoformat(),
|
||||
"last_temperature_mesure": self._last_temperature_mesure.replace(
|
||||
tzinfo=self._current_tz
|
||||
).isoformat(),
|
||||
"last_ext_temperature_mesure": self._last_ext_temperature_mesure.replace(
|
||||
tzinfo=self._current_tz
|
||||
).isoformat(),
|
||||
"current_temp": self._cur_temp,
|
||||
"current_ext_temp": self._cur_ext_temp,
|
||||
"target_temp": self.target_temperature,
|
||||
@@ -1862,8 +1886,12 @@ class VersatileThermostat(ClimateEntity, RestoreEntity):
|
||||
EventType.SECURITY_EVENT,
|
||||
{
|
||||
"type": "start",
|
||||
"last_temperature_mesure": self._last_temperature_mesure.isoformat(),
|
||||
"last_ext_temperature_mesure": self._last_ext_temperature_mesure.isoformat(),
|
||||
"last_temperature_mesure": self._last_temperature_mesure.replace(
|
||||
tzinfo=self._current_tz
|
||||
).isoformat(),
|
||||
"last_ext_temperature_mesure": self._last_ext_temperature_mesure.replace(
|
||||
tzinfo=self._current_tz
|
||||
).isoformat(),
|
||||
"current_temp": self._cur_temp,
|
||||
"current_ext_temp": self._cur_ext_temp,
|
||||
"target_temp": self.target_temperature,
|
||||
@@ -1892,8 +1920,12 @@ class VersatileThermostat(ClimateEntity, RestoreEntity):
|
||||
EventType.SECURITY_EVENT,
|
||||
{
|
||||
"type": "end",
|
||||
"last_temperature_mesure": self._last_temperature_mesure.isoformat(),
|
||||
"last_ext_temperature_mesure": self._last_ext_temperature_mesure.isoformat(),
|
||||
"last_temperature_mesure": self._last_temperature_mesure.replace(
|
||||
tzinfo=self._current_tz
|
||||
).isoformat(),
|
||||
"last_ext_temperature_mesure": self._last_ext_temperature_mesure.replace(
|
||||
tzinfo=self._current_tz
|
||||
).isoformat(),
|
||||
"current_temp": self._cur_temp,
|
||||
"current_ext_temp": self._cur_ext_temp,
|
||||
"target_temp": self.target_temperature,
|
||||
@@ -2101,14 +2133,21 @@ class VersatileThermostat(ClimateEntity, RestoreEntity):
|
||||
"security_delay_min": self._security_delay_min,
|
||||
"security_min_on_percent": self._security_min_on_percent,
|
||||
"security_default_on_percent": self._security_default_on_percent,
|
||||
"last_temperature_datetime": self._last_temperature_mesure.isoformat(),
|
||||
"last_ext_temperature_datetime": self._last_ext_temperature_mesure.isoformat(),
|
||||
"last_temperature_datetime": self._last_temperature_mesure.replace(
|
||||
tzinfo=self._current_tz
|
||||
).isoformat(),
|
||||
"last_ext_temperature_datetime": self._last_ext_temperature_mesure.replace(
|
||||
tzinfo=self._current_tz
|
||||
).isoformat(),
|
||||
"security_state": self._security_state,
|
||||
"minimal_activation_delay_sec": self._minimal_activation_delay,
|
||||
"device_power": self._device_power,
|
||||
ATTR_MEAN_POWER_CYCLE: self.mean_cycle_power,
|
||||
ATTR_TOTAL_ENERGY: self.total_energy,
|
||||
"last_update_datetime": datetime.now().isoformat(),
|
||||
"last_update_datetime": datetime.now()
|
||||
.replace(tzinfo=self._current_tz)
|
||||
.isoformat(),
|
||||
"timezone": str(self._current_tz),
|
||||
}
|
||||
if self._is_over_climate:
|
||||
self._attr_extra_state_attributes[
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
""" The TPI calculation module """
|
||||
import logging
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
@@ -21,7 +22,7 @@ class PropAlgorithm:
|
||||
tpi_coef_ext,
|
||||
cycle_min: int,
|
||||
minimal_activation_delay: int,
|
||||
):
|
||||
) -> None:
|
||||
"""Initialisation of the Proportional Algorithm"""
|
||||
_LOGGER.debug(
|
||||
"Creation new PropAlgorithm function_type: %s, tpi_coef_int: %s, tpi_coef_ext: %s, cycle_min:%d, minimal_activation_delay:%d",
|
||||
|
||||
@@ -2,11 +2,12 @@
|
||||
from unittest.mock import patch
|
||||
|
||||
from homeassistant.core import HomeAssistant, Event, EVENT_STATE_CHANGED, State
|
||||
from homeassistant.const import UnitOfTemperature
|
||||
from homeassistant.const import UnitOfTemperature, STATE_ON, STATE_OFF
|
||||
|
||||
from homeassistant.config_entries import ConfigEntryState
|
||||
from pytest_homeassistant_custom_component.common import MockConfigEntry
|
||||
from homeassistant.util import dt as dt_util
|
||||
from homeassistant.helpers.entity_component import EntityComponent
|
||||
from pytest_homeassistant_custom_component.common import MockConfigEntry
|
||||
|
||||
from ..climate import VersatileThermostat
|
||||
from ..const import *
|
||||
@@ -113,7 +114,7 @@ async def send_temperature_change_event(entity: VersatileThermostat, new_temp, d
|
||||
)
|
||||
},
|
||||
)
|
||||
await entity._async_temperature_changed(temp_event)
|
||||
return await entity._async_temperature_changed(temp_event)
|
||||
|
||||
|
||||
async def send_power_change_event(entity: VersatileThermostat, new_power, date):
|
||||
@@ -129,11 +130,11 @@ async def send_power_change_event(entity: VersatileThermostat, new_power, date):
|
||||
)
|
||||
},
|
||||
)
|
||||
await entity._async_power_changed(power_event)
|
||||
return await entity._async_power_changed(power_event)
|
||||
|
||||
|
||||
async def send_max_power_change_event(entity: VersatileThermostat, new_power_max, date):
|
||||
"""Sending a new power event simulating a change on power max sensor"""
|
||||
"""Sending a new power max event simulating a change on power max sensor"""
|
||||
power_event = Event(
|
||||
EVENT_STATE_CHANGED,
|
||||
{
|
||||
@@ -145,4 +146,33 @@ async def send_max_power_change_event(entity: VersatileThermostat, new_power_max
|
||||
)
|
||||
},
|
||||
)
|
||||
await entity._async_max_power_changed(power_event)
|
||||
return await entity._async_max_power_changed(power_event)
|
||||
|
||||
|
||||
async def send_window_change_event(entity: VersatileThermostat, new_state: bool, date):
|
||||
"""Sending a new window event simulating a change on the window state"""
|
||||
window_event = Event(
|
||||
EVENT_STATE_CHANGED,
|
||||
{
|
||||
"new_state": State(
|
||||
entity_id=entity.entity_id,
|
||||
state=STATE_ON if new_state else STATE_OFF,
|
||||
last_changed=date,
|
||||
last_updated=date,
|
||||
),
|
||||
"old_state": State(
|
||||
entity_id=entity.entity_id,
|
||||
state=STATE_ON if not new_state else STATE_OFF,
|
||||
last_changed=date,
|
||||
last_updated=date,
|
||||
),
|
||||
},
|
||||
)
|
||||
ret = await entity._async_windows_changed(window_event)
|
||||
return ret
|
||||
|
||||
|
||||
def get_tz(hass):
|
||||
"""Get the current timezone"""
|
||||
|
||||
return dt_util.get_time_zone(hass.config.time_zone)
|
||||
|
||||
@@ -19,6 +19,8 @@ async def test_security_feature(hass: HomeAssistant, skip_hass_states_is_state):
|
||||
6. check that security is off and preset is changed to boost
|
||||
"""
|
||||
|
||||
tz = get_tz(hass)
|
||||
|
||||
entry = MockConfigEntry(
|
||||
domain=DOMAIN,
|
||||
title="TheOverSwitchMockName",
|
||||
@@ -102,8 +104,12 @@ async def test_security_feature(hass: HomeAssistant, skip_hass_states_is_state):
|
||||
call.send_event(
|
||||
EventType.TEMPERATURE_EVENT,
|
||||
{
|
||||
"last_temperature_mesure": event_timestamp.isoformat(),
|
||||
"last_ext_temperature_mesure": entity._last_ext_temperature_mesure.isoformat(),
|
||||
"last_temperature_mesure": event_timestamp.replace(
|
||||
tzinfo=tz
|
||||
).isoformat(),
|
||||
"last_ext_temperature_mesure": entity._last_ext_temperature_mesure.replace(
|
||||
tzinfo=tz
|
||||
).isoformat(),
|
||||
"current_temp": 15,
|
||||
"current_ext_temp": None,
|
||||
"target_temp": 18,
|
||||
@@ -113,8 +119,12 @@ async def test_security_feature(hass: HomeAssistant, skip_hass_states_is_state):
|
||||
EventType.SECURITY_EVENT,
|
||||
{
|
||||
"type": "start",
|
||||
"last_temperature_mesure": event_timestamp.isoformat(),
|
||||
"last_ext_temperature_mesure": entity._last_ext_temperature_mesure.isoformat(),
|
||||
"last_temperature_mesure": event_timestamp.replace(
|
||||
tzinfo=tz
|
||||
).isoformat(),
|
||||
"last_ext_temperature_mesure": entity._last_ext_temperature_mesure.replace(
|
||||
tzinfo=tz
|
||||
).isoformat(),
|
||||
"current_temp": 15,
|
||||
"current_ext_temp": None,
|
||||
"target_temp": 18,
|
||||
@@ -166,8 +176,12 @@ async def test_security_feature(hass: HomeAssistant, skip_hass_states_is_state):
|
||||
EventType.SECURITY_EVENT,
|
||||
{
|
||||
"type": "end",
|
||||
"last_temperature_mesure": event_timestamp.isoformat(),
|
||||
"last_ext_temperature_mesure": entity._last_ext_temperature_mesure.isoformat(),
|
||||
"last_temperature_mesure": event_timestamp.replace(
|
||||
tzinfo=tz
|
||||
).isoformat(),
|
||||
"last_ext_temperature_mesure": entity._last_ext_temperature_mesure.replace(
|
||||
tzinfo=tz
|
||||
).isoformat(),
|
||||
"current_temp": 15.2,
|
||||
"current_ext_temp": None,
|
||||
"target_temp": 19,
|
||||
|
||||
200
custom_components/versatile_thermostat/tests/test_window.py
Normal file
200
custom_components/versatile_thermostat/tests/test_window.py
Normal file
@@ -0,0 +1,200 @@
|
||||
""" Test the Window management """
|
||||
from unittest.mock import patch, call
|
||||
from .commons import * # pylint: disable=wildcard-import, unused-wildcard-import
|
||||
from datetime import datetime
|
||||
import time
|
||||
|
||||
import logging
|
||||
|
||||
logging.getLogger().setLevel(logging.DEBUG)
|
||||
|
||||
|
||||
async def test_window_management_time_not_enough(
|
||||
hass: HomeAssistant, skip_hass_states_is_state
|
||||
):
|
||||
"""Test the Power management"""
|
||||
|
||||
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,
|
||||
"eco_temp": 17,
|
||||
"comfort_temp": 18,
|
||||
"boost_temp": 19,
|
||||
CONF_USE_WINDOW_FEATURE: True,
|
||||
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_WINDOW_SENSOR: "binary_sensor.mock_window_sensor",
|
||||
CONF_WINDOW_DELAY: 0, # important to not been obliged to wait
|
||||
},
|
||||
)
|
||||
|
||||
entity: VersatileThermostat = await create_thermostat(
|
||||
hass, entry, "climate.theoverswitchmockname"
|
||||
)
|
||||
assert entity
|
||||
|
||||
tpi_algo = entity._prop_algorithm
|
||||
assert tpi_algo
|
||||
|
||||
await entity.async_set_hvac_mode(HVACMode.HEAT)
|
||||
await entity.async_set_preset_mode(PRESET_BOOST)
|
||||
assert entity.hvac_mode is HVACMode.HEAT
|
||||
assert entity.preset_mode is PRESET_BOOST
|
||||
assert entity.overpowering_state is None
|
||||
assert entity.target_temperature == 19
|
||||
|
||||
assert entity.window_state is None
|
||||
|
||||
# Open the window, but condition of time is not satisfied and check the thermostat don't turns off
|
||||
with patch(
|
||||
"custom_components.versatile_thermostat.climate.VersatileThermostat.send_event"
|
||||
) as mock_send_event, patch(
|
||||
"custom_components.versatile_thermostat.climate.VersatileThermostat._async_heater_turn_on"
|
||||
) as mock_heater_on, patch(
|
||||
"custom_components.versatile_thermostat.climate.VersatileThermostat._async_underlying_entity_turn_off"
|
||||
) as mock_heater_off, patch(
|
||||
"homeassistant.helpers.condition.state", return_value=False
|
||||
) as mock_condition:
|
||||
await send_temperature_change_event(entity, 15, datetime.now())
|
||||
try_window_condition = await send_window_change_event(
|
||||
entity, True, datetime.now()
|
||||
)
|
||||
# simulate the call to try_window_condition
|
||||
await try_window_condition(None)
|
||||
|
||||
assert mock_send_event.call_count == 0
|
||||
assert mock_heater_on.call_count == 1
|
||||
assert mock_heater_off.call_count == 0
|
||||
assert mock_condition.call_count == 1
|
||||
|
||||
assert entity.window_state == STATE_OFF
|
||||
|
||||
# Close the window
|
||||
try_window_condition = await send_window_change_event(
|
||||
entity, False, datetime.now()
|
||||
)
|
||||
# simulate the call to try_window_condition
|
||||
await try_window_condition(None)
|
||||
assert entity.window_state == STATE_OFF
|
||||
|
||||
|
||||
async def test_window_management_time_enough(
|
||||
hass: HomeAssistant, skip_hass_states_is_state
|
||||
):
|
||||
"""Test the Power management"""
|
||||
|
||||
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,
|
||||
"eco_temp": 17,
|
||||
"comfort_temp": 18,
|
||||
"boost_temp": 19,
|
||||
CONF_USE_WINDOW_FEATURE: True,
|
||||
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_WINDOW_SENSOR: "binary_sensor.mock_window_sensor",
|
||||
CONF_WINDOW_DELAY: 0, # important to not been obliged to wait
|
||||
},
|
||||
)
|
||||
|
||||
entity: VersatileThermostat = await create_thermostat(
|
||||
hass, entry, "climate.theoverswitchmockname"
|
||||
)
|
||||
assert entity
|
||||
|
||||
tpi_algo = entity._prop_algorithm
|
||||
assert tpi_algo
|
||||
|
||||
await entity.async_set_hvac_mode(HVACMode.HEAT)
|
||||
await entity.async_set_preset_mode(PRESET_BOOST)
|
||||
assert entity.hvac_mode is HVACMode.HEAT
|
||||
assert entity.preset_mode is PRESET_BOOST
|
||||
assert entity.overpowering_state is None
|
||||
assert entity.target_temperature == 19
|
||||
|
||||
assert entity.window_state is None
|
||||
|
||||
# Open the window, but condition of time is not satisfied and check the thermostat don't turns off
|
||||
with patch(
|
||||
"custom_components.versatile_thermostat.climate.VersatileThermostat.send_event"
|
||||
) as mock_send_event, patch(
|
||||
"custom_components.versatile_thermostat.climate.VersatileThermostat._async_heater_turn_on"
|
||||
) as mock_heater_on, patch(
|
||||
"custom_components.versatile_thermostat.climate.VersatileThermostat._async_underlying_entity_turn_off"
|
||||
) as mock_heater_off, patch(
|
||||
"homeassistant.helpers.condition.state", return_value=True
|
||||
) as mock_condition, patch(
|
||||
"custom_components.versatile_thermostat.climate.VersatileThermostat._is_device_active",
|
||||
return_value=True,
|
||||
):
|
||||
await send_temperature_change_event(entity, 15, datetime.now())
|
||||
try_window_condition = await send_window_change_event(
|
||||
entity, True, datetime.now()
|
||||
)
|
||||
# simulate the call to try_window_condition
|
||||
await try_window_condition(None)
|
||||
|
||||
assert mock_send_event.call_count == 1
|
||||
mock_send_event.assert_has_calls(
|
||||
[call.send_event(EventType.HVAC_MODE_EVENT, {"hvac_mode": HVACMode.OFF})]
|
||||
)
|
||||
assert mock_heater_on.call_count == 1
|
||||
# One call in turn_oiff and one call in the control_heating
|
||||
assert mock_heater_off.call_count == 2
|
||||
assert mock_condition.call_count == 1
|
||||
|
||||
assert entity.window_state == STATE_ON
|
||||
|
||||
# Close the window
|
||||
try_window_condition = await send_window_change_event(
|
||||
entity, False, datetime.now()
|
||||
)
|
||||
# simulate the call to try_window_condition
|
||||
await try_window_condition(None)
|
||||
assert entity.window_state == STATE_OFF
|
||||
assert mock_heater_on.call_count == 2
|
||||
assert mock_send_event.call_count == 2
|
||||
mock_send_event.assert_has_calls(
|
||||
[
|
||||
call.send_event(EventType.HVAC_MODE_EVENT, {"hvac_mode": HVACMode.OFF}),
|
||||
call.send_event(
|
||||
EventType.HVAC_MODE_EVENT, {"hvac_mode": HVACMode.HEAT}
|
||||
),
|
||||
],
|
||||
any_order=False,
|
||||
)
|
||||
assert entity.preset_mode is PRESET_BOOST
|
||||
Reference in New Issue
Block a user