Skip to content
Merged
Show file tree
Hide file tree
Changes from 5 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): cv.enum(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): cv.enum(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:
Comment thread
MartinHjelmare marked this conversation as resolved.
"""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