Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion homeassistant/components/atag/climate.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ def __init__(self, coordinator, atag_id):
self._attr_temperature_unit = coordinator.data.climate.temp_unit

@property
def hvac_mode(self) -> str | None: # type: ignore[override]
def hvac_mode(self) -> str | None:
"""Return hvac operation ie. heat, cool mode."""
if self.coordinator.data.climate.hvac_mode in HVAC_MODES:
return self.coordinator.data.climate.hvac_mode
Expand Down
44 changes: 22 additions & 22 deletions homeassistant/components/climate/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@
SUPPORT_TARGET_TEMPERATURE,
SUPPORT_TARGET_TEMPERATURE_RANGE,
ClimateEntityFeature,
HVACMode,
)

DEFAULT_MIN_TEMP = 7
Expand All @@ -99,7 +100,7 @@
vol.Exclusive(ATTR_TEMPERATURE, "temperature"): vol.Coerce(float),
vol.Inclusive(ATTR_TARGET_TEMP_HIGH, "temperature"): vol.Coerce(float),
vol.Inclusive(ATTR_TARGET_TEMP_LOW, "temperature"): vol.Coerce(float),
vol.Optional(ATTR_HVAC_MODE): vol.In(HVAC_MODES),
vol.Optional(ATTR_HVAC_MODE): vol.Coerce(HVACMode),
}
),
)
Expand All @@ -116,7 +117,7 @@ async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
component.async_register_entity_service(SERVICE_TURN_OFF, {}, "async_turn_off")
component.async_register_entity_service(
SERVICE_SET_HVAC_MODE,
{vol.Required(ATTR_HVAC_MODE): vol.In(HVAC_MODES)},
{vol.Required(ATTR_HVAC_MODE): vol.Coerce(HVACMode)},
"async_set_hvac_mode",
)
component.async_register_entity_service(
Expand Down Expand Up @@ -188,8 +189,8 @@ class ClimateEntity(Entity):
_attr_fan_mode: str | None
_attr_fan_modes: list[str] | None
_attr_hvac_action: str | None = None
_attr_hvac_mode: str
_attr_hvac_modes: list[str]
_attr_hvac_mode: HVACMode | str | None
_attr_hvac_modes: list[HVACMode | str]
_attr_is_aux_heat: bool | None
_attr_max_humidity: int = DEFAULT_MAX_HUMIDITY
_attr_max_temp: float
Expand All @@ -208,10 +209,15 @@ class ClimateEntity(Entity):
_attr_target_temperature: float | None = None
_attr_temperature_unit: str

@final
@property
def state(self) -> str:
def state(self) -> str | None:
"""Return the current state."""
return self.hvac_mode
if self.hvac_mode is None:
return None
if not isinstance(self.hvac_mode, HVACMode):
return HVACMode(self.hvac_mode).value
return self.hvac_mode.value

@property
def precision(self) -> float:
Expand All @@ -226,7 +232,7 @@ def precision(self) -> float:
def capability_attributes(self) -> dict[str, Any] | None:
"""Return the capability attributes."""
supported_features = self.supported_features
data = {
data: dict[str, Any] = {
ATTR_HVAC_MODES: self.hvac_modes,
ATTR_MIN_TEMP: show_temp(
self.hass, self.min_temp, self.temperature_unit, self.precision
Expand Down Expand Up @@ -329,19 +335,13 @@ def target_humidity(self) -> int | None:
return self._attr_target_humidity

@property
def hvac_mode(self) -> str:
"""Return hvac operation ie. heat, cool mode.

Need to be one of HVAC_MODE_*.
"""
def hvac_mode(self) -> HVACMode | str | None:
"""Return hvac operation ie. heat, cool mode."""
return self._attr_hvac_mode

@property
def hvac_modes(self) -> list[str]:
"""Return the list of available hvac operation modes.

Need to be a subset of HVAC_MODES.
"""
def hvac_modes(self) -> list[HVACMode | str]:
"""Return the list of available hvac operation modes."""
return self._attr_hvac_modes

@property
Expand Down Expand Up @@ -465,11 +465,11 @@ async def async_set_fan_mode(self, fan_mode: str) -> None:
"""Set new target fan mode."""
await self.hass.async_add_executor_job(self.set_fan_mode, fan_mode)

def set_hvac_mode(self, hvac_mode: str) -> None:
def set_hvac_mode(self, hvac_mode: HVACMode | str) -> None:
"""Set new target hvac mode."""
raise NotImplementedError()

async def async_set_hvac_mode(self, hvac_mode: str) -> None:
async def async_set_hvac_mode(self, hvac_mode: HVACMode | str) -> None:
"""Set new target hvac mode."""
await self.hass.async_add_executor_job(self.set_hvac_mode, hvac_mode)

Expand Down Expand Up @@ -512,7 +512,7 @@ async def async_turn_on(self) -> None:
return

# Fake turn on
for mode in (HVAC_MODE_HEAT_COOL, HVAC_MODE_HEAT, HVAC_MODE_COOL):
for mode in (HVACMode.HEAT_COOL, HVACMode.HEAT, HVACMode.COOL):
if mode not in self.hvac_modes:
continue
await self.async_set_hvac_mode(mode)
Expand All @@ -525,8 +525,8 @@ async def async_turn_off(self) -> None:
return

# Fake turn off
if HVAC_MODE_OFF in self.hvac_modes:
await self.async_set_hvac_mode(HVAC_MODE_OFF)
if HVACMode.OFF in self.hvac_modes:
await self.async_set_hvac_mode(HVACMode.OFF)

@property
def supported_features(self) -> int:
Expand Down
58 changes: 33 additions & 25 deletions homeassistant/components/climate/const.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,37 +2,45 @@

from enum import IntEnum

# All activity disabled / Device is off/standby
HVAC_MODE_OFF = "off"
from homeassistant.backports.enum import StrEnum

# Heating
HVAC_MODE_HEAT = "heat"

# Cooling
HVAC_MODE_COOL = "cool"
class HVACMode(StrEnum):
"""HVAC mode for climate devices."""

# The device supports heating/cooling to a range
HVAC_MODE_HEAT_COOL = "heat_cool"
# All activity disabled / Device is off/standby
OFF = "off"

# The temperature is set based on a schedule, learned behavior, AI or some
# other related mechanism. User is not able to adjust the temperature
HVAC_MODE_AUTO = "auto"
# Heating
HEAT = "heat"

# Device is in Dry/Humidity mode
HVAC_MODE_DRY = "dry"
# Cooling
COOL = "cool"

# Only the fan is on, not fan and another mode like cool
HVAC_MODE_FAN_ONLY = "fan_only"
# The device supports heating/cooling to a range
HEAT_COOL = "heat_cool"

HVAC_MODES = [
HVAC_MODE_OFF,
HVAC_MODE_HEAT,
HVAC_MODE_COOL,
HVAC_MODE_HEAT_COOL,
HVAC_MODE_AUTO,
HVAC_MODE_DRY,
HVAC_MODE_FAN_ONLY,
]
# The temperature is set based on a schedule, learned behavior, AI or some
# other related mechanism. User is not able to adjust the temperature
AUTO = "auto"

# Device is in Dry/Humidity mode
DRY = "dry"

# Only the fan is on, not fan and another mode like cool
FAN_ONLY = "fan_only"


# These HVAC_MODE_* constants are deprecated as of Home Assistant 2022.5.
# Please use the HVACMode enum instead.
HVAC_MODE_OFF = "off"
HVAC_MODE_HEAT = "heat"
HVAC_MODE_COOL = "cool"
HVAC_MODE_HEAT_COOL = "heat_cool"
HVAC_MODE_AUTO = "auto"
HVAC_MODE_DRY = "dry"
HVAC_MODE_FAN_ONLY = "fan_only"
HVAC_MODES = [cls.value for cls in HVACMode]

# No preset is active
PRESET_NONE = "none"
Expand Down Expand Up @@ -149,7 +157,7 @@ class ClimateEntityFeature(IntEnum):


# These SUPPORT_* constants are deprecated as of Home Assistant 2022.5.
# Pleease use the ClimateEntityFeature enum instead.
# Please use the ClimateEntityFeature enum instead.
SUPPORT_TARGET_TEMPERATURE = 1
SUPPORT_TARGET_TEMPERATURE_RANGE = 2
SUPPORT_TARGET_HUMIDITY = 4
Expand Down
4 changes: 2 additions & 2 deletions homeassistant/components/climate/group.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
from homeassistant.const import STATE_OFF
from homeassistant.core import HomeAssistant, callback

from .const import HVAC_MODE_OFF, HVAC_MODES
from .const import HVAC_MODES, HVACMode


@callback
Expand All @@ -14,6 +14,6 @@ def async_describe_on_off_states(
) -> None:
"""Describe group on off states."""
registry.on_off_states(
set(HVAC_MODES) - {HVAC_MODE_OFF},
set(HVAC_MODES) - {HVACMode.OFF},
STATE_OFF,
)
21 changes: 8 additions & 13 deletions homeassistant/components/demo/climate.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,8 @@
ATTR_TARGET_TEMP_LOW,
CURRENT_HVAC_COOL,
CURRENT_HVAC_HEAT,
HVAC_MODE_AUTO,
HVAC_MODE_COOL,
HVAC_MODE_HEAT,
HVAC_MODE_HEAT_COOL,
HVAC_MODE_OFF,
HVAC_MODES,
ClimateEntityFeature,
HVACMode,
)
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import ATTR_TEMPERATURE, TEMP_CELSIUS, TEMP_FAHRENHEIT
Expand Down Expand Up @@ -47,12 +42,12 @@ async def async_setup_platform(
target_humidity=None,
current_humidity=None,
swing_mode=None,
hvac_mode=HVAC_MODE_HEAT,
hvac_mode=HVACMode.HEAT,
hvac_action=CURRENT_HVAC_HEAT,
aux=None,
target_temp_high=None,
target_temp_low=None,
hvac_modes=[HVAC_MODE_HEAT, HVAC_MODE_OFF],
hvac_modes=[HVACMode.HEAT, HVACMode.OFF],
),
DemoClimate(
unique_id="climate_2",
Expand All @@ -65,12 +60,12 @@ async def async_setup_platform(
target_humidity=67,
current_humidity=54,
swing_mode="Off",
hvac_mode=HVAC_MODE_COOL,
hvac_mode=HVACMode.COOL,
hvac_action=CURRENT_HVAC_COOL,
aux=False,
target_temp_high=None,
target_temp_low=None,
hvac_modes=[mode for mode in HVAC_MODES if mode != HVAC_MODE_HEAT_COOL],
hvac_modes=[cls.value for cls in HVACMode if cls != HVACMode.HEAT_COOL],
),
DemoClimate(
unique_id="climate_3",
Expand All @@ -84,12 +79,12 @@ async def async_setup_platform(
target_humidity=None,
current_humidity=None,
swing_mode="Auto",
hvac_mode=HVAC_MODE_HEAT_COOL,
hvac_mode=HVACMode.HEAT_COOL,
hvac_action=None,
aux=None,
target_temp_high=24,
target_temp_low=21,
hvac_modes=[HVAC_MODE_HEAT_COOL, HVAC_MODE_COOL, HVAC_MODE_HEAT],
hvac_modes=[cls.value for cls in HVACMode if cls != HVACMode.HEAT],
),
]
)
Expand Down Expand Up @@ -147,7 +142,7 @@ def __init__(
self._support_flags = self._support_flags | ClimateEntityFeature.SWING_MODE
if aux is not None:
self._support_flags = self._support_flags | ClimateEntityFeature.AUX_HEAT
if HVAC_MODE_HEAT_COOL in hvac_modes or HVAC_MODE_AUTO in hvac_modes:
if HVACMode.HEAT_COOL in hvac_modes or HVACMode.AUTO in hvac_modes:
self._support_flags = (
self._support_flags | ClimateEntityFeature.TARGET_TEMPERATURE_RANGE
)
Expand Down
2 changes: 1 addition & 1 deletion homeassistant/components/esphome/climate.py
Original file line number Diff line number Diff line change
Expand Up @@ -230,7 +230,7 @@ def supported_features(self) -> int:
return features

@esphome_state_property
def hvac_mode(self) -> str | None: # type: ignore[override]
def hvac_mode(self) -> str | None:
"""Return current operation ie. heat, cool, idle."""
return _CLIMATE_MODES.from_esphome(self._state.mode)

Expand Down
Loading