climate.py 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171
  1. """
  2. Kogan WiFi Heater device.
  3. dps:
  4. 2 = target temperature (integer)
  5. 3 = current temperature (integer)
  6. 4 = preset_mode (string Low/High)
  7. 6 = timer state (boolean) [not supported - use HA based timers]
  8. 7 = hvac_mode (boolean)
  9. 8 = timer (integer) [not supported - use HA based timers]
  10. """
  11. from homeassistant.const import (
  12. ATTR_TEMPERATURE, TEMP_CELSIUS, STATE_UNAVAILABLE
  13. )
  14. from homeassistant.components.climate import ClimateDevice
  15. from homeassistant.components.climate.const import (
  16. ATTR_HVAC_MODE, ATTR_PRESET_MODE,
  17. HVAC_MODE_OFF, HVAC_MODE_HEAT,
  18. SUPPORT_TARGET_TEMPERATURE, SUPPORT_PRESET_MODE
  19. )
  20. from custom_components.goldair_climate import GoldairTuyaDevice
  21. ATTR_TARGET_TEMPERATURE = 'target_temperature'
  22. PRESET_LOW = 'LOW'
  23. PRESET_HIGH = 'HIGH'
  24. PROPERTY_TO_DPS_ID = {
  25. ATTR_HVAC_MODE: '7',
  26. ATTR_TARGET_TEMPERATURE: '2',
  27. ATTR_TEMPERATURE: '3',
  28. ATTR_PRESET_MODE: '4',
  29. }
  30. HVAC_MODE_TO_DPS_MODE = {
  31. HVAC_MODE_OFF: False,
  32. HVAC_MODE_HEAT: True
  33. }
  34. PRESET_MODE_TO_DPS_MODE = {
  35. PRESET_LOW: 'Low',
  36. PRESET_HIGH: 'High'
  37. }
  38. SUPPORT_FLAGS = SUPPORT_TARGET_TEMPERATURE | SUPPORT_PRESET_MODE
  39. class KoganHeater(ClimateDevice):
  40. """Representation of a Kogan WiFi heater."""
  41. def __init__(self, device):
  42. """Initialize the heater.
  43. Args:
  44. name (str): The device's name.
  45. device (GoldairTuyaDevice): The device API instance."""
  46. self._device = device
  47. self._support_flags = SUPPORT_FLAGS
  48. self._TEMPERATURE_STEP = 1
  49. self._TEMPERATURE_LIMITS = {
  50. 'min': 15,
  51. 'max': 35
  52. }
  53. @property
  54. def supported_features(self):
  55. """Return the list of supported features."""
  56. return self._support_flags
  57. @property
  58. def should_poll(self):
  59. """Return the polling state."""
  60. return True
  61. @property
  62. def name(self):
  63. """Return the name of the climate device."""
  64. return self._device.name
  65. @property
  66. def temperature_unit(self):
  67. """Return the unit of measurement."""
  68. return self._device.temperature_unit
  69. @property
  70. def target_temperature(self):
  71. """Return the temperature we try to reach."""
  72. return self._device.get_property(PROPERTY_TO_DPS_ID[ATTR_TARGET_TEMPERATURE])
  73. @property
  74. def target_temperature_step(self):
  75. """Return the supported step of target temperature."""
  76. return self._TEMPERATURE_STEP
  77. @property
  78. def min_temp(self):
  79. """Return the minimum temperature."""
  80. return self._TEMPERATURE_LIMITS['min']
  81. @property
  82. def max_temp(self):
  83. """Return the maximum temperature."""
  84. return self._TEMPERATURE_LIMITS['max']
  85. def set_temperature(self, **kwargs):
  86. """Set new target temperatures."""
  87. if kwargs.get(ATTR_PRESET_MODE) is not None:
  88. self.set_preset_mode(kwargs.get(ATTR_PRESET_MODE))
  89. if kwargs.get(ATTR_TEMPERATURE) is not None:
  90. self.set_target_temperature(kwargs.get(ATTR_TEMPERATURE))
  91. def set_target_temperature(self, target_temperature):
  92. target_temperature = int(round(target_temperature))
  93. limits = self._TEMPERATURE_LIMITS
  94. if not limits['min'] <= target_temperature <= limits['max']:
  95. raise ValueError(
  96. f'Target temperature ({target_temperature}) must be between '
  97. f'{limits["min"]} and {limits["max"]}'
  98. )
  99. self._device.set_property(PROPERTY_TO_DPS_ID[ATTR_TARGET_TEMPERATURE], target_temperature)
  100. @property
  101. def current_temperature(self):
  102. """Return the current temperature."""
  103. return self._device.get_property(PROPERTY_TO_DPS_ID[ATTR_TEMPERATURE])
  104. @property
  105. def hvac_mode(self):
  106. """Return current HVAC mode, ie Heat or Off."""
  107. dps_mode = self._device.get_property(PROPERTY_TO_DPS_ID[ATTR_HVAC_MODE])
  108. if dps_mode is not None:
  109. return GoldairTuyaDevice.get_key_for_value(HVAC_MODE_TO_DPS_MODE, dps_mode)
  110. else:
  111. return STATE_UNAVAILABLE
  112. @property
  113. def hvac_modes(self):
  114. """Return the list of available HVAC modes."""
  115. return list(HVAC_MODE_TO_DPS_MODE.keys())
  116. def set_hvac_mode(self, hvac_mode):
  117. """Set new HVAC mode."""
  118. dps_mode = HVAC_MODE_TO_DPS_MODE[hvac_mode]
  119. self._device.set_property(PROPERTY_TO_DPS_ID[ATTR_HVAC_MODE], dps_mode)
  120. @property
  121. def preset_mode(self):
  122. """Return current preset mode, ie Low or High."""
  123. dps_mode = self._device.get_property(PROPERTY_TO_DPS_ID[ATTR_PRESET_MODE])
  124. if dps_mode is not None:
  125. return GoldairTuyaDevice.get_key_for_value(PRESET_MODE_TO_DPS_MODE, dps_mode)
  126. else:
  127. return None
  128. @property
  129. def preset_modes(self):
  130. """Return the list of available preset modes."""
  131. return list(PRESET_MODE_TO_DPS_MODE.keys())
  132. def set_preset_mode(self, preset_mode):
  133. """Set new preset mode."""
  134. dps_mode = PRESET_MODE_TO_DPS_MODE[preset_mode]
  135. self._device.set_property(PROPERTY_TO_DPS_ID[ATTR_PRESET_MODE], dps_mode)
  136. def update(self):
  137. self._device.refresh()