hass-core/tests/components/nest/test_climate_sdm.py
PeteRager 504ce8e93a
Set nest entities as unavailable on lost connection (#78773)
* NEST - Issues with lost internet connectivity #70479

Update Climate and Sensor entities to be unavailable when the device connectivity trait indicates the device is offline.

The prior behavior, the last known values would be displayed indefinitely if the device lost internet connectivity.  This was creating the illusion that the device was still connected.  With this change, the Home Assistant entities will become unavailable when the device loses connectivity.

* Update formatting

* Add doc strings, fix indentation

* Fix doc strings

* Update test_climate_sdm.py

* Update test_climate_sdm.py

* Update test_sensor_sdm.py

* Update test_sensor_sdm.py

* more formatting fixes

* Place availability logic in mixin

1. Consolidate repeated code into mixin and apply mixin to Climate and Sensor entities
2. Return true instead of super.available()
3. No unit test changes required to maintain code coverage

* Define self._device is mixin to make linter happier

* Remove logger used for debugging

* restore whitespace

* Fix test due to underlying merge change

* Update availability_mixin.py

* Move availability logic into device_info

* Update sensor_sdm.py
2022-09-28 19:23:11 -07:00

1508 lines
51 KiB
Python

"""
Test for Nest climate platform for the Smart Device Management API.
These tests fake out the subscriber/devicemanager, and are not using a real
pubsub subscriber.
"""
from collections.abc import Awaitable, Callable
from http import HTTPStatus
from typing import Any
import aiohttp
from google_nest_sdm.auth import AbstractAuth
from google_nest_sdm.event import EventMessage
import pytest
from homeassistant.components.climate import (
ATTR_CURRENT_TEMPERATURE,
ATTR_FAN_MODE,
ATTR_FAN_MODES,
ATTR_HVAC_ACTION,
ATTR_HVAC_MODES,
ATTR_PRESET_MODE,
ATTR_PRESET_MODES,
ATTR_TARGET_TEMP_HIGH,
ATTR_TARGET_TEMP_LOW,
FAN_LOW,
FAN_OFF,
FAN_ON,
PRESET_ECO,
PRESET_NONE,
PRESET_SLEEP,
ClimateEntityFeature,
HVACAction,
HVACMode,
)
from homeassistant.const import (
ATTR_SUPPORTED_FEATURES,
ATTR_TEMPERATURE,
STATE_UNAVAILABLE,
)
from homeassistant.core import HomeAssistant
from homeassistant.exceptions import HomeAssistantError
from .common import (
DEVICE_COMMAND,
DEVICE_ID,
CreateDevice,
FakeSubscriber,
PlatformSetup,
)
from .conftest import FakeAuth
from tests.components.climate import common
CreateEvent = Callable[[dict[str, Any]], Awaitable[None]]
EVENT_ID = "some-event-id"
@pytest.fixture
def platforms() -> list[str]:
"""Fixture to specify platforms to test."""
return ["climate"]
@pytest.fixture
def device_traits() -> dict[str, Any]:
"""Fixture that sets default traits used for devices."""
return {"sdm.devices.traits.Info": {"customName": "My Thermostat"}}
@pytest.fixture
async def create_event(
hass: HomeAssistant,
auth: AbstractAuth,
subscriber: FakeSubscriber,
) -> CreateEvent:
"""Fixture to send a pub/sub event."""
async def create_event(traits: dict[str, Any]) -> None:
await subscriber.async_receive_event(
EventMessage(
{
"eventId": EVENT_ID,
"timestamp": "2019-01-01T00:00:01Z",
"resourceUpdate": {
"name": DEVICE_ID,
"traits": traits,
},
},
auth=auth,
)
)
await hass.async_block_till_done()
return create_event
async def test_no_devices(hass: HomeAssistant, setup_platform: PlatformSetup) -> None:
"""Test no devices returned by the api."""
await setup_platform()
assert len(hass.states.async_all()) == 0
async def test_climate_devices(
hass: HomeAssistant, setup_platform: PlatformSetup, create_device: CreateDevice
) -> None:
"""Test no eligible climate devices returned by the api."""
create_device.create({"sdm.devices.traits.CameraImage": {}})
await setup_platform()
assert len(hass.states.async_all()) == 0
async def test_thermostat_off(
hass: HomeAssistant, setup_platform: PlatformSetup, create_device: CreateDevice
):
"""Test a thermostat that is not running."""
create_device.create(
{
"sdm.devices.traits.ThermostatHvac": {"status": "OFF"},
"sdm.devices.traits.ThermostatMode": {
"availableModes": ["HEAT", "COOL", "HEATCOOL", "OFF"],
"mode": "OFF",
},
"sdm.devices.traits.Temperature": {
"ambientTemperatureCelsius": 16.2,
},
},
)
await setup_platform()
assert len(hass.states.async_all()) == 1
thermostat = hass.states.get("climate.my_thermostat")
assert thermostat is not None
assert thermostat.state == HVACMode.OFF
assert thermostat.attributes[ATTR_HVAC_ACTION] == HVACAction.OFF
assert thermostat.attributes[ATTR_CURRENT_TEMPERATURE] == 16.2
assert set(thermostat.attributes[ATTR_HVAC_MODES]) == {
HVACMode.HEAT,
HVACMode.COOL,
HVACMode.HEAT_COOL,
HVACMode.OFF,
}
assert thermostat.attributes[ATTR_TEMPERATURE] is None
assert thermostat.attributes[ATTR_TARGET_TEMP_LOW] is None
assert thermostat.attributes[ATTR_TARGET_TEMP_HIGH] is None
assert ATTR_PRESET_MODE not in thermostat.attributes
assert ATTR_PRESET_MODES not in thermostat.attributes
assert ATTR_FAN_MODE not in thermostat.attributes
assert ATTR_FAN_MODES not in thermostat.attributes
async def test_thermostat_heat(
hass: HomeAssistant, setup_platform: PlatformSetup, create_device: CreateDevice
):
"""Test a thermostat that is heating."""
create_device.create(
{
"sdm.devices.traits.ThermostatHvac": {
"status": "HEATING",
},
"sdm.devices.traits.ThermostatMode": {
"availableModes": ["HEAT", "COOL", "HEATCOOL", "OFF"],
"mode": "HEAT",
},
"sdm.devices.traits.Temperature": {
"ambientTemperatureCelsius": 16.2,
},
"sdm.devices.traits.ThermostatTemperatureSetpoint": {
"heatCelsius": 22.0,
},
},
)
await setup_platform()
assert len(hass.states.async_all()) == 1
thermostat = hass.states.get("climate.my_thermostat")
assert thermostat is not None
assert thermostat.state == HVACMode.HEAT
assert thermostat.attributes[ATTR_HVAC_ACTION] == HVACAction.HEATING
assert thermostat.attributes[ATTR_CURRENT_TEMPERATURE] == 16.2
assert set(thermostat.attributes[ATTR_HVAC_MODES]) == {
HVACMode.HEAT,
HVACMode.COOL,
HVACMode.HEAT_COOL,
HVACMode.OFF,
}
assert thermostat.attributes[ATTR_TEMPERATURE] == 22.0
assert thermostat.attributes[ATTR_TARGET_TEMP_LOW] is None
assert thermostat.attributes[ATTR_TARGET_TEMP_HIGH] is None
assert ATTR_PRESET_MODE not in thermostat.attributes
assert ATTR_PRESET_MODES not in thermostat.attributes
async def test_thermostat_cool(
hass: HomeAssistant, setup_platform: PlatformSetup, create_device: CreateDevice
):
"""Test a thermostat that is cooling."""
create_device.create(
{
"sdm.devices.traits.ThermostatHvac": {
"status": "COOLING",
},
"sdm.devices.traits.ThermostatMode": {
"availableModes": ["HEAT", "COOL", "HEATCOOL", "OFF"],
"mode": "COOL",
},
"sdm.devices.traits.Temperature": {
"ambientTemperatureCelsius": 29.9,
},
"sdm.devices.traits.ThermostatTemperatureSetpoint": {
"coolCelsius": 28.0,
},
},
)
await setup_platform()
assert len(hass.states.async_all()) == 1
thermostat = hass.states.get("climate.my_thermostat")
assert thermostat is not None
assert thermostat.state == HVACMode.COOL
assert thermostat.attributes[ATTR_HVAC_ACTION] == HVACAction.COOLING
assert thermostat.attributes[ATTR_CURRENT_TEMPERATURE] == 29.9
assert set(thermostat.attributes[ATTR_HVAC_MODES]) == {
HVACMode.HEAT,
HVACMode.COOL,
HVACMode.HEAT_COOL,
HVACMode.OFF,
}
assert thermostat.attributes[ATTR_TEMPERATURE] == 28.0
assert thermostat.attributes[ATTR_TARGET_TEMP_LOW] is None
assert thermostat.attributes[ATTR_TARGET_TEMP_HIGH] is None
assert ATTR_PRESET_MODE not in thermostat.attributes
assert ATTR_PRESET_MODES not in thermostat.attributes
async def test_thermostat_heatcool(
hass: HomeAssistant, setup_platform: PlatformSetup, create_device: CreateDevice
):
"""Test a thermostat that is cooling in heatcool mode."""
create_device.create(
{
"sdm.devices.traits.ThermostatHvac": {
"status": "COOLING",
},
"sdm.devices.traits.ThermostatMode": {
"availableModes": ["HEAT", "COOL", "HEATCOOL", "OFF"],
"mode": "HEATCOOL",
},
"sdm.devices.traits.Temperature": {
"ambientTemperatureCelsius": 29.9,
},
"sdm.devices.traits.ThermostatTemperatureSetpoint": {
"heatCelsius": 22.0,
"coolCelsius": 28.0,
},
},
)
await setup_platform()
assert len(hass.states.async_all()) == 1
thermostat = hass.states.get("climate.my_thermostat")
assert thermostat is not None
assert thermostat.state == HVACMode.HEAT_COOL
assert thermostat.attributes[ATTR_HVAC_ACTION] == HVACAction.COOLING
assert thermostat.attributes[ATTR_CURRENT_TEMPERATURE] == 29.9
assert set(thermostat.attributes[ATTR_HVAC_MODES]) == {
HVACMode.HEAT,
HVACMode.COOL,
HVACMode.HEAT_COOL,
HVACMode.OFF,
}
assert thermostat.attributes[ATTR_TARGET_TEMP_LOW] == 22.0
assert thermostat.attributes[ATTR_TARGET_TEMP_HIGH] == 28.0
assert thermostat.attributes[ATTR_TEMPERATURE] is None
assert ATTR_PRESET_MODE not in thermostat.attributes
assert ATTR_PRESET_MODES not in thermostat.attributes
async def test_thermostat_eco_off(
hass: HomeAssistant, setup_platform: PlatformSetup, create_device: CreateDevice
) -> None:
"""Test a thermostat cooling with eco off."""
create_device.create(
{
"sdm.devices.traits.ThermostatHvac": {
"status": "COOLING",
},
"sdm.devices.traits.ThermostatMode": {
"availableModes": ["HEAT", "COOL", "HEATCOOL", "OFF"],
"mode": "HEATCOOL",
},
"sdm.devices.traits.ThermostatEco": {
"availableModes": ["MANUAL_ECO", "OFF"],
"mode": "OFF",
"heatCelsius": 20.0,
"coolCelsius": 22.0,
},
"sdm.devices.traits.Temperature": {
"ambientTemperatureCelsius": 29.9,
},
"sdm.devices.traits.ThermostatTemperatureSetpoint": {
"heatCelsius": 22.0,
"coolCelsius": 28.0,
},
},
)
await setup_platform()
assert len(hass.states.async_all()) == 1
thermostat = hass.states.get("climate.my_thermostat")
assert thermostat is not None
assert thermostat.state == HVACMode.HEAT_COOL
assert thermostat.attributes[ATTR_HVAC_ACTION] == HVACAction.COOLING
assert thermostat.attributes[ATTR_CURRENT_TEMPERATURE] == 29.9
assert set(thermostat.attributes[ATTR_HVAC_MODES]) == {
HVACMode.HEAT,
HVACMode.COOL,
HVACMode.HEAT_COOL,
HVACMode.OFF,
}
assert thermostat.attributes[ATTR_TARGET_TEMP_LOW] == 22.0
assert thermostat.attributes[ATTR_TARGET_TEMP_HIGH] == 28.0
assert thermostat.attributes[ATTR_TEMPERATURE] is None
assert thermostat.attributes[ATTR_PRESET_MODE] == PRESET_NONE
assert thermostat.attributes[ATTR_PRESET_MODES] == [PRESET_ECO, PRESET_NONE]
async def test_thermostat_eco_on(
hass: HomeAssistant, setup_platform: PlatformSetup, create_device: CreateDevice
) -> None:
"""Test a thermostat in eco mode."""
create_device.create(
{
"sdm.devices.traits.ThermostatHvac": {
"status": "COOLING",
},
"sdm.devices.traits.ThermostatMode": {
"availableModes": ["HEAT", "COOL", "HEATCOOL", "OFF"],
"mode": "HEATCOOL",
},
"sdm.devices.traits.ThermostatEco": {
"availableModes": ["MANUAL_ECO", "OFF"],
"mode": "MANUAL_ECO",
"heatCelsius": 21.0,
"coolCelsius": 29.0,
},
"sdm.devices.traits.Temperature": {
"ambientTemperatureCelsius": 29.9,
},
"sdm.devices.traits.ThermostatTemperatureSetpoint": {
"heatCelsius": 22.0,
"coolCelsius": 28.0,
},
},
)
await setup_platform()
assert len(hass.states.async_all()) == 1
thermostat = hass.states.get("climate.my_thermostat")
assert thermostat is not None
assert thermostat.state == HVACMode.HEAT_COOL
assert thermostat.attributes[ATTR_HVAC_ACTION] == HVACAction.COOLING
assert thermostat.attributes[ATTR_CURRENT_TEMPERATURE] == 29.9
assert set(thermostat.attributes[ATTR_HVAC_MODES]) == {
HVACMode.HEAT,
HVACMode.COOL,
HVACMode.HEAT_COOL,
HVACMode.OFF,
}
assert thermostat.attributes[ATTR_TARGET_TEMP_LOW] == 21.0
assert thermostat.attributes[ATTR_TARGET_TEMP_HIGH] == 29.0
assert thermostat.attributes[ATTR_TEMPERATURE] is None
assert thermostat.attributes[ATTR_PRESET_MODE] == PRESET_ECO
assert thermostat.attributes[ATTR_PRESET_MODES] == [PRESET_ECO, PRESET_NONE]
async def test_thermostat_eco_heat_only(
hass: HomeAssistant, setup_platform: PlatformSetup, create_device: CreateDevice
) -> None:
"""Test a thermostat in eco mode that only supports heat."""
create_device.create(
{
"sdm.devices.traits.ThermostatHvac": {
"status": "OFF",
},
"sdm.devices.traits.ThermostatMode": {
"availableModes": ["HEAT", "OFF"],
"mode": "HEAT",
},
"sdm.devices.traits.ThermostatEco": {
"availableModes": ["MANUAL_ECO", "OFF"],
"mode": "MANUAL_ECO",
"heatCelsius": 21.0,
"coolCelsius": 29.0,
},
"sdm.devices.traits.Temperature": {
"ambientTemperatureCelsius": 29.9,
},
"sdm.devices.traits.ThermostatTemperatureSetpoint": {},
},
)
await setup_platform()
assert len(hass.states.async_all()) == 1
thermostat = hass.states.get("climate.my_thermostat")
assert thermostat is not None
assert thermostat.state == HVACMode.HEAT
assert thermostat.attributes[ATTR_HVAC_ACTION] == HVACAction.IDLE
assert thermostat.attributes[ATTR_CURRENT_TEMPERATURE] == 29.9
assert set(thermostat.attributes[ATTR_HVAC_MODES]) == {
HVACMode.HEAT,
HVACMode.OFF,
}
assert thermostat.attributes[ATTR_TEMPERATURE] == 21.0
assert ATTR_TARGET_TEMP_LOW not in thermostat.attributes
assert ATTR_TARGET_TEMP_HIGH not in thermostat.attributes
assert thermostat.attributes[ATTR_PRESET_MODE] == PRESET_ECO
assert thermostat.attributes[ATTR_PRESET_MODES] == [PRESET_ECO, PRESET_NONE]
async def test_thermostat_set_hvac_mode(
hass: HomeAssistant,
setup_platform: PlatformSetup,
auth: FakeAuth,
create_device: CreateDevice,
create_event: CreateEvent,
) -> None:
"""Test a thermostat changing hvac modes."""
create_device.create(
{
"sdm.devices.traits.ThermostatHvac": {"status": "OFF"},
"sdm.devices.traits.ThermostatMode": {
"availableModes": ["HEAT", "COOL", "HEATCOOL", "OFF"],
"mode": "OFF",
},
}
)
await setup_platform()
assert len(hass.states.async_all()) == 1
thermostat = hass.states.get("climate.my_thermostat")
assert thermostat is not None
assert thermostat.state == HVACMode.OFF
assert thermostat.attributes[ATTR_HVAC_ACTION] == HVACAction.OFF
await common.async_set_hvac_mode(hass, HVACMode.HEAT)
await hass.async_block_till_done()
assert auth.method == "post"
assert auth.url == DEVICE_COMMAND
assert auth.json == {
"command": "sdm.devices.commands.ThermostatMode.SetMode",
"params": {"mode": "HEAT"},
}
# Local state does not reflect the update
thermostat = hass.states.get("climate.my_thermostat")
assert thermostat is not None
assert thermostat.state == HVACMode.OFF
assert thermostat.attributes[ATTR_HVAC_ACTION] == HVACAction.OFF
# Simulate pubsub message when mode changes
await create_event(
{
"sdm.devices.traits.ThermostatMode": {
"availableModes": ["HEAT", "COOL", "HEATCOOL", "OFF"],
"mode": "HEAT",
},
}
)
thermostat = hass.states.get("climate.my_thermostat")
assert thermostat is not None
assert thermostat.state == HVACMode.HEAT
assert thermostat.attributes[ATTR_HVAC_ACTION] == HVACAction.IDLE
# Simulate pubsub message when the thermostat starts heating
await create_event(
{
"sdm.devices.traits.ThermostatHvac": {
"status": "HEATING",
},
}
)
thermostat = hass.states.get("climate.my_thermostat")
assert thermostat is not None
assert thermostat.state == HVACMode.HEAT
assert thermostat.attributes[ATTR_HVAC_ACTION] == HVACAction.HEATING
async def test_thermostat_invalid_hvac_mode(
hass: HomeAssistant,
setup_platform: PlatformSetup,
auth: FakeAuth,
create_device: CreateDevice,
) -> None:
"""Test setting an hvac_mode that is not supported."""
create_device.create(
{
"sdm.devices.traits.ThermostatHvac": {"status": "OFF"},
"sdm.devices.traits.ThermostatMode": {
"availableModes": ["HEAT", "COOL", "HEATCOOL", "OFF"],
"mode": "OFF",
},
}
)
await setup_platform()
assert len(hass.states.async_all()) == 1
thermostat = hass.states.get("climate.my_thermostat")
assert thermostat is not None
assert thermostat.state == HVACMode.OFF
assert thermostat.attributes[ATTR_HVAC_ACTION] == HVACAction.OFF
with pytest.raises(ValueError):
await common.async_set_hvac_mode(hass, HVACMode.DRY)
await hass.async_block_till_done()
assert thermostat.state == HVACMode.OFF
assert auth.method is None # No communication with API
async def test_thermostat_set_eco_preset(
hass: HomeAssistant,
setup_platform: PlatformSetup,
auth: FakeAuth,
create_device: CreateDevice,
create_event: CreateEvent,
) -> None:
"""Test a thermostat put into eco mode."""
create_device.create(
{
"sdm.devices.traits.ThermostatHvac": {"status": "OFF"},
"sdm.devices.traits.ThermostatEco": {
"availableModes": ["MANUAL_ECO", "OFF"],
"mode": "OFF",
"heatCelsius": 15.0,
"coolCelsius": 28.0,
},
"sdm.devices.traits.ThermostatMode": {
"availableModes": ["HEAT", "COOL", "HEATCOOL", "OFF"],
"mode": "OFF",
},
}
)
await setup_platform()
assert len(hass.states.async_all()) == 1
thermostat = hass.states.get("climate.my_thermostat")
assert thermostat is not None
assert thermostat.state == HVACMode.OFF
assert thermostat.attributes[ATTR_HVAC_ACTION] == HVACAction.OFF
assert thermostat.attributes[ATTR_PRESET_MODE] == PRESET_NONE
# Turn on eco mode
await common.async_set_preset_mode(hass, PRESET_ECO)
await hass.async_block_till_done()
assert auth.method == "post"
assert auth.url == DEVICE_COMMAND
assert auth.json == {
"command": "sdm.devices.commands.ThermostatEco.SetMode",
"params": {"mode": "MANUAL_ECO"},
}
# Local state does not reflect the update
thermostat = hass.states.get("climate.my_thermostat")
assert thermostat is not None
assert thermostat.state == HVACMode.OFF
assert thermostat.attributes[ATTR_HVAC_ACTION] == HVACAction.OFF
assert thermostat.attributes[ATTR_PRESET_MODE] == PRESET_NONE
# Simulate pubsub message when mode changes
await create_event(
{
"sdm.devices.traits.ThermostatEco": {
"availableModes": ["HEAT", "COOL", "HEATCOOL", "OFF"],
"mode": "MANUAL_ECO",
"heatCelsius": 15.0,
"coolCelsius": 28.0,
},
}
)
thermostat = hass.states.get("climate.my_thermostat")
assert thermostat is not None
assert thermostat.state == HVACMode.OFF
assert thermostat.attributes[ATTR_HVAC_ACTION] == HVACAction.OFF
assert thermostat.attributes[ATTR_PRESET_MODE] == PRESET_ECO
# Turn off eco mode
await common.async_set_preset_mode(hass, PRESET_NONE)
await hass.async_block_till_done()
assert auth.method == "post"
assert auth.url == DEVICE_COMMAND
assert auth.json == {
"command": "sdm.devices.commands.ThermostatEco.SetMode",
"params": {"mode": "OFF"},
}
async def test_thermostat_set_cool(
hass: HomeAssistant,
setup_platform: PlatformSetup,
auth: FakeAuth,
create_device: CreateDevice,
) -> None:
"""Test a thermostat in cool mode with a temperature change."""
create_device.create(
{
"sdm.devices.traits.ThermostatHvac": {"status": "OFF"},
"sdm.devices.traits.ThermostatMode": {
"availableModes": ["HEAT", "COOL", "HEATCOOL", "OFF"],
"mode": "COOL",
},
"sdm.devices.traits.ThermostatTemperatureSetpoint": {
"coolCelsius": 25.0,
},
},
)
await setup_platform()
assert len(hass.states.async_all()) == 1
thermostat = hass.states.get("climate.my_thermostat")
assert thermostat is not None
assert thermostat.state == HVACMode.COOL
await common.async_set_temperature(hass, temperature=24.0)
await hass.async_block_till_done()
assert auth.method == "post"
assert auth.url == DEVICE_COMMAND
assert auth.json == {
"command": "sdm.devices.commands.ThermostatTemperatureSetpoint.SetCool",
"params": {"coolCelsius": 24.0},
}
async def test_thermostat_set_heat(
hass: HomeAssistant,
setup_platform: PlatformSetup,
auth: FakeAuth,
create_device: CreateDevice,
) -> None:
"""Test a thermostat heating mode with a temperature change."""
create_device.create(
{
"sdm.devices.traits.ThermostatHvac": {"status": "OFF"},
"sdm.devices.traits.ThermostatMode": {
"availableModes": ["HEAT", "COOL", "HEATCOOL", "OFF"],
"mode": "HEAT",
},
"sdm.devices.traits.ThermostatTemperatureSetpoint": {
"heatCelsius": 19.0,
},
}
)
await setup_platform()
assert len(hass.states.async_all()) == 1
thermostat = hass.states.get("climate.my_thermostat")
assert thermostat is not None
assert thermostat.state == HVACMode.HEAT
await common.async_set_temperature(hass, temperature=20.0)
await hass.async_block_till_done()
assert auth.method == "post"
assert auth.url == DEVICE_COMMAND
assert auth.json == {
"command": "sdm.devices.commands.ThermostatTemperatureSetpoint.SetHeat",
"params": {"heatCelsius": 20.0},
}
async def test_thermostat_set_temperature_hvac_mode(
hass: HomeAssistant,
setup_platform: PlatformSetup,
auth: FakeAuth,
create_device: CreateDevice,
) -> None:
"""Test setting HVAC mode while setting temperature."""
create_device.create(
{
"sdm.devices.traits.ThermostatHvac": {"status": "OFF"},
"sdm.devices.traits.ThermostatMode": {
"availableModes": ["HEAT", "COOL", "HEATCOOL", "OFF"],
"mode": "OFF",
},
"sdm.devices.traits.ThermostatTemperatureSetpoint": {
"coolCelsius": 25.0,
},
},
)
await setup_platform()
assert len(hass.states.async_all()) == 1
thermostat = hass.states.get("climate.my_thermostat")
assert thermostat is not None
assert thermostat.state == HVACMode.OFF
await common.async_set_temperature(hass, temperature=24.0, hvac_mode=HVACMode.COOL)
await hass.async_block_till_done()
assert auth.method == "post"
assert auth.url == DEVICE_COMMAND
assert auth.json == {
"command": "sdm.devices.commands.ThermostatTemperatureSetpoint.SetCool",
"params": {"coolCelsius": 24.0},
}
await common.async_set_temperature(hass, temperature=26.0, hvac_mode=HVACMode.HEAT)
await hass.async_block_till_done()
assert auth.method == "post"
assert auth.url == DEVICE_COMMAND
assert auth.json == {
"command": "sdm.devices.commands.ThermostatTemperatureSetpoint.SetHeat",
"params": {"heatCelsius": 26.0},
}
await common.async_set_temperature(
hass, target_temp_low=20.0, target_temp_high=24.0, hvac_mode=HVACMode.HEAT_COOL
)
await hass.async_block_till_done()
assert auth.method == "post"
assert auth.url == DEVICE_COMMAND
assert auth.json == {
"command": "sdm.devices.commands.ThermostatTemperatureSetpoint.SetRange",
"params": {"heatCelsius": 20.0, "coolCelsius": 24.0},
}
async def test_thermostat_set_heat_cool(
hass: HomeAssistant,
setup_platform: PlatformSetup,
auth: FakeAuth,
create_device: CreateDevice,
) -> None:
"""Test a thermostat in heatcool mode with a temperature change."""
create_device.create(
{
"sdm.devices.traits.ThermostatHvac": {"status": "OFF"},
"sdm.devices.traits.ThermostatMode": {
"availableModes": ["HEAT", "COOL", "HEATCOOL", "OFF"],
"mode": "HEATCOOL",
},
"sdm.devices.traits.ThermostatTemperatureSetpoint": {
"heatCelsius": 19.0,
"coolCelsius": 25.0,
},
}
)
await setup_platform()
assert len(hass.states.async_all()) == 1
thermostat = hass.states.get("climate.my_thermostat")
assert thermostat is not None
assert thermostat.state == HVACMode.HEAT_COOL
await common.async_set_temperature(
hass, target_temp_low=20.0, target_temp_high=24.0
)
await hass.async_block_till_done()
assert auth.method == "post"
assert auth.url == DEVICE_COMMAND
assert auth.json == {
"command": "sdm.devices.commands.ThermostatTemperatureSetpoint.SetRange",
"params": {"heatCelsius": 20.0, "coolCelsius": 24.0},
}
async def test_thermostat_fan_off(
hass: HomeAssistant,
setup_platform: PlatformSetup,
create_device: CreateDevice,
) -> None:
"""Test a thermostat with the fan not running."""
create_device.create(
{
"sdm.devices.traits.Fan": {
"timerMode": "OFF",
"timerTimeout": "2019-05-10T03:22:54Z",
},
"sdm.devices.traits.ThermostatHvac": {"status": "OFF"},
"sdm.devices.traits.ThermostatMode": {
"availableModes": ["HEAT", "COOL", "HEATCOOL", "OFF"],
"mode": "COOL",
},
"sdm.devices.traits.Temperature": {
"ambientTemperatureCelsius": 16.2,
},
}
)
await setup_platform()
assert len(hass.states.async_all()) == 1
thermostat = hass.states.get("climate.my_thermostat")
assert thermostat is not None
assert thermostat.state == HVACMode.COOL
assert thermostat.attributes[ATTR_HVAC_ACTION] == HVACAction.IDLE
assert thermostat.attributes[ATTR_CURRENT_TEMPERATURE] == 16.2
assert set(thermostat.attributes[ATTR_HVAC_MODES]) == {
HVACMode.HEAT,
HVACMode.COOL,
HVACMode.HEAT_COOL,
HVACMode.OFF,
}
assert thermostat.attributes[ATTR_FAN_MODE] == FAN_OFF
assert thermostat.attributes[ATTR_FAN_MODES] == [FAN_ON, FAN_OFF]
assert thermostat.attributes[ATTR_SUPPORTED_FEATURES] == (
ClimateEntityFeature.TARGET_TEMPERATURE
| ClimateEntityFeature.TARGET_TEMPERATURE_RANGE
| ClimateEntityFeature.FAN_MODE
)
async def test_thermostat_fan_on(
hass: HomeAssistant,
setup_platform: PlatformSetup,
create_device: CreateDevice,
) -> None:
"""Test a thermostat with the fan running."""
create_device.create(
{
"sdm.devices.traits.Fan": {
"timerMode": "ON",
"timerTimeout": "2019-05-10T03:22:54Z",
},
"sdm.devices.traits.ThermostatHvac": {
"status": "OFF",
},
"sdm.devices.traits.ThermostatMode": {
"availableModes": ["HEAT", "COOL", "HEATCOOL", "OFF"],
"mode": "COOL",
},
"sdm.devices.traits.Temperature": {
"ambientTemperatureCelsius": 16.2,
},
}
)
await setup_platform()
assert len(hass.states.async_all()) == 1
thermostat = hass.states.get("climate.my_thermostat")
assert thermostat is not None
assert thermostat.state == HVACMode.COOL
assert thermostat.attributes[ATTR_HVAC_ACTION] == HVACAction.IDLE
assert thermostat.attributes[ATTR_CURRENT_TEMPERATURE] == 16.2
assert set(thermostat.attributes[ATTR_HVAC_MODES]) == {
HVACMode.HEAT,
HVACMode.COOL,
HVACMode.HEAT_COOL,
HVACMode.OFF,
}
assert thermostat.attributes[ATTR_FAN_MODE] == FAN_ON
assert thermostat.attributes[ATTR_FAN_MODES] == [FAN_ON, FAN_OFF]
assert thermostat.attributes[ATTR_SUPPORTED_FEATURES] == (
ClimateEntityFeature.TARGET_TEMPERATURE
| ClimateEntityFeature.TARGET_TEMPERATURE_RANGE
| ClimateEntityFeature.FAN_MODE
)
async def test_thermostat_cool_with_fan(
hass: HomeAssistant,
setup_platform: PlatformSetup,
create_device: CreateDevice,
) -> None:
"""Test a thermostat cooling while the fan is on."""
create_device.create(
{
"sdm.devices.traits.Fan": {
"timerMode": "ON",
"timerTimeout": "2019-05-10T03:22:54Z",
},
"sdm.devices.traits.ThermostatHvac": {
"status": "OFF",
},
"sdm.devices.traits.ThermostatMode": {
"availableModes": ["HEAT", "COOL", "HEATCOOL", "OFF"],
"mode": "COOL",
},
},
)
await setup_platform()
assert len(hass.states.async_all()) == 1
thermostat = hass.states.get("climate.my_thermostat")
assert thermostat is not None
assert thermostat.state == HVACMode.COOL
assert thermostat.attributes[ATTR_HVAC_ACTION] == HVACAction.IDLE
assert set(thermostat.attributes[ATTR_HVAC_MODES]) == {
HVACMode.HEAT,
HVACMode.COOL,
HVACMode.HEAT_COOL,
HVACMode.OFF,
}
assert thermostat.attributes[ATTR_FAN_MODE] == FAN_ON
assert thermostat.attributes[ATTR_FAN_MODES] == [FAN_ON, FAN_OFF]
assert thermostat.attributes[ATTR_SUPPORTED_FEATURES] == (
ClimateEntityFeature.TARGET_TEMPERATURE
| ClimateEntityFeature.TARGET_TEMPERATURE_RANGE
| ClimateEntityFeature.FAN_MODE
)
async def test_thermostat_set_fan(
hass: HomeAssistant,
setup_platform: PlatformSetup,
auth: FakeAuth,
create_device: CreateDevice,
) -> None:
"""Test a thermostat enabling the fan."""
create_device.create(
{
"sdm.devices.traits.Fan": {
"timerMode": "ON",
"timerTimeout": "2019-05-10T03:22:54Z",
},
"sdm.devices.traits.ThermostatHvac": {
"status": "OFF",
},
"sdm.devices.traits.ThermostatMode": {
"availableModes": ["HEAT", "COOL", "HEATCOOL", "OFF"],
"mode": "HEAT",
},
}
)
await setup_platform()
assert len(hass.states.async_all()) == 1
thermostat = hass.states.get("climate.my_thermostat")
assert thermostat is not None
assert thermostat.state == HVACMode.HEAT
assert thermostat.attributes[ATTR_FAN_MODE] == FAN_ON
assert thermostat.attributes[ATTR_FAN_MODES] == [FAN_ON, FAN_OFF]
assert thermostat.attributes[ATTR_SUPPORTED_FEATURES] == (
ClimateEntityFeature.TARGET_TEMPERATURE
| ClimateEntityFeature.TARGET_TEMPERATURE_RANGE
| ClimateEntityFeature.FAN_MODE
)
# Turn off fan mode
await common.async_set_fan_mode(hass, FAN_OFF)
await hass.async_block_till_done()
assert auth.method == "post"
assert auth.url == DEVICE_COMMAND
assert auth.json == {
"command": "sdm.devices.commands.Fan.SetTimer",
"params": {"timerMode": "OFF"},
}
# Turn on fan mode
await common.async_set_fan_mode(hass, FAN_ON)
await hass.async_block_till_done()
assert auth.method == "post"
assert auth.url == DEVICE_COMMAND
assert auth.json == {
"command": "sdm.devices.commands.Fan.SetTimer",
"params": {
"duration": "43200s",
"timerMode": "ON",
},
}
async def test_thermostat_set_fan_when_off(
hass: HomeAssistant,
setup_platform: PlatformSetup,
auth: FakeAuth,
create_device: CreateDevice,
) -> None:
"""Test a thermostat enabling the fan."""
create_device.create(
{
"sdm.devices.traits.Fan": {
"timerMode": "ON",
"timerTimeout": "2019-05-10T03:22:54Z",
},
"sdm.devices.traits.ThermostatHvac": {
"status": "OFF",
},
"sdm.devices.traits.ThermostatMode": {
"availableModes": ["HEAT", "COOL", "HEATCOOL", "OFF"],
"mode": "OFF",
},
}
)
await setup_platform()
assert len(hass.states.async_all()) == 1
thermostat = hass.states.get("climate.my_thermostat")
assert thermostat is not None
assert thermostat.state == HVACMode.OFF
assert thermostat.attributes[ATTR_FAN_MODE] == FAN_ON
assert thermostat.attributes[ATTR_FAN_MODES] == [FAN_ON, FAN_OFF]
assert thermostat.attributes[ATTR_SUPPORTED_FEATURES] == (
ClimateEntityFeature.TARGET_TEMPERATURE
| ClimateEntityFeature.TARGET_TEMPERATURE_RANGE
| ClimateEntityFeature.FAN_MODE
)
# Fan cannot be turned on when HVAC is off
with pytest.raises(ValueError):
await common.async_set_fan_mode(hass, FAN_ON, entity_id="climate.my_thermostat")
async def test_thermostat_fan_empty(
hass: HomeAssistant,
setup_platform: PlatformSetup,
create_device: CreateDevice,
) -> None:
"""Test a fan trait with an empty response."""
create_device.create(
{
"sdm.devices.traits.Fan": {},
"sdm.devices.traits.ThermostatHvac": {"status": "OFF"},
"sdm.devices.traits.ThermostatMode": {
"availableModes": ["HEAT", "COOL", "HEATCOOL", "OFF"],
"mode": "OFF",
},
"sdm.devices.traits.Temperature": {
"ambientTemperatureCelsius": 16.2,
},
}
)
await setup_platform()
assert len(hass.states.async_all()) == 1
thermostat = hass.states.get("climate.my_thermostat")
assert thermostat is not None
assert thermostat.state == HVACMode.OFF
assert thermostat.attributes[ATTR_HVAC_ACTION] == HVACAction.OFF
assert thermostat.attributes[ATTR_CURRENT_TEMPERATURE] == 16.2
assert set(thermostat.attributes[ATTR_HVAC_MODES]) == {
HVACMode.HEAT,
HVACMode.COOL,
HVACMode.HEAT_COOL,
HVACMode.OFF,
}
assert ATTR_FAN_MODE not in thermostat.attributes
assert ATTR_FAN_MODES not in thermostat.attributes
assert thermostat.attributes[ATTR_SUPPORTED_FEATURES] == (
ClimateEntityFeature.TARGET_TEMPERATURE
| ClimateEntityFeature.TARGET_TEMPERATURE_RANGE
)
# Ignores set_fan_mode since it is lacking SUPPORT_FAN_MODE
await common.async_set_fan_mode(hass, FAN_ON)
await hass.async_block_till_done()
assert ATTR_FAN_MODE not in thermostat.attributes
assert ATTR_FAN_MODES not in thermostat.attributes
async def test_thermostat_invalid_fan_mode(
hass: HomeAssistant,
setup_platform: PlatformSetup,
create_device: CreateDevice,
) -> None:
"""Test setting a fan mode that is not supported."""
create_device.create(
{
"sdm.devices.traits.Fan": {
"timerMode": "ON",
"timerTimeout": "2019-05-10T03:22:54Z",
},
"sdm.devices.traits.ThermostatHvac": {"status": "OFF"},
"sdm.devices.traits.ThermostatMode": {
"availableModes": ["HEAT", "COOL", "HEATCOOL", "OFF"],
"mode": "COOL",
},
"sdm.devices.traits.Temperature": {
"ambientTemperatureCelsius": 16.2,
},
}
)
await setup_platform()
assert len(hass.states.async_all()) == 1
thermostat = hass.states.get("climate.my_thermostat")
assert thermostat is not None
assert thermostat.state == HVACMode.COOL
assert thermostat.attributes[ATTR_HVAC_ACTION] == HVACAction.IDLE
assert thermostat.attributes[ATTR_CURRENT_TEMPERATURE] == 16.2
assert set(thermostat.attributes[ATTR_HVAC_MODES]) == {
HVACMode.HEAT,
HVACMode.COOL,
HVACMode.HEAT_COOL,
HVACMode.OFF,
}
assert thermostat.attributes[ATTR_FAN_MODE] == FAN_ON
assert thermostat.attributes[ATTR_FAN_MODES] == [FAN_ON, FAN_OFF]
with pytest.raises(ValueError):
await common.async_set_fan_mode(hass, FAN_LOW)
await hass.async_block_till_done()
async def test_thermostat_target_temp(
hass: HomeAssistant,
setup_platform: PlatformSetup,
create_device: CreateDevice,
create_event: CreateEvent,
) -> None:
"""Test a thermostat changing hvac modes and affected on target temps."""
create_device.create(
{
"sdm.devices.traits.ThermostatHvac": {
"status": "HEATING",
},
"sdm.devices.traits.ThermostatMode": {
"availableModes": ["HEAT", "COOL", "HEATCOOL", "OFF"],
"mode": "HEAT",
},
"sdm.devices.traits.Temperature": {
"ambientTemperatureCelsius": 20.1,
},
"sdm.devices.traits.ThermostatTemperatureSetpoint": {
"heatCelsius": 23.0,
},
}
)
await setup_platform()
assert len(hass.states.async_all()) == 1
thermostat = hass.states.get("climate.my_thermostat")
assert thermostat is not None
assert thermostat.state == HVACMode.HEAT
assert thermostat.attributes[ATTR_TEMPERATURE] == 23.0
assert thermostat.attributes[ATTR_TARGET_TEMP_LOW] is None
assert thermostat.attributes[ATTR_TARGET_TEMP_HIGH] is None
# Simulate pubsub message changing modes
await create_event(
{
"sdm.devices.traits.ThermostatMode": {
"availableModes": ["HEAT", "COOL", "HEATCOOL", "OFF"],
"mode": "HEATCOOL",
},
"sdm.devices.traits.ThermostatTemperatureSetpoint": {
"heatCelsius": 22.0,
"coolCelsius": 28.0,
},
}
)
thermostat = hass.states.get("climate.my_thermostat")
assert thermostat is not None
assert thermostat.state == HVACMode.HEAT_COOL
assert thermostat.attributes[ATTR_TARGET_TEMP_LOW] == 22.0
assert thermostat.attributes[ATTR_TARGET_TEMP_HIGH] == 28.0
assert thermostat.attributes[ATTR_TEMPERATURE] is None
async def test_thermostat_missing_mode_traits(
hass: HomeAssistant,
setup_platform: PlatformSetup,
create_device: CreateDevice,
) -> None:
"""Test a thermostat missing many thermostat traits in api response."""
create_device.create(
{
"sdm.devices.traits.ThermostatHvac": {"status": "OFF"},
}
)
await setup_platform()
assert len(hass.states.async_all()) == 1
thermostat = hass.states.get("climate.my_thermostat")
assert thermostat is not None
assert thermostat.state == HVACMode.OFF
assert thermostat.attributes[ATTR_HVAC_ACTION] == HVACAction.OFF
assert thermostat.attributes[ATTR_CURRENT_TEMPERATURE] is None
assert set(thermostat.attributes[ATTR_HVAC_MODES]) == set()
assert ATTR_TEMPERATURE not in thermostat.attributes
assert ATTR_TARGET_TEMP_LOW not in thermostat.attributes
assert ATTR_TARGET_TEMP_HIGH not in thermostat.attributes
assert ATTR_PRESET_MODE not in thermostat.attributes
assert ATTR_PRESET_MODES not in thermostat.attributes
assert ATTR_FAN_MODE not in thermostat.attributes
assert ATTR_FAN_MODES not in thermostat.attributes
await common.async_set_temperature(hass, temperature=24.0)
await hass.async_block_till_done()
assert ATTR_TEMPERATURE not in thermostat.attributes
await common.async_set_preset_mode(hass, PRESET_ECO)
await hass.async_block_till_done()
assert ATTR_PRESET_MODE not in thermostat.attributes
async def test_thermostat_missing_temperature_trait(
hass: HomeAssistant,
setup_platform: PlatformSetup,
create_device: CreateDevice,
) -> None:
"""Test a thermostat missing many thermostat traits in api response."""
create_device.create(
{
"sdm.devices.traits.ThermostatHvac": {"status": "OFF"},
"sdm.devices.traits.ThermostatMode": {
"availableModes": ["HEAT", "COOL", "HEATCOOL", "OFF"],
"mode": "HEAT",
},
}
)
await setup_platform()
assert len(hass.states.async_all()) == 1
thermostat = hass.states.get("climate.my_thermostat")
assert thermostat is not None
assert thermostat.state == HVACMode.HEAT
assert thermostat.attributes[ATTR_HVAC_ACTION] == HVACAction.IDLE
assert thermostat.attributes[ATTR_CURRENT_TEMPERATURE] is None
assert set(thermostat.attributes[ATTR_HVAC_MODES]) == {
HVACMode.HEAT,
HVACMode.COOL,
HVACMode.HEAT_COOL,
HVACMode.OFF,
}
assert thermostat.attributes[ATTR_TEMPERATURE] is None
assert thermostat.attributes[ATTR_TARGET_TEMP_LOW] is None
assert thermostat.attributes[ATTR_TARGET_TEMP_HIGH] is None
assert ATTR_PRESET_MODE not in thermostat.attributes
assert ATTR_PRESET_MODES not in thermostat.attributes
assert ATTR_FAN_MODE not in thermostat.attributes
assert ATTR_FAN_MODES not in thermostat.attributes
await common.async_set_temperature(hass, temperature=24.0)
await hass.async_block_till_done()
assert thermostat.attributes[ATTR_TEMPERATURE] is None
async def test_thermostat_unexpected_hvac_status(
hass: HomeAssistant,
setup_platform: PlatformSetup,
create_device: CreateDevice,
) -> None:
"""Test a thermostat missing many thermostat traits in api response."""
create_device.create(
{
"sdm.devices.traits.ThermostatHvac": {"status": "UNEXPECTED"},
}
)
await setup_platform()
assert len(hass.states.async_all()) == 1
thermostat = hass.states.get("climate.my_thermostat")
assert thermostat is not None
assert thermostat.state == HVACMode.OFF
assert ATTR_HVAC_ACTION not in thermostat.attributes
assert thermostat.attributes[ATTR_CURRENT_TEMPERATURE] is None
assert set(thermostat.attributes[ATTR_HVAC_MODES]) == set()
assert ATTR_TEMPERATURE not in thermostat.attributes
assert ATTR_TARGET_TEMP_LOW not in thermostat.attributes
assert ATTR_TARGET_TEMP_HIGH not in thermostat.attributes
assert ATTR_PRESET_MODE not in thermostat.attributes
assert ATTR_PRESET_MODES not in thermostat.attributes
assert ATTR_FAN_MODE not in thermostat.attributes
assert ATTR_FAN_MODES not in thermostat.attributes
with pytest.raises(ValueError):
await common.async_set_hvac_mode(hass, HVACMode.DRY)
await hass.async_block_till_done()
assert thermostat.state == HVACMode.OFF
async def test_thermostat_missing_set_point(
hass: HomeAssistant,
setup_platform: PlatformSetup,
create_device: CreateDevice,
) -> None:
"""Test a thermostat missing many thermostat traits in api response."""
create_device.create(
{
"sdm.devices.traits.ThermostatHvac": {"status": "OFF"},
"sdm.devices.traits.ThermostatMode": {
"availableModes": ["HEAT", "COOL", "HEATCOOL", "OFF"],
"mode": "HEATCOOL",
},
},
)
await setup_platform()
assert len(hass.states.async_all()) == 1
thermostat = hass.states.get("climate.my_thermostat")
assert thermostat is not None
assert thermostat.state == HVACMode.HEAT_COOL
assert thermostat.attributes[ATTR_HVAC_ACTION] == HVACAction.IDLE
assert thermostat.attributes[ATTR_CURRENT_TEMPERATURE] is None
assert set(thermostat.attributes[ATTR_HVAC_MODES]) == {
HVACMode.HEAT,
HVACMode.COOL,
HVACMode.HEAT_COOL,
HVACMode.OFF,
}
assert thermostat.attributes[ATTR_TEMPERATURE] is None
assert thermostat.attributes[ATTR_TARGET_TEMP_LOW] is None
assert thermostat.attributes[ATTR_TARGET_TEMP_HIGH] is None
assert ATTR_PRESET_MODE not in thermostat.attributes
assert ATTR_PRESET_MODES not in thermostat.attributes
assert ATTR_FAN_MODE not in thermostat.attributes
assert ATTR_FAN_MODES not in thermostat.attributes
async def test_thermostat_unexepected_hvac_mode(
hass: HomeAssistant,
setup_platform: PlatformSetup,
create_device: CreateDevice,
) -> None:
"""Test a thermostat missing many thermostat traits in api response."""
create_device.create(
{
"sdm.devices.traits.ThermostatHvac": {"status": "OFF"},
"sdm.devices.traits.ThermostatMode": {
"availableModes": ["HEAT", "COOL", "HEATCOOL", "OFF", "UNEXPECTED"],
"mode": "UNEXPECTED",
},
}
)
await setup_platform()
assert len(hass.states.async_all()) == 1
thermostat = hass.states.get("climate.my_thermostat")
assert thermostat is not None
assert thermostat.state == HVACMode.OFF
assert thermostat.attributes[ATTR_HVAC_ACTION] == HVACAction.OFF
assert thermostat.attributes[ATTR_CURRENT_TEMPERATURE] is None
assert set(thermostat.attributes[ATTR_HVAC_MODES]) == {
HVACMode.HEAT,
HVACMode.COOL,
HVACMode.HEAT_COOL,
HVACMode.OFF,
}
assert thermostat.attributes[ATTR_TEMPERATURE] is None
assert thermostat.attributes[ATTR_TARGET_TEMP_LOW] is None
assert thermostat.attributes[ATTR_TARGET_TEMP_HIGH] is None
assert ATTR_PRESET_MODE not in thermostat.attributes
assert ATTR_PRESET_MODES not in thermostat.attributes
assert ATTR_FAN_MODE not in thermostat.attributes
assert ATTR_FAN_MODES not in thermostat.attributes
async def test_thermostat_invalid_set_preset_mode(
hass: HomeAssistant,
setup_platform: PlatformSetup,
auth: FakeAuth,
create_device: CreateDevice,
) -> None:
"""Test a thermostat set with an invalid preset mode."""
create_device.create(
{
"sdm.devices.traits.ThermostatHvac": {"status": "OFF"},
"sdm.devices.traits.ThermostatEco": {
"availableModes": ["MANUAL_ECO", "OFF"],
"mode": "OFF",
"heatCelsius": 15.0,
"coolCelsius": 28.0,
},
}
)
await setup_platform()
assert len(hass.states.async_all()) == 1
thermostat = hass.states.get("climate.my_thermostat")
assert thermostat is not None
assert thermostat.state == HVACMode.OFF
assert thermostat.attributes[ATTR_PRESET_MODE] == PRESET_NONE
assert thermostat.attributes[ATTR_PRESET_MODES] == [PRESET_ECO, PRESET_NONE]
# Set preset mode that is invalid
with pytest.raises(ValueError):
await common.async_set_preset_mode(hass, PRESET_SLEEP)
await hass.async_block_till_done()
# No RPC sent
assert auth.method is None
# Preset is unchanged
assert thermostat.attributes[ATTR_PRESET_MODE] == PRESET_NONE
assert thermostat.attributes[ATTR_PRESET_MODES] == [PRESET_ECO, PRESET_NONE]
async def test_thermostat_hvac_mode_failure(
hass: HomeAssistant,
setup_platform: PlatformSetup,
auth: FakeAuth,
create_device: CreateDevice,
) -> None:
"""Test setting an hvac_mode that is not supported."""
create_device.create(
{
"sdm.devices.traits.ThermostatHvac": {"status": "OFF"},
"sdm.devices.traits.ThermostatMode": {
"availableModes": ["HEAT", "COOL", "HEATCOOL", "OFF"],
"mode": "COOL",
},
"sdm.devices.traits.Fan": {
"timerMode": "OFF",
"timerTimeout": "2019-05-10T03:22:54Z",
},
"sdm.devices.traits.ThermostatEco": {
"availableModes": ["MANUAL_ECO", "OFF"],
"mode": "OFF",
"heatCelsius": 15.0,
"coolCelsius": 28.0,
},
}
)
await setup_platform()
assert len(hass.states.async_all()) == 1
thermostat = hass.states.get("climate.my_thermostat")
assert thermostat is not None
assert thermostat.state == HVACMode.COOL
assert thermostat.attributes[ATTR_HVAC_ACTION] == HVACAction.IDLE
auth.responses = [aiohttp.web.Response(status=HTTPStatus.BAD_REQUEST)]
with pytest.raises(HomeAssistantError):
await common.async_set_hvac_mode(hass, HVACMode.HEAT)
await hass.async_block_till_done()
auth.responses = [aiohttp.web.Response(status=HTTPStatus.BAD_REQUEST)]
with pytest.raises(HomeAssistantError):
await common.async_set_temperature(
hass, hvac_mode=HVACMode.HEAT, temperature=25.0
)
await hass.async_block_till_done()
auth.responses = [aiohttp.web.Response(status=HTTPStatus.BAD_REQUEST)]
with pytest.raises(HomeAssistantError):
await common.async_set_fan_mode(hass, FAN_ON)
await hass.async_block_till_done()
auth.responses = [aiohttp.web.Response(status=HTTPStatus.BAD_REQUEST)]
with pytest.raises(HomeAssistantError):
await common.async_set_preset_mode(hass, PRESET_ECO)
await hass.async_block_till_done()
async def test_thermostat_available(
hass: HomeAssistant, setup_platform: PlatformSetup, create_device: CreateDevice
):
"""Test a thermostat that is available."""
create_device.create(
{
"sdm.devices.traits.ThermostatHvac": {
"status": "COOLING",
},
"sdm.devices.traits.ThermostatMode": {
"availableModes": ["HEAT", "COOL", "HEATCOOL", "OFF"],
"mode": "COOL",
},
"sdm.devices.traits.Temperature": {
"ambientTemperatureCelsius": 29.9,
},
"sdm.devices.traits.ThermostatTemperatureSetpoint": {
"coolCelsius": 28.0,
},
"sdm.devices.traits.Connectivity": {"status": "ONLINE"},
},
)
await setup_platform()
assert len(hass.states.async_all()) == 1
thermostat = hass.states.get("climate.my_thermostat")
assert thermostat is not None
assert thermostat.state == HVACMode.COOL
async def test_thermostat_unavailable(
hass: HomeAssistant, setup_platform: PlatformSetup, create_device: CreateDevice
):
"""Test a thermostat that is unavailable."""
create_device.create(
{
"sdm.devices.traits.ThermostatHvac": {
"status": "COOLING",
},
"sdm.devices.traits.ThermostatMode": {
"availableModes": ["HEAT", "COOL", "HEATCOOL", "OFF"],
"mode": "COOL",
},
"sdm.devices.traits.Temperature": {
"ambientTemperatureCelsius": 29.9,
},
"sdm.devices.traits.ThermostatTemperatureSetpoint": {
"coolCelsius": 28.0,
},
"sdm.devices.traits.Connectivity": {"status": "OFFLINE"},
},
)
await setup_platform()
assert len(hass.states.async_all()) == 1
thermostat = hass.states.get("climate.my_thermostat")
assert thermostat is not None
assert thermostat.state == STATE_UNAVAILABLE