climate.py 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279
  1. """
  2. Goldair WiFi Dehumidifier device.
  3. """
  4. from homeassistant.components.climate import ClimateDevice
  5. from homeassistant.components.climate.const import (
  6. ATTR_FAN_MODE,
  7. ATTR_HUMIDITY,
  8. ATTR_HVAC_MODE,
  9. ATTR_PRESET_MODE,
  10. FAN_HIGH,
  11. FAN_LOW,
  12. SUPPORT_FAN_MODE,
  13. SUPPORT_PRESET_MODE,
  14. SUPPORT_TARGET_HUMIDITY,
  15. )
  16. from homeassistant.const import ATTR_TEMPERATURE, STATE_UNAVAILABLE
  17. from ..device import GoldairTuyaDevice
  18. from .const import (
  19. ATTR_AIR_CLEAN_ON,
  20. ATTR_DEFROSTING,
  21. ATTR_ERROR,
  22. ATTR_TARGET_HUMIDITY,
  23. ERROR_CODE_TO_DPS_CODE,
  24. ERROR_TANK,
  25. FAN_MODE_TO_DPS_MODE,
  26. HVAC_MODE_TO_DPS_MODE,
  27. PRESET_AIR_CLEAN,
  28. PRESET_DRY_CLOTHES,
  29. PRESET_HIGH,
  30. PRESET_LOW,
  31. PRESET_MODE_TO_DPS_MODE,
  32. PRESET_NORMAL,
  33. PROPERTY_TO_DPS_ID,
  34. )
  35. SUPPORT_FLAGS = SUPPORT_TARGET_HUMIDITY | SUPPORT_PRESET_MODE | SUPPORT_FAN_MODE
  36. class GoldairDehumidifier(ClimateDevice):
  37. """Representation of a Goldair WiFi dehumidifier."""
  38. def __init__(self, device):
  39. """Initialize the dehumidifier.
  40. Args:
  41. name (str): The device's name.
  42. device (GoldairTuyaDevice): The device API instance."""
  43. self._device = device
  44. self._support_flags = SUPPORT_FLAGS
  45. self._HUMIDITY_STEP = 5
  46. self._HUMIDITY_LIMITS = {"min": 30, "max": 80}
  47. @property
  48. def supported_features(self):
  49. """Return the list of supported features."""
  50. return self._support_flags
  51. @property
  52. def should_poll(self):
  53. """Return the polling state."""
  54. return True
  55. @property
  56. def name(self):
  57. """Return the name of the climate device."""
  58. return self._device.name
  59. @property
  60. def unique_id(self):
  61. """Return the unique id for this dehumidifier."""
  62. return self._device.unique_id
  63. @property
  64. def device_info(self):
  65. """Return device information about this dehumidifier."""
  66. return self._device.device_info
  67. @property
  68. def icon(self):
  69. """Return the icon to use in the frontend based on the device state."""
  70. if self.tank_full_or_missing:
  71. return "mdi:cup-water"
  72. elif self.defrosting:
  73. return "mdi:snowflake-melt"
  74. else:
  75. return "mdi:air-humidifier"
  76. @property
  77. def current_humidity(self):
  78. """Return the current reading of the humidity sensor."""
  79. return self._device.get_property(PROPERTY_TO_DPS_ID[ATTR_HUMIDITY])
  80. @property
  81. def min_humidity(self):
  82. """Return the minimum humidity setting."""
  83. return self._HUMIDITY_LIMITS["min"]
  84. @property
  85. def max_humidity(self):
  86. """Return the maximum humidity setting."""
  87. return self._HUMIDITY_LIMITS["max"]
  88. @property
  89. def target_humidity(self):
  90. """Return the current target humidity."""
  91. return self._device.get_property(PROPERTY_TO_DPS_ID[ATTR_TARGET_HUMIDITY])
  92. async def async_set_humidity(self, humidity):
  93. """Set the device's target humidity."""
  94. if self.preset_mode in [PRESET_AIR_CLEAN, PRESET_DRY_CLOTHES]:
  95. raise ValueError(
  96. "Humidity can only be changed while in Normal, Low or High preset modes."
  97. )
  98. humidity = int(
  99. self._HUMIDITY_STEP * round(float(humidity) / self._HUMIDITY_STEP)
  100. )
  101. await self._device.async_set_property(
  102. PROPERTY_TO_DPS_ID[ATTR_TARGET_HUMIDITY], humidity
  103. )
  104. @property
  105. def temperature_unit(self):
  106. """Return the unit of measurement."""
  107. return self._device.temperature_unit
  108. @property
  109. def min_temp(self):
  110. """Return the minimum temperature setting."""
  111. return None
  112. @property
  113. def max_temp(self):
  114. """Return the maximum temperature setting."""
  115. return None
  116. @property
  117. def current_temperature(self):
  118. """Return the current temperature."""
  119. return self._device.get_property(PROPERTY_TO_DPS_ID[ATTR_TEMPERATURE])
  120. @property
  121. def hvac_mode(self):
  122. """Return current HVAC mode, ie Dry or Off."""
  123. dps_mode = self._device.get_property(PROPERTY_TO_DPS_ID[ATTR_HVAC_MODE])
  124. if dps_mode is not None:
  125. return GoldairTuyaDevice.get_key_for_value(HVAC_MODE_TO_DPS_MODE, dps_mode)
  126. else:
  127. return STATE_UNAVAILABLE
  128. @property
  129. def hvac_modes(self):
  130. """Return the list of available HVAC modes."""
  131. return list(HVAC_MODE_TO_DPS_MODE.keys())
  132. async def async_set_hvac_mode(self, hvac_mode):
  133. """Set new HVAC mode."""
  134. dps_mode = HVAC_MODE_TO_DPS_MODE[hvac_mode]
  135. await self._device.async_set_property(
  136. PROPERTY_TO_DPS_ID[ATTR_HVAC_MODE], dps_mode
  137. )
  138. @property
  139. def preset_mode(self):
  140. """Return current preset mode, ie Normal, Low, High, Dry Clothes, or Air Clean."""
  141. air_clean_on = self._device.get_property(PROPERTY_TO_DPS_ID[ATTR_AIR_CLEAN_ON])
  142. dps_mode = self._device.get_property(PROPERTY_TO_DPS_ID[ATTR_PRESET_MODE])
  143. if air_clean_on:
  144. return PRESET_AIR_CLEAN
  145. elif dps_mode is not None:
  146. return GoldairTuyaDevice.get_key_for_value(
  147. PRESET_MODE_TO_DPS_MODE, dps_mode
  148. )
  149. else:
  150. return None
  151. @property
  152. def preset_modes(self):
  153. """Return the list of available preset modes."""
  154. return list(PRESET_MODE_TO_DPS_MODE.keys()) + [PRESET_AIR_CLEAN]
  155. async def async_set_preset_mode(self, preset_mode):
  156. """Set new preset mode."""
  157. if preset_mode == PRESET_AIR_CLEAN:
  158. await self._device.async_set_property(
  159. PROPERTY_TO_DPS_ID[ATTR_AIR_CLEAN_ON], True
  160. )
  161. self._device.anticipate_property_value(
  162. PROPERTY_TO_DPS_ID[ATTR_FAN_MODE], FAN_HIGH
  163. )
  164. else:
  165. dps_mode = PRESET_MODE_TO_DPS_MODE[preset_mode]
  166. await self._device.async_set_property(
  167. PROPERTY_TO_DPS_ID[ATTR_AIR_CLEAN_ON], False
  168. )
  169. await self._device.async_set_property(
  170. PROPERTY_TO_DPS_ID[ATTR_PRESET_MODE], dps_mode
  171. )
  172. if preset_mode == PRESET_LOW:
  173. self._device.anticipate_property_value(
  174. PROPERTY_TO_DPS_ID[ATTR_FAN_MODE], FAN_LOW
  175. )
  176. elif preset_mode in [PRESET_HIGH, PRESET_DRY_CLOTHES]:
  177. self._device.anticipate_property_value(
  178. PROPERTY_TO_DPS_ID[ATTR_FAN_MODE], FAN_HIGH
  179. )
  180. @property
  181. def fan_mode(self):
  182. """Return the fan mode."""
  183. preset = self.preset_mode
  184. if preset in [PRESET_HIGH, PRESET_DRY_CLOTHES, PRESET_AIR_CLEAN]:
  185. return FAN_HIGH
  186. elif preset == PRESET_LOW:
  187. return FAN_LOW
  188. else:
  189. dps_mode = self._device.get_property(PROPERTY_TO_DPS_ID[ATTR_FAN_MODE])
  190. if dps_mode is not None:
  191. return GoldairTuyaDevice.get_key_for_value(
  192. FAN_MODE_TO_DPS_MODE, dps_mode
  193. )
  194. else:
  195. return None
  196. @property
  197. def fan_modes(self):
  198. """List of fan modes."""
  199. preset = self.preset_mode
  200. if preset in [PRESET_HIGH, PRESET_DRY_CLOTHES, PRESET_AIR_CLEAN]:
  201. return [FAN_HIGH]
  202. elif preset == PRESET_LOW:
  203. return [FAN_LOW]
  204. elif preset == PRESET_NORMAL:
  205. return list(FAN_MODE_TO_DPS_MODE.keys())
  206. else:
  207. return []
  208. async def async_set_fan_mode(self, fan_mode):
  209. """Set new fan mode."""
  210. if self.preset_mode != PRESET_NORMAL:
  211. raise ValueError(
  212. "Fan mode can only be changed while in Normal preset mode."
  213. )
  214. if fan_mode not in FAN_MODE_TO_DPS_MODE.keys():
  215. raise ValueError(f"Invalid fan mode: {fan_mode}")
  216. dps_mode = FAN_MODE_TO_DPS_MODE[fan_mode]
  217. await self._device.async_set_property(
  218. PROPERTY_TO_DPS_ID[ATTR_FAN_MODE], dps_mode
  219. )
  220. @property
  221. def tank_full_or_missing(self):
  222. error = self._device.get_property(PROPERTY_TO_DPS_ID[ATTR_ERROR])
  223. return error == ERROR_TANK
  224. @property
  225. def defrosting(self):
  226. return self._device.get_property(PROPERTY_TO_DPS_ID[ATTR_DEFROSTING])
  227. @property
  228. def device_state_attributes(self):
  229. """Get additional attributes that HA doesn't naturally support."""
  230. error = self._device.get_property(PROPERTY_TO_DPS_ID[ATTR_ERROR])
  231. if error:
  232. error = GoldairTuyaDevice.get_key_for_value(
  233. ERROR_CODE_TO_DPS_CODE, error, error
  234. )
  235. return {ATTR_ERROR: error or None, ATTR_DEFROSTING: self.defrosting}
  236. async def async_update(self):
  237. await self._device.async_refresh()