siren.py 3.5 KB

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