valve.py 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. """
  2. Support for Tuya valve devices
  3. """
  4. import logging
  5. from homeassistant.components.valve import (
  6. ValveDeviceClass,
  7. ValveEntity,
  8. ValveEntityFeature,
  9. )
  10. from .device import TuyaLocalDevice
  11. from .entity import TuyaLocalEntity
  12. from .helpers.config import async_tuya_setup_platform
  13. from .helpers.device_config import TuyaEntityConfig
  14. _LOGGER = logging.getLogger(__name__)
  15. async def async_setup_entry(hass, config_entry, async_add_entities):
  16. config = {**config_entry.data, **config_entry.options}
  17. await async_tuya_setup_platform(
  18. hass,
  19. async_add_entities,
  20. config,
  21. "valve",
  22. TuyaLocalValve,
  23. )
  24. class TuyaLocalValve(TuyaLocalEntity, ValveEntity):
  25. """Representation of a Tuya Valve"""
  26. def __init__(self, device: TuyaLocalDevice, config: TuyaEntityConfig):
  27. """
  28. Initialise the valve.
  29. Args:
  30. device (TuyaLocalDevice): The device API instance.
  31. """
  32. super().__init__()
  33. dps_map = self._init_begin(device, config)
  34. self._valve_dp = dps_map.pop("valve")
  35. self._switch_dp = dps_map.pop("switch", None)
  36. self._init_end(dps_map)
  37. if not self._valve_dp.readonly or self._switch_dp:
  38. self._attr_supported_features |= ValveEntityFeature.OPEN
  39. self._attr_supported_features |= ValveEntityFeature.CLOSE
  40. if self._valve_dp.type is int or (
  41. self._valve_dp.values(device)
  42. and self._valve_dp.values(device)[0] is int
  43. ):
  44. self._attr_supported_features |= ValveEntityFeature.SET_POSITION
  45. # HA defines translated names for valve classes, but does not use them
  46. def _default_to_device_class_name(self) -> bool:
  47. """Return True if an unnamed entity should be named by its device class.
  48. For valves we make this True if the entity has a device class.
  49. """
  50. return self.device_class is not None
  51. @property
  52. def device_class(self):
  53. """Return the class of this device"""
  54. dclass = self._config.device_class
  55. try:
  56. return ValveDeviceClass(dclass)
  57. except ValueError:
  58. if dclass:
  59. _LOGGER.warning(
  60. "%s/%s: Unrecognised valve device class of %s ignored",
  61. self._config._device.config,
  62. self.name or "valve",
  63. dclass,
  64. )
  65. @property
  66. def reports_position(self):
  67. """If the valve is an integer, it reports position."""
  68. return self._valve_dp.type is int or (
  69. self._valve_dp.values(self._device)
  70. and self._valve_dp.values(self._device)[0] is int
  71. )
  72. @property
  73. def current_position(self):
  74. """Report the position of the valve."""
  75. pos = self._valve_dp.get_value(self._device)
  76. if isinstance(pos, int):
  77. return pos
  78. @property
  79. def is_closed(self):
  80. """Report whether the valve is closed."""
  81. if self._switch_dp and self._switch_dp.get_value(self._device) is False:
  82. return True
  83. pos = self._valve_dp.get_value(self._device)
  84. return not pos
  85. async def async_open_valve(self):
  86. """Open the valve."""
  87. if self._switch_dp:
  88. await self._switch_dp.async_set_value(self._device, True)
  89. if self._valve_dp.get_value(self._device):
  90. return
  91. await self._valve_dp.async_set_value(
  92. self._device,
  93. 100 if self.reports_position else True,
  94. )
  95. async def async_close_valve(self):
  96. """Close the valve"""
  97. if self._switch_dp:
  98. await self._switch_dp.async_set_value(self._device, False)
  99. else:
  100. await self._valve_dp.async_set_value(
  101. self._device,
  102. 0 if self.reports_position else False,
  103. )
  104. async def async_set_valve_position(self, position):
  105. """Set the position of the valve"""
  106. if not self.reports_position:
  107. raise NotImplementedError()
  108. await self._valve_dp.async_set_value(self._device, position)