siren.py 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
  1. """
  2. Setup for Tuya siren devices
  3. """
  4. from homeassistant.components.siren import (
  5. SirenEntity,
  6. SirenEntityDescription,
  7. SirenEntityFeature,
  8. )
  9. from .device import TuyaLocalDevice
  10. from .helpers.config import async_tuya_setup_platform
  11. from .helpers.device_config import TuyaEntityConfig
  12. from .helpers.mixin import TuyaLocalEntity
  13. async def async_setup_entry(hass, config_entry, async_add_entities):
  14. config = {**config_entry.data, **config_entry.options}
  15. await async_tuya_setup_platform(
  16. hass,
  17. async_add_entities,
  18. config,
  19. "siren",
  20. TuyaLocalSiren,
  21. )
  22. class TuyaLocalSiren(TuyaLocalEntity, SirenEntity):
  23. """Representation of a Tuya siren"""
  24. def __init__(self, device: TuyaLocalDevice, config: TuyaEntityConfig):
  25. """
  26. Initialize the siren.
  27. Args:
  28. device (TuyaLocalDevice): The device API instance.
  29. config (TuyaEntityConfig): The config for this entity.
  30. """
  31. dps_map = self._init_begin(device, config)
  32. self._tone_dp = dps_map.get("tone", None)
  33. self._volume_dp = dps_map.get("volume_level", None)
  34. self._duration_dp = dps_map.get("duration", None)
  35. self._init_end(dps_map)
  36. # All control of features is through the turn_on service, so we need to
  37. # support that, even if the siren does not support direct control
  38. support = 0
  39. if self._tone_dp:
  40. support |= (
  41. SirenEntityFeature.TONES
  42. | SirenEntityFeature.TURN_ON
  43. | SirenEntityFeature.TURN_OFF
  44. )
  45. self.entity_description = SirenEntityDescription
  46. self.entity_description.available_tones = [
  47. x for x in self._tone_dp.values(device) if x != "off"
  48. ]
  49. self._default_tone = self._tone_dp.default()
  50. if self._volume_dp:
  51. support |= SirenEntityFeature.VOLUME_SET
  52. if self._duration_dp:
  53. support |= SirenEntityFeature.DURATION
  54. self._attr_supported_features = support
  55. @property
  56. def is_on(self):
  57. """Return whether the siren is on."""
  58. if self._tone_dp:
  59. return self._tone_dp.get_value(self._device) != "off"
  60. async def async_turn_on(self, **kwargs) -> None:
  61. tone = kwargs.get("tone", None)
  62. duration = kwargs.get("duration", None)
  63. volume = kwargs.get("volume", None)
  64. set_dps = {}
  65. if self._tone_dp:
  66. if tone is None:
  67. tone = self._tone_dp.get_value(self._device)
  68. if tone == "off":
  69. tone = self._default_tone
  70. set_dps = {
  71. **set_dps,
  72. **self._tone_dp.get_values_to_set(self._device, tone),
  73. }
  74. if duration is not None and self._duration_dp:
  75. set_dps = {
  76. **set_dps,
  77. **self._duration_dp.get_values_to_set(self._device, duration),
  78. }
  79. if volume is not None and self._volume_dp:
  80. # Volume is a float, range 0.0-1.0 in Home Assistant
  81. # In tuya it is likely an integer or a fixed list of values.
  82. # For integer, expect scale and step to do the conversion,
  83. # for fixed values, we need to snap to closest value.
  84. if self._volume_dp.values(self._device) is not None:
  85. volume = min(
  86. self._volume_dp.values(self._device), key=lambda x: abs(x - volume)
  87. )
  88. set_dps = {
  89. **set_dps,
  90. **self._volume_dp.get_values_to_set(self._device, volume),
  91. }
  92. await self._device.async_set_properties(set_dps)
  93. async def async_turn_off(self) -> None:
  94. """Turn off the siren"""
  95. if self._tone_dp:
  96. await self._tone_dp.async_set_value(self._device, "off")