Home Assistant Unofficial Reference 2024.12.1
climate.py
Go to the documentation of this file.
1 """Climate on Zigbee Home Automation networks.
2 
3 For more details on this platform, please refer to the documentation
4 at https://home-assistant.io/components/zha.climate/
5 """
6 
7 from __future__ import annotations
8 
9 from collections.abc import Mapping
10 import functools
11 from typing import Any
12 
13 from zha.application.platforms.climate.const import (
14  ClimateEntityFeature as ZHAClimateEntityFeature,
15  HVACAction as ZHAHVACAction,
16  HVACMode as ZHAHVACMode,
17 )
18 
20  ATTR_HVAC_MODE,
21  ATTR_TARGET_TEMP_HIGH,
22  ATTR_TARGET_TEMP_LOW,
23  ATTR_TEMPERATURE,
24  ClimateEntity,
25  ClimateEntityFeature,
26  HVACAction,
27  HVACMode,
28 )
29 from homeassistant.config_entries import ConfigEntry
30 from homeassistant.const import PRECISION_TENTHS, Platform, UnitOfTemperature
31 from homeassistant.core import HomeAssistant, callback
32 from homeassistant.helpers.dispatcher import async_dispatcher_connect
33 from homeassistant.helpers.entity_platform import AddEntitiesCallback
34 
35 from .entity import ZHAEntity
36 from .helpers import (
37  SIGNAL_ADD_ENTITIES,
38  EntityData,
39  async_add_entities as zha_async_add_entities,
40  convert_zha_error_to_ha_error,
41  exclude_none_values,
42  get_zha_data,
43 )
44 
45 ZHA_TO_HA_HVAC_MODE = {
46  ZHAHVACMode.OFF: HVACMode.OFF,
47  ZHAHVACMode.AUTO: HVACMode.AUTO,
48  ZHAHVACMode.HEAT: HVACMode.HEAT,
49  ZHAHVACMode.COOL: HVACMode.COOL,
50  ZHAHVACMode.HEAT_COOL: HVACMode.HEAT_COOL,
51  ZHAHVACMode.DRY: HVACMode.DRY,
52  ZHAHVACMode.FAN_ONLY: HVACMode.FAN_ONLY,
53 }
54 
55 ZHA_TO_HA_HVAC_ACTION = {
56  ZHAHVACAction.OFF: HVACAction.OFF,
57  ZHAHVACAction.HEATING: HVACAction.HEATING,
58  ZHAHVACAction.COOLING: HVACAction.COOLING,
59  ZHAHVACAction.DRYING: HVACAction.DRYING,
60  ZHAHVACAction.IDLE: HVACAction.IDLE,
61  ZHAHVACAction.FAN: HVACAction.FAN,
62  ZHAHVACAction.PREHEATING: HVACAction.PREHEATING,
63 }
64 
65 
67  hass: HomeAssistant,
68  config_entry: ConfigEntry,
69  async_add_entities: AddEntitiesCallback,
70 ) -> None:
71  """Set up the Zigbee Home Automation sensor from config entry."""
72  zha_data = get_zha_data(hass)
73  entities_to_create = zha_data.platforms[Platform.CLIMATE]
74 
76  hass,
77  SIGNAL_ADD_ENTITIES,
78  functools.partial(
79  zha_async_add_entities, async_add_entities, Thermostat, entities_to_create
80  ),
81  )
82  config_entry.async_on_unload(unsub)
83 
84 
86  """Representation of a ZHA Thermostat device."""
87 
88  _attr_precision = PRECISION_TENTHS
89  _attr_temperature_unit = UnitOfTemperature.CELSIUS
90  _attr_translation_key: str = "thermostat"
91  _enable_turn_on_off_backwards_compatibility = False
92 
93  def __init__(self, entity_data: EntityData, **kwargs: Any) -> None:
94  """Initialize the ZHA thermostat entity."""
95  super().__init__(entity_data, **kwargs)
96  self._attr_hvac_modes_attr_hvac_modes = [
97  ZHA_TO_HA_HVAC_MODE[mode] for mode in self.entity_data.entity.hvac_modes
98  ]
99  self._attr_hvac_mode_attr_hvac_mode = ZHA_TO_HA_HVAC_MODE.get(
100  self.entity_data.entity.hvac_mode
101  )
102  self._attr_hvac_action_attr_hvac_action = ZHA_TO_HA_HVAC_ACTION.get(
103  self.entity_data.entity.hvac_action
104  )
105 
106  features: ClimateEntityFeature = ClimateEntityFeature(0)
107  zha_features: ZHAClimateEntityFeature = (
108  self.entity_data.entity.supported_features
109  )
110 
111  if ZHAClimateEntityFeature.TARGET_TEMPERATURE in zha_features:
112  features |= ClimateEntityFeature.TARGET_TEMPERATURE
113  if ZHAClimateEntityFeature.TARGET_TEMPERATURE_RANGE in zha_features:
114  features |= ClimateEntityFeature.TARGET_TEMPERATURE_RANGE
115  if ZHAClimateEntityFeature.TARGET_HUMIDITY in zha_features:
116  features |= ClimateEntityFeature.TARGET_HUMIDITY
117  if ZHAClimateEntityFeature.PRESET_MODE in zha_features:
118  features |= ClimateEntityFeature.PRESET_MODE
119  if ZHAClimateEntityFeature.FAN_MODE in zha_features:
120  features |= ClimateEntityFeature.FAN_MODE
121  if ZHAClimateEntityFeature.SWING_MODE in zha_features:
122  features |= ClimateEntityFeature.SWING_MODE
123  if ZHAClimateEntityFeature.TURN_OFF in zha_features:
124  features |= ClimateEntityFeature.TURN_OFF
125  if ZHAClimateEntityFeature.TURN_ON in zha_features:
126  features |= ClimateEntityFeature.TURN_ON
127 
128  self._attr_supported_features_attr_supported_features = features
129 
130  @property
131  def extra_state_attributes(self) -> Mapping[str, Any] | None:
132  """Return entity specific state attributes."""
133  state = self.entity_data.entity.state
134 
135  return exclude_none_values(
136  {
137  "occupancy": state.get("occupancy"),
138  "occupied_cooling_setpoint": state.get("occupied_cooling_setpoint"),
139  "occupied_heating_setpoint": state.get("occupied_heating_setpoint"),
140  "pi_cooling_demand": state.get("pi_cooling_demand"),
141  "pi_heating_demand": state.get("pi_heating_demand"),
142  "system_mode": state.get("system_mode"),
143  "unoccupied_cooling_setpoint": state.get("unoccupied_cooling_setpoint"),
144  "unoccupied_heating_setpoint": state.get("unoccupied_heating_setpoint"),
145  }
146  )
147 
148  @property
149  def current_temperature(self) -> float | None:
150  """Return the current temperature."""
151  return self.entity_data.entity.current_temperature
152 
153  @property
154  def fan_mode(self) -> str | None:
155  """Return current FAN mode."""
156  return self.entity_data.entity.fan_mode
157 
158  @property
159  def fan_modes(self) -> list[str] | None:
160  """Return supported FAN modes."""
161  return self.entity_data.entity.fan_modes
162 
163  @property
164  def preset_mode(self) -> str:
165  """Return current preset mode."""
166  return self.entity_data.entity.preset_mode
167 
168  @property
169  def preset_modes(self) -> list[str] | None:
170  """Return supported preset modes."""
171  return self.entity_data.entity.preset_modes
172 
173  @property
174  def target_temperature(self) -> float | None:
175  """Return the temperature we try to reach."""
176  return self.entity_data.entity.target_temperature
177 
178  @property
179  def target_temperature_high(self) -> float | None:
180  """Return the upper bound temperature we try to reach."""
181  return self.entity_data.entity.target_temperature_high
182 
183  @property
184  def target_temperature_low(self) -> float | None:
185  """Return the lower bound temperature we try to reach."""
186  return self.entity_data.entity.target_temperature_low
187 
188  @property
189  def max_temp(self) -> float:
190  """Return the maximum temperature."""
191  return self.entity_data.entity.max_temp
192 
193  @property
194  def min_temp(self) -> float:
195  """Return the minimum temperature."""
196  return self.entity_data.entity.min_temp
197 
198  @callback
199  def _handle_entity_events(self, event: Any) -> None:
200  """Entity state changed."""
201  self._attr_hvac_mode_attr_hvac_mode = self._attr_hvac_mode_attr_hvac_mode = ZHA_TO_HA_HVAC_MODE.get(
202  self.entity_data.entity.hvac_mode
203  )
204  self._attr_hvac_action_attr_hvac_action = ZHA_TO_HA_HVAC_ACTION.get(
205  self.entity_data.entity.hvac_action
206  )
207  super()._handle_entity_events(event)
208 
209  @convert_zha_error_to_ha_error
210  async def async_set_fan_mode(self, fan_mode: str) -> None:
211  """Set fan mode."""
212  await self.entity_data.entity.async_set_fan_mode(fan_mode=fan_mode)
213  self.async_write_ha_stateasync_write_ha_state()
214 
215  @convert_zha_error_to_ha_error
216  async def async_set_hvac_mode(self, hvac_mode: HVACMode) -> None:
217  """Set new target operation mode."""
218  await self.entity_data.entity.async_set_hvac_mode(hvac_mode=hvac_mode)
219  self.async_write_ha_stateasync_write_ha_state()
220 
221  @convert_zha_error_to_ha_error
222  async def async_set_preset_mode(self, preset_mode: str) -> None:
223  """Set new preset mode."""
224  await self.entity_data.entity.async_set_preset_mode(preset_mode=preset_mode)
225  self.async_write_ha_stateasync_write_ha_state()
226 
227  @convert_zha_error_to_ha_error
228  async def async_set_temperature(self, **kwargs: Any) -> None:
229  """Set new target temperature."""
230  await self.entity_data.entity.async_set_temperature(
231  target_temp_low=kwargs.get(ATTR_TARGET_TEMP_LOW),
232  target_temp_high=kwargs.get(ATTR_TARGET_TEMP_HIGH),
233  temperature=kwargs.get(ATTR_TEMPERATURE),
234  hvac_mode=kwargs.get(ATTR_HVAC_MODE),
235  )
236  self.async_write_ha_stateasync_write_ha_state()
None __init__(self, EntityData entity_data, **Any kwargs)
Definition: climate.py:93
Mapping[str, Any]|None extra_state_attributes(self)
Definition: climate.py:131
None async_set_hvac_mode(self, HVACMode hvac_mode)
Definition: climate.py:216
None async_set_preset_mode(self, str preset_mode)
Definition: climate.py:222
None async_set_temperature(self, **Any kwargs)
Definition: climate.py:228
None async_set_fan_mode(self, str fan_mode)
Definition: climate.py:210
None async_setup_entry(HomeAssistant hass, ConfigEntry config_entry, AddEntitiesCallback async_add_entities)
Definition: climate.py:70
HAZHAData get_zha_data(HomeAssistant hass)
Definition: helpers.py:1020
dict[str, Any] exclude_none_values(Mapping[str, Any] obj)
Definition: helpers.py:1342
Callable[[], None] async_dispatcher_connect(HomeAssistant hass, str signal, Callable[..., Any] target)
Definition: dispatcher.py:103