Add TURN_OFF and TURN_ON to ClimateEntityFeature (#101673)

* Add ClimateEntityFeature.TURN_OFF

* Fixes

* Fixes

* wording

* Change to services

* Fixing

* Fixing

* Last bits

* Review comments

* Add hvac_modes checks

* Fixes

* Add tests

* Review comments

* Update snapshots

* balboa

* coolmaster

* ecobee

* mqtt

* nest

* plugwise

* smarttub

* whirlpool

* zwave_js

* fix test climate

* test climate

* zwave

* nexia

* nuheat

* venstar

* tado

* smartthings

* self.hvac_modes not None

* more tests

* homekit_controller

* homekit controller snapshot
pull/108964/head
G Johansson 2024-01-30 15:07:47 +01:00 committed by GitHub
parent cece117c93
commit bc720b48b4
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
31 changed files with 534 additions and 110 deletions

View File

@ -1,6 +1,7 @@
"""Provides functionality to interact with climate devices."""
from __future__ import annotations
import asyncio
from datetime import timedelta
import functools as ft
import logging
@ -34,6 +35,7 @@ from homeassistant.helpers.deprecation import (
)
from homeassistant.helpers.entity import Entity, EntityDescription
from homeassistant.helpers.entity_component import EntityComponent
from homeassistant.helpers.entity_platform import EntityPlatform
from homeassistant.helpers.temperature import display_temp as show_temp
from homeassistant.helpers.typing import ConfigType
from homeassistant.util.unit_conversion import TemperatureConverter
@ -152,8 +154,18 @@ async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
)
await component.async_setup(config)
component.async_register_entity_service(SERVICE_TURN_ON, {}, "async_turn_on")
component.async_register_entity_service(SERVICE_TURN_OFF, {}, "async_turn_off")
component.async_register_entity_service(
SERVICE_TURN_ON,
{},
"async_turn_on",
[ClimateEntityFeature.TURN_ON],
)
component.async_register_entity_service(
SERVICE_TURN_OFF,
{},
"async_turn_off",
[ClimateEntityFeature.TURN_OFF],
)
component.async_register_entity_service(
SERVICE_SET_HVAC_MODE,
{vol.Required(ATTR_HVAC_MODE): vol.Coerce(HVACMode)},
@ -288,6 +300,102 @@ class ClimateEntity(Entity, cached_properties=CACHED_PROPERTIES_WITH_ATTR_):
_attr_target_temperature: float | None = None
_attr_temperature_unit: str
__mod_supported_features: ClimateEntityFeature = ClimateEntityFeature(0)
def __getattribute__(self, __name: str) -> Any:
"""Get attribute.
Modify return of `supported_features` to
include `_mod_supported_features` if attribute is set.
"""
if __name != "supported_features":
return super().__getattribute__(__name)
# Convert the supported features to ClimateEntityFeature.
# Remove this compatibility shim in 2025.1 or later.
_supported_features = super().__getattribute__(__name)
if type(_supported_features) is int: # noqa: E721
new_features = ClimateEntityFeature(_supported_features)
self._report_deprecated_supported_features_values(new_features)
# Add automatically calculated ClimateEntityFeature.TURN_OFF/TURN_ON to
# supported features and return it
return _supported_features | super().__getattribute__(
"_ClimateEntity__mod_supported_features"
)
@callback
def add_to_platform_start(
self,
hass: HomeAssistant,
platform: EntityPlatform,
parallel_updates: asyncio.Semaphore | None,
) -> None:
"""Start adding an entity to a platform."""
super().add_to_platform_start(hass, platform, parallel_updates)
def _report_turn_on_off(feature: str, method: str) -> None:
"""Log warning not implemented turn on/off feature."""
report_issue = self._suggest_report_issue()
if feature.startswith("TURN"):
message = (
"Entity %s (%s) does not set ClimateEntityFeature.%s"
" but implements the %s method. Please %s"
)
else:
message = (
"Entity %s (%s) implements HVACMode(s): %s and therefore implicitly"
" supports the %s service without setting the proper"
" ClimateEntityFeature. Please %s"
)
_LOGGER.warning(
message,
self.entity_id,
type(self),
feature,
feature.lower(),
report_issue,
)
# Adds ClimateEntityFeature.TURN_OFF/TURN_ON depending on service calls implemented
# This should be removed in 2025.1.
if not self.supported_features & ClimateEntityFeature.TURN_OFF:
if (
type(self).async_turn_off is not ClimateEntity.async_turn_off
or type(self).turn_off is not ClimateEntity.turn_off
):
# turn_off implicitly supported by implementing turn_off method
_report_turn_on_off("TURN_OFF", "turn_off")
self.__mod_supported_features |= ( # pylint: disable=unused-private-member
ClimateEntityFeature.TURN_OFF
)
elif self.hvac_modes and HVACMode.OFF in self.hvac_modes:
# turn_off implicitly supported by including HVACMode.OFF
_report_turn_on_off("off", "turn_off")
self.__mod_supported_features |= ( # pylint: disable=unused-private-member
ClimateEntityFeature.TURN_OFF
)
if not self.supported_features & ClimateEntityFeature.TURN_ON:
if (
type(self).async_turn_on is not ClimateEntity.async_turn_on
or type(self).turn_on is not ClimateEntity.turn_on
):
# turn_on implicitly supported by implementing turn_on method
_report_turn_on_off("TURN_ON", "turn_on")
self.__mod_supported_features |= ( # pylint: disable=unused-private-member
ClimateEntityFeature.TURN_ON
)
elif self.hvac_modes and any(
_mode != HVACMode.OFF and _mode is not None for _mode in self.hvac_modes
):
# turn_on implicitly supported by including any other HVACMode than HVACMode.OFF
_modes = [_mode for _mode in self.hvac_modes if _mode != HVACMode.OFF]
_report_turn_on_off(", ".join(_modes or []), "turn_on")
self.__mod_supported_features |= ( # pylint: disable=unused-private-member
ClimateEntityFeature.TURN_ON
)
@final
@property
def state(self) -> str | None:
@ -312,7 +420,7 @@ class ClimateEntity(Entity, cached_properties=CACHED_PROPERTIES_WITH_ATTR_):
@property
def capability_attributes(self) -> dict[str, Any] | None:
"""Return the capability attributes."""
supported_features = self.supported_features_compat
supported_features = self.supported_features
temperature_unit = self.temperature_unit
precision = self.precision
hass = self.hass
@ -345,7 +453,7 @@ class ClimateEntity(Entity, cached_properties=CACHED_PROPERTIES_WITH_ATTR_):
@property
def state_attributes(self) -> dict[str, Any]:
"""Return the optional state attributes."""
supported_features = self.supported_features_compat
supported_features = self.supported_features
temperature_unit = self.temperature_unit
precision = self.precision
hass = self.hass
@ -625,9 +733,14 @@ class ClimateEntity(Entity, cached_properties=CACHED_PROPERTIES_WITH_ATTR_):
"""Turn auxiliary heater off."""
await self.hass.async_add_executor_job(self.turn_aux_heat_off)
def turn_on(self) -> None:
"""Turn the entity on."""
raise NotImplementedError
async def async_turn_on(self) -> None:
"""Turn the entity on."""
if hasattr(self, "turn_on"):
# Forward to self.turn_on if it's been overridden.
if type(self).turn_on is not ClimateEntity.turn_on:
await self.hass.async_add_executor_job(self.turn_on)
return
@ -646,9 +759,14 @@ class ClimateEntity(Entity, cached_properties=CACHED_PROPERTIES_WITH_ATTR_):
await self.async_set_hvac_mode(mode)
break
def turn_off(self) -> None:
"""Turn the entity off."""
raise NotImplementedError
async def async_turn_off(self) -> None:
"""Turn the entity off."""
if hasattr(self, "turn_off"):
# Forward to self.turn_on if it's been overridden.
if type(self).turn_off is not ClimateEntity.turn_off:
await self.hass.async_add_executor_job(self.turn_off)
return
@ -661,19 +779,6 @@ class ClimateEntity(Entity, cached_properties=CACHED_PROPERTIES_WITH_ATTR_):
"""Return the list of supported features."""
return self._attr_supported_features
@property
def supported_features_compat(self) -> ClimateEntityFeature:
"""Return the supported features as ClimateEntityFeature.
Remove this compatibility shim in 2025.1 or later.
"""
features = self.supported_features
if type(features) is int: # noqa: E721
new_features = ClimateEntityFeature(features)
self._report_deprecated_supported_features_values(new_features)
return new_features
return features
@cached_property
def min_temp(self) -> float:
"""Return the minimum temperature."""

View File

@ -163,6 +163,8 @@ class ClimateEntityFeature(IntFlag):
PRESET_MODE = 16
SWING_MODE = 32
AUX_HEAT = 64
TURN_OFF = 128
TURN_ON = 256
# These SUPPORT_* constants are deprecated as of Home Assistant 2022.5.

View File

@ -139,8 +139,12 @@ turn_on:
target:
entity:
domain: climate
supported_features:
- climate.ClimateEntityFeature.TURN_ON
turn_off:
target:
entity:
domain: climate
supported_features:
- climate.ClimateEntityFeature.TURN_OFF

View File

@ -40,7 +40,7 @@
]),
'max_temp': 32,
'min_temp': 16,
'supported_features': <ClimateEntityFeature: 11>,
'supported_features': <ClimateEntityFeature: 395>,
'target_temp_high': 24,
'target_temp_low': 20,
'target_temp_step': 1,

View File

@ -51,7 +51,10 @@ async def test_spa_defaults(
assert state
assert (
state.attributes["supported_features"]
== ClimateEntityFeature.TARGET_TEMPERATURE | ClimateEntityFeature.PRESET_MODE
== ClimateEntityFeature.TARGET_TEMPERATURE
| ClimateEntityFeature.PRESET_MODE
| ClimateEntityFeature.TURN_OFF
| ClimateEntityFeature.TURN_ON
)
assert state.state == HVACMode.HEAT
assert state.attributes[ATTR_MIN_TEMP] == 10.0
@ -71,7 +74,10 @@ async def test_spa_defaults_fake_tscale(
assert state
assert (
state.attributes["supported_features"]
== ClimateEntityFeature.TARGET_TEMPERATURE | ClimateEntityFeature.PRESET_MODE
== ClimateEntityFeature.TARGET_TEMPERATURE
| ClimateEntityFeature.PRESET_MODE
| ClimateEntityFeature.TURN_OFF
| ClimateEntityFeature.TURN_ON
)
assert state.state == HVACMode.HEAT
assert state.attributes[ATTR_MIN_TEMP] == 10.0
@ -174,6 +180,8 @@ async def test_spa_with_blower(hass: HomeAssistant, client: MagicMock) -> None:
== ClimateEntityFeature.TARGET_TEMPERATURE
| ClimateEntityFeature.PRESET_MODE
| ClimateEntityFeature.FAN_MODE
| ClimateEntityFeature.TURN_OFF
| ClimateEntityFeature.TURN_ON
)
assert state.state == HVACMode.HEAT
assert state.attributes[ATTR_MIN_TEMP] == 10.0

View File

@ -45,7 +45,7 @@
'original_name': None,
'platform': 'ccm15',
'previous_unique_id': None,
'supported_features': <ClimateEntityFeature: 41>,
'supported_features': <ClimateEntityFeature: 425>,
'translation_key': None,
'unique_id': '1.1.1.1.0',
'unit_of_measurement': None,
@ -97,7 +97,7 @@
'original_name': None,
'platform': 'ccm15',
'previous_unique_id': None,
'supported_features': <ClimateEntityFeature: 41>,
'supported_features': <ClimateEntityFeature: 425>,
'translation_key': None,
'unique_id': '1.1.1.1.1',
'unit_of_measurement': None,
@ -125,7 +125,7 @@
]),
'max_temp': 35,
'min_temp': 7,
'supported_features': <ClimateEntityFeature: 41>,
'supported_features': <ClimateEntityFeature: 425>,
'swing_mode': 'off',
'swing_modes': list([
'off',
@ -163,7 +163,7 @@
]),
'max_temp': 35,
'min_temp': 7,
'supported_features': <ClimateEntityFeature: 41>,
'supported_features': <ClimateEntityFeature: 425>,
'swing_mode': 'off',
'swing_modes': list([
'off',
@ -225,7 +225,7 @@
'original_name': None,
'platform': 'ccm15',
'previous_unique_id': None,
'supported_features': <ClimateEntityFeature: 41>,
'supported_features': <ClimateEntityFeature: 425>,
'translation_key': None,
'unique_id': '1.1.1.1.0',
'unit_of_measurement': None,
@ -277,7 +277,7 @@
'original_name': None,
'platform': 'ccm15',
'previous_unique_id': None,
'supported_features': <ClimateEntityFeature: 41>,
'supported_features': <ClimateEntityFeature: 425>,
'translation_key': None,
'unique_id': '1.1.1.1.1',
'unit_of_measurement': None,
@ -302,7 +302,7 @@
]),
'max_temp': 35,
'min_temp': 7,
'supported_features': <ClimateEntityFeature: 41>,
'supported_features': <ClimateEntityFeature: 425>,
'swing_modes': list([
'off',
'on',
@ -335,7 +335,7 @@
]),
'max_temp': 35,
'min_temp': 7,
'supported_features': <ClimateEntityFeature: 41>,
'supported_features': <ClimateEntityFeature: 425>,
'swing_modes': list([
'off',
'on',

View File

@ -25,7 +25,7 @@ from homeassistant.components.climate.const import (
ClimateEntityFeature,
)
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import UnitOfTemperature
from homeassistant.const import SERVICE_TURN_OFF, SERVICE_TURN_ON, UnitOfTemperature
from homeassistant.core import HomeAssistant
from homeassistant.exceptions import ServiceValidationError
from homeassistant.helpers.entity_platform import AddEntitiesCallback
@ -154,7 +154,8 @@ async def test_sync_turn_off(hass: HomeAssistant) -> None:
def _create_tuples(enum: Enum, constant_prefix: str) -> list[tuple[Enum, str]]:
result = []
for enum in enum:
result.append((enum, constant_prefix))
if enum not in [ClimateEntityFeature.TURN_ON, ClimateEntityFeature.TURN_OFF]:
result.append((enum, constant_prefix))
return result
@ -355,11 +356,262 @@ def test_deprecated_supported_features_ints(caplog: pytest.LogCaptureFixture) ->
return 1
entity = MockClimateEntity()
assert entity.supported_features_compat is ClimateEntityFeature(1)
assert entity.supported_features is ClimateEntityFeature(1)
assert "MockClimateEntity" in caplog.text
assert "is using deprecated supported features values" in caplog.text
assert "Instead it should use" in caplog.text
assert "ClimateEntityFeature.TARGET_TEMPERATURE" in caplog.text
caplog.clear()
assert entity.supported_features_compat is ClimateEntityFeature(1)
assert entity.supported_features is ClimateEntityFeature(1)
assert "is using deprecated supported features values" not in caplog.text
async def test_warning_not_implemented_turn_on_off_feature(
hass: HomeAssistant, caplog: pytest.LogCaptureFixture, config_flow_fixture: None
) -> None:
"""Test adding feature flag and warn if missing when methods are set."""
called = []
class MockClimateEntityTest(MockClimateEntity):
"""Mock Climate device."""
def turn_on(self) -> None:
"""Turn on."""
called.append("turn_on")
def turn_off(self) -> None:
"""Turn off."""
called.append("turn_off")
async def async_setup_entry_init(
hass: HomeAssistant, config_entry: ConfigEntry
) -> bool:
"""Set up test config entry."""
await hass.config_entries.async_forward_entry_setups(config_entry, [DOMAIN])
return True
async def async_setup_entry_climate_platform(
hass: HomeAssistant,
config_entry: ConfigEntry,
async_add_entities: AddEntitiesCallback,
) -> None:
"""Set up test climate platform via config entry."""
async_add_entities(
[MockClimateEntityTest(name="test", entity_id="climate.test")]
)
mock_integration(
hass,
MockModule(
"test",
async_setup_entry=async_setup_entry_init,
),
built_in=False,
)
mock_platform(
hass,
"test.climate",
MockPlatform(async_setup_entry=async_setup_entry_climate_platform),
)
config_entry = MockConfigEntry(domain="test")
config_entry.add_to_hass(hass)
assert await hass.config_entries.async_setup(config_entry.entry_id)
await hass.async_block_till_done()
state = hass.states.get("climate.test")
assert state is not None
assert (
"Entity climate.test (<class 'tests.components.climate.test_init."
"test_warning_not_implemented_turn_on_off_feature.<locals>.MockClimateEntityTest'>)"
" does not set ClimateEntityFeature.TURN_OFF but implements the turn_off method."
" Please report it to the author of the 'test' custom integration"
in caplog.text
)
assert (
"Entity climate.test (<class 'tests.components.climate.test_init."
"test_warning_not_implemented_turn_on_off_feature.<locals>.MockClimateEntityTest'>)"
" does not set ClimateEntityFeature.TURN_ON but implements the turn_on method."
" Please report it to the author of the 'test' custom integration"
in caplog.text
)
await hass.services.async_call(
DOMAIN,
SERVICE_TURN_ON,
{
"entity_id": "climate.test",
},
blocking=True,
)
await hass.services.async_call(
DOMAIN,
SERVICE_TURN_OFF,
{
"entity_id": "climate.test",
},
blocking=True,
)
assert len(called) == 2
assert "turn_on" in called
assert "turn_off" in called
async def test_implicit_warning_not_implemented_turn_on_off_feature(
hass: HomeAssistant, caplog: pytest.LogCaptureFixture, config_flow_fixture: None
) -> None:
"""Test adding feature flag and warn if missing when methods are not set.
(implicit by hvac mode)
"""
class MockClimateEntityTest(MockEntity, ClimateEntity):
"""Mock Climate device."""
_attr_temperature_unit = UnitOfTemperature.CELSIUS
@property
def hvac_mode(self) -> HVACMode:
"""Return hvac operation ie. heat, cool mode.
Need to be one of HVACMode.*.
"""
return HVACMode.HEAT
@property
def hvac_modes(self) -> list[HVACMode]:
"""Return the list of available hvac operation modes.
Need to be a subset of HVAC_MODES.
"""
return [HVACMode.OFF, HVACMode.HEAT]
async def async_setup_entry_init(
hass: HomeAssistant, config_entry: ConfigEntry
) -> bool:
"""Set up test config entry."""
await hass.config_entries.async_forward_entry_setups(config_entry, [DOMAIN])
return True
async def async_setup_entry_climate_platform(
hass: HomeAssistant,
config_entry: ConfigEntry,
async_add_entities: AddEntitiesCallback,
) -> None:
"""Set up test climate platform via config entry."""
async_add_entities(
[MockClimateEntityTest(name="test", entity_id="climate.test")]
)
mock_integration(
hass,
MockModule(
"test",
async_setup_entry=async_setup_entry_init,
),
built_in=False,
)
mock_platform(
hass,
"test.climate",
MockPlatform(async_setup_entry=async_setup_entry_climate_platform),
)
config_entry = MockConfigEntry(domain="test")
config_entry.add_to_hass(hass)
assert await hass.config_entries.async_setup(config_entry.entry_id)
await hass.async_block_till_done()
state = hass.states.get("climate.test")
assert state is not None
assert (
"Entity climate.test (<class 'tests.components.climate.test_init."
"test_implicit_warning_not_implemented_turn_on_off_feature.<locals>.MockClimateEntityTest'>)"
" implements HVACMode(s): off and therefore implicitly supports the off service without setting"
" the proper ClimateEntityFeature. Please report it to the author of the 'test' custom integration"
in caplog.text
)
assert (
"Entity climate.test (<class 'tests.components.climate.test_init."
"test_implicit_warning_not_implemented_turn_on_off_feature.<locals>.MockClimateEntityTest'>)"
" implements HVACMode(s): heat and therefore implicitly supports the heat service without setting"
" the proper ClimateEntityFeature. Please report it to the author of the 'test' custom integration"
in caplog.text
)
async def test_no_warning_implemented_turn_on_off_feature(
hass: HomeAssistant, caplog: pytest.LogCaptureFixture, config_flow_fixture: None
) -> None:
"""Test no warning when feature flags are set."""
class MockClimateEntityTest(MockClimateEntity):
"""Mock Climate device."""
_attr_supported_features = (
ClimateEntityFeature.FAN_MODE
| ClimateEntityFeature.PRESET_MODE
| ClimateEntityFeature.SWING_MODE
| ClimateEntityFeature.TURN_OFF
| ClimateEntityFeature.TURN_ON
)
async def async_setup_entry_init(
hass: HomeAssistant, config_entry: ConfigEntry
) -> bool:
"""Set up test config entry."""
await hass.config_entries.async_forward_entry_setups(config_entry, [DOMAIN])
return True
async def async_setup_entry_climate_platform(
hass: HomeAssistant,
config_entry: ConfigEntry,
async_add_entities: AddEntitiesCallback,
) -> None:
"""Set up test climate platform via config entry."""
async_add_entities(
[MockClimateEntityTest(name="test", entity_id="climate.test")]
)
mock_integration(
hass,
MockModule(
"test",
async_setup_entry=async_setup_entry_init,
),
built_in=False,
)
mock_platform(
hass,
"test.climate",
MockPlatform(async_setup_entry=async_setup_entry_climate_platform),
)
config_entry = MockConfigEntry(domain="test")
config_entry.add_to_hass(hass)
assert await hass.config_entries.async_setup(config_entry.entry_id)
await hass.async_block_till_done()
state = hass.states.get("climate.test")
assert state is not None
assert (
"does not set ClimateEntityFeature.TURN_OFF but implements the turn_off method."
not in caplog.text
)
assert (
"does not set ClimateEntityFeature.TURN_ON but implements the turn_on method."
not in caplog.text
)
assert (
"implements HVACMode.off and therefore implicitly implements the off method without setting"
not in caplog.text
)
assert (
"implements HVACMode.heat and therefore implicitly implements the heat method without setting"
not in caplog.text
)

View File

@ -60,12 +60,17 @@ async def test_climate_supported_features(
) -> None:
"""Test the Coolmaster climate supported features."""
assert hass.states.get("climate.l1_100").attributes[ATTR_SUPPORTED_FEATURES] == (
ClimateEntityFeature.TARGET_TEMPERATURE | ClimateEntityFeature.FAN_MODE
ClimateEntityFeature.TARGET_TEMPERATURE
| ClimateEntityFeature.FAN_MODE
| ClimateEntityFeature.TURN_OFF
| ClimateEntityFeature.TURN_ON
)
assert hass.states.get("climate.l1_101").attributes[ATTR_SUPPORTED_FEATURES] == (
ClimateEntityFeature.TARGET_TEMPERATURE
| ClimateEntityFeature.FAN_MODE
| ClimateEntityFeature.SWING_MODE
| ClimateEntityFeature.TURN_OFF
| ClimateEntityFeature.TURN_ON
)

View File

@ -9,7 +9,7 @@
]),
'max_temp': 24,
'min_temp': 4,
'supported_features': <ClimateEntityFeature: 1>,
'supported_features': <ClimateEntityFeature: 257>,
'target_temp_step': 0.5,
'temperature': 20,
}),
@ -52,7 +52,7 @@
'original_name': None,
'platform': 'devolo_home_control',
'previous_unique_id': None,
'supported_features': <ClimateEntityFeature: 1>,
'supported_features': <ClimateEntityFeature: 257>,
'translation_key': None,
'unique_id': 'Test',
'unit_of_measurement': None,

View File

@ -98,6 +98,8 @@ async def test_aux_heat_not_supported_by_default(hass: HomeAssistant) -> None:
| ClimateEntityFeature.TARGET_HUMIDITY
| ClimateEntityFeature.TARGET_TEMPERATURE_RANGE
| ClimateEntityFeature.TARGET_TEMPERATURE
| ClimateEntityFeature.TURN_OFF
| ClimateEntityFeature.TURN_ON
)
@ -115,6 +117,8 @@ async def test_aux_heat_supported_with_heat_pump(hass: HomeAssistant) -> None:
| ClimateEntityFeature.TARGET_TEMPERATURE_RANGE
| ClimateEntityFeature.TARGET_TEMPERATURE
| ClimateEntityFeature.AUX_HEAT
| ClimateEntityFeature.TURN_OFF
| ClimateEntityFeature.TURN_ON
)

View File

@ -16,7 +16,7 @@
'home',
'boost',
]),
'supported_features': <ClimateEntityFeature: 17>,
'supported_features': <ClimateEntityFeature: 401>,
'target_temp_step': 0.5,
'temperature': 22.0,
}),
@ -65,7 +65,7 @@
'original_name': None,
'platform': 'flexit_bacnet',
'previous_unique_id': None,
'supported_features': <ClimateEntityFeature: 17>,
'supported_features': <ClimateEntityFeature: 401>,
'translation_key': None,
'unique_id': '0000-0001',
'unit_of_measurement': None,

View File

@ -32,7 +32,7 @@
'none',
'sleep',
]),
'supported_features': <ClimateEntityFeature: 57>,
'supported_features': <ClimateEntityFeature: 441>,
'swing_mode': 'off',
'swing_modes': list([
'off',
@ -110,7 +110,7 @@
'original_name': None,
'platform': 'gree',
'previous_unique_id': None,
'supported_features': <ClimateEntityFeature: 57>,
'supported_features': <ClimateEntityFeature: 441>,
'translation_key': None,
'unique_id': 'aabbcc112233',
'unit_of_measurement': None,

View File

@ -3067,7 +3067,7 @@
'original_name': 'HomeW',
'platform': 'homekit_controller',
'previous_unique_id': None,
'supported_features': <ClimateEntityFeature: 7>,
'supported_features': <ClimateEntityFeature: 391>,
'translation_key': None,
'unique_id': '00:00:00:00:00:00_1_16',
'unit_of_measurement': None,
@ -3089,7 +3089,7 @@
'max_temp': 33.3,
'min_humidity': 20,
'min_temp': 7.2,
'supported_features': <ClimateEntityFeature: 7>,
'supported_features': <ClimateEntityFeature: 391>,
'target_temp_high': None,
'target_temp_low': None,
'temperature': 22.2,
@ -3775,7 +3775,7 @@
'original_name': 'HomeW',
'platform': 'homekit_controller',
'previous_unique_id': None,
'supported_features': <ClimateEntityFeature: 7>,
'supported_features': <ClimateEntityFeature: 391>,
'translation_key': None,
'unique_id': '00:00:00:00:00:00_1_16',
'unit_of_measurement': None,
@ -3797,7 +3797,7 @@
'max_temp': 33.3,
'min_humidity': 20,
'min_temp': 7.2,
'supported_features': <ClimateEntityFeature: 7>,
'supported_features': <ClimateEntityFeature: 391>,
'target_temp_high': None,
'target_temp_low': None,
'temperature': 22.2,
@ -4188,7 +4188,7 @@
'original_name': 'HomeW',
'platform': 'homekit_controller',
'previous_unique_id': None,
'supported_features': <ClimateEntityFeature: 7>,
'supported_features': <ClimateEntityFeature: 391>,
'translation_key': None,
'unique_id': '00:00:00:00:00:00_1_16',
'unit_of_measurement': None,
@ -4210,7 +4210,7 @@
'max_temp': 33.3,
'min_humidity': 20,
'min_temp': 7.2,
'supported_features': <ClimateEntityFeature: 7>,
'supported_features': <ClimateEntityFeature: 391>,
'target_temp_high': None,
'target_temp_low': None,
'temperature': 22.2,
@ -4853,7 +4853,7 @@
'original_name': 'My ecobee',
'platform': 'homekit_controller',
'previous_unique_id': None,
'supported_features': <ClimateEntityFeature: 15>,
'supported_features': <ClimateEntityFeature: 399>,
'translation_key': None,
'unique_id': '00:00:00:00:00:00_1_16',
'unit_of_measurement': None,
@ -4880,7 +4880,7 @@
'max_temp': 33.3,
'min_humidity': 20,
'min_temp': 7.2,
'supported_features': <ClimateEntityFeature: 15>,
'supported_features': <ClimateEntityFeature: 399>,
'target_temp_high': 25.6,
'target_temp_low': 7.2,
'temperature': None,
@ -7004,7 +7004,7 @@
'original_name': '89 Living Room',
'platform': 'homekit_controller',
'previous_unique_id': None,
'supported_features': 0,
'supported_features': <ClimateEntityFeature: 384>,
'translation_key': None,
'unique_id': '00:00:00:00:00:00_1233851541_169',
'unit_of_measurement': None,
@ -7022,7 +7022,7 @@
]),
'max_temp': 35,
'min_temp': 7,
'supported_features': <ClimateEntityFeature: 0>,
'supported_features': <ClimateEntityFeature: 384>,
'target_temp_step': 1.0,
}),
'entity_id': 'climate.89_living_room',
@ -8431,7 +8431,7 @@
'original_name': '89 Living Room',
'platform': 'homekit_controller',
'previous_unique_id': None,
'supported_features': <ClimateEntityFeature: 32>,
'supported_features': <ClimateEntityFeature: 416>,
'translation_key': None,
'unique_id': '00:00:00:00:00:00_1233851541_169',
'unit_of_measurement': None,
@ -8449,7 +8449,7 @@
]),
'max_temp': 35,
'min_temp': 7,
'supported_features': <ClimateEntityFeature: 32>,
'supported_features': <ClimateEntityFeature: 416>,
'swing_mode': 'vertical',
'swing_modes': list([
'off',
@ -9509,7 +9509,7 @@
'original_name': 'Air Conditioner SlaveID 1',
'platform': 'homekit_controller',
'previous_unique_id': None,
'supported_features': <ClimateEntityFeature: 9>,
'supported_features': <ClimateEntityFeature: 393>,
'translation_key': None,
'unique_id': '00:00:00:00:00:00_1_9',
'unit_of_measurement': None,
@ -9534,7 +9534,7 @@
]),
'max_temp': 32,
'min_temp': 18,
'supported_features': <ClimateEntityFeature: 9>,
'supported_features': <ClimateEntityFeature: 393>,
'target_temp_step': 0.5,
'temperature': 24.5,
}),
@ -12059,7 +12059,7 @@
'original_name': 'Lennox',
'platform': 'homekit_controller',
'previous_unique_id': None,
'supported_features': <ClimateEntityFeature: 3>,
'supported_features': <ClimateEntityFeature: 387>,
'translation_key': None,
'unique_id': '00:00:00:00:00:00_1_100',
'unit_of_measurement': None,
@ -12078,7 +12078,7 @@
]),
'max_temp': 37,
'min_temp': 4.5,
'supported_features': <ClimateEntityFeature: 3>,
'supported_features': <ClimateEntityFeature: 387>,
'target_temp_high': 29.5,
'target_temp_low': 21,
'temperature': None,
@ -13027,7 +13027,7 @@
'original_name': 'Mysa-85dda9 Thermostat',
'platform': 'homekit_controller',
'previous_unique_id': None,
'supported_features': <ClimateEntityFeature: 1>,
'supported_features': <ClimateEntityFeature: 385>,
'translation_key': None,
'unique_id': '00:00:00:00:00:00_1_20',
'unit_of_measurement': None,
@ -13046,7 +13046,7 @@
]),
'max_temp': 35,
'min_temp': 7,
'supported_features': <ClimateEntityFeature: 1>,
'supported_features': <ClimateEntityFeature: 385>,
'temperature': None,
}),
'entity_id': 'climate.mysa_85dda9_thermostat',

View File

@ -107,6 +107,8 @@ async def test_ecobee3_setup(hass: HomeAssistant) -> None:
ClimateEntityFeature.TARGET_TEMPERATURE
| ClimateEntityFeature.TARGET_TEMPERATURE_RANGE
| ClimateEntityFeature.TARGET_HUMIDITY
| ClimateEntityFeature.TURN_OFF
| ClimateEntityFeature.TURN_ON
),
capabilities={
"hvac_modes": ["off", "heat", "cool", "heat_cool"],

View File

@ -28,7 +28,10 @@ async def test_cover_add_feature_at_runtime(
assert climate.unique_id == "00:00:00:00:00:00_1233851541_169"
climate_state = hass.states.get("climate.89_living_room")
assert climate_state.attributes[ATTR_SUPPORTED_FEATURES] is ClimateEntityFeature(0)
assert (
climate_state.attributes[ATTR_SUPPORTED_FEATURES]
is ClimateEntityFeature.TURN_OFF | ClimateEntityFeature.TURN_ON
)
assert ATTR_SWING_MODES not in climate_state.attributes
climate = entity_registry.async_get("climate.89_living_room")
@ -44,5 +47,7 @@ async def test_cover_add_feature_at_runtime(
assert (
climate_state.attributes[ATTR_SUPPORTED_FEATURES]
is ClimateEntityFeature.SWING_MODE
| ClimateEntityFeature.TURN_OFF
| ClimateEntityFeature.TURN_ON
)
assert climate_state.attributes[ATTR_SWING_MODES] == ["off", "vertical"]

View File

@ -30,7 +30,7 @@
'away',
'hold',
]),
'supported_features': <ClimateEntityFeature: 95>,
'supported_features': <ClimateEntityFeature: 479>,
'target_temp_high': None,
'target_temp_low': None,
'temperature': None,

View File

@ -89,7 +89,10 @@ async def test_setup_thermostat(
assert state.attributes.get(ATTR_PRESET_MODE) == PRESET_NONE
assert (
state.attributes.get(ATTR_SUPPORTED_FEATURES)
== ClimateEntityFeature.TARGET_TEMPERATURE | ClimateEntityFeature.PRESET_MODE
== ClimateEntityFeature.TARGET_TEMPERATURE
| ClimateEntityFeature.PRESET_MODE
| ClimateEntityFeature.TURN_OFF
| ClimateEntityFeature.TURN_ON
)
assert state.attributes.get(ATTR_MAX_TEMP) == MAX_TEMPERATURE
assert state.attributes.get(ATTR_MIN_TEMP) == 5.0

View File

@ -226,6 +226,8 @@ async def test_supported_features(
| ClimateEntityFeature.PRESET_MODE
| ClimateEntityFeature.TARGET_TEMPERATURE_RANGE
| ClimateEntityFeature.TARGET_HUMIDITY
| ClimateEntityFeature.TURN_OFF
| ClimateEntityFeature.TURN_ON
)
assert state.attributes.get("supported_features") == support
@ -1327,6 +1329,8 @@ async def test_set_aux(
| ClimateEntityFeature.PRESET_MODE
| ClimateEntityFeature.TARGET_TEMPERATURE_RANGE
| ClimateEntityFeature.TARGET_HUMIDITY
| ClimateEntityFeature.TURN_OFF
| ClimateEntityFeature.TURN_ON
)
assert state.attributes.get("supported_features") == support

View File

@ -909,6 +909,8 @@ async def test_thermostat_fan_off(
ClimateEntityFeature.TARGET_TEMPERATURE
| ClimateEntityFeature.TARGET_TEMPERATURE_RANGE
| ClimateEntityFeature.FAN_MODE
| ClimateEntityFeature.TURN_OFF
| ClimateEntityFeature.TURN_ON
)
@ -956,6 +958,8 @@ async def test_thermostat_fan_on(
ClimateEntityFeature.TARGET_TEMPERATURE
| ClimateEntityFeature.TARGET_TEMPERATURE_RANGE
| ClimateEntityFeature.FAN_MODE
| ClimateEntityFeature.TURN_OFF
| ClimateEntityFeature.TURN_ON
)
@ -999,6 +1003,8 @@ async def test_thermostat_cool_with_fan(
ClimateEntityFeature.TARGET_TEMPERATURE
| ClimateEntityFeature.TARGET_TEMPERATURE_RANGE
| ClimateEntityFeature.FAN_MODE
| ClimateEntityFeature.TURN_OFF
| ClimateEntityFeature.TURN_ON
)
@ -1036,6 +1042,8 @@ async def test_thermostat_set_fan(
ClimateEntityFeature.TARGET_TEMPERATURE
| ClimateEntityFeature.TARGET_TEMPERATURE_RANGE
| ClimateEntityFeature.FAN_MODE
| ClimateEntityFeature.TURN_OFF
| ClimateEntityFeature.TURN_ON
)
# Turn off fan mode
@ -1098,6 +1106,8 @@ async def test_thermostat_set_fan_when_off(
ClimateEntityFeature.TARGET_TEMPERATURE
| ClimateEntityFeature.TARGET_TEMPERATURE_RANGE
| ClimateEntityFeature.FAN_MODE
| ClimateEntityFeature.TURN_OFF
| ClimateEntityFeature.TURN_ON
)
# Fan cannot be turned on when HVAC is off
@ -1143,6 +1153,8 @@ async def test_thermostat_fan_empty(
assert thermostat.attributes[ATTR_SUPPORTED_FEATURES] == (
ClimateEntityFeature.TARGET_TEMPERATURE
| ClimateEntityFeature.TARGET_TEMPERATURE_RANGE
| ClimateEntityFeature.TURN_OFF
| ClimateEntityFeature.TURN_ON
)
# Ignores set_fan_mode since it is lacking SUPPORT_FAN_MODE

View File

@ -38,7 +38,7 @@
'original_name': 'Bureau',
'platform': 'netatmo',
'previous_unique_id': None,
'supported_features': <ClimateEntityFeature: 17>,
'supported_features': <ClimateEntityFeature: 401>,
'translation_key': None,
'unique_id': '222452125-DeviceType.OTM',
'unit_of_measurement': None,
@ -61,7 +61,7 @@
'Frost Guard',
'Schedule',
]),
'supported_features': <ClimateEntityFeature: 17>,
'supported_features': <ClimateEntityFeature: 401>,
'target_temp_step': 0.5,
}),
'context': <ANY>,
@ -110,7 +110,7 @@
'original_name': 'Cocina',
'platform': 'netatmo',
'previous_unique_id': None,
'supported_features': <ClimateEntityFeature: 17>,
'supported_features': <ClimateEntityFeature: 401>,
'translation_key': None,
'unique_id': '2940411577-DeviceType.NRV',
'unit_of_measurement': None,
@ -138,7 +138,7 @@
'Schedule',
]),
'selected_schedule': 'Default',
'supported_features': <ClimateEntityFeature: 17>,
'supported_features': <ClimateEntityFeature: 401>,
'target_temp_step': 0.5,
'temperature': 7,
}),
@ -188,7 +188,7 @@
'original_name': 'Corridor',
'platform': 'netatmo',
'previous_unique_id': None,
'supported_features': <ClimateEntityFeature: 17>,
'supported_features': <ClimateEntityFeature: 401>,
'translation_key': None,
'unique_id': '1002003001-DeviceType.BNS',
'unit_of_measurement': None,
@ -215,7 +215,7 @@
'Schedule',
]),
'selected_schedule': 'Default',
'supported_features': <ClimateEntityFeature: 17>,
'supported_features': <ClimateEntityFeature: 401>,
'target_temp_step': 0.5,
'temperature': 22,
}),
@ -265,7 +265,7 @@
'original_name': 'Entrada',
'platform': 'netatmo',
'previous_unique_id': None,
'supported_features': <ClimateEntityFeature: 17>,
'supported_features': <ClimateEntityFeature: 401>,
'translation_key': None,
'unique_id': '2833524037-DeviceType.NRV',
'unit_of_measurement': None,
@ -293,7 +293,7 @@
'Schedule',
]),
'selected_schedule': 'Default',
'supported_features': <ClimateEntityFeature: 17>,
'supported_features': <ClimateEntityFeature: 401>,
'target_temp_step': 0.5,
'temperature': 7,
}),
@ -344,7 +344,7 @@
'original_name': 'Livingroom',
'platform': 'netatmo',
'previous_unique_id': None,
'supported_features': <ClimateEntityFeature: 17>,
'supported_features': <ClimateEntityFeature: 401>,
'translation_key': None,
'unique_id': '2746182631-DeviceType.NATherm1',
'unit_of_measurement': None,
@ -372,7 +372,7 @@
'Schedule',
]),
'selected_schedule': 'Default',
'supported_features': <ClimateEntityFeature: 17>,
'supported_features': <ClimateEntityFeature: 401>,
'target_temp_step': 0.5,
'temperature': 12,
}),

View File

@ -29,7 +29,7 @@ async def test_climate_zones(hass: HomeAssistant) -> None:
"min_temp": 12.8,
"preset_mode": "None",
"preset_modes": ["None", "Home", "Away", "Sleep"],
"supported_features": 31,
"supported_features": 415,
"target_temp_high": 26.1,
"target_temp_low": 17.2,
"target_temp_step": 1.0,
@ -61,7 +61,7 @@ async def test_climate_zones(hass: HomeAssistant) -> None:
"min_temp": 12.8,
"preset_mode": "None",
"preset_modes": ["None", "Home", "Away", "Sleep"],
"supported_features": 31,
"supported_features": 415,
"target_temp_high": 26.1,
"target_temp_low": 17.2,
"target_temp_step": 1.0,

View File

@ -12,7 +12,7 @@
]),
'max_temp': 35.0,
'min_temp': 5.0,
'supported_features': <ClimateEntityFeature: 3>,
'supported_features': <ClimateEntityFeature: 259>,
'target_temp_high': 30.0,
'target_temp_low': 21.0,
'target_temp_step': 0.5,
@ -36,7 +36,7 @@
]),
'max_temp': 35.0,
'min_temp': 5.0,
'supported_features': <ClimateEntityFeature: 3>,
'supported_features': <ClimateEntityFeature: 259>,
'target_temp_step': 0.5,
}),
'context': <ANY>,
@ -59,7 +59,7 @@
]),
'max_temp': 35.0,
'min_temp': 5.0,
'supported_features': <ClimateEntityFeature: 3>,
'supported_features': <ClimateEntityFeature: 259>,
'target_temp_high': 30.0,
'target_temp_low': 21.0,
'target_temp_step': 0.5,
@ -83,7 +83,7 @@
]),
'max_temp': 35.0,
'min_temp': 5.0,
'supported_features': <ClimateEntityFeature: 3>,
'supported_features': <ClimateEntityFeature: 259>,
'target_temp_step': 0.5,
}),
'context': <ANY>,
@ -112,7 +112,7 @@
]),
'max_temp': 35.0,
'min_temp': 5.0,
'supported_features': <ClimateEntityFeature: 3>,
'supported_features': <ClimateEntityFeature: 259>,
'target_temp_high': 30.0,
'target_temp_low': 21.0,
'target_temp_step': 0.5,
@ -138,7 +138,7 @@
]),
'max_temp': 35.0,
'min_temp': 5.0,
'supported_features': <ClimateEntityFeature: 3>,
'supported_features': <ClimateEntityFeature: 259>,
'target_temp_high': None,
'target_temp_low': None,
'target_temp_step': 0.5,
@ -164,7 +164,7 @@
]),
'max_temp': 35.0,
'min_temp': 5.0,
'supported_features': <ClimateEntityFeature: 3>,
'supported_features': <ClimateEntityFeature: 259>,
'target_temp_high': None,
'target_temp_low': None,
'target_temp_step': 0.5,
@ -190,7 +190,7 @@
]),
'max_temp': 35.0,
'min_temp': 5.0,
'supported_features': <ClimateEntityFeature: 3>,
'supported_features': <ClimateEntityFeature: 259>,
'target_temp_high': 30.0,
'target_temp_low': 21.0,
'target_temp_step': 0.5,
@ -216,7 +216,7 @@
]),
'max_temp': 35.0,
'min_temp': 5.0,
'supported_features': <ClimateEntityFeature: 3>,
'supported_features': <ClimateEntityFeature: 259>,
'target_temp_high': 30.0,
'target_temp_low': 21.0,
'target_temp_step': 0.5,
@ -242,7 +242,7 @@
]),
'max_temp': 35.0,
'min_temp': 5.0,
'supported_features': <ClimateEntityFeature: 3>,
'supported_features': <ClimateEntityFeature: 259>,
'target_temp_high': 30.0,
'target_temp_low': 21.0,
'target_temp_step': 0.5,
@ -268,7 +268,7 @@
]),
'max_temp': 35.0,
'min_temp': 5.0,
'supported_features': <ClimateEntityFeature: 3>,
'supported_features': <ClimateEntityFeature: 259>,
'target_temp_high': None,
'target_temp_low': None,
'target_temp_step': 0.5,
@ -294,7 +294,7 @@
]),
'max_temp': 35.0,
'min_temp': 5.0,
'supported_features': <ClimateEntityFeature: 3>,
'supported_features': <ClimateEntityFeature: 259>,
'target_temp_high': None,
'target_temp_low': None,
'target_temp_step': 0.5,
@ -320,7 +320,7 @@
]),
'max_temp': 35.0,
'min_temp': 5.0,
'supported_features': <ClimateEntityFeature: 3>,
'supported_features': <ClimateEntityFeature: 259>,
'target_temp_high': 30.0,
'target_temp_low': 21.0,
'target_temp_step': 0.5,
@ -346,7 +346,7 @@
]),
'max_temp': 35.0,
'min_temp': 5.0,
'supported_features': <ClimateEntityFeature: 3>,
'supported_features': <ClimateEntityFeature: 259>,
'target_temp_high': None,
'target_temp_low': None,
'target_temp_step': 0.5,
@ -372,7 +372,7 @@
]),
'max_temp': 35.0,
'min_temp': 5.0,
'supported_features': <ClimateEntityFeature: 3>,
'supported_features': <ClimateEntityFeature: 259>,
'target_temp_high': None,
'target_temp_low': None,
'target_temp_step': 0.5,
@ -398,7 +398,7 @@
]),
'max_temp': 35.0,
'min_temp': 5.0,
'supported_features': <ClimateEntityFeature: 3>,
'supported_features': <ClimateEntityFeature: 259>,
'target_temp_high': 30.0,
'target_temp_low': 21.0,
'target_temp_step': 0.5,
@ -424,7 +424,7 @@
]),
'max_temp': 35.0,
'min_temp': 5.0,
'supported_features': <ClimateEntityFeature: 3>,
'supported_features': <ClimateEntityFeature: 259>,
'target_temp_high': 30.0,
'target_temp_low': 21.0,
'target_temp_step': 0.5,
@ -450,7 +450,7 @@
]),
'max_temp': 35.0,
'min_temp': 5.0,
'supported_features': <ClimateEntityFeature: 3>,
'supported_features': <ClimateEntityFeature: 259>,
'target_temp_high': 30.0,
'target_temp_low': 21.0,
'target_temp_step': 0.5,
@ -476,7 +476,7 @@
]),
'max_temp': 35.0,
'min_temp': 5.0,
'supported_features': <ClimateEntityFeature: 3>,
'supported_features': <ClimateEntityFeature: 259>,
'target_temp_high': None,
'target_temp_low': None,
'target_temp_step': 0.5,
@ -502,7 +502,7 @@
]),
'max_temp': 35.0,
'min_temp': 5.0,
'supported_features': <ClimateEntityFeature: 3>,
'supported_features': <ClimateEntityFeature: 259>,
'target_temp_high': None,
'target_temp_low': None,
'target_temp_step': 0.5,

View File

@ -44,7 +44,7 @@ async def test_climate_thermostat_run(hass: HomeAssistant) -> None:
"min_temp": 5.0,
"preset_mode": "Run Schedule",
"preset_modes": ["Run Schedule", "Temporary Hold", "Permanent Hold"],
"supported_features": 17,
"supported_features": 273,
"temperature": 22.2,
}
# Only test for a subset of attributes in case
@ -77,7 +77,7 @@ async def test_climate_thermostat_schedule_hold_unavailable(
"max_temp": 180.6,
"min_temp": -6.1,
"preset_modes": ["Run Schedule", "Temporary Hold", "Permanent Hold"],
"supported_features": 17,
"supported_features": 273,
}
# Only test for a subset of attributes in case
# HA changes the implementation and a new one appears
@ -110,7 +110,7 @@ async def test_climate_thermostat_schedule_hold_available(hass: HomeAssistant) -
"min_temp": -6.1,
"preset_mode": "Run Schedule",
"preset_modes": ["Run Schedule", "Temporary Hold", "Permanent Hold"],
"supported_features": 17,
"supported_features": 273,
"temperature": 26.1,
}
# Only test for a subset of attributes in case
@ -144,7 +144,7 @@ async def test_climate_thermostat_schedule_temporary_hold(hass: HomeAssistant) -
"min_temp": -0.6,
"preset_mode": "Run Schedule",
"preset_modes": ["Run Schedule", "Temporary Hold", "Permanent Hold"],
"supported_features": 17,
"supported_features": 273,
"temperature": 37.2,
}
# Only test for a subset of attributes in case

View File

@ -34,7 +34,7 @@ async def test_adam_climate_entity_attributes(
assert state.attributes["current_temperature"] == 20.9
assert state.attributes["preset_mode"] == "home"
assert state.attributes["supported_features"] == 17
assert state.attributes["supported_features"] == 273
assert state.attributes["temperature"] == 21.5
assert state.attributes["min_temp"] == 0.0
assert state.attributes["max_temp"] == 35.0
@ -303,7 +303,7 @@ async def test_anna_climate_entity_attributes(
assert state.attributes["current_temperature"] == 19.3
assert state.attributes["preset_mode"] == "home"
assert state.attributes["supported_features"] == 18
assert state.attributes["supported_features"] == 274
assert state.attributes["target_temp_high"] == 30
assert state.attributes["target_temp_low"] == 20.5
assert state.attributes["min_temp"] == 4
@ -325,7 +325,7 @@ async def test_anna_2_climate_entity_attributes(
HVACMode.AUTO,
HVACMode.HEAT_COOL,
]
assert state.attributes["supported_features"] == 18
assert state.attributes["supported_features"] == 274
assert state.attributes["target_temp_high"] == 30
assert state.attributes["target_temp_low"] == 20.5

View File

@ -20,7 +20,7 @@
]),
'max_temp': 20,
'min_temp': 10,
'supported_features': <ClimateEntityFeature: 41>,
'supported_features': <ClimateEntityFeature: 425>,
'swing_mode': 'stopped',
'swing_modes': list([
'stopped',

View File

@ -320,6 +320,8 @@ async def test_air_conditioner_entity_state(
| ClimateEntityFeature.TARGET_TEMPERATURE
| ClimateEntityFeature.PRESET_MODE
| ClimateEntityFeature.SWING_MODE
| ClimateEntityFeature.TURN_OFF
| ClimateEntityFeature.TURN_ON
)
assert sorted(state.attributes[ATTR_HVAC_MODES]) == [
HVACMode.COOL,

View File

@ -52,7 +52,9 @@ async def test_thermostat_update(
assert state.state == HVACMode.HEAT
assert (
state.attributes[ATTR_SUPPORTED_FEATURES]
== ClimateEntityFeature.PRESET_MODE | ClimateEntityFeature.TARGET_TEMPERATURE
== ClimateEntityFeature.PRESET_MODE
| ClimateEntityFeature.TARGET_TEMPERATURE
| ClimateEntityFeature.TURN_ON
)
assert state.attributes[ATTR_CURRENT_TEMPERATURE] == 38
assert state.attributes[ATTR_TEMPERATURE] == 39

View File

@ -24,7 +24,7 @@ async def test_air_con(hass: HomeAssistant) -> None:
"min_temp": 16.0,
"preset_mode": "auto",
"preset_modes": ["away", "home", "auto"],
"supported_features": 25,
"supported_features": 409,
"target_temp_step": 1,
"temperature": 17.8,
}
@ -51,7 +51,7 @@ async def test_heater(hass: HomeAssistant) -> None:
"min_temp": 16.0,
"preset_mode": "auto",
"preset_modes": ["away", "home", "auto"],
"supported_features": 17,
"supported_features": 401,
"target_temp_step": 1,
"temperature": 20.5,
}
@ -81,7 +81,7 @@ async def test_smartac_with_swing(hass: HomeAssistant) -> None:
"preset_mode": "auto",
"preset_modes": ["away", "home", "auto"],
"swing_modes": ["on", "off"],
"supported_features": 57,
"supported_features": 441,
"target_temp_step": 1.0,
"temperature": 20.0,
}

View File

@ -10,6 +10,8 @@ EXPECTED_BASE_SUPPORTED_FEATURES = (
ClimateEntityFeature.TARGET_TEMPERATURE
| ClimateEntityFeature.FAN_MODE
| ClimateEntityFeature.PRESET_MODE
| ClimateEntityFeature.TURN_OFF
| ClimateEntityFeature.TURN_ON
)

View File

@ -97,6 +97,8 @@ async def test_static_attributes(
== ClimateEntityFeature.TARGET_TEMPERATURE
| ClimateEntityFeature.FAN_MODE
| ClimateEntityFeature.SWING_MODE
| ClimateEntityFeature.TURN_OFF
| ClimateEntityFeature.TURN_ON
)
assert attributes[ATTR_HVAC_MODES] == [
HVACMode.COOL,

View File

@ -83,6 +83,8 @@ async def test_thermostat_v2(
== ClimateEntityFeature.TARGET_TEMPERATURE
| ClimateEntityFeature.TARGET_TEMPERATURE_RANGE
| ClimateEntityFeature.FAN_MODE
| ClimateEntityFeature.TURN_OFF
| ClimateEntityFeature.TURN_ON
)
client.async_send_command.reset_mock()
@ -330,7 +332,7 @@ async def test_setpoint_thermostat(
assert state.attributes[ATTR_HVAC_MODES] == [HVACMode.HEAT]
assert (
state.attributes[ATTR_SUPPORTED_FEATURES]
== ClimateEntityFeature.TARGET_TEMPERATURE
== ClimateEntityFeature.TARGET_TEMPERATURE | ClimateEntityFeature.TURN_ON
)
client.async_send_command_no_wait.reset_mock()
@ -432,7 +434,10 @@ async def test_thermostat_heatit_z_trm6(
assert state.attributes[ATTR_HVAC_ACTION] == HVACAction.IDLE
assert (
state.attributes[ATTR_SUPPORTED_FEATURES]
== ClimateEntityFeature.TARGET_TEMPERATURE | ClimateEntityFeature.PRESET_MODE
== ClimateEntityFeature.TARGET_TEMPERATURE
| ClimateEntityFeature.PRESET_MODE
| ClimateEntityFeature.TURN_OFF
| ClimateEntityFeature.TURN_ON
)
assert state.attributes[ATTR_MIN_TEMP] == 5
assert state.attributes[ATTR_MAX_TEMP] == 40
@ -513,6 +518,8 @@ async def test_thermostat_heatit_z_trm3(
assert (
state.attributes[ATTR_SUPPORTED_FEATURES]
== ClimateEntityFeature.TARGET_TEMPERATURE
| ClimateEntityFeature.TURN_OFF
| ClimateEntityFeature.TURN_ON
)
assert state.attributes[ATTR_MIN_TEMP] == 5
assert state.attributes[ATTR_MAX_TEMP] == 35
@ -582,7 +589,10 @@ async def test_thermostat_heatit_z_trm2fx(
assert state.attributes[ATTR_TEMPERATURE] == 29
assert (
state.attributes[ATTR_SUPPORTED_FEATURES]
== ClimateEntityFeature.TARGET_TEMPERATURE | ClimateEntityFeature.PRESET_MODE
== ClimateEntityFeature.TARGET_TEMPERATURE
| ClimateEntityFeature.PRESET_MODE
| ClimateEntityFeature.TURN_OFF
| ClimateEntityFeature.TURN_ON
)
assert state.attributes[ATTR_MIN_TEMP] == 7
assert state.attributes[ATTR_MAX_TEMP] == 35
@ -627,7 +637,7 @@ async def test_thermostat_srt321_hrt4_zw(
HVACMode.HEAT,
]
assert state.attributes[ATTR_CURRENT_TEMPERATURE] is None
assert state.attributes[ATTR_SUPPORTED_FEATURES] == 0
assert state.attributes[ATTR_SUPPORTED_FEATURES] == 384
async def test_preset_and_no_setpoint(