Home Assistant Unofficial Reference 2024.12.1
climate.py
Go to the documentation of this file.
1 """Support for climates."""
2 
3 from __future__ import annotations
4 
5 from enum import StrEnum
6 from typing import Any
7 
8 from aiocomelit import ComelitSerialBridgeObject
9 from aiocomelit.const import CLIMATE
10 
12  ClimateEntity,
13  ClimateEntityFeature,
14  HVACAction,
15  HVACMode,
16  UnitOfTemperature,
17 )
18 from homeassistant.config_entries import ConfigEntry
19 from homeassistant.const import ATTR_TEMPERATURE, PRECISION_TENTHS
20 from homeassistant.core import HomeAssistant
21 from homeassistant.helpers.entity_platform import AddEntitiesCallback
22 from homeassistant.helpers.update_coordinator import CoordinatorEntity
23 
24 from .const import DOMAIN
25 from .coordinator import ComelitSerialBridge
26 
27 
28 class ClimaComelitMode(StrEnum):
29  """Serial Bridge clima modes."""
30 
31  AUTO = "A"
32  OFF = "O"
33  LOWER = "L"
34  UPPER = "U"
35 
36 
37 class ClimaComelitCommand(StrEnum):
38  """Serial Bridge clima commands."""
39 
40  OFF = "off"
41  ON = "on"
42  MANUAL = "man"
43  SET = "set"
44  AUTO = "auto"
45 
46 
47 API_STATUS: dict[str, dict[str, Any]] = {
48  ClimaComelitMode.OFF: {
49  "action": "off",
50  "hvac_mode": HVACMode.OFF,
51  "hvac_action": HVACAction.OFF,
52  },
53  ClimaComelitMode.LOWER: {
54  "action": "lower",
55  "hvac_mode": HVACMode.COOL,
56  "hvac_action": HVACAction.COOLING,
57  },
58  ClimaComelitMode.UPPER: {
59  "action": "upper",
60  "hvac_mode": HVACMode.HEAT,
61  "hvac_action": HVACAction.HEATING,
62  },
63 }
64 
65 MODE_TO_ACTION: dict[HVACMode, ClimaComelitCommand] = {
66  HVACMode.OFF: ClimaComelitCommand.OFF,
67  HVACMode.AUTO: ClimaComelitCommand.AUTO,
68  HVACMode.COOL: ClimaComelitCommand.MANUAL,
69  HVACMode.HEAT: ClimaComelitCommand.MANUAL,
70 }
71 
72 
74  hass: HomeAssistant,
75  config_entry: ConfigEntry,
76  async_add_entities: AddEntitiesCallback,
77 ) -> None:
78  """Set up Comelit climates."""
79 
80  coordinator: ComelitSerialBridge = hass.data[DOMAIN][config_entry.entry_id]
81 
83  ComelitClimateEntity(coordinator, device, config_entry.entry_id)
84  for device in coordinator.data[CLIMATE].values()
85  )
86 
87 
88 class ComelitClimateEntity(CoordinatorEntity[ComelitSerialBridge], ClimateEntity):
89  """Climate device."""
90 
91  _attr_hvac_modes = [HVACMode.AUTO, HVACMode.COOL, HVACMode.HEAT, HVACMode.OFF]
92  _attr_max_temp = 30
93  _attr_min_temp = 5
94  _attr_supported_features = (
95  ClimateEntityFeature.TARGET_TEMPERATURE
96  | ClimateEntityFeature.TURN_OFF
97  | ClimateEntityFeature.TURN_ON
98  )
99  _attr_target_temperature_step = PRECISION_TENTHS
100  _attr_temperature_unit = UnitOfTemperature.CELSIUS
101  _attr_has_entity_name = True
102  _attr_name = None
103  _enable_turn_on_off_backwards_compatibility = False
104 
105  def __init__(
106  self,
107  coordinator: ComelitSerialBridge,
108  device: ComelitSerialBridgeObject,
109  config_entry_entry_id: str,
110  ) -> None:
111  """Init light entity."""
112  self._api_api = coordinator.api
113  self._device_device_device = device
114  super().__init__(coordinator)
115  # Use config_entry.entry_id as base for unique_id
116  # because no serial number or mac is available
117  self._attr_unique_id_attr_unique_id = f"{config_entry_entry_id}-{device.index}"
118  self._attr_device_info_attr_device_info = coordinator.platform_device_info(device, device.type)
119 
120  @property
121  def _clima(self) -> list[Any]:
122  """Return clima device data."""
123  # CLIMATE has a 2 item tuple:
124  # - first for Clima
125  # - second for Humidifier
126  return self.coordinator.data[CLIMATE][self._device_device_device.index].val[0]
127 
128  @property
129  def _api_mode(self) -> str:
130  """Return device mode."""
131  # Values from API: "O", "L", "U"
132  return self._clima_clima[2]
133 
134  @property
135  def _api_active(self) -> bool:
136  "Return device active/idle."
137  return self._clima_clima[1]
138 
139  @property
140  def _api_automatic(self) -> bool:
141  """Return device in automatic/manual mode."""
142  return self._clima_clima[3] == ClimaComelitMode.AUTO
143 
144  @property
145  def target_temperature(self) -> float:
146  """Set target temperature."""
147  return self._clima_clima[4] / 10
148 
149  @property
150  def current_temperature(self) -> float:
151  """Return current temperature."""
152  return self._clima_clima[0] / 10
153 
154  @property
155  def hvac_mode(self) -> HVACMode | None:
156  """HVAC current mode."""
157 
158  if self._api_mode_api_mode_api_mode == ClimaComelitMode.OFF:
159  return HVACMode.OFF
160 
161  if self._api_automatic_api_automatic:
162  return HVACMode.AUTO
163 
164  if self._api_mode_api_mode_api_mode in API_STATUS:
165  return API_STATUS[self._api_mode_api_mode_api_mode]["hvac_mode"]
166 
167  return None
168 
169  @property
170  def hvac_action(self) -> HVACAction | None:
171  """HVAC current action."""
172 
173  if self._api_mode_api_mode_api_mode == ClimaComelitMode.OFF:
174  return HVACAction.OFF
175 
176  if not self._api_active_api_active:
177  return HVACAction.IDLE
178 
179  if self._api_mode_api_mode_api_mode in API_STATUS:
180  return API_STATUS[self._api_mode_api_mode_api_mode]["hvac_action"]
181 
182  return None
183 
184  async def async_set_temperature(self, **kwargs: Any) -> None:
185  """Set new target temperature."""
186  if (
187  target_temp := kwargs.get(ATTR_TEMPERATURE)
188  ) is None or self.hvac_modehvac_modehvac_modehvac_modehvac_mode == HVACMode.OFF:
189  return
190 
191  await self.coordinator.api.set_clima_status(
192  self._device_device_device.index, ClimaComelitCommand.MANUAL
193  )
194  await self.coordinator.api.set_clima_status(
195  self._device_device_device.index, ClimaComelitCommand.SET, target_temp
196  )
197 
198  async def async_set_hvac_mode(self, hvac_mode: HVACMode) -> None:
199  """Set hvac mode."""
200 
201  if hvac_mode != HVACMode.OFF:
202  await self.coordinator.api.set_clima_status(
203  self._device_device_device.index, ClimaComelitCommand.ON
204  )
205  await self.coordinator.api.set_clima_status(
206  self._device_device_device.index, MODE_TO_ACTION[hvac_mode]
207  )
None __init__(self, ComelitSerialBridge coordinator, ComelitSerialBridgeObject device, str config_entry_entry_id)
Definition: climate.py:110
None async_setup_entry(HomeAssistant hass, ConfigEntry config_entry, AddEntitiesCallback async_add_entities)
Definition: climate.py:77