Home Assistant Unofficial Reference 2024.12.1
light.py
Go to the documentation of this file.
1 """Support for VeSync bulbs and wall dimmers."""
2 
3 import logging
4 from typing import Any
5 
7  ATTR_BRIGHTNESS,
8  ATTR_COLOR_TEMP,
9  ColorMode,
10  LightEntity,
11 )
12 from homeassistant.config_entries import ConfigEntry
13 from homeassistant.core import HomeAssistant, callback
14 from homeassistant.helpers.dispatcher import async_dispatcher_connect
15 from homeassistant.helpers.entity_platform import AddEntitiesCallback
16 
17 from .const import DEV_TYPE_TO_HA, DOMAIN, VS_DISCOVERY, VS_LIGHTS
18 from .entity import VeSyncDevice
19 
20 _LOGGER = logging.getLogger(__name__)
21 
22 
24  hass: HomeAssistant,
25  config_entry: ConfigEntry,
26  async_add_entities: AddEntitiesCallback,
27 ) -> None:
28  """Set up lights."""
29 
30  @callback
31  def discover(devices):
32  """Add new devices to platform."""
33  _setup_entities(devices, async_add_entities)
34 
35  config_entry.async_on_unload(
36  async_dispatcher_connect(hass, VS_DISCOVERY.format(VS_LIGHTS), discover)
37  )
38 
39  _setup_entities(hass.data[DOMAIN][VS_LIGHTS], async_add_entities)
40 
41 
42 @callback
43 def _setup_entities(devices, async_add_entities):
44  """Check if device is online and add entity."""
45  entities = []
46  for dev in devices:
47  if DEV_TYPE_TO_HA.get(dev.device_type) in ("walldimmer", "bulb-dimmable"):
48  entities.append(VeSyncDimmableLightHA(dev))
49  elif DEV_TYPE_TO_HA.get(dev.device_type) in ("bulb-tunable-white",):
50  entities.append(VeSyncTunableWhiteLightHA(dev))
51  else:
52  _LOGGER.debug(
53  "%s - Unknown device type - %s", dev.device_name, dev.device_type
54  )
55  continue
56 
57  async_add_entities(entities, update_before_add=True)
58 
59 
61  """Base class for VeSync Light Devices Representations."""
62 
63  _attr_name = None
64 
65  @property
66  def brightness(self) -> int:
67  """Get light brightness."""
68  # get value from pyvesync library api,
69  result = self.devicedevice.brightness
70  try:
71  # check for validity of brightness value received
72  brightness_value = int(result)
73  except ValueError:
74  # deal if any unexpected/non numeric value
75  _LOGGER.debug(
76  "VeSync - received unexpected 'brightness' value from pyvesync api: %s",
77  result,
78  )
79  return 0
80  # convert percent brightness to ha expected range
81  return round((max(1, brightness_value) / 100) * 255)
82 
83  def turn_on(self, **kwargs: Any) -> None:
84  """Turn the device on."""
85  attribute_adjustment_only = False
86  # set white temperature
87  if self.color_modecolor_modecolor_mode == ColorMode.COLOR_TEMP and ATTR_COLOR_TEMP in kwargs:
88  # get white temperature from HA data
89  color_temp = int(kwargs[ATTR_COLOR_TEMP])
90  # ensure value between min-max supported Mireds
91  color_temp = max(self.min_miredsmin_mireds, min(color_temp, self.max_miredsmax_mireds))
92  # convert Mireds to Percent value that api expects
93  color_temp = round(
94  ((color_temp - self.min_miredsmin_mireds) / (self.max_miredsmax_mireds - self.min_miredsmin_mireds))
95  * 100
96  )
97  # flip cold/warm to what pyvesync api expects
98  color_temp = 100 - color_temp
99  # ensure value between 0-100
100  color_temp = max(0, min(color_temp, 100))
101  # call pyvesync library api method to set color_temp
102  self.devicedevice.set_color_temp(color_temp)
103  # flag attribute_adjustment_only, so it doesn't turn_on the device redundantly
104  attribute_adjustment_only = True
105  # set brightness level
106  if (
107  self.color_modecolor_modecolor_mode in (ColorMode.BRIGHTNESS, ColorMode.COLOR_TEMP)
108  and ATTR_BRIGHTNESS in kwargs
109  ):
110  # get brightness from HA data
111  brightness = int(kwargs[ATTR_BRIGHTNESS])
112  # ensure value between 1-255
113  brightness = max(1, min(brightness, 255))
114  # convert to percent that vesync api expects
115  brightness = round((brightness / 255) * 100)
116  # ensure value between 1-100
117  brightness = max(1, min(brightness, 100))
118  # call pyvesync library api method to set brightness
119  self.devicedevice.set_brightness(brightness)
120  # flag attribute_adjustment_only, so it doesn't
121  # turn_on the device redundantly
122  attribute_adjustment_only = True
123  # check flag if should skip sending the turn_on command
124  if attribute_adjustment_only:
125  return
126  # send turn_on command to pyvesync api
127  self.devicedevice.turn_on()
128 
129 
131  """Representation of a VeSync dimmable light device."""
132 
133  _attr_color_mode = ColorMode.BRIGHTNESS
134  _attr_supported_color_modes = {ColorMode.BRIGHTNESS}
135 
136 
138  """Representation of a VeSync Tunable White Light device."""
139 
140  _attr_color_mode = ColorMode.COLOR_TEMP
141  _attr_max_mireds = 370 # 1,000,000 divided by 2700 Kelvin = 370 Mireds
142  _attr_min_mireds = 154 # 1,000,000 divided by 6500 Kelvin = 154 Mireds
143  _attr_supported_color_modes = {ColorMode.COLOR_TEMP}
144 
145  @property
146  def color_temp(self) -> int:
147  """Get device white temperature."""
148  # get value from pyvesync library api,
149  result = self.devicedevice.color_temp_pct
150  try:
151  # check for validity of brightness value received
152  color_temp_value = int(result)
153  except ValueError:
154  # deal if any unexpected/non numeric value
155  _LOGGER.debug(
156  (
157  "VeSync - received unexpected 'color_temp_pct' value from pyvesync"
158  " api: %s"
159  ),
160  result,
161  )
162  return 0
163  # flip cold/warm
164  color_temp_value = 100 - color_temp_value
165  # ensure value between 0-100
166  color_temp_value = max(0, min(color_temp_value, 100))
167  # convert percent value to Mireds
168  color_temp_value = round(
169  self.min_miredsmin_mireds
170  + ((self.max_miredsmax_mireds - self.min_miredsmin_mireds) / 100 * color_temp_value)
171  )
172  # ensure value between minimum and maximum Mireds
173  return max(self.min_miredsmin_mireds, min(color_temp_value, self.max_miredsmax_mireds))
ColorMode|str|None color_mode(self)
Definition: __init__.py:909
list[tuple[str, int]] discover(HomeAssistant hass)
Definition: config_flow.py:97
None async_setup_entry(HomeAssistant hass, ConfigEntry config_entry, AddEntitiesCallback async_add_entities)
Definition: light.py:27
def _setup_entities(devices, async_add_entities)
Definition: light.py:43
Callable[[], None] async_dispatcher_connect(HomeAssistant hass, str signal, Callable[..., Any] target)
Definition: dispatcher.py:103