light.py 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  1. """
  2. Platform to control Tuya lights.
  3. Initially based on the secondary panel lighting control on some climate
  4. devices, so only providing simple on/off control.
  5. """
  6. from homeassistant.components.light import (
  7. LightEntity,
  8. ATTR_BRIGHTNESS,
  9. COLOR_MODE_BRIGHTNESS,
  10. COLOR_MODE_ONOFF,
  11. COLOR_MODE_UNKNOWN,
  12. SUPPORT_EFFECT,
  13. )
  14. from ..device import TuyaLocalDevice
  15. from ..helpers.device_config import TuyaEntityConfig
  16. class TuyaLocalLight(LightEntity):
  17. """Representation of a Tuya WiFi-connected light."""
  18. def __init__(self, device: TuyaLocalDevice, config: TuyaEntityConfig):
  19. """
  20. Initialize the light.
  21. Args:
  22. device (TuyaLocalDevice): The device API instance.
  23. config (TuyaEntityConfig): The configuration for this entity.
  24. """
  25. self._device = device
  26. self._config = config
  27. self._attr_dps = []
  28. dps_map = {c.name: c for c in config.dps()}
  29. self._switch_dps = dps_map.pop("switch", None)
  30. self._brightness_dps = dps_map.pop("brightness", None)
  31. self._effect_dps = dps_map.pop("effect", None)
  32. for d in dps_map.values():
  33. if not d.hidden:
  34. self._attr_dps.append(d)
  35. @property
  36. def should_poll(self):
  37. """Return the polling state."""
  38. return True
  39. @property
  40. def name(self):
  41. """Return the friendly name for this entity."""
  42. return self._config.name(self._device.name)
  43. @property
  44. def unique_id(self):
  45. """Return the unique id for this heater LED display."""
  46. return self._config.unique_id(self._device.unique_id)
  47. @property
  48. def device_info(self):
  49. """Return device information about this heater LED display."""
  50. return self._device.device_info
  51. @property
  52. def icon(self):
  53. """Return the icon to use in the frontend for this device."""
  54. icon = self._config.icon(self._device)
  55. if icon:
  56. return icon
  57. else:
  58. return super().icon
  59. @property
  60. def supported_color_modes(self):
  61. """Return the supported color modes for this light."""
  62. if self._brightness_dps:
  63. return [COLOR_MODE_BRIGHTNESS]
  64. elif self._switch_dps:
  65. return [COLOR_MODE_ONOFF]
  66. else:
  67. return []
  68. @property
  69. def supported_features(self):
  70. """Return the supported features for this light."""
  71. if self._effect_dps:
  72. return SUPPORT_EFFECT
  73. else:
  74. return 0
  75. @property
  76. def color_mode(self):
  77. """Return the color mode of the light"""
  78. if self._brightness_dps:
  79. return COLOR_MODE_BRIGHTNESS
  80. elif self._switch_dps:
  81. return COLOR_MODE_ONOFF
  82. else:
  83. return COLOR_MODE_UNKNOWN
  84. @property
  85. def is_on(self):
  86. """Return the current state."""
  87. if self._switch_dps:
  88. return self._switch_dps.get_value(self._device)
  89. elif self._brightness_dps:
  90. b = self.brightness
  91. return isinstance(b, int) and b > 0
  92. else:
  93. # There shouldn't be lights without control, but if there are, assume always on
  94. return True
  95. @property
  96. def brightness(self):
  97. """Get the current brightness of the light"""
  98. if self._brightness_dps is None:
  99. return None
  100. return self._brightness_dps.get_value(self._device)
  101. @property
  102. def effect_list(self):
  103. """Return the list of valid effects for the light"""
  104. if self._effect_dps is None:
  105. return None
  106. return self._effect_dps.values(self._device)
  107. @property
  108. def effect(self):
  109. """Return the current effect setting of this light"""
  110. if self._effect_dps is None:
  111. return None
  112. return self._effect_dps.get_value(self._device)
  113. @property
  114. def device_state_attributes(self):
  115. """Get additional attributes that the integration itself does not support."""
  116. attr = {}
  117. for a in self._attr_dps:
  118. attr[a.name] = a.get_value(self._device)
  119. return attr
  120. async def async_turn_on(self, **params):
  121. settings = {}
  122. if self._switch_dps:
  123. settings = {
  124. **settings,
  125. **self._switch_dps.get_values_to_set(self._device, True),
  126. }
  127. if self._brightness_dps:
  128. bright = params.get(ATTR_BRIGHTNESS, 255)
  129. bright_values = self._brightness_dps.get_values_to_set(self._device, bright)
  130. settings = {
  131. **settings,
  132. **bright_values,
  133. }
  134. if self._effect_dps:
  135. effect = params.get(ATTR_EFFECT, None)
  136. if effect:
  137. effect_values = self._effect_dps.get_values_to_set(self._device, effect)
  138. settings = {
  139. **settings,
  140. **effect_values,
  141. }
  142. await self._device.async_set_properties(settings)
  143. async def async_turn_off(self):
  144. if self._switch_dps:
  145. await self._switch_dps.async_set_value(self._device, False)
  146. elif self._brightness_dps:
  147. await self._brightness_dps.async_set_value(self._device, 0)
  148. else:
  149. raise NotImplementedError()
  150. async def async_toggle(self):
  151. dps_display_on = self.is_on
  152. await (self.async_turn_on() if not dps_display_on else self.async_turn_off())
  153. async def async_update(self):
  154. await self._device.async_refresh()