Skip to main content
The climate platform allows integrations to control HVAC (heating, ventilation, air conditioning) devices. Climate entities can control temperature, humidity, fan mode, and more.

Base Class

All climate entities inherit from ClimateEntity, which is defined in homeassistant.components.climate.
from homeassistant.components.climate import ClimateEntity

class MyClimate(ClimateEntity):
    """Representation of a climate device."""

HVAC Modes

Climate entities operate in different HVAC modes:
from homeassistant.components.climate import HVACMode

class MyClimate(ClimateEntity):
    """A climate device."""

    _attr_hvac_modes = [HVACMode.OFF, HVACMode.HEAT, HVACMode.COOL, HVACMode.AUTO]
Available HVAC modes:
  • OFF - HVAC is off
  • HEAT - Heating mode
  • COOL - Cooling mode
  • HEAT_COOL - Heat/cool to a temperature range
  • AUTO - Automatic mode
  • DRY - Dry/dehumidify mode
  • FAN_ONLY - Fan only mode

Required Properties

hvac_mode

The current HVAC mode.
@cached_property
def hvac_mode(self) -> HVACMode | None:
    """Return hvac operation ie. heat, cool mode."""
    return self._attr_hvac_mode

hvac_modes

List of available HVAC modes.
@cached_property
def hvac_modes(self) -> list[HVACMode]:
    """Return the list of available hvac operation modes."""
    return self._attr_hvac_modes

temperature_unit

The unit of temperature (Celsius or Fahrenheit).
@cached_property
def temperature_unit(self) -> str:
    """Return the unit of measurement used by the platform."""
    return self._attr_temperature_unit

Required Methods

set_hvac_mode

Set the HVAC mode.
async def async_set_hvac_mode(self, hvac_mode: HVACMode) -> None:
    """Set new target hvac mode."""
    await self._device.set_mode(hvac_mode)
    self._attr_hvac_mode = hvac_mode
    self.async_write_ha_state()

set_temperature

Set target temperature (and optionally HVAC mode).
async def async_set_temperature(self, **kwargs: Any) -> None:
    """Set new target temperature."""
    if (temperature := kwargs.get(ATTR_TEMPERATURE)) is not None:
        await self._device.set_temperature(temperature)
        self._attr_target_temperature = temperature
    
    if (hvac_mode := kwargs.get(ATTR_HVAC_MODE)) is not None:
        await self.async_set_hvac_mode(hvac_mode)
    
    self.async_write_ha_state()

Optional Properties

current_temperature

The current temperature reading.
@cached_property
def current_temperature(self) -> float | None:
    """Return the current temperature."""
    return self._attr_current_temperature

target_temperature

The target temperature. Required if ClimateEntityFeature.TARGET_TEMPERATURE is set.
@cached_property
def target_temperature(self) -> float | None:
    """Return the temperature we try to reach."""
    return self._attr_target_temperature

target_temperature_high / target_temperature_low

Temperature range for heat/cool mode. Required if ClimateEntityFeature.TARGET_TEMPERATURE_RANGE is set.
@cached_property
def target_temperature_high(self) -> float | None:
    """Return the highbound target temperature we try to reach."""
    return self._attr_target_temperature_high

@cached_property
def target_temperature_low(self) -> float | None:
    """Return the lowbound target temperature we try to reach."""
    return self._attr_target_temperature_low

current_humidity

The current humidity reading.
@cached_property
def current_humidity(self) -> float | None:
    """Return the current humidity."""
    return self._attr_current_humidity

target_humidity

The target humidity. Required if ClimateEntityFeature.TARGET_HUMIDITY is set.
@cached_property
def target_humidity(self) -> float | None:
    """Return the humidity we try to reach."""
    return self._attr_target_humidity

hvac_action

The current action (what the device is actually doing).
@cached_property
def hvac_action(self) -> HVACAction | None:
    """Return the current running hvac operation if supported."""
    return self._attr_hvac_action
Available HVAC actions:
  • OFF - Device is off
  • HEATING - Device is heating
  • COOLING - Device is cooling
  • DRYING - Device is drying
  • IDLE - Device is idle (on but not actively heating/cooling)
  • FAN - Device fan is running

fan_mode / fan_modes

Fan mode control. Requires ClimateEntityFeature.FAN_MODE.
@cached_property
def fan_mode(self) -> str | None:
    """Return the fan setting."""
    return self._attr_fan_mode

@cached_property
def fan_modes(self) -> list[str] | None:
    """Return the list of available fan modes."""
    return self._attr_fan_modes
Common fan modes: auto, low, medium, high, on, off

preset_mode / preset_modes

Preset mode control. Requires ClimateEntityFeature.PRESET_MODE.
@cached_property
def preset_mode(self) -> str | None:
    """Return the current preset mode."""
    return self._attr_preset_mode

@cached_property
def preset_modes(self) -> list[str] | None:
    """Return a list of available preset modes."""
    return self._attr_preset_modes
Common preset modes: none, eco, away, boost, comfort, home, sleep, activity

swing_mode / swing_modes

Swing mode control. Requires ClimateEntityFeature.SWING_MODE.
@cached_property
def swing_mode(self) -> str | None:
    """Return the swing setting."""
    return self._attr_swing_mode

@cached_property
def swing_modes(self) -> list[str] | None:
    """Return the list of available swing modes."""
    return self._attr_swing_modes
Common swing modes: off, on, vertical, horizontal, both

min_temp / max_temp

Temperature range limits.
@cached_property
def min_temp(self) -> float:
    """Return the minimum temperature."""
    return self._attr_min_temp

@cached_property
def max_temp(self) -> float:
    """Return the maximum temperature."""
    return self._attr_max_temp

min_humidity / max_humidity

Humidity range limits.
@cached_property
def min_humidity(self) -> float:
    """Return the minimum humidity."""
    return self._attr_min_humidity

@cached_property
def max_humidity(self) -> float:
    """Return the maximum humidity."""
    return self._attr_max_humidity

supported_features

Flags indicating which features are supported.
@cached_property
def supported_features(self) -> ClimateEntityFeature:
    """Return the list of supported features."""
    return self._attr_supported_features
Available features:
  • TARGET_TEMPERATURE - Can set target temperature
  • TARGET_TEMPERATURE_RANGE - Can set temperature range (high/low)
  • TARGET_HUMIDITY - Can set target humidity
  • FAN_MODE - Supports fan mode control
  • PRESET_MODE - Supports preset modes
  • SWING_MODE - Supports swing mode
  • SWING_HORIZONTAL_MODE - Supports horizontal swing
  • TURN_ON - Can be turned on
  • TURN_OFF - Can be turned off

Example Implementation

from homeassistant.components.climate import (
    ClimateEntity,
    ClimateEntityFeature,
    HVACMode,
)
from homeassistant.const import ATTR_TEMPERATURE, UnitOfTemperature

class SimpleThermostat(ClimateEntity):
    """A simple thermostat."""

    _attr_temperature_unit = UnitOfTemperature.CELSIUS
    _attr_hvac_modes = [HVACMode.OFF, HVACMode.HEAT, HVACMode.COOL, HVACMode.AUTO]
    _attr_supported_features = ClimateEntityFeature.TARGET_TEMPERATURE
    _attr_min_temp = 7
    _attr_max_temp = 35

    def __init__(self, name: str, device_id: str) -> None:
        """Initialize the climate device."""
        self._attr_name = name
        self._attr_unique_id = f"{device_id}_climate"
        self._attr_hvac_mode = HVACMode.OFF
        self._attr_current_temperature = None
        self._attr_target_temperature = 20

    async def async_set_hvac_mode(self, hvac_mode: HVACMode) -> None:
        """Set new target hvac mode."""
        await self._device.set_mode(hvac_mode)
        self._attr_hvac_mode = hvac_mode
        self.async_write_ha_state()

    async def async_set_temperature(self, **kwargs: Any) -> None:
        """Set new target temperature."""
        if (temperature := kwargs.get(ATTR_TEMPERATURE)) is not None:
            await self._device.set_temperature(temperature)
            self._attr_target_temperature = temperature
            self.async_write_ha_state()

    async def async_update(self) -> None:
        """Fetch new state data."""
        self._attr_current_temperature = await self._device.get_temperature()

Advanced Example with Multiple Features

class AdvancedClimate(ClimateEntity):
    """Climate device with humidity, fan, and preset control."""

    _attr_temperature_unit = UnitOfTemperature.CELSIUS
    _attr_hvac_modes = [HVACMode.OFF, HVACMode.HEAT, HVACMode.COOL, HVACMode.AUTO]
    _attr_fan_modes = ["auto", "low", "medium", "high"]
    _attr_preset_modes = ["none", "eco", "away", "boost"]
    _attr_supported_features = (
        ClimateEntityFeature.TARGET_TEMPERATURE
        | ClimateEntityFeature.TARGET_HUMIDITY
        | ClimateEntityFeature.FAN_MODE
        | ClimateEntityFeature.PRESET_MODE
    )

    def __init__(self) -> None:
        """Initialize the climate device."""
        self._attr_hvac_mode = HVACMode.OFF
        self._attr_current_temperature = 22
        self._attr_target_temperature = 22
        self._attr_current_humidity = 50
        self._attr_target_humidity = 50
        self._attr_fan_mode = "auto"
        self._attr_preset_mode = "none"

    async def async_set_temperature(self, **kwargs: Any) -> None:
        """Set new target temperature."""
        if (temp := kwargs.get(ATTR_TEMPERATURE)) is not None:
            self._attr_target_temperature = temp
        self.async_write_ha_state()

    async def async_set_humidity(self, humidity: int) -> None:
        """Set new target humidity."""
        self._attr_target_humidity = humidity
        self.async_write_ha_state()

    async def async_set_fan_mode(self, fan_mode: str) -> None:
        """Set new fan mode."""
        self._attr_fan_mode = fan_mode
        self.async_write_ha_state()

    async def async_set_preset_mode(self, preset_mode: str) -> None:
        """Set new preset mode."""
        self._attr_preset_mode = preset_mode
        self.async_write_ha_state()

    async def async_set_hvac_mode(self, hvac_mode: HVACMode) -> None:
        """Set new hvac mode."""
        self._attr_hvac_mode = hvac_mode
        self.async_write_ha_state()

Turn On/Off Support

Climate devices can implement turn on/off if they support it:
class ClimateWithPower(ClimateEntity):
    """Climate device with power control."""

    _attr_supported_features = (
        ClimateEntityFeature.TARGET_TEMPERATURE
        | ClimateEntityFeature.TURN_ON
        | ClimateEntityFeature.TURN_OFF
    )

    async def async_turn_on(self) -> None:
        """Turn the entity on."""
        await self._device.power_on()
        # Default implementation sets to first non-OFF mode
        await self.async_set_hvac_mode(HVACMode.AUTO)

    async def async_turn_off(self) -> None:
        """Turn the entity off."""
        await self.async_set_hvac_mode(HVACMode.OFF)

Important Notes

  • Climate entities must set hvac_mode, hvac_modes, and temperature_unit
  • The state property is final and returns the current hvac_mode value
  • Always declare supported_features to indicate which features your device supports
  • Home Assistant handles temperature unit conversion automatically
  • Service calls validate parameters against min/max values and available modes
  • Use async_write_ha_state() after state changes to update Home Assistant

Services

The climate platform automatically registers these services:
  • climate.set_hvac_mode - Set HVAC mode
  • climate.set_temperature - Set target temperature
  • climate.set_humidity - Set target humidity (if supported)
  • climate.set_fan_mode - Set fan mode (if supported)
  • climate.set_preset_mode - Set preset mode (if supported)
  • climate.set_swing_mode - Set swing mode (if supported)
  • climate.turn_on - Turn on (if supported)
  • climate.turn_off - Turn off (if supported)
  • climate.toggle - Toggle on/off (if supported)

See Also

Build docs developers (and LLMs) love