mirror of
https://github.com/home-assistant/core.git
synced 2025-12-19 18:38:58 +00:00
[esphome] Implement feature_flags for climate (#153507)
Co-authored-by: J. Nick Koston <nick@koston.org>
This commit is contained in:
@@ -9,6 +9,7 @@ from typing import Any, cast
|
||||
from aioesphomeapi import (
|
||||
ClimateAction,
|
||||
ClimateFanMode,
|
||||
ClimateFeature,
|
||||
ClimateInfo,
|
||||
ClimateMode,
|
||||
ClimatePreset,
|
||||
@@ -134,12 +135,16 @@ class EsphomeClimateEntity(EsphomeEntity[ClimateInfo, ClimateState], ClimateEnti
|
||||
|
||||
_attr_temperature_unit = UnitOfTemperature.CELSIUS
|
||||
_attr_translation_key = "climate"
|
||||
_feature_flags = ClimateFeature(0)
|
||||
|
||||
@callback
|
||||
def _on_static_info_update(self, static_info: EntityInfo) -> None:
|
||||
"""Set attrs from static info."""
|
||||
super()._on_static_info_update(static_info)
|
||||
static_info = self._static_info
|
||||
self._feature_flags = ClimateFeature(
|
||||
static_info.supported_feature_flags_compat(self._api_version)
|
||||
)
|
||||
self._attr_precision = self._get_precision()
|
||||
self._attr_hvac_modes = [
|
||||
_CLIMATE_MODES.from_esphome(mode) for mode in static_info.supported_modes
|
||||
@@ -163,11 +168,18 @@ class EsphomeClimateEntity(EsphomeEntity[ClimateInfo, ClimateState], ClimateEnti
|
||||
self._attr_max_temp = static_info.visual_max_temperature
|
||||
self._attr_min_humidity = round(static_info.visual_min_humidity)
|
||||
self._attr_max_humidity = round(static_info.visual_max_humidity)
|
||||
features = ClimateEntityFeature.TARGET_TEMPERATURE
|
||||
if static_info.supports_two_point_target_temperature:
|
||||
features |= ClimateEntityFeature.TARGET_TEMPERATURE_RANGE
|
||||
if static_info.supports_target_humidity:
|
||||
features = ClimateEntityFeature(0)
|
||||
if self._feature_flags & ClimateFeature.SUPPORTS_TARGET_HUMIDITY:
|
||||
features |= ClimateEntityFeature.TARGET_HUMIDITY
|
||||
if self._feature_flags & ClimateFeature.REQUIRES_TWO_POINT_TARGET_TEMPERATURE:
|
||||
features |= ClimateEntityFeature.TARGET_TEMPERATURE_RANGE
|
||||
else:
|
||||
features |= ClimateEntityFeature.TARGET_TEMPERATURE
|
||||
if (
|
||||
self._feature_flags
|
||||
& ClimateFeature.SUPPORTS_TWO_POINT_TARGET_TEMPERATURE
|
||||
):
|
||||
features |= ClimateEntityFeature.TARGET_TEMPERATURE_RANGE
|
||||
if self.preset_modes:
|
||||
features |= ClimateEntityFeature.PRESET_MODE
|
||||
if self.fan_modes:
|
||||
@@ -203,7 +215,7 @@ class EsphomeClimateEntity(EsphomeEntity[ClimateInfo, ClimateState], ClimateEnti
|
||||
def hvac_action(self) -> HVACAction | None:
|
||||
"""Return current action."""
|
||||
# HA has no support feature field for hvac_action
|
||||
if not self._static_info.supports_action:
|
||||
if not self._feature_flags & ClimateFeature.SUPPORTS_ACTION:
|
||||
return None
|
||||
return _CLIMATE_ACTIONS.from_esphome(self._state.action)
|
||||
|
||||
@@ -233,7 +245,7 @@ class EsphomeClimateEntity(EsphomeEntity[ClimateInfo, ClimateState], ClimateEnti
|
||||
@esphome_float_state_property
|
||||
def current_temperature(self) -> float | None:
|
||||
"""Return the current temperature."""
|
||||
if not self._static_info.supports_current_temperature:
|
||||
if not self._feature_flags & ClimateFeature.SUPPORTS_CURRENT_TEMPERATURE:
|
||||
return None
|
||||
return self._state.current_temperature
|
||||
|
||||
@@ -242,7 +254,7 @@ class EsphomeClimateEntity(EsphomeEntity[ClimateInfo, ClimateState], ClimateEnti
|
||||
def current_humidity(self) -> int | None:
|
||||
"""Return the current humidity."""
|
||||
if (
|
||||
not self._static_info.supports_current_humidity
|
||||
(not self._feature_flags & ClimateFeature.SUPPORTS_CURRENT_HUMIDITY)
|
||||
or (val := self._state.current_humidity) is None
|
||||
or not isfinite(val)
|
||||
):
|
||||
@@ -254,7 +266,11 @@ class EsphomeClimateEntity(EsphomeEntity[ClimateInfo, ClimateState], ClimateEnti
|
||||
def target_temperature(self) -> float | None:
|
||||
"""Return the temperature we try to reach."""
|
||||
if (
|
||||
not self._static_info.supports_two_point_target_temperature
|
||||
not self._feature_flags
|
||||
& (
|
||||
ClimateFeature.REQUIRES_TWO_POINT_TARGET_TEMPERATURE
|
||||
| ClimateFeature.SUPPORTS_TWO_POINT_TARGET_TEMPERATURE
|
||||
)
|
||||
and self.hvac_mode != HVACMode.AUTO
|
||||
):
|
||||
return self._state.target_temperature
|
||||
@@ -295,7 +311,10 @@ class EsphomeClimateEntity(EsphomeEntity[ClimateInfo, ClimateState], ClimateEnti
|
||||
cast(HVACMode, kwargs[ATTR_HVAC_MODE])
|
||||
)
|
||||
if ATTR_TEMPERATURE in kwargs:
|
||||
if not self._static_info.supports_two_point_target_temperature:
|
||||
if not self._feature_flags & (
|
||||
ClimateFeature.REQUIRES_TWO_POINT_TARGET_TEMPERATURE
|
||||
| ClimateFeature.SUPPORTS_TWO_POINT_TARGET_TEMPERATURE
|
||||
):
|
||||
data["target_temperature"] = kwargs[ATTR_TEMPERATURE]
|
||||
else:
|
||||
hvac_mode = kwargs.get(ATTR_HVAC_MODE) or self.hvac_mode
|
||||
|
||||
@@ -7,6 +7,7 @@ from aioesphomeapi import (
|
||||
APIClient,
|
||||
ClimateAction,
|
||||
ClimateFanMode,
|
||||
ClimateFeature,
|
||||
ClimateInfo,
|
||||
ClimateMode,
|
||||
ClimatePreset,
|
||||
@@ -107,11 +108,10 @@ async def test_climate_entity_with_step_and_two_point(
|
||||
object_id="myclimate",
|
||||
key=1,
|
||||
name="my climate",
|
||||
supports_current_temperature=True,
|
||||
supports_two_point_target_temperature=True,
|
||||
feature_flags=ClimateFeature.SUPPORTS_CURRENT_TEMPERATURE
|
||||
| ClimateFeature.SUPPORTS_TWO_POINT_TARGET_TEMPERATURE,
|
||||
visual_target_temperature_step=2,
|
||||
visual_current_temperature_step=2,
|
||||
supports_action=False,
|
||||
visual_min_temperature=10.0,
|
||||
visual_max_temperature=30.0,
|
||||
supported_modes=[ClimateMode.COOL, ClimateMode.HEAT, ClimateMode.AUTO],
|
||||
@@ -346,13 +346,13 @@ async def test_climate_entity_with_humidity(
|
||||
object_id="myclimate",
|
||||
key=1,
|
||||
name="my climate",
|
||||
supports_current_temperature=True,
|
||||
supports_two_point_target_temperature=True,
|
||||
supports_action=True,
|
||||
feature_flags=ClimateFeature.SUPPORTS_CURRENT_TEMPERATURE
|
||||
| ClimateFeature.SUPPORTS_TWO_POINT_TARGET_TEMPERATURE
|
||||
| ClimateFeature.SUPPORTS_CURRENT_HUMIDITY
|
||||
| ClimateFeature.SUPPORTS_TARGET_HUMIDITY
|
||||
| ClimateFeature.SUPPORTS_ACTION,
|
||||
visual_min_temperature=10.0,
|
||||
visual_max_temperature=30.0,
|
||||
supports_current_humidity=True,
|
||||
supports_target_humidity=True,
|
||||
visual_min_humidity=10.1,
|
||||
visual_max_humidity=29.7,
|
||||
)
|
||||
@@ -407,9 +407,9 @@ async def test_climate_entity_with_heat(
|
||||
object_id="myclimate",
|
||||
key=1,
|
||||
name="my climate",
|
||||
supports_current_temperature=True,
|
||||
supports_two_point_target_temperature=True,
|
||||
supports_action=True,
|
||||
feature_flags=ClimateFeature.SUPPORTS_CURRENT_TEMPERATURE
|
||||
| ClimateFeature.SUPPORTS_TWO_POINT_TARGET_TEMPERATURE
|
||||
| ClimateFeature.SUPPORTS_ACTION,
|
||||
visual_min_temperature=10.0,
|
||||
visual_max_temperature=30.0,
|
||||
supported_modes=[ClimateMode.COOL, ClimateMode.HEAT, ClimateMode.AUTO],
|
||||
@@ -456,9 +456,9 @@ async def test_climate_entity_with_heat_cool(
|
||||
object_id="myclimate",
|
||||
key=1,
|
||||
name="my climate",
|
||||
supports_current_temperature=True,
|
||||
supports_two_point_target_temperature=True,
|
||||
supports_action=True,
|
||||
feature_flags=ClimateFeature.SUPPORTS_CURRENT_TEMPERATURE
|
||||
| ClimateFeature.SUPPORTS_TWO_POINT_TARGET_TEMPERATURE
|
||||
| ClimateFeature.SUPPORTS_ACTION,
|
||||
visual_min_temperature=10.0,
|
||||
visual_max_temperature=30.0,
|
||||
supported_modes=[ClimateMode.COOL, ClimateMode.HEAT, ClimateMode.HEAT_COOL],
|
||||
@@ -516,7 +516,7 @@ async def test_climate_set_temperature_unsupported_mode(
|
||||
object_id="myclimate",
|
||||
key=1,
|
||||
name="my climate",
|
||||
supports_two_point_target_temperature=True,
|
||||
feature_flags=ClimateFeature.SUPPORTS_TWO_POINT_TARGET_TEMPERATURE,
|
||||
supported_modes=[ClimateMode.HEAT, ClimateMode.COOL, ClimateMode.AUTO],
|
||||
visual_min_temperature=10.0,
|
||||
visual_max_temperature=30.0,
|
||||
@@ -563,13 +563,13 @@ async def test_climate_entity_with_inf_value(
|
||||
object_id="myclimate",
|
||||
key=1,
|
||||
name="my climate",
|
||||
supports_current_temperature=True,
|
||||
supports_two_point_target_temperature=True,
|
||||
supports_action=True,
|
||||
feature_flags=ClimateFeature.SUPPORTS_CURRENT_TEMPERATURE
|
||||
| ClimateFeature.SUPPORTS_TWO_POINT_TARGET_TEMPERATURE
|
||||
| ClimateFeature.SUPPORTS_CURRENT_HUMIDITY
|
||||
| ClimateFeature.SUPPORTS_TARGET_HUMIDITY
|
||||
| ClimateFeature.SUPPORTS_ACTION,
|
||||
visual_min_temperature=10.0,
|
||||
visual_max_temperature=30.0,
|
||||
supports_current_humidity=True,
|
||||
supports_target_humidity=True,
|
||||
visual_min_humidity=10.1,
|
||||
visual_max_humidity=29.7,
|
||||
)
|
||||
@@ -616,10 +616,10 @@ async def test_climate_entity_attributes(
|
||||
object_id="myclimate",
|
||||
key=1,
|
||||
name="my climate",
|
||||
supports_current_temperature=True,
|
||||
feature_flags=ClimateFeature.SUPPORTS_CURRENT_TEMPERATURE
|
||||
| ClimateFeature.SUPPORTS_ACTION,
|
||||
visual_target_temperature_step=2,
|
||||
visual_current_temperature_step=2,
|
||||
supports_action=True,
|
||||
visual_min_temperature=10.0,
|
||||
visual_max_temperature=30.0,
|
||||
supported_fan_modes=[ClimateFanMode.LOW, ClimateFanMode.HIGH],
|
||||
|
||||
Reference in New Issue
Block a user