climate.py 5.8 KB

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