climate.py 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249
  1. """
  2. Goldair WiFi Dehumidifier device.
  3. """
  4. from homeassistant.const import (
  5. ATTR_TEMPERATURE, TEMP_CELSIUS, STATE_UNAVAILABLE
  6. )
  7. from homeassistant.components.climate import ClimateDevice
  8. from homeassistant.components.climate.const import (
  9. ATTR_FAN_MODE, ATTR_HUMIDITY, ATTR_HVAC_MODE, ATTR_PRESET_MODE,
  10. FAN_OFF, FAN_LOW, FAN_HIGH,
  11. HVAC_MODE_OFF, HVAC_MODE_DRY,
  12. SUPPORT_TARGET_HUMIDITY, SUPPORT_PRESET_MODE, SUPPORT_FAN_MODE
  13. )
  14. from custom_components.tuya_local import TuyaLocalDevice
  15. ATTR_TARGET_HUMIDITY = 'target_humidity'
  16. ATTR_AIR_CLEAN_ON = 'air_clean_on'
  17. ATTR_CHILD_LOCK = 'child_lock'
  18. ATTR_FAULT = 'fault'
  19. ATTR_DISPLAY_ON = 'display_on'
  20. PRESET_NORMAL = 'Normal'
  21. PRESET_LOW = 'Low'
  22. PRESET_HIGH = 'High'
  23. PRESET_DRY_CLOTHES = 'Dry clothes'
  24. PRESET_AIR_CLEAN = 'Air clean'
  25. FAULT_NONE = 'No fault'
  26. FAULT_TANK = 'Tank full or missing'
  27. PROPERTY_TO_DPS_ID = {
  28. ATTR_HVAC_MODE: '1',
  29. ATTR_PRESET_MODE: '2',
  30. ATTR_TARGET_HUMIDITY: '4',
  31. ATTR_AIR_CLEAN_ON: '5',
  32. ATTR_FAN_MODE: '6',
  33. ATTR_CHILD_LOCK: '7',
  34. ATTR_FAULT: '11',
  35. ATTR_DISPLAY_ON: '102',
  36. ATTR_TEMPERATURE: '103',
  37. ATTR_HUMIDITY: '104'
  38. }
  39. HVAC_MODE_TO_DPS_MODE = {
  40. HVAC_MODE_OFF: False,
  41. HVAC_MODE_DRY: True
  42. }
  43. PRESET_MODE_TO_DPS_MODE = {
  44. PRESET_NORMAL: '0',
  45. PRESET_LOW: '1',
  46. PRESET_HIGH: '2',
  47. PRESET_DRY_CLOTHES: '3'
  48. }
  49. FAN_MODE_TO_DPS_MODE = {
  50. FAN_LOW: '1',
  51. FAN_HIGH: '3'
  52. }
  53. FAULT_CODE_TO_DPS_CODE = {
  54. FAULT_NONE: 0,
  55. FAULT_TANK: 8
  56. }
  57. SUPPORT_FLAGS = SUPPORT_TARGET_HUMIDITY | SUPPORT_PRESET_MODE | SUPPORT_FAN_MODE
  58. class GoldairDehumidifier(ClimateDevice):
  59. """Representation of a Goldair WiFi dehumidifier."""
  60. def __init__(self, device):
  61. """Initialize the dehumidifier.
  62. Args:
  63. name (str): The device's name.
  64. device (TuyaLocalDevice): The device API instance."""
  65. self._device = device
  66. self._support_flags = SUPPORT_FLAGS
  67. self._HUMIDITY_STEP = 5
  68. self._HUMIDITY_LIMITS = {
  69. 'min': 30,
  70. 'max': 80
  71. }
  72. @property
  73. def supported_features(self):
  74. """Return the list of supported features."""
  75. return self._support_flags
  76. @property
  77. def should_poll(self):
  78. """Return the polling state."""
  79. return True
  80. @property
  81. def name(self):
  82. """Return the name of the climate device."""
  83. return self._device.name
  84. @property
  85. def current_humidity(self):
  86. """Return the current reading of the humidity sensor."""
  87. return self._device.get_property(PROPERTY_TO_DPS_ID[ATTR_HUMIDITY])
  88. @property
  89. def min_humidity(self):
  90. """Return the minimum humidity setting."""
  91. return self._HUMIDITY_LIMITS['min']
  92. @property
  93. def max_humidity(self):
  94. """Return the maximum humidity setting."""
  95. return self._HUMIDITY_LIMITS['max']
  96. @property
  97. def target_humidity(self):
  98. """Return the current target humidity."""
  99. return self._device.get_property(PROPERTY_TO_DPS_ID[ATTR_TARGET_HUMIDITY])
  100. def set_humidity(self, humidity):
  101. """Set the device's target humidity."""
  102. if self.preset_mode in [PRESET_AIR_CLEAN, PRESET_DRY_CLOTHES]:
  103. raise ValueError('Humidity can only be changed while in Normal, Low or High preset modes.')
  104. humidity = int(self._HUMIDITY_STEP * round(float(humidity) / self._HUMIDITY_STEP))
  105. self._device.set_property(PROPERTY_TO_DPS_ID[ATTR_TARGET_HUMIDITY], humidity)
  106. @property
  107. def temperature_unit(self):
  108. """Return the unit of measurement."""
  109. return self._device.temperature_unit
  110. @property
  111. def min_temp(self):
  112. """Return the minimum temperature setting."""
  113. return None
  114. @property
  115. def max_temp(self):
  116. """Return the maximum temperature setting."""
  117. return None
  118. @property
  119. def current_temperature(self):
  120. """Return the current temperature."""
  121. return self._device.get_property(PROPERTY_TO_DPS_ID[ATTR_TEMPERATURE])
  122. @property
  123. def hvac_mode(self):
  124. """Return current HVAC mode, ie Dry or Off."""
  125. dps_mode = self._device.get_property(PROPERTY_TO_DPS_ID[ATTR_HVAC_MODE])
  126. if dps_mode is not None:
  127. return TuyaLocalDevice.get_key_for_value(HVAC_MODE_TO_DPS_MODE, dps_mode)
  128. else:
  129. return STATE_UNAVAILABLE
  130. @property
  131. def hvac_modes(self):
  132. """Return the list of available HVAC modes."""
  133. return list(HVAC_MODE_TO_DPS_MODE.keys())
  134. def set_hvac_mode(self, hvac_mode):
  135. """Set new HVAC mode."""
  136. dps_mode = HVAC_MODE_TO_DPS_MODE[hvac_mode]
  137. self._device.set_property(PROPERTY_TO_DPS_ID[ATTR_HVAC_MODE], dps_mode)
  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 TuyaLocalDevice.get_key_for_value(PRESET_MODE_TO_DPS_MODE, dps_mode)
  147. else:
  148. return None
  149. @property
  150. def preset_modes(self):
  151. """Return the list of available preset modes."""
  152. return list(PRESET_MODE_TO_DPS_MODE.keys()) + [PRESET_AIR_CLEAN]
  153. def set_preset_mode(self, preset_mode):
  154. """Set new preset mode."""
  155. if preset_mode == PRESET_AIR_CLEAN:
  156. self._device.set_property(PROPERTY_TO_DPS_ID[ATTR_AIR_CLEAN_ON], True)
  157. self._device.anticipate_property_value(PROPERTY_TO_DPS_ID[ATTR_FAN_MODE], FAN_HIGH)
  158. else:
  159. dps_mode = PRESET_MODE_TO_DPS_MODE[preset_mode]
  160. self._device.set_property(PROPERTY_TO_DPS_ID[ATTR_AIR_CLEAN_ON], False)
  161. self._device.set_property(PROPERTY_TO_DPS_ID[ATTR_PRESET_MODE], dps_mode)
  162. if preset_mode == PRESET_LOW:
  163. self._device.anticipate_property_value(PROPERTY_TO_DPS_ID[ATTR_FAN_MODE], FAN_LOW)
  164. elif preset_mode in [PRESET_HIGH, PRESET_DRY_CLOTHES]:
  165. self._device.anticipate_property_value(PROPERTY_TO_DPS_ID[ATTR_FAN_MODE], FAN_HIGH)
  166. @property
  167. def fan_mode(self):
  168. """Return the fan mode."""
  169. preset = self.preset_mode
  170. if preset in [PRESET_HIGH, PRESET_DRY_CLOTHES, PRESET_AIR_CLEAN]:
  171. return FAN_HIGH
  172. elif preset == PRESET_LOW:
  173. return FAN_LOW
  174. else:
  175. dps_mode = self._device.get_property(PROPERTY_TO_DPS_ID[ATTR_FAN_MODE])
  176. if dps_mode is not None:
  177. return TuyaLocalDevice.get_key_for_value(FAN_MODE_TO_DPS_MODE, dps_mode)
  178. else:
  179. return None
  180. @property
  181. def fan_modes(self):
  182. """List of fan modes."""
  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. elif preset == PRESET_NORMAL:
  189. return list(FAN_MODE_TO_DPS_MODE.keys())
  190. else:
  191. return []
  192. def set_fan_mode(self, fan_mode):
  193. """Set new fan mode."""
  194. if self.preset_mode != PRESET_NORMAL:
  195. raise ValueError('Fan mode can only be changed while in Normal preset mode.')
  196. if fan_mode not in FAN_MODE_TO_DPS_MODE.keys():
  197. raise ValueError(f'Invalid fan mode: {fan_mode}')
  198. dps_mode = FAN_MODE_TO_DPS_MODE[fan_mode]
  199. self._device.set_property(PROPERTY_TO_DPS_ID[ATTR_FAN_MODE], dps_mode)
  200. @property
  201. def fault(self):
  202. """Get the current fault status."""
  203. fault = self._device.get_property(PROPERTY_TO_DPS_ID[ATTR_FAULT])
  204. if fault is None or fault == FAULT_NONE:
  205. return None
  206. else:
  207. return TuyaLocalDevice.get_key_for_value(FAULT_CODE_TO_DPS_CODE, fault)
  208. def update(self):
  209. self._device.refresh()