climate.py 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184
  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 = child_lock (boolean)
  8. 7 = hvac_mode (boolean)
  9. 8 = timer (integer) [supported for read only - use HA based timers]
  10. """
  11. from homeassistant.components.climate import ClimateEntity
  12. from homeassistant.components.climate.const import (
  13. ATTR_HVAC_MODE,
  14. ATTR_PRESET_MODE,
  15. HVAC_MODE_HEAT,
  16. SUPPORT_PRESET_MODE,
  17. SUPPORT_TARGET_TEMPERATURE,
  18. )
  19. from homeassistant.const import ATTR_TEMPERATURE, STATE_UNAVAILABLE
  20. from ..device import TuyaLocalDevice
  21. from .const import (
  22. ATTR_TARGET_TEMPERATURE,
  23. ATTR_TIMER,
  24. HVAC_MODE_TO_DPS_MODE,
  25. PRESET_MODE_TO_DPS_MODE,
  26. PROPERTY_TO_DPS_ID,
  27. )
  28. SUPPORT_FLAGS = SUPPORT_TARGET_TEMPERATURE | SUPPORT_PRESET_MODE
  29. class KoganHeater(ClimateEntity):
  30. """Representation of a Kogan WiFi heater."""
  31. def __init__(self, device):
  32. """Initialize the heater.
  33. Args:
  34. name (str): The device's name.
  35. device (TuyaLocalDevice): The device API instance."""
  36. self._device = device
  37. self._support_flags = SUPPORT_FLAGS
  38. self._TEMPERATURE_STEP = 1
  39. self._TEMPERATURE_LIMITS = {"min": 15, "max": 35}
  40. @property
  41. def supported_features(self):
  42. """Return the list of supported features."""
  43. return self._support_flags
  44. @property
  45. def should_poll(self):
  46. """Return the polling state."""
  47. return True
  48. @property
  49. def name(self):
  50. """Return the name of the climate device."""
  51. return self._device.name
  52. @property
  53. def unique_id(self):
  54. """Return the unique id for this heater."""
  55. return self._device.unique_id
  56. @property
  57. def device_info(self):
  58. """Return device information about this heater."""
  59. return self._device.device_info
  60. @property
  61. def icon(self):
  62. """Return the icon to use in the frontend for this device."""
  63. hvac_mode = self.hvac_mode
  64. if hvac_mode == HVAC_MODE_HEAT:
  65. return "mdi:radiator"
  66. else:
  67. return "mdi:radiator-disabled"
  68. @property
  69. def temperature_unit(self):
  70. """Return the unit of measurement."""
  71. return self._device.temperature_unit
  72. @property
  73. def target_temperature(self):
  74. """Return the temperature we try to reach."""
  75. return self._device.get_property(PROPERTY_TO_DPS_ID[ATTR_TARGET_TEMPERATURE])
  76. @property
  77. def target_temperature_step(self):
  78. """Return the supported step of target temperature."""
  79. return self._TEMPERATURE_STEP
  80. @property
  81. def min_temp(self):
  82. """Return the minimum temperature."""
  83. return self._TEMPERATURE_LIMITS["min"]
  84. @property
  85. def max_temp(self):
  86. """Return the maximum temperature."""
  87. return self._TEMPERATURE_LIMITS["max"]
  88. async def async_set_temperature(self, **kwargs):
  89. """Set new target temperatures."""
  90. if kwargs.get(ATTR_PRESET_MODE) is not None:
  91. await self.async_set_preset_mode(kwargs.get(ATTR_PRESET_MODE))
  92. if kwargs.get(ATTR_TEMPERATURE) is not None:
  93. await self.async_set_target_temperature(kwargs.get(ATTR_TEMPERATURE))
  94. async def async_set_target_temperature(self, target_temperature):
  95. target_temperature = int(round(target_temperature))
  96. limits = self._TEMPERATURE_LIMITS
  97. if not limits["min"] <= target_temperature <= limits["max"]:
  98. raise ValueError(
  99. f"Target temperature ({target_temperature}) must be between "
  100. f'{limits["min"]} and {limits["max"]}'
  101. )
  102. await self._device.async_set_property(
  103. PROPERTY_TO_DPS_ID[ATTR_TARGET_TEMPERATURE], target_temperature
  104. )
  105. @property
  106. def current_temperature(self):
  107. """Return the current temperature."""
  108. return self._device.get_property(PROPERTY_TO_DPS_ID[ATTR_TEMPERATURE])
  109. @property
  110. def hvac_mode(self):
  111. """Return current HVAC mode, ie Heat or Off."""
  112. dps_mode = self._device.get_property(PROPERTY_TO_DPS_ID[ATTR_HVAC_MODE])
  113. if dps_mode is not None:
  114. return TuyaLocalDevice.get_key_for_value(HVAC_MODE_TO_DPS_MODE, dps_mode)
  115. else:
  116. return STATE_UNAVAILABLE
  117. @property
  118. def hvac_modes(self):
  119. """Return the list of available HVAC modes."""
  120. return list(HVAC_MODE_TO_DPS_MODE.keys())
  121. async def async_set_hvac_mode(self, hvac_mode):
  122. """Set new HVAC mode."""
  123. dps_mode = HVAC_MODE_TO_DPS_MODE[hvac_mode]
  124. await self._device.async_set_property(
  125. PROPERTY_TO_DPS_ID[ATTR_HVAC_MODE], dps_mode
  126. )
  127. @property
  128. def preset_mode(self):
  129. """Return current preset mode, ie Low or High."""
  130. dps_mode = self._device.get_property(PROPERTY_TO_DPS_ID[ATTR_PRESET_MODE])
  131. if dps_mode is not None:
  132. return TuyaLocalDevice.get_key_for_value(PRESET_MODE_TO_DPS_MODE, dps_mode)
  133. else:
  134. return None
  135. @property
  136. def preset_modes(self):
  137. """Return the list of available preset modes."""
  138. return list(PRESET_MODE_TO_DPS_MODE.keys())
  139. async def async_set_preset_mode(self, preset_mode):
  140. """Set new preset mode."""
  141. dps_mode = PRESET_MODE_TO_DPS_MODE[preset_mode]
  142. await self._device.async_set_property(
  143. PROPERTY_TO_DPS_ID[ATTR_PRESET_MODE], dps_mode
  144. )
  145. @property
  146. def device_state_attributes(self):
  147. """Get additional attributes that HA doesn't naturally support."""
  148. timer = self._device.get_property(PROPERTY_TO_DPS_ID[ATTR_TIMER])
  149. return {ATTR_TIMER: timer}
  150. async def async_update(self):
  151. await self._device.async_refresh()