Home Assistant Unofficial Reference 2024.12.1
climate.py
Go to the documentation of this file.
1 """Support for Rheem EcoNet thermostats."""
2 
3 from typing import Any
4 
5 from pyeconet.equipment import EquipmentType
6 from pyeconet.equipment.thermostat import ThermostatFanMode, ThermostatOperationMode
7 
9  ATTR_TARGET_TEMP_HIGH,
10  ATTR_TARGET_TEMP_LOW,
11  FAN_AUTO,
12  FAN_HIGH,
13  FAN_LOW,
14  FAN_MEDIUM,
15  ClimateEntity,
16  ClimateEntityFeature,
17  HVACMode,
18 )
19 from homeassistant.config_entries import ConfigEntry
20 from homeassistant.const import ATTR_TEMPERATURE, UnitOfTemperature
21 from homeassistant.core import HomeAssistant
22 from homeassistant.helpers.entity_platform import AddEntitiesCallback
23 from homeassistant.helpers.issue_registry import IssueSeverity, async_create_issue
24 
25 from .const import DOMAIN, EQUIPMENT
26 from .entity import EcoNetEntity
27 
28 ECONET_STATE_TO_HA = {
29  ThermostatOperationMode.HEATING: HVACMode.HEAT,
30  ThermostatOperationMode.COOLING: HVACMode.COOL,
31  ThermostatOperationMode.OFF: HVACMode.OFF,
32  ThermostatOperationMode.AUTO: HVACMode.HEAT_COOL,
33  ThermostatOperationMode.FAN_ONLY: HVACMode.FAN_ONLY,
34 }
35 HA_STATE_TO_ECONET = {value: key for key, value in ECONET_STATE_TO_HA.items()}
36 
37 ECONET_FAN_STATE_TO_HA = {
38  ThermostatFanMode.AUTO: FAN_AUTO,
39  ThermostatFanMode.LOW: FAN_LOW,
40  ThermostatFanMode.MEDIUM: FAN_MEDIUM,
41  ThermostatFanMode.HIGH: FAN_HIGH,
42 }
43 HA_FAN_STATE_TO_ECONET = {value: key for key, value in ECONET_FAN_STATE_TO_HA.items()}
44 
45 SUPPORT_FLAGS_THERMOSTAT = (
46  ClimateEntityFeature.TARGET_TEMPERATURE
47  | ClimateEntityFeature.TARGET_TEMPERATURE_RANGE
48  | ClimateEntityFeature.FAN_MODE
49  | ClimateEntityFeature.AUX_HEAT
50 )
51 
52 
54  hass: HomeAssistant, entry: ConfigEntry, async_add_entities: AddEntitiesCallback
55 ) -> None:
56  """Set up EcoNet thermostat based on a config entry."""
57  equipment = hass.data[DOMAIN][EQUIPMENT][entry.entry_id]
59  [
60  EcoNetThermostat(thermostat)
61  for thermostat in equipment[EquipmentType.THERMOSTAT]
62  ],
63  )
64 
65 
67  """Define an Econet thermostat."""
68 
69  _attr_should_poll = True
70  _attr_temperature_unit = UnitOfTemperature.FAHRENHEIT
71  _enable_turn_on_off_backwards_compatibility = False
72 
73  def __init__(self, thermostat):
74  """Initialize."""
75  super().__init__(thermostat)
76  self._attr_hvac_modes_attr_hvac_modes = []
77  for mode in self._econet_econet.modes:
78  if mode not in [
79  ThermostatOperationMode.UNKNOWN,
80  ThermostatOperationMode.EMERGENCY_HEAT,
81  ]:
82  ha_mode = ECONET_STATE_TO_HA[mode]
83  self._attr_hvac_modes_attr_hvac_modes.append(ha_mode)
84 
85  self._attr_supported_features |= SUPPORT_FLAGS_THERMOSTAT
86  if thermostat.supports_humidifier:
87  self._attr_supported_features |= ClimateEntityFeature.TARGET_HUMIDITY
88  if len(self.hvac_modeshvac_modes) > 1 and HVACMode.OFF in self.hvac_modeshvac_modes:
89  self._attr_supported_features |= (
90  ClimateEntityFeature.TURN_OFF | ClimateEntityFeature.TURN_ON
91  )
92 
93  @property
95  """Return the current temperature."""
96  return self._econet_econet.set_point
97 
98  @property
99  def current_humidity(self):
100  """Return the current humidity."""
101  return self._econet_econet.humidity
102 
103  @property
104  def target_humidity(self):
105  """Return the humidity we try to reach."""
106  if self._econet_econet.supports_humidifier:
107  return self._econet_econet.dehumidifier_set_point
108  return None
109 
110  @property
112  """Return the temperature we try to reach."""
113  if self.hvac_modehvac_modehvac_modehvac_modehvac_mode == HVACMode.COOL:
114  return self._econet_econet.cool_set_point
115  if self.hvac_modehvac_modehvac_modehvac_modehvac_mode == HVACMode.HEAT:
116  return self._econet_econet.heat_set_point
117  return None
118 
119  @property
121  """Return the lower bound temperature we try to reach."""
122  if self.hvac_modehvac_modehvac_modehvac_modehvac_mode == HVACMode.HEAT_COOL:
123  return self._econet_econet.heat_set_point
124  return None
125 
126  @property
128  """Return the higher bound temperature we try to reach."""
129  if self.hvac_modehvac_modehvac_modehvac_modehvac_mode == HVACMode.HEAT_COOL:
130  return self._econet_econet.cool_set_point
131  return None
132 
133  def set_temperature(self, **kwargs: Any) -> None:
134  """Set new target temperature."""
135  target_temp = kwargs.get(ATTR_TEMPERATURE)
136  target_temp_low = kwargs.get(ATTR_TARGET_TEMP_LOW)
137  target_temp_high = kwargs.get(ATTR_TARGET_TEMP_HIGH)
138  if target_temp:
139  self._econet_econet.set_set_point(target_temp, None, None)
140  if target_temp_low or target_temp_high:
141  self._econet_econet.set_set_point(None, target_temp_high, target_temp_low)
142 
143  @property
144  def is_aux_heat(self):
145  """Return true if aux heater."""
146  return self._econet_econet.mode == ThermostatOperationMode.EMERGENCY_HEAT
147 
148  @property
149  def hvac_mode(self) -> HVACMode:
150  """Return hvac operation ie. heat, cool, mode.
151 
152  Needs to be one of HVAC_MODE_*.
153  """
154  econet_mode = self._econet_econet.mode
155  _current_op = HVACMode.OFF
156  if econet_mode is not None:
157  _current_op = ECONET_STATE_TO_HA[econet_mode]
158 
159  return _current_op
160 
161  def set_hvac_mode(self, hvac_mode: HVACMode) -> None:
162  """Set new target hvac mode."""
163  hvac_mode_to_set = HA_STATE_TO_ECONET.get(hvac_mode)
164  if hvac_mode_to_set is None:
165  raise ValueError(f"{hvac_mode} is not a valid mode.")
166  self._econet_econet.set_mode(hvac_mode_to_set)
167 
168  def set_humidity(self, humidity: int) -> None:
169  """Set new target humidity."""
170  self._econet_econet.set_dehumidifier_set_point(humidity)
171 
172  @property
173  def fan_mode(self):
174  """Return the current fan mode."""
175  econet_fan_mode = self._econet_econet.fan_mode
176 
177  # Remove this after we figure out how to handle med lo and med hi
178  if econet_fan_mode in [ThermostatFanMode.MEDHI, ThermostatFanMode.MEDLO]:
179  econet_fan_mode = ThermostatFanMode.MEDIUM
180 
181  _current_fan_mode = FAN_AUTO
182  if econet_fan_mode is not None:
183  _current_fan_mode = ECONET_FAN_STATE_TO_HA[econet_fan_mode]
184  return _current_fan_mode
185 
186  @property
187  def fan_modes(self):
188  """Return the fan modes."""
189  return [
190  ECONET_FAN_STATE_TO_HA[mode]
191  for mode in self._econet_econet.fan_modes
192  # Remove the MEDLO MEDHI once we figure out how to handle it
193  if mode
194  not in [
195  ThermostatFanMode.UNKNOWN,
196  ThermostatFanMode.MEDLO,
197  ThermostatFanMode.MEDHI,
198  ]
199  ]
200 
201  def set_fan_mode(self, fan_mode: str) -> None:
202  """Set the fan mode."""
203  self._econet_econet.set_fan_mode(HA_FAN_STATE_TO_ECONET[fan_mode])
204 
205  def turn_aux_heat_on(self) -> None:
206  """Turn auxiliary heater on."""
208  self.hasshass,
209  DOMAIN,
210  "migrate_aux_heat",
211  breaks_in_ha_version="2025.4.0",
212  is_fixable=True,
213  is_persistent=True,
214  translation_key="migrate_aux_heat",
215  severity=IssueSeverity.WARNING,
216  )
217  self._econet_econet.set_mode(ThermostatOperationMode.EMERGENCY_HEAT)
218 
219  def turn_aux_heat_off(self) -> None:
220  """Turn auxiliary heater off."""
222  self.hasshass,
223  DOMAIN,
224  "migrate_aux_heat",
225  breaks_in_ha_version="2025.4.0",
226  is_fixable=True,
227  is_persistent=True,
228  translation_key="migrate_aux_heat",
229  severity=IssueSeverity.WARNING,
230  )
231  self._econet_econet.set_mode(ThermostatOperationMode.HEATING)
232 
233  @property
234  def min_temp(self):
235  """Return the minimum temperature."""
236  return self._econet_econet.set_point_limits[0]
237 
238  @property
239  def max_temp(self):
240  """Return the maximum temperature."""
241  return self._econet_econet.set_point_limits[1]
242 
243  @property
244  def min_humidity(self) -> int:
245  """Return the minimum humidity."""
246  return self._econet_econet.dehumidifier_set_point_limits[0]
247 
248  @property
249  def max_humidity(self) -> int:
250  """Return the maximum humidity."""
251  return self._econet_econet.dehumidifier_set_point_limits[1]
None set_hvac_mode(self, HVACMode hvac_mode)
Definition: climate.py:161
None async_setup_entry(HomeAssistant hass, ConfigEntry entry, AddEntitiesCallback async_add_entities)
Definition: climate.py:55
None async_create_issue(HomeAssistant hass, str entry_id)
Definition: repairs.py:69