Home Assistant Unofficial Reference 2024.12.1
climate.py
Go to the documentation of this file.
1 """Support for Melissa Climate A/C."""
2 
3 from __future__ import annotations
4 
5 import logging
6 from typing import Any
7 
9  FAN_AUTO,
10  FAN_HIGH,
11  FAN_LOW,
12  FAN_MEDIUM,
13  ClimateEntity,
14  ClimateEntityFeature,
15  HVACMode,
16 )
17 from homeassistant.const import ATTR_TEMPERATURE, PRECISION_WHOLE, UnitOfTemperature
18 from homeassistant.core import HomeAssistant
19 from homeassistant.helpers.entity_platform import AddEntitiesCallback
20 from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType
21 
22 from . import DATA_MELISSA
23 
24 _LOGGER = logging.getLogger(__name__)
25 
26 OP_MODES = [
27  HVACMode.HEAT,
28  HVACMode.COOL,
29  HVACMode.DRY,
30  HVACMode.FAN_ONLY,
31  HVACMode.OFF,
32 ]
33 
34 FAN_MODES = [FAN_AUTO, FAN_HIGH, FAN_MEDIUM, FAN_LOW]
35 
36 
38  hass: HomeAssistant,
39  config: ConfigType,
40  async_add_entities: AddEntitiesCallback,
41  discovery_info: DiscoveryInfoType | None = None,
42 ) -> None:
43  """Iterate through and add all Melissa devices."""
44  api = hass.data[DATA_MELISSA]
45  devices = (await api.async_fetch_devices()).values()
46 
48  (
49  MelissaClimate(api, device["serial_number"], device)
50  for device in devices
51  if device["type"] == "melissa"
52  ),
53  True,
54  )
55 
56 
58  """Representation of a Melissa Climate device."""
59 
60  _attr_hvac_modes = OP_MODES
61  _attr_supported_features = (
62  ClimateEntityFeature.FAN_MODE
63  | ClimateEntityFeature.TARGET_TEMPERATURE
64  | ClimateEntityFeature.TURN_OFF
65  | ClimateEntityFeature.TURN_ON
66  )
67  _attr_temperature_unit = UnitOfTemperature.CELSIUS
68  _enable_turn_on_off_backwards_compatibility = False
69 
70  def __init__(self, api, serial_number, init_data):
71  """Initialize the climate device."""
72  self._name_name = init_data["name"]
73  self._api_api = api
74  self._serial_number_serial_number = serial_number
75  self._data_data = init_data["controller_log"]
76  self._state_state = None
77  self._cur_settings_cur_settings = None
78 
79  @property
80  def name(self):
81  """Return the name of the thermostat, if any."""
82  return self._name_name
83 
84  @property
85  def fan_mode(self):
86  """Return the current fan mode."""
87  if self._cur_settings_cur_settings is not None:
88  return self.melissa_fan_to_hassmelissa_fan_to_hass(self._cur_settings_cur_settings[self._api_api.FAN])
89  return None
90 
91  @property
93  """Return the current temperature."""
94  if self._data_data:
95  return self._data_data[self._api_api.TEMP]
96  return None
97 
98  @property
99  def current_humidity(self):
100  """Return the current humidity value."""
101  if self._data_data:
102  return self._data_data[self._api_api.HUMIDITY]
103  return None
104 
105  @property
107  """Return the supported step of target temperature."""
108  return PRECISION_WHOLE
109 
110  @property
111  def hvac_mode(self) -> HVACMode | None:
112  """Return the current operation mode."""
113  if self._cur_settings_cur_settings is None:
114  return None
115 
116  is_on = self._cur_settings_cur_settings[self._api_api.STATE] in (
117  self._api_api.STATE_ON,
118  self._api_api.STATE_IDLE,
119  )
120 
121  if not is_on:
122  return HVACMode.OFF
123 
124  return self.melissa_op_to_hassmelissa_op_to_hass(self._cur_settings_cur_settings[self._api_api.MODE])
125 
126  @property
127  def fan_modes(self):
128  """List of available fan modes."""
129  return FAN_MODES
130 
131  @property
133  """Return the temperature we try to reach."""
134  if self._cur_settings_cur_settings is None:
135  return None
136  return self._cur_settings_cur_settings[self._api_api.TEMP]
137 
138  @property
139  def min_temp(self):
140  """Return the minimum supported temperature for the thermostat."""
141  return 16
142 
143  @property
144  def max_temp(self):
145  """Return the maximum supported temperature for the thermostat."""
146  return 30
147 
148  async def async_set_temperature(self, **kwargs: Any) -> None:
149  """Set new target temperature."""
150  temp = kwargs.get(ATTR_TEMPERATURE)
151  await self.async_sendasync_send({self._api_api.TEMP: temp})
152 
153  async def async_set_fan_mode(self, fan_mode: str) -> None:
154  """Set fan mode."""
155  melissa_fan_mode = self.hass_fan_to_melissahass_fan_to_melissa(fan_mode)
156  await self.async_sendasync_send({self._api_api.FAN: melissa_fan_mode})
157 
158  async def async_set_hvac_mode(self, hvac_mode: HVACMode) -> None:
159  """Set operation mode."""
160  if hvac_mode == HVACMode.OFF:
161  await self.async_sendasync_send({self._api_api.STATE: self._api_api.STATE_OFF})
162  return
163 
164  mode = self.hass_mode_to_melissahass_mode_to_melissa(hvac_mode)
165  await self.async_sendasync_send(
166  {self._api_api.MODE: mode, self._api_api.STATE: self._api_api.STATE_ON}
167  )
168 
169  async def async_send(self, value):
170  """Send action to service."""
171  try:
172  old_value = self._cur_settings_cur_settings.copy()
173  self._cur_settings_cur_settings.update(value)
174  except AttributeError:
175  old_value = None
176  if not await self._api_api.async_send(
177  self._serial_number_serial_number, "melissa", self._cur_settings_cur_settings
178  ):
179  self._cur_settings_cur_settings = old_value
180 
181  async def async_update(self) -> None:
182  """Get latest data from Melissa."""
183  try:
184  self._data_data = (await self._api_api.async_status(cached=True))[
185  self._serial_number_serial_number
186  ]
187  self._cur_settings_cur_settings = (
188  await self._api_api.async_cur_settings(self._serial_number_serial_number)
189  )["controller"]["_relation"]["command_log"]
190  except KeyError:
191  _LOGGER.warning("Unable to update entity %s", self.entity_identity_id)
192 
193  def melissa_op_to_hass(self, mode):
194  """Translate Melissa modes to hass states."""
195  if mode == self._api_api.MODE_HEAT:
196  return HVACMode.HEAT
197  if mode == self._api_api.MODE_COOL:
198  return HVACMode.COOL
199  if mode == self._api_api.MODE_DRY:
200  return HVACMode.DRY
201  if mode == self._api_api.MODE_FAN:
202  return HVACMode.FAN_ONLY
203  _LOGGER.warning("Operation mode %s could not be mapped to hass", mode)
204  return None
205 
206  def melissa_fan_to_hass(self, fan):
207  """Translate Melissa fan modes to hass modes."""
208  if fan == self._api_api.FAN_AUTO:
209  return FAN_AUTO
210  if fan == self._api_api.FAN_LOW:
211  return FAN_LOW
212  if fan == self._api_api.FAN_MEDIUM:
213  return FAN_MEDIUM
214  if fan == self._api_api.FAN_HIGH:
215  return FAN_HIGH
216  _LOGGER.warning("Fan mode %s could not be mapped to hass", fan)
217  return None
218 
219  def hass_mode_to_melissa(self, mode):
220  """Translate hass states to melissa modes."""
221  if mode == HVACMode.HEAT:
222  return self._api_api.MODE_HEAT
223  if mode == HVACMode.COOL:
224  return self._api_api.MODE_COOL
225  if mode == HVACMode.DRY:
226  return self._api_api.MODE_DRY
227  if mode == HVACMode.FAN_ONLY:
228  return self._api_api.MODE_FAN
229  _LOGGER.warning("Melissa have no setting for %s mode", mode)
230  return None
231 
232  def hass_fan_to_melissa(self, fan):
233  """Translate hass fan modes to melissa modes."""
234  if fan == FAN_AUTO:
235  return self._api_api.FAN_AUTO
236  if fan == FAN_LOW:
237  return self._api_api.FAN_LOW
238  if fan == FAN_MEDIUM:
239  return self._api_api.FAN_MEDIUM
240  if fan == FAN_HIGH:
241  return self._api_api.FAN_HIGH
242  _LOGGER.warning("Melissa have no setting for %s fan mode", fan)
243  return None
def __init__(self, api, serial_number, init_data)
Definition: climate.py:70
None async_set_hvac_mode(self, HVACMode hvac_mode)
Definition: climate.py:158
IssData update(pyiss.ISS iss)
Definition: __init__.py:33
None async_setup_platform(HomeAssistant hass, ConfigType config, AddEntitiesCallback async_add_entities, DiscoveryInfoType|None discovery_info=None)
Definition: climate.py:42