Home Assistant Unofficial Reference 2024.12.1
humidifier.py
Go to the documentation of this file.
1 """Support for HomeKit Controller humidifier."""
2 
3 from __future__ import annotations
4 
5 from typing import Any
6 
7 from aiohomekit.model.characteristics import CharacteristicsTypes
8 from aiohomekit.model.services import Service, ServicesTypes
9 from propcache import cached_property
10 
12  DEFAULT_MAX_HUMIDITY,
13  DEFAULT_MIN_HUMIDITY,
14  MODE_AUTO,
15  MODE_NORMAL,
16  HumidifierDeviceClass,
17  HumidifierEntity,
18  HumidifierEntityFeature,
19 )
20 from homeassistant.config_entries import ConfigEntry
21 from homeassistant.const import Platform
22 from homeassistant.core import HomeAssistant, callback
23 from homeassistant.helpers.entity_platform import AddEntitiesCallback
24 from homeassistant.helpers.typing import ConfigType
25 
26 from . import KNOWN_DEVICES
27 from .connection import HKDevice
28 from .entity import HomeKitEntity
29 
30 HK_MODE_TO_HA = {
31  0: "off",
32  1: MODE_AUTO,
33  2: "humidifying",
34  3: "dehumidifying",
35 }
36 
37 HA_MODE_TO_HK = {
38  MODE_AUTO: 0,
39  "humidifying": 1,
40  "dehumidifying": 2,
41 }
42 
43 
45  """Representation of a HomeKit Controller Humidifier."""
46 
47  _attr_supported_features = HumidifierEntityFeature.MODES
48  _attr_available_modes = [MODE_NORMAL, MODE_AUTO]
49  _humidity_char = CharacteristicsTypes.RELATIVE_HUMIDITY_HUMIDIFIER_THRESHOLD
50  _on_mode_value = 1
51 
52  @callback
53  def _async_reconfigure(self) -> None:
54  """Reconfigure entity."""
55  self._async_clear_property_cache_async_clear_property_cache(("max_humidity", "min_humidity"))
56  super()._async_reconfigure()
57 
58  @property
59  def is_on(self) -> bool:
60  """Return true if device is on."""
61  return self.serviceservice.value(CharacteristicsTypes.ACTIVE)
62 
63  @property
64  def mode(self) -> str | None:
65  """Return the current mode, e.g., home, auto, baby.
66 
67  Requires HumidifierEntityFeature.MODES.
68  """
69  mode = self.serviceservice.value(
70  CharacteristicsTypes.CURRENT_HUMIDIFIER_DEHUMIDIFIER_STATE
71  )
72  return MODE_AUTO if mode == 1 else MODE_NORMAL
73 
74  @property
75  def current_humidity(self) -> int | None:
76  """Return the current humidity."""
77  return self.serviceservice.value(CharacteristicsTypes.RELATIVE_HUMIDITY_CURRENT)
78 
79  @property
80  def target_humidity(self) -> int | None:
81  """Return the humidity we try to reach."""
82  return self.serviceservice.value(self._humidity_char_humidity_char)
83 
84  @cached_property
85  def min_humidity(self) -> int:
86  """Return the minimum humidity."""
87  return int(self.serviceservice[self._humidity_char_humidity_char].minValue or DEFAULT_MIN_HUMIDITY)
88 
89  @cached_property
90  def max_humidity(self) -> int:
91  """Return the maximum humidity."""
92  return int(self.serviceservice[self._humidity_char_humidity_char].maxValue or DEFAULT_MAX_HUMIDITY)
93 
94  async def async_set_humidity(self, humidity: int) -> None:
95  """Set new target humidity."""
96  await self.async_put_characteristicsasync_put_characteristics({self._humidity_char_humidity_char: humidity})
97 
98  async def async_turn_on(self, **kwargs: Any) -> None:
99  """Turn the specified valve on."""
100  await self.async_put_characteristicsasync_put_characteristics({CharacteristicsTypes.ACTIVE: True})
101 
102  async def async_turn_off(self, **kwargs: Any) -> None:
103  """Turn the specified valve off."""
104  await self.async_put_characteristicsasync_put_characteristics({CharacteristicsTypes.ACTIVE: False})
105 
106  async def async_set_mode(self, mode: str) -> None:
107  """Set new mode."""
108  if mode == MODE_AUTO:
109  await self.async_put_characteristicsasync_put_characteristics(
110  {
111  CharacteristicsTypes.TARGET_HUMIDIFIER_DEHUMIDIFIER_STATE: 0,
112  CharacteristicsTypes.ACTIVE: True,
113  }
114  )
115  else:
116  await self.async_put_characteristicsasync_put_characteristics(
117  {
118  CharacteristicsTypes.TARGET_HUMIDIFIER_DEHUMIDIFIER_STATE: self._on_mode_value_on_mode_value,
119  CharacteristicsTypes.ACTIVE: True,
120  }
121  )
122 
123  def get_characteristic_types(self) -> list[str]:
124  """Define the homekit characteristics the entity cares about."""
125  return [
126  CharacteristicsTypes.ACTIVE,
127  CharacteristicsTypes.CURRENT_HUMIDIFIER_DEHUMIDIFIER_STATE,
128  CharacteristicsTypes.TARGET_HUMIDIFIER_DEHUMIDIFIER_STATE,
129  CharacteristicsTypes.RELATIVE_HUMIDITY_HUMIDIFIER_THRESHOLD,
130  ]
131 
132 
134  """Representation of a HomeKit Controller Humidifier."""
135 
136  _attr_device_class = HumidifierDeviceClass.HUMIDIFIER
137 
138 
140  """Representation of a HomeKit Controller Humidifier."""
141 
142  _attr_device_class = HumidifierDeviceClass.DEHUMIDIFIER
143  _humidity_char = CharacteristicsTypes.RELATIVE_HUMIDITY_DEHUMIDIFIER_THRESHOLD
144  _on_mode_value = 2
145 
146  def __init__(self, accessory: HKDevice, devinfo: ConfigType) -> None:
147  """Initialise the dehumidifier."""
148  super().__init__(accessory, devinfo)
149  self._attr_unique_id_attr_unique_id_attr_unique_id = f"{accessory.unique_id}_{self._iid}_{self.device_class}"
150 
151  def get_characteristic_types(self) -> list[str]:
152  """Define the homekit characteristics the entity cares about."""
153  return [
154  *super().get_characteristic_types(),
155  CharacteristicsTypes.RELATIVE_HUMIDITY_DEHUMIDIFIER_THRESHOLD,
156  ]
157 
158  @property
159  def old_unique_id(self) -> str:
160  """Return the old ID of this device."""
161  serial = self.accessory_infoaccessory_info.value(CharacteristicsTypes.SERIAL_NUMBER)
162  return f"homekit-{serial}-{self._iid}-{self.device_class}"
163 
164 
166  hass: HomeAssistant,
167  config_entry: ConfigEntry,
168  async_add_entities: AddEntitiesCallback,
169 ) -> None:
170  """Set up Homekit humidifer."""
171  hkid: str = config_entry.data["AccessoryPairingID"]
172  conn: HKDevice = hass.data[KNOWN_DEVICES][hkid]
173 
174  @callback
175  def async_add_service(service: Service) -> bool:
176  if service.type != ServicesTypes.HUMIDIFIER_DEHUMIDIFIER:
177  return False
178 
179  info = {"aid": service.accessory.aid, "iid": service.iid}
180 
181  entities: list[HomeKitHumidifier | HomeKitDehumidifier] = []
182 
183  if service.has(CharacteristicsTypes.RELATIVE_HUMIDITY_HUMIDIFIER_THRESHOLD):
184  entities.append(HomeKitHumidifier(conn, info))
185 
186  if service.has(CharacteristicsTypes.RELATIVE_HUMIDITY_DEHUMIDIFIER_THRESHOLD):
187  entities.append(HomeKitDehumidifier(conn, info))
188 
189  for entity in entities:
190  conn.async_migrate_unique_id(
191  entity.old_unique_id, entity.unique_id, Platform.HUMIDIFIER
192  )
193 
194  async_add_entities(entities)
195 
196  return True
197 
198  conn.add_listener(async_add_service)
None async_put_characteristics(self, dict[str, Any] characteristics)
Definition: entity.py:125
None _async_clear_property_cache(self, tuple[str,...] properties)
Definition: entity.py:79
None __init__(self, HKDevice accessory, ConfigType devinfo)
Definition: humidifier.py:146
None async_setup_entry(HomeAssistant hass, ConfigEntry config_entry, AddEntitiesCallback async_add_entities)
Definition: humidifier.py:169