Home Assistant Unofficial Reference 2024.12.1
light.py
Go to the documentation of this file.
1 """Support for Lutron Caseta lights."""
2 
3 from datetime import timedelta
4 from typing import Any
5 
6 from pylutron_caseta.color_value import (
7  ColorMode as LutronColorMode,
8  FullColorValue,
9  WarmCoolColorValue,
10 )
11 
13  ATTR_BRIGHTNESS,
14  ATTR_COLOR_TEMP_KELVIN,
15  ATTR_HS_COLOR,
16  ATTR_TRANSITION,
17  ATTR_WHITE,
18  DOMAIN as LIGHT_DOMAIN,
19  ColorMode,
20  LightEntity,
21  LightEntityFeature,
22 )
23 from homeassistant.config_entries import ConfigEntry
24 from homeassistant.core import HomeAssistant
25 from homeassistant.helpers.entity_platform import AddEntitiesCallback
26 
27 from .const import DEVICE_TYPE_SPECTRUM_TUNE, DEVICE_TYPE_WHITE_TUNE
28 from .entity import LutronCasetaUpdatableEntity
29 from .models import LutronCasetaData
30 
31 SUPPORTED_COLOR_MODE_DICT = {
32  DEVICE_TYPE_SPECTRUM_TUNE: {
33  ColorMode.HS,
34  ColorMode.COLOR_TEMP,
35  ColorMode.WHITE,
36  },
37  DEVICE_TYPE_WHITE_TUNE: {ColorMode.COLOR_TEMP},
38 }
39 
40 WARM_DEVICE_TYPES = {DEVICE_TYPE_WHITE_TUNE, DEVICE_TYPE_SPECTRUM_TUNE}
41 
42 
43 def to_lutron_level(level):
44  """Convert the given Home Assistant light level (0-255) to Lutron (0-100)."""
45  return int(round((level * 100) / 255))
46 
47 
48 def to_hass_level(level):
49  """Convert the given Lutron (0-100) light level to Home Assistant (0-255)."""
50  return int((level * 255) // 100)
51 
52 
54  hass: HomeAssistant,
55  config_entry: ConfigEntry,
56  async_add_entities: AddEntitiesCallback,
57 ) -> None:
58  """Set up the Lutron Caseta light platform.
59 
60  Adds dimmers from the Caseta bridge associated with the config_entry as
61  light entities.
62  """
63  data = config_entry.runtime_data
64  bridge = data.bridge
65  light_devices = bridge.get_devices_by_domain(LIGHT_DOMAIN)
67  LutronCasetaLight(light_device, data) for light_device in light_devices
68  )
69 
70 
72  """Representation of a Lutron Light, including dimmable, white tune, and spectrum tune."""
73 
74  _attr_supported_features = LightEntityFeature.TRANSITION
75 
76  def __init__(self, light: dict[str, Any], data: LutronCasetaData) -> None:
77  """Initialize the light and set the supported color modes.
78 
79  :param light: The lutron light device to initialize.
80  :param data: The integration data
81  """
82  super().__init__(light, data)
83 
84  self._attr_min_color_temp_kelvin_attr_min_color_temp_kelvin = self._get_min_color_temp_kelvin_get_min_color_temp_kelvin(light)
85  self._attr_max_color_temp_kelvin_attr_max_color_temp_kelvin = self._get_max_color_temp_kelvin_get_max_color_temp_kelvin(light)
86 
87  light_type = light["type"]
88  self._attr_supported_color_modes_attr_supported_color_modes = SUPPORTED_COLOR_MODE_DICT.get(
89  light_type, {ColorMode.BRIGHTNESS}
90  )
91 
92  self.supports_warm_coolsupports_warm_cool = light_type in WARM_DEVICE_TYPES
93  self.supports_warm_dimsupports_warm_dim = light_type == DEVICE_TYPE_SPECTRUM_TUNE
94  self.supports_spectrum_tunesupports_spectrum_tune = light_type == DEVICE_TYPE_SPECTRUM_TUNE
95 
96  def _get_min_color_temp_kelvin(self, light: dict[str, Any]) -> int:
97  """Return minimum supported color temperature.
98 
99  :param light: The light to get the minimum color temperature for.
100  """
101  white_tune_range = light.get("white_tuning_range")
102  # Default to 1.4k if not found
103  if white_tune_range is None or "Min" not in white_tune_range:
104  return 1400
105 
106  return white_tune_range.get("Min")
107 
108  def _get_max_color_temp_kelvin(self, light: dict[str, Any]) -> int:
109  """Return maximum supported color temperature.
110 
111  :param light: The light to get the maximum color temperature for.
112  """
113  white_tune_range = light.get("white_tuning_range")
114  # Default to 10k if not found
115  if white_tune_range is None or "Max" not in white_tune_range:
116  return 10000
117 
118  return white_tune_range.get("Max")
119 
120  @property
121  def brightness(self) -> int:
122  """Return the brightness of the light."""
123  return to_hass_level(self._device_device_device["current_state"])
124 
126  self, brightness: int | None, color_value: LutronColorMode | None, **kwargs: Any
127  ) -> None:
128  args = {}
129  if ATTR_TRANSITION in kwargs:
130  args["fade_time"] = timedelta(seconds=kwargs[ATTR_TRANSITION])
131 
132  if brightness is not None:
133  brightness = to_lutron_level(brightness)
134  await self._smartbridge_smartbridge.set_value(
135  self.device_iddevice_id, value=brightness, color_value=color_value, **args
136  )
137 
138  async def _async_set_warm_dim(self, brightness: int | None, **kwargs: Any):
139  """Set the light to warm dim mode."""
140  set_warm_dim_kwargs: dict[str, Any] = {}
141  if ATTR_TRANSITION in kwargs:
142  set_warm_dim_kwargs["fade_time"] = timedelta(
143  seconds=kwargs[ATTR_TRANSITION]
144  )
145 
146  if brightness is not None:
147  brightness = to_lutron_level(brightness)
148 
149  await self._smartbridge_smartbridge.set_warm_dim(
150  self.device_iddevice_id, brightness, **set_warm_dim_kwargs
151  )
152 
153  async def async_turn_on(self, **kwargs: Any) -> None:
154  """Turn the light on."""
155  # first check for "white mode" (WarmDim)
156  if (white_color := kwargs.get(ATTR_WHITE)) is not None:
157  await self._async_set_warm_dim_async_set_warm_dim(white_color)
158  return
159 
160  brightness = kwargs.pop(ATTR_BRIGHTNESS, None)
161  color: LutronColorMode | None = None
162  hs_color: tuple[float, float] | None = kwargs.pop(ATTR_HS_COLOR, None)
163  kelvin_color: int | None = kwargs.pop(ATTR_COLOR_TEMP_KELVIN, None)
164 
165  if hs_color is not None:
166  color = FullColorValue(hs_color[0], hs_color[1])
167  elif kelvin_color is not None:
168  color = WarmCoolColorValue(kelvin_color)
169 
170  # if user is pressing on button nothing is set, so set brightness to 255
171  if color is None and brightness is None:
172  brightness = 255
173 
174  await self._async_set_brightness_async_set_brightness(brightness, color, **kwargs)
175 
176  async def async_turn_off(self, **kwargs: Any) -> None:
177  """Turn the light off."""
178  await self._async_set_brightness_async_set_brightness(0, None, **kwargs)
179 
180  @property
181  def color_mode(self) -> ColorMode:
182  """Return the current color mode of the light."""
183 
184  currently_warm_dim = self._device_device_device.get("warm_dim", False)
185  if self.supports_warm_dimsupports_warm_dim and currently_warm_dim:
186  return ColorMode.WHITE
187 
188  current_color = self._device_device_device.get("color")
189  if self.supports_warm_coolsupports_warm_cool and isinstance(current_color, WarmCoolColorValue):
190  return ColorMode.COLOR_TEMP
191 
192  if self.supports_spectrum_tunesupports_spectrum_tune and isinstance(current_color, FullColorValue):
193  return ColorMode.HS
194 
195  return ColorMode.BRIGHTNESS
196 
197  @property
198  def is_on(self) -> bool:
199  """Return true if device is on."""
200  return self._device_device_device["current_state"] > 0
201 
202  @property
203  def hs_color(self) -> tuple[float, float] | None:
204  """Return the current color of the light."""
205  current_color: FullColorValue | WarmCoolColorValue | None = self._device_device_device.get(
206  "color"
207  )
208 
209  # if bulb is set to full spectrum, return the hue and saturation
210  if isinstance(current_color, FullColorValue):
211  return (current_color.hue, current_color.saturation)
212 
213  return None
214 
215  @property
216  def color_temp_kelvin(self) -> int | None:
217  """Return the CT color value in kelvin."""
218  current_color: FullColorValue | WarmCoolColorValue | None = self._device_device_device.get(
219  "color"
220  )
221 
222  # if bulb is set to warm cool mode, return the kelvin value
223  if isinstance(current_color, WarmCoolColorValue):
224  return current_color.kelvin
225 
226  return None
None __init__(self, dict[str, Any] light, LutronCasetaData data)
Definition: light.py:76
def _async_set_warm_dim(self, int|None brightness, **Any kwargs)
Definition: light.py:138
int _get_min_color_temp_kelvin(self, dict[str, Any] light)
Definition: light.py:96
None _async_set_brightness(self, int|None brightness, LutronColorMode|None color_value, **Any kwargs)
Definition: light.py:127
int _get_max_color_temp_kelvin(self, dict[str, Any] light)
Definition: light.py:108
web.Response get(self, web.Request request, str config_key)
Definition: view.py:88
None async_setup_entry(HomeAssistant hass, ConfigEntry config_entry, AddEntitiesCallback async_add_entities)
Definition: light.py:57