light.py 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184
  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 name of the light."""
  42. return self._device.name
  43. @property
  44. def friendly_name(self):
  45. """Return the friendly name for this entity."""
  46. return self._config.name
  47. @property
  48. def unique_id(self):
  49. """Return the unique id for this heater LED display."""
  50. return self._device.unique_id
  51. @property
  52. def device_info(self):
  53. """Return device information about this heater LED display."""
  54. return self._device.device_info
  55. @property
  56. def icon(self):
  57. """Return the icon to use in the frontend for this device."""
  58. icon = self._config.icon(self._device)
  59. if icon:
  60. return icon
  61. else:
  62. return super().icon
  63. @property
  64. def supported_color_modes(self):
  65. """Return the supported color modes for this light."""
  66. if self._brightness_dps:
  67. return [COLOR_MODE_BRIGHTNESS]
  68. elif self._switch_dps:
  69. return [COLOR_MODE_ONOFF]
  70. else:
  71. return []
  72. @property
  73. def supported_features(self):
  74. """Return the supported features for this light."""
  75. if self._effect_dps:
  76. return SUPPORT_EFFECT
  77. else:
  78. return 0
  79. @property
  80. def color_mode(self):
  81. """Return the color mode of the light"""
  82. if self._brightness_dps:
  83. return COLOR_MODE_BRIGHTNESS
  84. elif self._switch_dps:
  85. return COLOR_MODE_ONOFF
  86. else:
  87. return COLOR_MODE_UNKNOWN
  88. @property
  89. def is_on(self):
  90. """Return the current state."""
  91. if self._switch_dps:
  92. return self._switch_dps.get_value(self._device)
  93. elif self._brightness_dps:
  94. b = self.brightness
  95. return isinstance(b, int) and b > 0
  96. else:
  97. # There shouldn't be lights without control, but if there are, assume always on
  98. return True
  99. @property
  100. def brightness(self):
  101. """Get the current brightness of the light"""
  102. if self._brightness_dps is None:
  103. return None
  104. return self._brightness_dps.get_value(self._device)
  105. @property
  106. def effect_list(self):
  107. """Return the list of valid effects for the light"""
  108. if self._effect_dps is None:
  109. return None
  110. return self._effect_dps.values(self._device)
  111. @property
  112. def effect(self):
  113. """Return the current effect setting of this light"""
  114. if self._effect_dps is None:
  115. return None
  116. return self._effect_dps.get_value(self._device)
  117. @property
  118. def device_state_attributes(self):
  119. """Get additional attributes that the integration itself does not support."""
  120. attr = {}
  121. for a in self._attr_dps:
  122. attr[a.name] = a.get_value(self._device)
  123. return attr
  124. async def async_turn_on(self, **params):
  125. settings = {}
  126. if self._switch_dps:
  127. settings = {
  128. **settings,
  129. **self._switch_dps.get_values_to_set(self._device, True),
  130. }
  131. if self._brightness_dps:
  132. bright = params.get(ATTR_BRIGHTNESS, 255)
  133. bright_values = self._brightness_dps.get_values_to_set(self._device, bright)
  134. settings = {
  135. **settings,
  136. **bright_values,
  137. }
  138. if self._effect_dps:
  139. effect = params.get(ATTR_EFFECT, None)
  140. if effect:
  141. effect_values = self._effect_dps.get_values_to_set(self._device, effect)
  142. settings = {
  143. **settings,
  144. **effect_values,
  145. }
  146. await self._device.async_set_properties(settings)
  147. async def async_turn_off(self):
  148. if self._switch_dps:
  149. await self._switch_dps.async_set_value(self._device, False)
  150. elif self._brightness_dps:
  151. await self._brightness_dps.async_set_value(self._device, 0)
  152. else:
  153. raise NotImplementedError()
  154. async def async_toggle(self):
  155. dps_display_on = self.is_on
  156. await (self.async_turn_on() if not dps_display_on else self.async_turn_off())
  157. async def async_update(self):
  158. await self._device.async_refresh()