236 lines
8.4 KiB
Python
236 lines
8.4 KiB
Python
"""Climate on Zigbee Home Automation networks.
|
|
|
|
For more details on this platform, please refer to the documentation
|
|
at https://home-assistant.io/components/zha.climate/
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
from collections.abc import Mapping
|
|
import functools
|
|
from typing import Any
|
|
|
|
from zha.application.platforms.climate.const import (
|
|
ClimateEntityFeature as ZHAClimateEntityFeature,
|
|
HVACAction as ZHAHVACAction,
|
|
HVACMode as ZHAHVACMode,
|
|
)
|
|
|
|
from homeassistant.components.climate import (
|
|
ATTR_HVAC_MODE,
|
|
ATTR_TARGET_TEMP_HIGH,
|
|
ATTR_TARGET_TEMP_LOW,
|
|
ATTR_TEMPERATURE,
|
|
ClimateEntity,
|
|
ClimateEntityFeature,
|
|
HVACAction,
|
|
HVACMode,
|
|
)
|
|
from homeassistant.config_entries import ConfigEntry
|
|
from homeassistant.const import PRECISION_TENTHS, Platform, UnitOfTemperature
|
|
from homeassistant.core import HomeAssistant, callback
|
|
from homeassistant.helpers.dispatcher import async_dispatcher_connect
|
|
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
|
|
|
from .entity import ZHAEntity
|
|
from .helpers import (
|
|
SIGNAL_ADD_ENTITIES,
|
|
EntityData,
|
|
async_add_entities as zha_async_add_entities,
|
|
convert_zha_error_to_ha_error,
|
|
exclude_none_values,
|
|
get_zha_data,
|
|
)
|
|
|
|
ZHA_TO_HA_HVAC_MODE = {
|
|
ZHAHVACMode.OFF: HVACMode.OFF,
|
|
ZHAHVACMode.AUTO: HVACMode.AUTO,
|
|
ZHAHVACMode.HEAT: HVACMode.HEAT,
|
|
ZHAHVACMode.COOL: HVACMode.COOL,
|
|
ZHAHVACMode.HEAT_COOL: HVACMode.HEAT_COOL,
|
|
ZHAHVACMode.DRY: HVACMode.DRY,
|
|
ZHAHVACMode.FAN_ONLY: HVACMode.FAN_ONLY,
|
|
}
|
|
|
|
ZHA_TO_HA_HVAC_ACTION = {
|
|
ZHAHVACAction.OFF: HVACAction.OFF,
|
|
ZHAHVACAction.HEATING: HVACAction.HEATING,
|
|
ZHAHVACAction.COOLING: HVACAction.COOLING,
|
|
ZHAHVACAction.DRYING: HVACAction.DRYING,
|
|
ZHAHVACAction.IDLE: HVACAction.IDLE,
|
|
ZHAHVACAction.FAN: HVACAction.FAN,
|
|
ZHAHVACAction.PREHEATING: HVACAction.PREHEATING,
|
|
}
|
|
|
|
|
|
async def async_setup_entry(
|
|
hass: HomeAssistant,
|
|
config_entry: ConfigEntry,
|
|
async_add_entities: AddEntitiesCallback,
|
|
) -> None:
|
|
"""Set up the Zigbee Home Automation sensor from config entry."""
|
|
zha_data = get_zha_data(hass)
|
|
entities_to_create = zha_data.platforms[Platform.CLIMATE]
|
|
|
|
unsub = async_dispatcher_connect(
|
|
hass,
|
|
SIGNAL_ADD_ENTITIES,
|
|
functools.partial(
|
|
zha_async_add_entities, async_add_entities, Thermostat, entities_to_create
|
|
),
|
|
)
|
|
config_entry.async_on_unload(unsub)
|
|
|
|
|
|
class Thermostat(ZHAEntity, ClimateEntity):
|
|
"""Representation of a ZHA Thermostat device."""
|
|
|
|
_attr_precision = PRECISION_TENTHS
|
|
_attr_temperature_unit = UnitOfTemperature.CELSIUS
|
|
_attr_translation_key: str = "thermostat"
|
|
|
|
def __init__(self, entity_data: EntityData, **kwargs: Any) -> None:
|
|
"""Initialize the ZHA thermostat entity."""
|
|
super().__init__(entity_data, **kwargs)
|
|
self._attr_hvac_modes = [
|
|
ZHA_TO_HA_HVAC_MODE[mode] for mode in self.entity_data.entity.hvac_modes
|
|
]
|
|
self._attr_hvac_mode = ZHA_TO_HA_HVAC_MODE.get(
|
|
self.entity_data.entity.hvac_mode
|
|
)
|
|
self._attr_hvac_action = ZHA_TO_HA_HVAC_ACTION.get(
|
|
self.entity_data.entity.hvac_action
|
|
)
|
|
|
|
features: ClimateEntityFeature = ClimateEntityFeature(0)
|
|
zha_features: ZHAClimateEntityFeature = (
|
|
self.entity_data.entity.supported_features
|
|
)
|
|
|
|
if ZHAClimateEntityFeature.TARGET_TEMPERATURE in zha_features:
|
|
features |= ClimateEntityFeature.TARGET_TEMPERATURE
|
|
if ZHAClimateEntityFeature.TARGET_TEMPERATURE_RANGE in zha_features:
|
|
features |= ClimateEntityFeature.TARGET_TEMPERATURE_RANGE
|
|
if ZHAClimateEntityFeature.TARGET_HUMIDITY in zha_features:
|
|
features |= ClimateEntityFeature.TARGET_HUMIDITY
|
|
if ZHAClimateEntityFeature.PRESET_MODE in zha_features:
|
|
features |= ClimateEntityFeature.PRESET_MODE
|
|
if ZHAClimateEntityFeature.FAN_MODE in zha_features:
|
|
features |= ClimateEntityFeature.FAN_MODE
|
|
if ZHAClimateEntityFeature.SWING_MODE in zha_features:
|
|
features |= ClimateEntityFeature.SWING_MODE
|
|
if ZHAClimateEntityFeature.TURN_OFF in zha_features:
|
|
features |= ClimateEntityFeature.TURN_OFF
|
|
if ZHAClimateEntityFeature.TURN_ON in zha_features:
|
|
features |= ClimateEntityFeature.TURN_ON
|
|
|
|
self._attr_supported_features = features
|
|
|
|
@property
|
|
def extra_state_attributes(self) -> Mapping[str, Any] | None:
|
|
"""Return entity specific state attributes."""
|
|
state = self.entity_data.entity.state
|
|
|
|
return exclude_none_values(
|
|
{
|
|
"occupancy": state.get("occupancy"),
|
|
"occupied_cooling_setpoint": state.get("occupied_cooling_setpoint"),
|
|
"occupied_heating_setpoint": state.get("occupied_heating_setpoint"),
|
|
"pi_cooling_demand": state.get("pi_cooling_demand"),
|
|
"pi_heating_demand": state.get("pi_heating_demand"),
|
|
"system_mode": state.get("system_mode"),
|
|
"unoccupied_cooling_setpoint": state.get("unoccupied_cooling_setpoint"),
|
|
"unoccupied_heating_setpoint": state.get("unoccupied_heating_setpoint"),
|
|
}
|
|
)
|
|
|
|
@property
|
|
def current_temperature(self) -> float | None:
|
|
"""Return the current temperature."""
|
|
return self.entity_data.entity.current_temperature
|
|
|
|
@property
|
|
def fan_mode(self) -> str | None:
|
|
"""Return current FAN mode."""
|
|
return self.entity_data.entity.fan_mode
|
|
|
|
@property
|
|
def fan_modes(self) -> list[str] | None:
|
|
"""Return supported FAN modes."""
|
|
return self.entity_data.entity.fan_modes
|
|
|
|
@property
|
|
def preset_mode(self) -> str:
|
|
"""Return current preset mode."""
|
|
return self.entity_data.entity.preset_mode
|
|
|
|
@property
|
|
def preset_modes(self) -> list[str] | None:
|
|
"""Return supported preset modes."""
|
|
return self.entity_data.entity.preset_modes
|
|
|
|
@property
|
|
def target_temperature(self) -> float | None:
|
|
"""Return the temperature we try to reach."""
|
|
return self.entity_data.entity.target_temperature
|
|
|
|
@property
|
|
def target_temperature_high(self) -> float | None:
|
|
"""Return the upper bound temperature we try to reach."""
|
|
return self.entity_data.entity.target_temperature_high
|
|
|
|
@property
|
|
def target_temperature_low(self) -> float | None:
|
|
"""Return the lower bound temperature we try to reach."""
|
|
return self.entity_data.entity.target_temperature_low
|
|
|
|
@property
|
|
def max_temp(self) -> float:
|
|
"""Return the maximum temperature."""
|
|
return self.entity_data.entity.max_temp
|
|
|
|
@property
|
|
def min_temp(self) -> float:
|
|
"""Return the minimum temperature."""
|
|
return self.entity_data.entity.min_temp
|
|
|
|
@callback
|
|
def _handle_entity_events(self, event: Any) -> None:
|
|
"""Entity state changed."""
|
|
self._attr_hvac_mode = self._attr_hvac_mode = ZHA_TO_HA_HVAC_MODE.get(
|
|
self.entity_data.entity.hvac_mode
|
|
)
|
|
self._attr_hvac_action = ZHA_TO_HA_HVAC_ACTION.get(
|
|
self.entity_data.entity.hvac_action
|
|
)
|
|
super()._handle_entity_events(event)
|
|
|
|
@convert_zha_error_to_ha_error
|
|
async def async_set_fan_mode(self, fan_mode: str) -> None:
|
|
"""Set fan mode."""
|
|
await self.entity_data.entity.async_set_fan_mode(fan_mode=fan_mode)
|
|
self.async_write_ha_state()
|
|
|
|
@convert_zha_error_to_ha_error
|
|
async def async_set_hvac_mode(self, hvac_mode: HVACMode) -> None:
|
|
"""Set new target operation mode."""
|
|
await self.entity_data.entity.async_set_hvac_mode(hvac_mode=hvac_mode)
|
|
self.async_write_ha_state()
|
|
|
|
@convert_zha_error_to_ha_error
|
|
async def async_set_preset_mode(self, preset_mode: str) -> None:
|
|
"""Set new preset mode."""
|
|
await self.entity_data.entity.async_set_preset_mode(preset_mode=preset_mode)
|
|
self.async_write_ha_state()
|
|
|
|
@convert_zha_error_to_ha_error
|
|
async def async_set_temperature(self, **kwargs: Any) -> None:
|
|
"""Set new target temperature."""
|
|
await self.entity_data.entity.async_set_temperature(
|
|
target_temp_low=kwargs.get(ATTR_TARGET_TEMP_LOW),
|
|
target_temp_high=kwargs.get(ATTR_TARGET_TEMP_HIGH),
|
|
temperature=kwargs.get(ATTR_TEMPERATURE),
|
|
hvac_mode=kwargs.get(ATTR_HVAC_MODE),
|
|
)
|
|
self.async_write_ha_state()
|