Home Assistant Unofficial Reference 2024.12.1
light.py
Go to the documentation of this file.
1 """Support for MySensors lights."""
2 
3 from __future__ import annotations
4 
5 from typing import Any, cast
6 
8  ATTR_BRIGHTNESS,
9  ATTR_RGB_COLOR,
10  ATTR_RGBW_COLOR,
11  ColorMode,
12  LightEntity,
13 )
14 from homeassistant.config_entries import ConfigEntry
15 from homeassistant.const import STATE_OFF, STATE_ON, Platform
16 from homeassistant.core import HomeAssistant, callback
17 from homeassistant.helpers.dispatcher import async_dispatcher_connect
18 from homeassistant.helpers.entity_platform import AddEntitiesCallback
19 from homeassistant.util.color import rgb_hex_to_rgb_list
20 
21 from . import setup_mysensors_platform
22 from .const import MYSENSORS_DISCOVERY, DiscoveryInfo, SensorType
23 from .entity import MySensorsChildEntity
24 from .helpers import on_unload
25 
26 
28  hass: HomeAssistant,
29  config_entry: ConfigEntry,
30  async_add_entities: AddEntitiesCallback,
31 ) -> None:
32  """Set up this platform for a specific ConfigEntry(==Gateway)."""
33  device_class_map: dict[SensorType, type[MySensorsChildEntity]] = {
34  "S_DIMMER": MySensorsLightDimmer,
35  "S_RGB_LIGHT": MySensorsLightRGB,
36  "S_RGBW_LIGHT": MySensorsLightRGBW,
37  }
38 
39  async def async_discover(discovery_info: DiscoveryInfo) -> None:
40  """Discover and add a MySensors light."""
42  hass,
43  Platform.LIGHT,
44  discovery_info,
45  device_class_map,
46  async_add_entities=async_add_entities,
47  )
48 
49  on_unload(
50  hass,
51  config_entry.entry_id,
53  hass,
54  MYSENSORS_DISCOVERY.format(config_entry.entry_id, Platform.LIGHT),
55  async_discover,
56  ),
57  )
58 
59 
61  """Representation of a MySensors Light child node."""
62 
63  def __init__(self, *args: Any) -> None:
64  """Initialize a MySensors Light."""
65  super().__init__(*args)
66  self._state_state: bool | None = None
67 
68  @property
69  def is_on(self) -> bool:
70  """Return true if device is on."""
71  return bool(self._state_state)
72 
73  def _turn_on_light(self) -> None:
74  """Turn on light child device."""
75  set_req = self.gateway.const.SetReq
76 
77  if self._state_state:
78  return
79  self.gateway.set_child_value(
80  self.node_id, self.child_id, set_req.V_LIGHT, 1, ack=1
81  )
82 
83  if self.assumed_stateassumed_state:
84  # optimistically assume that light has changed state
85  self._state_state = True
86  self._values[set_req.V_LIGHT] = STATE_ON
87 
88  def _turn_on_dimmer(self, **kwargs: Any) -> None:
89  """Turn on dimmer child device."""
90  set_req = self.gateway.const.SetReq
91 
92  if (
93  ATTR_BRIGHTNESS not in kwargs
94  or kwargs[ATTR_BRIGHTNESS] == self._attr_brightness_attr_brightness
95  or set_req.V_DIMMER not in self._values
96  ):
97  return
98  brightness: int = kwargs[ATTR_BRIGHTNESS]
99  percent = round(100 * brightness / 255)
100  self.gateway.set_child_value(
101  self.node_id, self.child_id, set_req.V_DIMMER, percent, ack=1
102  )
103 
104  if self.assumed_stateassumed_state:
105  # optimistically assume that light has changed state
106  self._attr_brightness_attr_brightness = brightness
107  self._values[set_req.V_DIMMER] = percent
108 
109  async def async_turn_off(self, **kwargs: Any) -> None:
110  """Turn the device off."""
111  value_type = self.gateway.const.SetReq.V_LIGHT
112  self.gateway.set_child_value(self.node_id, self.child_id, value_type, 0, ack=1)
113  if self.assumed_stateassumed_state:
114  # optimistically assume that light has changed state
115  self._state_state = False
116  self._values[value_type] = STATE_OFF
117  self.async_write_ha_stateasync_write_ha_state()
118 
119  @callback
120  def _async_update_light(self) -> None:
121  """Update the controller with values from light child."""
122  value_type = self.gateway.const.SetReq.V_LIGHT
123  self._state_state = self._values[value_type] == STATE_ON
124 
125  @callback
126  def _async_update_dimmer(self) -> None:
127  """Update the controller with values from dimmer child."""
128  value_type = self.gateway.const.SetReq.V_DIMMER
129  if value_type in self._values:
130  self._attr_brightness_attr_brightness = round(255 * int(self._values[value_type]) / 100)
131  if self._attr_brightness_attr_brightness == 0:
132  self._state_state = False
133 
134 
136  """Dimmer child class to MySensorsLight."""
137 
138  _attr_supported_color_modes = {ColorMode.BRIGHTNESS}
139  _attr_color_mode = ColorMode.BRIGHTNESS
140 
141  async def async_turn_on(self, **kwargs: Any) -> None:
142  """Turn the device on."""
143  self._turn_on_light_turn_on_light()
144  self._turn_on_dimmer_turn_on_dimmer(**kwargs)
145  if self.assumed_stateassumed_state:
146  self.async_write_ha_stateasync_write_ha_state()
147 
148  @callback
149  def _async_update(self) -> None:
150  """Update the controller with the latest value from a sensor."""
151  super()._async_update()
152  self._async_update_light_async_update_light()
153  self._async_update_dimmer_async_update_dimmer()
154 
155 
157  """RGB child class to MySensorsLight."""
158 
159  _attr_supported_color_modes = {ColorMode.RGB}
160  _attr_color_mode = ColorMode.RGB
161 
162  async def async_turn_on(self, **kwargs: Any) -> None:
163  """Turn the device on."""
164  self._turn_on_light_turn_on_light()
165  self._turn_on_dimmer_turn_on_dimmer(**kwargs)
166  self._turn_on_rgb_turn_on_rgb(**kwargs)
167  if self.assumed_stateassumed_state:
168  self.async_write_ha_stateasync_write_ha_state()
169 
170  def _turn_on_rgb(self, **kwargs: Any) -> None:
171  """Turn on RGB child device."""
172  hex_color = self._values.get(self.value_type)
173  new_rgb: tuple[int, int, int] | None = kwargs.get(ATTR_RGB_COLOR)
174  if new_rgb is None:
175  return
176  red, green, blue = new_rgb
177  hex_color = f"{red:02x}{green:02x}{blue:02x}"
178  self.gateway.set_child_value(
179  self.node_id, self.child_id, self.value_type, hex_color, ack=1
180  )
181 
182  if self.assumed_stateassumed_state:
183  # optimistically assume that light has changed state
184  self._attr_rgb_color_attr_rgb_color = new_rgb
185  self._values[self.value_type] = hex_color
186 
187  @callback
188  def _async_update(self) -> None:
189  """Update the controller with the latest value from a sensor."""
190  super()._async_update()
191  self._async_update_light_async_update_light()
192  self._async_update_dimmer_async_update_dimmer()
193  self._async_update_rgb_or_w_async_update_rgb_or_w()
194 
195  @callback
196  def _async_update_rgb_or_w(self) -> None:
197  """Update the controller with values from RGB child."""
198  value = self._values[self.value_type]
199  self._attr_rgb_color_attr_rgb_color = cast(
200  tuple[int, int, int], tuple(rgb_hex_to_rgb_list(value))
201  )
202 
203 
205  """RGBW child class to MySensorsLightRGB."""
206 
207  _attr_supported_color_modes = {ColorMode.RGBW}
208  _attr_color_mode = ColorMode.RGBW
209 
210  async def async_turn_on(self, **kwargs: Any) -> None:
211  """Turn the device on."""
212  self._turn_on_light_turn_on_light()
213  self._turn_on_dimmer_turn_on_dimmer(**kwargs)
214  self._turn_on_rgbw_turn_on_rgbw(**kwargs)
215  if self.assumed_stateassumed_state:
216  self.async_write_ha_stateasync_write_ha_state()
217 
218  def _turn_on_rgbw(self, **kwargs: Any) -> None:
219  """Turn on RGBW child device."""
220  hex_color = self._values.get(self.value_type)
221  new_rgbw: tuple[int, int, int, int] | None = kwargs.get(ATTR_RGBW_COLOR)
222  if new_rgbw is None:
223  return
224  red, green, blue, white = new_rgbw
225  hex_color = f"{red:02x}{green:02x}{blue:02x}{white:02x}"
226  self.gateway.set_child_value(
227  self.node_id, self.child_id, self.value_type, hex_color, ack=1
228  )
229 
230  if self.assumed_stateassumed_state:
231  # optimistically assume that light has changed state
232  self._attr_rgbw_color_attr_rgbw_color = new_rgbw
233  self._values[self.value_type] = hex_color
234 
235  @callback
236  def _async_update_rgb_or_w(self) -> None:
237  """Update the controller with values from RGBW child."""
238  value = self._values[self.value_type]
239  self._attr_rgbw_color_attr_rgbw_color = cast(
240  tuple[int, int, int, int], tuple(rgb_hex_to_rgb_list(value))
241  )
web.Response get(self, web.Request request, str config_key)
Definition: view.py:88
None on_unload(HomeAssistant hass, GatewayId gateway_id, Callable fnct)
Definition: helpers.py:45
None async_setup_entry(HomeAssistant hass, ConfigEntry config_entry, AddEntitiesCallback async_add_entities)
Definition: light.py:31
None async_discover(DiscoveryInfo discovery_info)
Definition: sensor.py:217
list[MySensorsChildEntity]|None setup_mysensors_platform(HomeAssistant hass, Platform domain, DiscoveryInfo discovery_info, type[MySensorsChildEntity]|Mapping[SensorType, type[MySensorsChildEntity]] device_class,(tuple|None) device_args=None, Callable|None async_add_entities=None)
Definition: __init__.py:112
Callable[[], None] async_dispatcher_connect(HomeAssistant hass, str signal, Callable[..., Any] target)
Definition: dispatcher.py:103
list[int] rgb_hex_to_rgb_list(str hex_string)
Definition: color.py:497