mirror of
https://github.com/home-assistant/core.git
synced 2025-05-12 01:49:16 +00:00

* feat: raise execption on hvac mode while device is locked * fix: test for setting hvac mode while device is locked. * feat: update translation * feat: add separate translations for HVAC and temperature * fix: test cases * fix: test cases for test_set_preset_mode_boost * rev: code review * rev: exception string * feat: updated error message and added helper function * Update homeassistant/components/fritzbox/strings.json Co-authored-by: Michael <35783820+mib1185@users.noreply.github.com> * fix: translation key * remove check_active_or_lock_mode from async_set_preset_mode --------- Co-authored-by: Michael <35783820+mib1185@users.noreply.github.com>
691 lines
22 KiB
Python
691 lines
22 KiB
Python
"""Tests for AVM Fritz!Box climate component."""
|
|
|
|
from datetime import timedelta
|
|
from unittest.mock import Mock, _Call, call, patch
|
|
|
|
from freezegun.api import FrozenDateTimeFactory
|
|
import pytest
|
|
from requests.exceptions import HTTPError
|
|
from syrupy import SnapshotAssertion
|
|
|
|
from homeassistant.components.climate import (
|
|
ATTR_CURRENT_TEMPERATURE,
|
|
ATTR_HVAC_MODE,
|
|
ATTR_HVAC_MODES,
|
|
ATTR_MAX_TEMP,
|
|
ATTR_MIN_TEMP,
|
|
ATTR_PRESET_MODE,
|
|
ATTR_PRESET_MODES,
|
|
DOMAIN as CLIMATE_DOMAIN,
|
|
PRESET_BOOST,
|
|
PRESET_COMFORT,
|
|
PRESET_ECO,
|
|
SERVICE_SET_HVAC_MODE,
|
|
SERVICE_SET_PRESET_MODE,
|
|
SERVICE_SET_TEMPERATURE,
|
|
HVACMode,
|
|
)
|
|
from homeassistant.components.fritzbox.climate import (
|
|
OFF_API_TEMPERATURE,
|
|
ON_API_TEMPERATURE,
|
|
PRESET_HOLIDAY,
|
|
PRESET_SUMMER,
|
|
)
|
|
from homeassistant.components.fritzbox.const import (
|
|
ATTR_STATE_HOLIDAY_MODE,
|
|
ATTR_STATE_SUMMER_MODE,
|
|
DOMAIN as FB_DOMAIN,
|
|
)
|
|
from homeassistant.config_entries import ConfigEntryState
|
|
from homeassistant.const import ATTR_ENTITY_ID, ATTR_TEMPERATURE, CONF_DEVICES, Platform
|
|
from homeassistant.core import HomeAssistant
|
|
from homeassistant.exceptions import HomeAssistantError
|
|
from homeassistant.helpers import entity_registry as er
|
|
from homeassistant.util import dt as dt_util
|
|
|
|
from . import (
|
|
FritzDeviceClimateMock,
|
|
FritzDeviceClimateWithoutTempSensorMock,
|
|
set_devices,
|
|
setup_config_entry,
|
|
)
|
|
from .const import CONF_FAKE_NAME, MOCK_CONFIG
|
|
|
|
from tests.common import async_fire_time_changed, snapshot_platform
|
|
|
|
ENTITY_ID = f"{CLIMATE_DOMAIN}.{CONF_FAKE_NAME}"
|
|
|
|
|
|
async def test_setup(
|
|
hass: HomeAssistant,
|
|
entity_registry: er.EntityRegistry,
|
|
snapshot: SnapshotAssertion,
|
|
fritz: Mock,
|
|
) -> None:
|
|
"""Test setup of platform."""
|
|
device = FritzDeviceClimateMock()
|
|
with patch("homeassistant.components.fritzbox.PLATFORMS", [Platform.CLIMATE]):
|
|
entry = await setup_config_entry(
|
|
hass, MOCK_CONFIG[FB_DOMAIN][CONF_DEVICES][0], ENTITY_ID, device, fritz
|
|
)
|
|
|
|
await snapshot_platform(hass, entity_registry, snapshot, entry.entry_id)
|
|
|
|
|
|
async def test_hkr_wo_temperature_sensor(hass: HomeAssistant, fritz: Mock) -> None:
|
|
"""Test hkr without exposing dedicated temperature sensor data block."""
|
|
device = FritzDeviceClimateWithoutTempSensorMock()
|
|
await setup_config_entry(
|
|
hass, MOCK_CONFIG[FB_DOMAIN][CONF_DEVICES][0], ENTITY_ID, device, fritz
|
|
)
|
|
|
|
state = hass.states.get(ENTITY_ID)
|
|
assert state
|
|
assert state.attributes[ATTR_CURRENT_TEMPERATURE] == 18.0
|
|
|
|
|
|
async def test_target_temperature_on(hass: HomeAssistant, fritz: Mock) -> None:
|
|
"""Test turn device on."""
|
|
device = FritzDeviceClimateMock()
|
|
device.target_temperature = 127.0
|
|
await setup_config_entry(
|
|
hass, MOCK_CONFIG[FB_DOMAIN][CONF_DEVICES][0], ENTITY_ID, device, fritz
|
|
)
|
|
|
|
state = hass.states.get(ENTITY_ID)
|
|
assert state
|
|
assert state.attributes[ATTR_TEMPERATURE] is None
|
|
|
|
|
|
async def test_target_temperature_off(hass: HomeAssistant, fritz: Mock) -> None:
|
|
"""Test turn device on."""
|
|
device = FritzDeviceClimateMock()
|
|
device.target_temperature = 126.5
|
|
await setup_config_entry(
|
|
hass, MOCK_CONFIG[FB_DOMAIN][CONF_DEVICES][0], ENTITY_ID, device, fritz
|
|
)
|
|
|
|
state = hass.states.get(ENTITY_ID)
|
|
assert state
|
|
assert state.attributes[ATTR_TEMPERATURE] is None
|
|
|
|
|
|
async def test_update(hass: HomeAssistant, fritz: Mock) -> None:
|
|
"""Test update without error."""
|
|
device = FritzDeviceClimateMock()
|
|
await setup_config_entry(
|
|
hass, MOCK_CONFIG[FB_DOMAIN][CONF_DEVICES][0], ENTITY_ID, device, fritz
|
|
)
|
|
|
|
state = hass.states.get(ENTITY_ID)
|
|
assert state
|
|
assert state.attributes[ATTR_CURRENT_TEMPERATURE] == 18
|
|
assert state.attributes[ATTR_MAX_TEMP] == 28
|
|
assert state.attributes[ATTR_MIN_TEMP] == 8
|
|
assert state.attributes[ATTR_TEMPERATURE] == 19.5
|
|
|
|
device.temperature = 19
|
|
device.target_temperature = 20
|
|
|
|
next_update = dt_util.utcnow() + timedelta(seconds=200)
|
|
async_fire_time_changed(hass, next_update)
|
|
await hass.async_block_till_done(wait_background_tasks=True)
|
|
state = hass.states.get(ENTITY_ID)
|
|
|
|
assert fritz().update_devices.call_count == 2
|
|
assert state
|
|
assert state.attributes[ATTR_CURRENT_TEMPERATURE] == 19
|
|
assert state.attributes[ATTR_TEMPERATURE] == 20
|
|
|
|
|
|
async def test_automatic_offset(hass: HomeAssistant, fritz: Mock) -> None:
|
|
"""Test when automatic offset is configured on fritz!box device."""
|
|
device = FritzDeviceClimateMock()
|
|
device.temperature = 18
|
|
device.actual_temperature = 19
|
|
device.target_temperature = 20
|
|
await setup_config_entry(
|
|
hass, MOCK_CONFIG[FB_DOMAIN][CONF_DEVICES][0], ENTITY_ID, device, fritz
|
|
)
|
|
|
|
state = hass.states.get(ENTITY_ID)
|
|
assert state
|
|
assert state.attributes[ATTR_CURRENT_TEMPERATURE] == 18
|
|
assert state.attributes[ATTR_MAX_TEMP] == 28
|
|
assert state.attributes[ATTR_MIN_TEMP] == 8
|
|
assert state.attributes[ATTR_TEMPERATURE] == 20
|
|
|
|
|
|
async def test_update_error(hass: HomeAssistant, fritz: Mock) -> None:
|
|
"""Test update with error."""
|
|
device = FritzDeviceClimateMock()
|
|
fritz().update_devices.side_effect = HTTPError("Boom")
|
|
entry = await setup_config_entry(
|
|
hass, MOCK_CONFIG[FB_DOMAIN][CONF_DEVICES][0], ENTITY_ID, device, fritz
|
|
)
|
|
assert entry.state is ConfigEntryState.SETUP_RETRY
|
|
|
|
assert fritz().update_devices.call_count == 2
|
|
assert fritz().login.call_count == 2
|
|
|
|
next_update = dt_util.utcnow() + timedelta(seconds=200)
|
|
async_fire_time_changed(hass, next_update)
|
|
await hass.async_block_till_done(wait_background_tasks=True)
|
|
|
|
assert fritz().update_devices.call_count == 4
|
|
assert fritz().login.call_count == 4
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
(
|
|
"service_data",
|
|
"expected_set_target_temperature_call_args",
|
|
"expected_set_hkr_state_call_args",
|
|
),
|
|
[
|
|
({ATTR_TEMPERATURE: 23}, [call(23, True)], []),
|
|
(
|
|
{
|
|
ATTR_HVAC_MODE: HVACMode.OFF,
|
|
ATTR_TEMPERATURE: 23,
|
|
},
|
|
[],
|
|
[call("off", True)],
|
|
),
|
|
(
|
|
{
|
|
ATTR_HVAC_MODE: HVACMode.HEAT,
|
|
ATTR_TEMPERATURE: 23,
|
|
},
|
|
[call(23, True)],
|
|
[],
|
|
),
|
|
],
|
|
)
|
|
async def test_set_temperature(
|
|
hass: HomeAssistant,
|
|
fritz: Mock,
|
|
service_data: dict,
|
|
expected_set_target_temperature_call_args: list[_Call],
|
|
expected_set_hkr_state_call_args: list[_Call],
|
|
) -> None:
|
|
"""Test setting temperature."""
|
|
device = FritzDeviceClimateMock()
|
|
device.lock = False
|
|
|
|
await setup_config_entry(
|
|
hass, MOCK_CONFIG[FB_DOMAIN][CONF_DEVICES][0], ENTITY_ID, device, fritz
|
|
)
|
|
|
|
await hass.services.async_call(
|
|
CLIMATE_DOMAIN,
|
|
SERVICE_SET_TEMPERATURE,
|
|
{ATTR_ENTITY_ID: ENTITY_ID, **service_data},
|
|
True,
|
|
)
|
|
assert device.set_target_temperature.call_count == len(
|
|
expected_set_target_temperature_call_args
|
|
)
|
|
assert (
|
|
device.set_target_temperature.call_args_list
|
|
== expected_set_target_temperature_call_args
|
|
)
|
|
assert device.set_hkr_state.call_count == len(expected_set_hkr_state_call_args)
|
|
assert device.set_hkr_state.call_args_list == expected_set_hkr_state_call_args
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
(
|
|
"service_data",
|
|
"target_temperature",
|
|
"current_preset",
|
|
"expected_set_target_temperature_call_args",
|
|
"expected_set_hkr_state_call_args",
|
|
),
|
|
[
|
|
# mode off always sets hkr state off
|
|
({ATTR_HVAC_MODE: HVACMode.OFF}, 22, PRESET_COMFORT, [], [call("off", True)]),
|
|
({ATTR_HVAC_MODE: HVACMode.OFF}, 16, PRESET_ECO, [], [call("off", True)]),
|
|
({ATTR_HVAC_MODE: HVACMode.OFF}, 16, None, [], [call("off", True)]),
|
|
# mode heat sets target temperature based on current scheduled preset,
|
|
# when not already in mode heat
|
|
(
|
|
{ATTR_HVAC_MODE: HVACMode.HEAT},
|
|
OFF_API_TEMPERATURE,
|
|
PRESET_COMFORT,
|
|
[call(22, True)],
|
|
[],
|
|
),
|
|
(
|
|
{ATTR_HVAC_MODE: HVACMode.HEAT},
|
|
OFF_API_TEMPERATURE,
|
|
PRESET_ECO,
|
|
[call(16, True)],
|
|
[],
|
|
),
|
|
(
|
|
{ATTR_HVAC_MODE: HVACMode.HEAT},
|
|
OFF_API_TEMPERATURE,
|
|
None,
|
|
[call(22, True)],
|
|
[],
|
|
),
|
|
# mode heat does not set target temperature, when already in mode heat
|
|
({ATTR_HVAC_MODE: HVACMode.HEAT}, 16, PRESET_COMFORT, [], []),
|
|
({ATTR_HVAC_MODE: HVACMode.HEAT}, 16, PRESET_ECO, [], []),
|
|
({ATTR_HVAC_MODE: HVACMode.HEAT}, 16, None, [], []),
|
|
({ATTR_HVAC_MODE: HVACMode.HEAT}, 22, PRESET_COMFORT, [], []),
|
|
({ATTR_HVAC_MODE: HVACMode.HEAT}, 22, PRESET_ECO, [], []),
|
|
({ATTR_HVAC_MODE: HVACMode.HEAT}, 22, None, [], []),
|
|
],
|
|
)
|
|
async def test_set_hvac_mode(
|
|
hass: HomeAssistant,
|
|
fritz: Mock,
|
|
service_data: dict,
|
|
target_temperature: float,
|
|
current_preset: str,
|
|
expected_set_target_temperature_call_args: list[_Call],
|
|
expected_set_hkr_state_call_args: list[_Call],
|
|
) -> None:
|
|
"""Test setting hvac mode."""
|
|
device = FritzDeviceClimateMock()
|
|
|
|
device.lock = False
|
|
device.target_temperature = target_temperature
|
|
|
|
if current_preset is PRESET_COMFORT:
|
|
device.nextchange_temperature = device.eco_temperature
|
|
elif current_preset is PRESET_ECO:
|
|
device.nextchange_temperature = device.comfort_temperature
|
|
else:
|
|
device.nextchange_endperiod = 0
|
|
|
|
await setup_config_entry(
|
|
hass, MOCK_CONFIG[FB_DOMAIN][CONF_DEVICES][0], ENTITY_ID, device, fritz
|
|
)
|
|
|
|
await hass.services.async_call(
|
|
CLIMATE_DOMAIN,
|
|
SERVICE_SET_HVAC_MODE,
|
|
{ATTR_ENTITY_ID: ENTITY_ID, **service_data},
|
|
True,
|
|
)
|
|
|
|
assert device.set_target_temperature.call_count == len(
|
|
expected_set_target_temperature_call_args
|
|
)
|
|
assert (
|
|
device.set_target_temperature.call_args_list
|
|
== expected_set_target_temperature_call_args
|
|
)
|
|
assert device.set_hkr_state.call_count == len(expected_set_hkr_state_call_args)
|
|
assert device.set_hkr_state.call_args_list == expected_set_hkr_state_call_args
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
("comfort_temperature", "expected_call_args"),
|
|
[
|
|
(20, [call("comfort", True)]),
|
|
(28, [call("comfort", True)]),
|
|
(ON_API_TEMPERATURE, [call("comfort", True)]),
|
|
],
|
|
)
|
|
async def test_set_preset_mode_comfort(
|
|
hass: HomeAssistant,
|
|
fritz: Mock,
|
|
comfort_temperature: int,
|
|
expected_call_args: list[_Call],
|
|
) -> None:
|
|
"""Test setting preset mode."""
|
|
device = FritzDeviceClimateMock()
|
|
|
|
device.lock = False
|
|
device.comfort_temperature = comfort_temperature
|
|
await setup_config_entry(
|
|
hass, MOCK_CONFIG[FB_DOMAIN][CONF_DEVICES][0], ENTITY_ID, device, fritz
|
|
)
|
|
|
|
await hass.services.async_call(
|
|
CLIMATE_DOMAIN,
|
|
SERVICE_SET_PRESET_MODE,
|
|
{ATTR_ENTITY_ID: ENTITY_ID, ATTR_PRESET_MODE: PRESET_COMFORT},
|
|
True,
|
|
)
|
|
assert device.set_hkr_state.call_count == len(expected_call_args)
|
|
assert device.set_hkr_state.call_args_list == expected_call_args
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
("eco_temperature", "expected_call_args"),
|
|
[
|
|
(20, [call("eco", True)]),
|
|
(16, [call("eco", True)]),
|
|
(OFF_API_TEMPERATURE, [call("eco", True)]),
|
|
],
|
|
)
|
|
async def test_set_preset_mode_eco(
|
|
hass: HomeAssistant,
|
|
fritz: Mock,
|
|
eco_temperature: int,
|
|
expected_call_args: list[_Call],
|
|
) -> None:
|
|
"""Test setting preset mode."""
|
|
device = FritzDeviceClimateMock()
|
|
|
|
device.lock = False
|
|
device.eco_temperature = eco_temperature
|
|
await setup_config_entry(
|
|
hass, MOCK_CONFIG[FB_DOMAIN][CONF_DEVICES][0], ENTITY_ID, device, fritz
|
|
)
|
|
|
|
await hass.services.async_call(
|
|
CLIMATE_DOMAIN,
|
|
SERVICE_SET_PRESET_MODE,
|
|
{ATTR_ENTITY_ID: ENTITY_ID, ATTR_PRESET_MODE: PRESET_ECO},
|
|
True,
|
|
)
|
|
assert device.set_hkr_state.call_count == len(expected_call_args)
|
|
assert device.set_hkr_state.call_args_list == expected_call_args
|
|
|
|
|
|
async def test_set_preset_mode_boost(
|
|
hass: HomeAssistant,
|
|
fritz: Mock,
|
|
) -> None:
|
|
"""Test setting preset mode."""
|
|
device = FritzDeviceClimateMock()
|
|
device.lock = False
|
|
|
|
await setup_config_entry(
|
|
hass, MOCK_CONFIG[FB_DOMAIN][CONF_DEVICES][0], ENTITY_ID, device, fritz
|
|
)
|
|
|
|
await hass.services.async_call(
|
|
CLIMATE_DOMAIN,
|
|
SERVICE_SET_PRESET_MODE,
|
|
{ATTR_ENTITY_ID: ENTITY_ID, ATTR_PRESET_MODE: PRESET_BOOST},
|
|
True,
|
|
)
|
|
assert device.set_hkr_state.call_count == 1
|
|
assert device.set_hkr_state.call_args_list == [call("on", True)]
|
|
|
|
|
|
async def test_preset_mode_update(hass: HomeAssistant, fritz: Mock) -> None:
|
|
"""Test preset mode."""
|
|
device = FritzDeviceClimateMock()
|
|
device.comfort_temperature = 23
|
|
device.eco_temperature = 20
|
|
await setup_config_entry(
|
|
hass, MOCK_CONFIG[FB_DOMAIN][CONF_DEVICES][0], ENTITY_ID, device, fritz
|
|
)
|
|
|
|
state = hass.states.get(ENTITY_ID)
|
|
assert state
|
|
assert state.attributes[ATTR_PRESET_MODE] is None
|
|
|
|
# test comfort preset
|
|
device.target_temperature = 23
|
|
next_update = dt_util.utcnow() + timedelta(seconds=200)
|
|
async_fire_time_changed(hass, next_update)
|
|
await hass.async_block_till_done(wait_background_tasks=True)
|
|
state = hass.states.get(ENTITY_ID)
|
|
|
|
assert fritz().update_devices.call_count == 2
|
|
assert state
|
|
assert state.attributes[ATTR_PRESET_MODE] == PRESET_COMFORT
|
|
|
|
# test eco preset
|
|
device.target_temperature = 20
|
|
next_update = dt_util.utcnow() + timedelta(seconds=200)
|
|
async_fire_time_changed(hass, next_update)
|
|
await hass.async_block_till_done(wait_background_tasks=True)
|
|
state = hass.states.get(ENTITY_ID)
|
|
|
|
assert fritz().update_devices.call_count == 3
|
|
assert state
|
|
assert state.attributes[ATTR_PRESET_MODE] == PRESET_ECO
|
|
|
|
# test boost preset
|
|
device.target_temperature = 127 # special temp from the api
|
|
next_update = dt_util.utcnow() + timedelta(seconds=200)
|
|
async_fire_time_changed(hass, next_update)
|
|
await hass.async_block_till_done(wait_background_tasks=True)
|
|
state = hass.states.get(ENTITY_ID)
|
|
|
|
assert fritz().update_devices.call_count == 4
|
|
assert state
|
|
assert state.attributes[ATTR_PRESET_MODE] == PRESET_BOOST
|
|
|
|
|
|
async def test_discover_new_device(hass: HomeAssistant, fritz: Mock) -> None:
|
|
"""Test adding new discovered devices during runtime."""
|
|
device = FritzDeviceClimateMock()
|
|
await setup_config_entry(
|
|
hass, MOCK_CONFIG[FB_DOMAIN][CONF_DEVICES][0], ENTITY_ID, device, fritz
|
|
)
|
|
|
|
state = hass.states.get(ENTITY_ID)
|
|
assert state
|
|
|
|
new_device = FritzDeviceClimateMock()
|
|
new_device.ain = "7890 1234"
|
|
new_device.name = "new_climate"
|
|
set_devices(fritz, devices=[device, new_device])
|
|
|
|
next_update = dt_util.utcnow() + timedelta(seconds=200)
|
|
async_fire_time_changed(hass, next_update)
|
|
await hass.async_block_till_done(wait_background_tasks=True)
|
|
|
|
state = hass.states.get(f"{CLIMATE_DOMAIN}.new_climate")
|
|
assert state
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
"service_data",
|
|
[
|
|
{ATTR_TEMPERATURE: 23},
|
|
{
|
|
ATTR_HVAC_MODE: HVACMode.HEAT,
|
|
ATTR_TEMPERATURE: 25,
|
|
},
|
|
],
|
|
)
|
|
async def test_set_temperature_lock(
|
|
hass: HomeAssistant,
|
|
fritz: Mock,
|
|
service_data: dict,
|
|
) -> None:
|
|
"""Test setting temperature while device is locked."""
|
|
device = FritzDeviceClimateMock()
|
|
|
|
device.lock = True
|
|
assert await setup_config_entry(
|
|
hass, MOCK_CONFIG[FB_DOMAIN][CONF_DEVICES][0], ENTITY_ID, device, fritz
|
|
)
|
|
|
|
with pytest.raises(
|
|
HomeAssistantError,
|
|
match="Can't change settings while manual access for telephone, app, or user interface is disabled on the device",
|
|
):
|
|
await hass.services.async_call(
|
|
CLIMATE_DOMAIN,
|
|
SERVICE_SET_TEMPERATURE,
|
|
{ATTR_ENTITY_ID: ENTITY_ID, **service_data},
|
|
True,
|
|
)
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
("service_data", "target_temperature", "current_preset", "expected_call_args"),
|
|
[
|
|
# mode off always sets target temperature to 0
|
|
({ATTR_HVAC_MODE: HVACMode.OFF}, 22, PRESET_COMFORT, [call(0, True)]),
|
|
({ATTR_HVAC_MODE: HVACMode.OFF}, 16, PRESET_ECO, [call(0, True)]),
|
|
({ATTR_HVAC_MODE: HVACMode.OFF}, 16, None, [call(0, True)]),
|
|
# mode heat sets target temperature based on current scheduled preset,
|
|
# when not already in mode heat
|
|
({ATTR_HVAC_MODE: HVACMode.HEAT}, 0.0, PRESET_COMFORT, [call(22, True)]),
|
|
({ATTR_HVAC_MODE: HVACMode.HEAT}, 0.0, PRESET_ECO, [call(16, True)]),
|
|
({ATTR_HVAC_MODE: HVACMode.HEAT}, 0.0, None, [call(22, True)]),
|
|
# mode heat does not set target temperature, when already in mode heat
|
|
({ATTR_HVAC_MODE: HVACMode.HEAT}, 16, PRESET_COMFORT, []),
|
|
({ATTR_HVAC_MODE: HVACMode.HEAT}, 16, PRESET_ECO, []),
|
|
({ATTR_HVAC_MODE: HVACMode.HEAT}, 16, None, []),
|
|
({ATTR_HVAC_MODE: HVACMode.HEAT}, 22, PRESET_COMFORT, []),
|
|
({ATTR_HVAC_MODE: HVACMode.HEAT}, 22, PRESET_ECO, []),
|
|
({ATTR_HVAC_MODE: HVACMode.HEAT}, 22, None, []),
|
|
],
|
|
)
|
|
async def test_set_hvac_mode_lock(
|
|
hass: HomeAssistant,
|
|
fritz: Mock,
|
|
service_data: dict,
|
|
target_temperature: float,
|
|
current_preset: str,
|
|
expected_call_args: list[_Call],
|
|
) -> None:
|
|
"""Test setting hvac mode while device is locked."""
|
|
device = FritzDeviceClimateMock()
|
|
|
|
device.lock = True
|
|
device.target_temperature = target_temperature
|
|
|
|
if current_preset is PRESET_COMFORT:
|
|
device.nextchange_temperature = device.eco_temperature
|
|
elif current_preset is PRESET_ECO:
|
|
device.nextchange_temperature = device.comfort_temperature
|
|
else:
|
|
device.nextchange_endperiod = 0
|
|
|
|
assert await setup_config_entry(
|
|
hass, MOCK_CONFIG[FB_DOMAIN][CONF_DEVICES][0], ENTITY_ID, device, fritz
|
|
)
|
|
|
|
with pytest.raises(
|
|
HomeAssistantError,
|
|
match="Can't change settings while manual access for telephone, app, or user interface is disabled on the device",
|
|
):
|
|
await hass.services.async_call(
|
|
CLIMATE_DOMAIN,
|
|
SERVICE_SET_HVAC_MODE,
|
|
{ATTR_ENTITY_ID: ENTITY_ID, **service_data},
|
|
True,
|
|
)
|
|
|
|
|
|
async def test_holidy_summer_mode(
|
|
hass: HomeAssistant, freezer: FrozenDateTimeFactory, fritz: Mock
|
|
) -> None:
|
|
"""Test holiday and summer mode."""
|
|
device = FritzDeviceClimateMock()
|
|
device.lock = False
|
|
|
|
await setup_config_entry(
|
|
hass, MOCK_CONFIG[FB_DOMAIN][CONF_DEVICES][0], ENTITY_ID, device, fritz
|
|
)
|
|
|
|
# initial state
|
|
state = hass.states.get(ENTITY_ID)
|
|
assert state
|
|
assert state.attributes[ATTR_STATE_HOLIDAY_MODE] is False
|
|
assert state.attributes[ATTR_STATE_SUMMER_MODE] is False
|
|
assert state.attributes[ATTR_HVAC_MODES] == [HVACMode.HEAT, HVACMode.OFF]
|
|
assert state.attributes[ATTR_PRESET_MODE] is None
|
|
assert state.attributes[ATTR_PRESET_MODES] == [
|
|
PRESET_ECO,
|
|
PRESET_COMFORT,
|
|
PRESET_BOOST,
|
|
]
|
|
|
|
# test holiday mode
|
|
device.holiday_active = True
|
|
device.summer_active = False
|
|
freezer.tick(timedelta(seconds=200))
|
|
async_fire_time_changed(hass)
|
|
await hass.async_block_till_done(wait_background_tasks=True)
|
|
|
|
state = hass.states.get(ENTITY_ID)
|
|
assert state
|
|
assert state.attributes[ATTR_STATE_HOLIDAY_MODE]
|
|
assert state.attributes[ATTR_STATE_SUMMER_MODE] is False
|
|
assert state.attributes[ATTR_HVAC_MODES] == [HVACMode.HEAT]
|
|
assert state.attributes[ATTR_PRESET_MODE] == PRESET_HOLIDAY
|
|
assert state.attributes[ATTR_PRESET_MODES] == [PRESET_HOLIDAY]
|
|
|
|
with pytest.raises(
|
|
HomeAssistantError,
|
|
match="Can't change settings while holiday or summer mode is active on the device",
|
|
):
|
|
await hass.services.async_call(
|
|
"climate",
|
|
SERVICE_SET_HVAC_MODE,
|
|
{"entity_id": ENTITY_ID, ATTR_HVAC_MODE: HVACMode.HEAT},
|
|
blocking=True,
|
|
)
|
|
with pytest.raises(
|
|
HomeAssistantError,
|
|
match="Can't change settings while holiday or summer mode is active on the device",
|
|
):
|
|
await hass.services.async_call(
|
|
"climate",
|
|
SERVICE_SET_PRESET_MODE,
|
|
{"entity_id": ENTITY_ID, ATTR_PRESET_MODE: PRESET_HOLIDAY},
|
|
blocking=True,
|
|
)
|
|
|
|
# test summer mode
|
|
device.holiday_active = False
|
|
device.summer_active = True
|
|
freezer.tick(timedelta(seconds=200))
|
|
async_fire_time_changed(hass)
|
|
await hass.async_block_till_done(wait_background_tasks=True)
|
|
|
|
state = hass.states.get(ENTITY_ID)
|
|
assert state
|
|
assert state.attributes[ATTR_STATE_HOLIDAY_MODE] is False
|
|
assert state.attributes[ATTR_STATE_SUMMER_MODE]
|
|
assert state.attributes[ATTR_HVAC_MODES] == [HVACMode.OFF]
|
|
assert state.attributes[ATTR_PRESET_MODE] == PRESET_SUMMER
|
|
assert state.attributes[ATTR_PRESET_MODES] == [PRESET_SUMMER]
|
|
|
|
with pytest.raises(
|
|
HomeAssistantError,
|
|
match="Can't change settings while holiday or summer mode is active on the device",
|
|
):
|
|
await hass.services.async_call(
|
|
"climate",
|
|
SERVICE_SET_HVAC_MODE,
|
|
{"entity_id": ENTITY_ID, ATTR_HVAC_MODE: HVACMode.HEAT},
|
|
blocking=True,
|
|
)
|
|
with pytest.raises(
|
|
HomeAssistantError,
|
|
match="Can't change settings while holiday or summer mode is active on the device",
|
|
):
|
|
await hass.services.async_call(
|
|
"climate",
|
|
SERVICE_SET_PRESET_MODE,
|
|
{"entity_id": ENTITY_ID, ATTR_PRESET_MODE: PRESET_SUMMER},
|
|
blocking=True,
|
|
)
|
|
|
|
# back to normal state
|
|
device.holiday_active = False
|
|
device.summer_active = False
|
|
freezer.tick(timedelta(seconds=200))
|
|
async_fire_time_changed(hass)
|
|
await hass.async_block_till_done(wait_background_tasks=True)
|
|
|
|
state = hass.states.get(ENTITY_ID)
|
|
assert state
|
|
assert state.attributes[ATTR_STATE_HOLIDAY_MODE] is False
|
|
assert state.attributes[ATTR_STATE_SUMMER_MODE] is False
|
|
assert state.attributes[ATTR_HVAC_MODES] == [HVACMode.HEAT, HVACMode.OFF]
|
|
assert state.attributes[ATTR_PRESET_MODE] is None
|
|
assert state.attributes[ATTR_PRESET_MODES] == [
|
|
PRESET_ECO,
|
|
PRESET_COMFORT,
|
|
PRESET_BOOST,
|
|
]
|