mirror of
https://github.com/home-assistant/core.git
synced 2025-07-12 15:57:06 +00:00
Fix fan support in nest, removing FAN_ONLY which isn't supported (#73422)
* Fix fan support in nest, removing FAN_ONLY which isn't supported * Revert change to make supported features dynamic
This commit is contained in:
parent
e08465fe8c
commit
0b7a030bd4
@ -70,6 +70,7 @@ FAN_MODE_MAP = {
|
|||||||
"OFF": FAN_OFF,
|
"OFF": FAN_OFF,
|
||||||
}
|
}
|
||||||
FAN_INV_MODE_MAP = {v: k for k, v in FAN_MODE_MAP.items()}
|
FAN_INV_MODE_MAP = {v: k for k, v in FAN_MODE_MAP.items()}
|
||||||
|
FAN_INV_MODES = list(FAN_INV_MODE_MAP)
|
||||||
|
|
||||||
MAX_FAN_DURATION = 43200 # 15 hours is the max in the SDM API
|
MAX_FAN_DURATION = 43200 # 15 hours is the max in the SDM API
|
||||||
MIN_TEMP = 10
|
MIN_TEMP = 10
|
||||||
@ -99,7 +100,7 @@ class ThermostatEntity(ClimateEntity):
|
|||||||
"""Initialize ThermostatEntity."""
|
"""Initialize ThermostatEntity."""
|
||||||
self._device = device
|
self._device = device
|
||||||
self._device_info = NestDeviceInfo(device)
|
self._device_info = NestDeviceInfo(device)
|
||||||
self._supported_features = 0
|
self._attr_supported_features = 0
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def should_poll(self) -> bool:
|
def should_poll(self) -> bool:
|
||||||
@ -124,7 +125,7 @@ class ThermostatEntity(ClimateEntity):
|
|||||||
|
|
||||||
async def async_added_to_hass(self) -> None:
|
async def async_added_to_hass(self) -> None:
|
||||||
"""Run when entity is added to register update signal handler."""
|
"""Run when entity is added to register update signal handler."""
|
||||||
self._supported_features = self._get_supported_features()
|
self._attr_supported_features = self._get_supported_features()
|
||||||
self.async_on_remove(
|
self.async_on_remove(
|
||||||
self._device.add_update_listener(self.async_write_ha_state)
|
self._device.add_update_listener(self.async_write_ha_state)
|
||||||
)
|
)
|
||||||
@ -198,8 +199,6 @@ class ThermostatEntity(ClimateEntity):
|
|||||||
trait = self._device.traits[ThermostatModeTrait.NAME]
|
trait = self._device.traits[ThermostatModeTrait.NAME]
|
||||||
if trait.mode in THERMOSTAT_MODE_MAP:
|
if trait.mode in THERMOSTAT_MODE_MAP:
|
||||||
hvac_mode = THERMOSTAT_MODE_MAP[trait.mode]
|
hvac_mode = THERMOSTAT_MODE_MAP[trait.mode]
|
||||||
if hvac_mode == HVACMode.OFF and self.fan_mode == FAN_ON:
|
|
||||||
hvac_mode = HVACMode.FAN_ONLY
|
|
||||||
return hvac_mode
|
return hvac_mode
|
||||||
|
|
||||||
@property
|
@property
|
||||||
@ -209,8 +208,6 @@ class ThermostatEntity(ClimateEntity):
|
|||||||
for mode in self._get_device_hvac_modes:
|
for mode in self._get_device_hvac_modes:
|
||||||
if mode in THERMOSTAT_MODE_MAP:
|
if mode in THERMOSTAT_MODE_MAP:
|
||||||
supported_modes.append(THERMOSTAT_MODE_MAP[mode])
|
supported_modes.append(THERMOSTAT_MODE_MAP[mode])
|
||||||
if self.supported_features & ClimateEntityFeature.FAN_MODE:
|
|
||||||
supported_modes.append(HVACMode.FAN_ONLY)
|
|
||||||
return supported_modes
|
return supported_modes
|
||||||
|
|
||||||
@property
|
@property
|
||||||
@ -252,7 +249,10 @@ class ThermostatEntity(ClimateEntity):
|
|||||||
@property
|
@property
|
||||||
def fan_mode(self) -> str:
|
def fan_mode(self) -> str:
|
||||||
"""Return the current fan mode."""
|
"""Return the current fan mode."""
|
||||||
if FanTrait.NAME in self._device.traits:
|
if (
|
||||||
|
self.supported_features & ClimateEntityFeature.FAN_MODE
|
||||||
|
and FanTrait.NAME in self._device.traits
|
||||||
|
):
|
||||||
trait = self._device.traits[FanTrait.NAME]
|
trait = self._device.traits[FanTrait.NAME]
|
||||||
return FAN_MODE_MAP.get(trait.timer_mode, FAN_OFF)
|
return FAN_MODE_MAP.get(trait.timer_mode, FAN_OFF)
|
||||||
return FAN_OFF
|
return FAN_OFF
|
||||||
@ -260,15 +260,12 @@ class ThermostatEntity(ClimateEntity):
|
|||||||
@property
|
@property
|
||||||
def fan_modes(self) -> list[str]:
|
def fan_modes(self) -> list[str]:
|
||||||
"""Return the list of available fan modes."""
|
"""Return the list of available fan modes."""
|
||||||
modes = []
|
if (
|
||||||
if FanTrait.NAME in self._device.traits:
|
self.supported_features & ClimateEntityFeature.FAN_MODE
|
||||||
modes = list(FAN_INV_MODE_MAP)
|
and FanTrait.NAME in self._device.traits
|
||||||
return modes
|
):
|
||||||
|
return FAN_INV_MODES
|
||||||
@property
|
return []
|
||||||
def supported_features(self) -> int:
|
|
||||||
"""Bitmap of supported features."""
|
|
||||||
return self._supported_features
|
|
||||||
|
|
||||||
def _get_supported_features(self) -> int:
|
def _get_supported_features(self) -> int:
|
||||||
"""Compute the bitmap of supported features from the current state."""
|
"""Compute the bitmap of supported features from the current state."""
|
||||||
@ -290,10 +287,6 @@ class ThermostatEntity(ClimateEntity):
|
|||||||
"""Set new target hvac mode."""
|
"""Set new target hvac mode."""
|
||||||
if hvac_mode not in self.hvac_modes:
|
if hvac_mode not in self.hvac_modes:
|
||||||
raise ValueError(f"Unsupported hvac_mode '{hvac_mode}'")
|
raise ValueError(f"Unsupported hvac_mode '{hvac_mode}'")
|
||||||
if hvac_mode == HVACMode.FAN_ONLY:
|
|
||||||
# Turn the fan on but also turn off the hvac if it is on
|
|
||||||
await self.async_set_fan_mode(FAN_ON)
|
|
||||||
hvac_mode = HVACMode.OFF
|
|
||||||
api_mode = THERMOSTAT_INV_MODE_MAP[hvac_mode]
|
api_mode = THERMOSTAT_INV_MODE_MAP[hvac_mode]
|
||||||
trait = self._device.traits[ThermostatModeTrait.NAME]
|
trait = self._device.traits[ThermostatModeTrait.NAME]
|
||||||
try:
|
try:
|
||||||
@ -338,6 +331,10 @@ class ThermostatEntity(ClimateEntity):
|
|||||||
"""Set new target fan mode."""
|
"""Set new target fan mode."""
|
||||||
if fan_mode not in self.fan_modes:
|
if fan_mode not in self.fan_modes:
|
||||||
raise ValueError(f"Unsupported fan_mode '{fan_mode}'")
|
raise ValueError(f"Unsupported fan_mode '{fan_mode}'")
|
||||||
|
if fan_mode == FAN_ON and self.hvac_mode == HVACMode.OFF:
|
||||||
|
raise ValueError(
|
||||||
|
"Cannot turn on fan, please set an HVAC mode (e.g. heat/cool) first"
|
||||||
|
)
|
||||||
trait = self._device.traits[FanTrait.NAME]
|
trait = self._device.traits[FanTrait.NAME]
|
||||||
duration = None
|
duration = None
|
||||||
if fan_mode != FAN_OFF:
|
if fan_mode != FAN_OFF:
|
||||||
|
@ -33,15 +33,15 @@ from homeassistant.components.climate.const import (
|
|||||||
FAN_ON,
|
FAN_ON,
|
||||||
HVAC_MODE_COOL,
|
HVAC_MODE_COOL,
|
||||||
HVAC_MODE_DRY,
|
HVAC_MODE_DRY,
|
||||||
HVAC_MODE_FAN_ONLY,
|
|
||||||
HVAC_MODE_HEAT,
|
HVAC_MODE_HEAT,
|
||||||
HVAC_MODE_HEAT_COOL,
|
HVAC_MODE_HEAT_COOL,
|
||||||
HVAC_MODE_OFF,
|
HVAC_MODE_OFF,
|
||||||
PRESET_ECO,
|
PRESET_ECO,
|
||||||
PRESET_NONE,
|
PRESET_NONE,
|
||||||
PRESET_SLEEP,
|
PRESET_SLEEP,
|
||||||
|
ClimateEntityFeature,
|
||||||
)
|
)
|
||||||
from homeassistant.const import ATTR_TEMPERATURE
|
from homeassistant.const import ATTR_SUPPORTED_FEATURES, ATTR_TEMPERATURE
|
||||||
from homeassistant.core import HomeAssistant
|
from homeassistant.core import HomeAssistant
|
||||||
from homeassistant.exceptions import HomeAssistantError
|
from homeassistant.exceptions import HomeAssistantError
|
||||||
|
|
||||||
@ -794,7 +794,7 @@ async def test_thermostat_fan_off(
|
|||||||
"sdm.devices.traits.ThermostatHvac": {"status": "OFF"},
|
"sdm.devices.traits.ThermostatHvac": {"status": "OFF"},
|
||||||
"sdm.devices.traits.ThermostatMode": {
|
"sdm.devices.traits.ThermostatMode": {
|
||||||
"availableModes": ["HEAT", "COOL", "HEATCOOL", "OFF"],
|
"availableModes": ["HEAT", "COOL", "HEATCOOL", "OFF"],
|
||||||
"mode": "OFF",
|
"mode": "COOL",
|
||||||
},
|
},
|
||||||
"sdm.devices.traits.Temperature": {
|
"sdm.devices.traits.Temperature": {
|
||||||
"ambientTemperatureCelsius": 16.2,
|
"ambientTemperatureCelsius": 16.2,
|
||||||
@ -806,18 +806,22 @@ async def test_thermostat_fan_off(
|
|||||||
assert len(hass.states.async_all()) == 1
|
assert len(hass.states.async_all()) == 1
|
||||||
thermostat = hass.states.get("climate.my_thermostat")
|
thermostat = hass.states.get("climate.my_thermostat")
|
||||||
assert thermostat is not None
|
assert thermostat is not None
|
||||||
assert thermostat.state == HVAC_MODE_OFF
|
assert thermostat.state == HVAC_MODE_COOL
|
||||||
assert thermostat.attributes[ATTR_HVAC_ACTION] == CURRENT_HVAC_OFF
|
assert thermostat.attributes[ATTR_HVAC_ACTION] == CURRENT_HVAC_IDLE
|
||||||
assert thermostat.attributes[ATTR_CURRENT_TEMPERATURE] == 16.2
|
assert thermostat.attributes[ATTR_CURRENT_TEMPERATURE] == 16.2
|
||||||
assert set(thermostat.attributes[ATTR_HVAC_MODES]) == {
|
assert set(thermostat.attributes[ATTR_HVAC_MODES]) == {
|
||||||
HVAC_MODE_HEAT,
|
HVAC_MODE_HEAT,
|
||||||
HVAC_MODE_COOL,
|
HVAC_MODE_COOL,
|
||||||
HVAC_MODE_HEAT_COOL,
|
HVAC_MODE_HEAT_COOL,
|
||||||
HVAC_MODE_FAN_ONLY,
|
|
||||||
HVAC_MODE_OFF,
|
HVAC_MODE_OFF,
|
||||||
}
|
}
|
||||||
assert thermostat.attributes[ATTR_FAN_MODE] == FAN_OFF
|
assert thermostat.attributes[ATTR_FAN_MODE] == FAN_OFF
|
||||||
assert thermostat.attributes[ATTR_FAN_MODES] == [FAN_ON, 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(
|
async def test_thermostat_fan_on(
|
||||||
@ -837,7 +841,7 @@ async def test_thermostat_fan_on(
|
|||||||
},
|
},
|
||||||
"sdm.devices.traits.ThermostatMode": {
|
"sdm.devices.traits.ThermostatMode": {
|
||||||
"availableModes": ["HEAT", "COOL", "HEATCOOL", "OFF"],
|
"availableModes": ["HEAT", "COOL", "HEATCOOL", "OFF"],
|
||||||
"mode": "OFF",
|
"mode": "COOL",
|
||||||
},
|
},
|
||||||
"sdm.devices.traits.Temperature": {
|
"sdm.devices.traits.Temperature": {
|
||||||
"ambientTemperatureCelsius": 16.2,
|
"ambientTemperatureCelsius": 16.2,
|
||||||
@ -849,18 +853,22 @@ async def test_thermostat_fan_on(
|
|||||||
assert len(hass.states.async_all()) == 1
|
assert len(hass.states.async_all()) == 1
|
||||||
thermostat = hass.states.get("climate.my_thermostat")
|
thermostat = hass.states.get("climate.my_thermostat")
|
||||||
assert thermostat is not None
|
assert thermostat is not None
|
||||||
assert thermostat.state == HVAC_MODE_FAN_ONLY
|
assert thermostat.state == HVAC_MODE_COOL
|
||||||
assert thermostat.attributes[ATTR_HVAC_ACTION] == CURRENT_HVAC_IDLE
|
assert thermostat.attributes[ATTR_HVAC_ACTION] == CURRENT_HVAC_IDLE
|
||||||
assert thermostat.attributes[ATTR_CURRENT_TEMPERATURE] == 16.2
|
assert thermostat.attributes[ATTR_CURRENT_TEMPERATURE] == 16.2
|
||||||
assert set(thermostat.attributes[ATTR_HVAC_MODES]) == {
|
assert set(thermostat.attributes[ATTR_HVAC_MODES]) == {
|
||||||
HVAC_MODE_HEAT,
|
HVAC_MODE_HEAT,
|
||||||
HVAC_MODE_COOL,
|
HVAC_MODE_COOL,
|
||||||
HVAC_MODE_HEAT_COOL,
|
HVAC_MODE_HEAT_COOL,
|
||||||
HVAC_MODE_FAN_ONLY,
|
|
||||||
HVAC_MODE_OFF,
|
HVAC_MODE_OFF,
|
||||||
}
|
}
|
||||||
assert thermostat.attributes[ATTR_FAN_MODE] == FAN_ON
|
assert thermostat.attributes[ATTR_FAN_MODE] == FAN_ON
|
||||||
assert thermostat.attributes[ATTR_FAN_MODES] == [FAN_ON, 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_cool_with_fan(
|
async def test_thermostat_cool_with_fan(
|
||||||
@ -895,11 +903,15 @@ async def test_thermostat_cool_with_fan(
|
|||||||
HVAC_MODE_HEAT,
|
HVAC_MODE_HEAT,
|
||||||
HVAC_MODE_COOL,
|
HVAC_MODE_COOL,
|
||||||
HVAC_MODE_HEAT_COOL,
|
HVAC_MODE_HEAT_COOL,
|
||||||
HVAC_MODE_FAN_ONLY,
|
|
||||||
HVAC_MODE_OFF,
|
HVAC_MODE_OFF,
|
||||||
}
|
}
|
||||||
assert thermostat.attributes[ATTR_FAN_MODE] == FAN_ON
|
assert thermostat.attributes[ATTR_FAN_MODE] == FAN_ON
|
||||||
assert thermostat.attributes[ATTR_FAN_MODES] == [FAN_ON, 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_set_fan(
|
async def test_thermostat_set_fan(
|
||||||
@ -907,6 +919,68 @@ async def test_thermostat_set_fan(
|
|||||||
setup_platform: PlatformSetup,
|
setup_platform: PlatformSetup,
|
||||||
auth: FakeAuth,
|
auth: FakeAuth,
|
||||||
create_device: CreateDevice,
|
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 == HVAC_MODE_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:
|
) -> None:
|
||||||
"""Test a thermostat enabling the fan."""
|
"""Test a thermostat enabling the fan."""
|
||||||
create_device.create(
|
create_device.create(
|
||||||
@ -929,34 +1003,18 @@ async def test_thermostat_set_fan(
|
|||||||
assert len(hass.states.async_all()) == 1
|
assert len(hass.states.async_all()) == 1
|
||||||
thermostat = hass.states.get("climate.my_thermostat")
|
thermostat = hass.states.get("climate.my_thermostat")
|
||||||
assert thermostat is not None
|
assert thermostat is not None
|
||||||
assert thermostat.state == HVAC_MODE_FAN_ONLY
|
assert thermostat.state == HVAC_MODE_OFF
|
||||||
assert thermostat.attributes[ATTR_FAN_MODE] == FAN_ON
|
assert thermostat.attributes[ATTR_FAN_MODE] == FAN_ON
|
||||||
assert thermostat.attributes[ATTR_FAN_MODES] == [FAN_ON, 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
|
||||||
|
)
|
||||||
|
|
||||||
# Turn off fan mode
|
# Fan cannot be turned on when HVAC is off
|
||||||
await common.async_set_fan_mode(hass, FAN_OFF)
|
with pytest.raises(ValueError):
|
||||||
await hass.async_block_till_done()
|
await common.async_set_fan_mode(hass, FAN_ON, entity_id="climate.my_thermostat")
|
||||||
|
|
||||||
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_fan_empty(
|
async def test_thermostat_fan_empty(
|
||||||
@ -994,6 +1052,10 @@ async def test_thermostat_fan_empty(
|
|||||||
}
|
}
|
||||||
assert ATTR_FAN_MODE not in thermostat.attributes
|
assert ATTR_FAN_MODE not in thermostat.attributes
|
||||||
assert ATTR_FAN_MODES 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
|
# Ignores set_fan_mode since it is lacking SUPPORT_FAN_MODE
|
||||||
await common.async_set_fan_mode(hass, FAN_ON)
|
await common.async_set_fan_mode(hass, FAN_ON)
|
||||||
@ -1018,7 +1080,7 @@ async def test_thermostat_invalid_fan_mode(
|
|||||||
"sdm.devices.traits.ThermostatHvac": {"status": "OFF"},
|
"sdm.devices.traits.ThermostatHvac": {"status": "OFF"},
|
||||||
"sdm.devices.traits.ThermostatMode": {
|
"sdm.devices.traits.ThermostatMode": {
|
||||||
"availableModes": ["HEAT", "COOL", "HEATCOOL", "OFF"],
|
"availableModes": ["HEAT", "COOL", "HEATCOOL", "OFF"],
|
||||||
"mode": "OFF",
|
"mode": "COOL",
|
||||||
},
|
},
|
||||||
"sdm.devices.traits.Temperature": {
|
"sdm.devices.traits.Temperature": {
|
||||||
"ambientTemperatureCelsius": 16.2,
|
"ambientTemperatureCelsius": 16.2,
|
||||||
@ -1030,14 +1092,13 @@ async def test_thermostat_invalid_fan_mode(
|
|||||||
assert len(hass.states.async_all()) == 1
|
assert len(hass.states.async_all()) == 1
|
||||||
thermostat = hass.states.get("climate.my_thermostat")
|
thermostat = hass.states.get("climate.my_thermostat")
|
||||||
assert thermostat is not None
|
assert thermostat is not None
|
||||||
assert thermostat.state == HVAC_MODE_FAN_ONLY
|
assert thermostat.state == HVAC_MODE_COOL
|
||||||
assert thermostat.attributes[ATTR_HVAC_ACTION] == CURRENT_HVAC_IDLE
|
assert thermostat.attributes[ATTR_HVAC_ACTION] == CURRENT_HVAC_IDLE
|
||||||
assert thermostat.attributes[ATTR_CURRENT_TEMPERATURE] == 16.2
|
assert thermostat.attributes[ATTR_CURRENT_TEMPERATURE] == 16.2
|
||||||
assert set(thermostat.attributes[ATTR_HVAC_MODES]) == {
|
assert set(thermostat.attributes[ATTR_HVAC_MODES]) == {
|
||||||
HVAC_MODE_HEAT,
|
HVAC_MODE_HEAT,
|
||||||
HVAC_MODE_COOL,
|
HVAC_MODE_COOL,
|
||||||
HVAC_MODE_HEAT_COOL,
|
HVAC_MODE_HEAT_COOL,
|
||||||
HVAC_MODE_FAN_ONLY,
|
|
||||||
HVAC_MODE_OFF,
|
HVAC_MODE_OFF,
|
||||||
}
|
}
|
||||||
assert thermostat.attributes[ATTR_FAN_MODE] == FAN_ON
|
assert thermostat.attributes[ATTR_FAN_MODE] == FAN_ON
|
||||||
@ -1048,58 +1109,6 @@ async def test_thermostat_invalid_fan_mode(
|
|||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
|
|
||||||
async def test_thermostat_set_hvac_fan_only(
|
|
||||||
hass: HomeAssistant,
|
|
||||||
setup_platform: PlatformSetup,
|
|
||||||
auth: FakeAuth,
|
|
||||||
create_device: CreateDevice,
|
|
||||||
) -> None:
|
|
||||||
"""Test a thermostat enabling the fan via hvac_mode."""
|
|
||||||
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": "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 == HVAC_MODE_OFF
|
|
||||||
assert thermostat.attributes[ATTR_FAN_MODE] == FAN_OFF
|
|
||||||
assert thermostat.attributes[ATTR_FAN_MODES] == [FAN_ON, FAN_OFF]
|
|
||||||
|
|
||||||
await common.async_set_hvac_mode(hass, HVAC_MODE_FAN_ONLY)
|
|
||||||
await hass.async_block_till_done()
|
|
||||||
|
|
||||||
assert len(auth.captured_requests) == 2
|
|
||||||
|
|
||||||
(method, url, json, headers) = auth.captured_requests.pop(0)
|
|
||||||
assert method == "post"
|
|
||||||
assert url == DEVICE_COMMAND
|
|
||||||
assert json == {
|
|
||||||
"command": "sdm.devices.commands.Fan.SetTimer",
|
|
||||||
"params": {"duration": "43200s", "timerMode": "ON"},
|
|
||||||
}
|
|
||||||
(method, url, json, headers) = auth.captured_requests.pop(0)
|
|
||||||
assert method == "post"
|
|
||||||
assert url == DEVICE_COMMAND
|
|
||||||
assert json == {
|
|
||||||
"command": "sdm.devices.commands.ThermostatMode.SetMode",
|
|
||||||
"params": {"mode": "OFF"},
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
async def test_thermostat_target_temp(
|
async def test_thermostat_target_temp(
|
||||||
hass: HomeAssistant,
|
hass: HomeAssistant,
|
||||||
setup_platform: PlatformSetup,
|
setup_platform: PlatformSetup,
|
||||||
@ -1397,7 +1406,7 @@ async def test_thermostat_hvac_mode_failure(
|
|||||||
"sdm.devices.traits.ThermostatHvac": {"status": "OFF"},
|
"sdm.devices.traits.ThermostatHvac": {"status": "OFF"},
|
||||||
"sdm.devices.traits.ThermostatMode": {
|
"sdm.devices.traits.ThermostatMode": {
|
||||||
"availableModes": ["HEAT", "COOL", "HEATCOOL", "OFF"],
|
"availableModes": ["HEAT", "COOL", "HEATCOOL", "OFF"],
|
||||||
"mode": "OFF",
|
"mode": "COOL",
|
||||||
},
|
},
|
||||||
"sdm.devices.traits.Fan": {
|
"sdm.devices.traits.Fan": {
|
||||||
"timerMode": "OFF",
|
"timerMode": "OFF",
|
||||||
@ -1416,8 +1425,8 @@ async def test_thermostat_hvac_mode_failure(
|
|||||||
assert len(hass.states.async_all()) == 1
|
assert len(hass.states.async_all()) == 1
|
||||||
thermostat = hass.states.get("climate.my_thermostat")
|
thermostat = hass.states.get("climate.my_thermostat")
|
||||||
assert thermostat is not None
|
assert thermostat is not None
|
||||||
assert thermostat.state == HVAC_MODE_OFF
|
assert thermostat.state == HVAC_MODE_COOL
|
||||||
assert thermostat.attributes[ATTR_HVAC_ACTION] == CURRENT_HVAC_OFF
|
assert thermostat.attributes[ATTR_HVAC_ACTION] == CURRENT_HVAC_IDLE
|
||||||
|
|
||||||
auth.responses = [aiohttp.web.Response(status=HTTPStatus.BAD_REQUEST)]
|
auth.responses = [aiohttp.web.Response(status=HTTPStatus.BAD_REQUEST)]
|
||||||
with pytest.raises(HomeAssistantError):
|
with pytest.raises(HomeAssistantError):
|
||||||
|
Loading…
x
Reference in New Issue
Block a user