Home Assistant Unofficial Reference 2024.12.1
light.py
Go to the documentation of this file.
1 """Support for Bond lights."""
2 
3 from __future__ import annotations
4 
5 import logging
6 from typing import Any
7 
8 from aiohttp.client_exceptions import ClientResponseError
9 from bond_async import Action, DeviceType
10 import voluptuous as vol
11 
12 from homeassistant.components.light import ATTR_BRIGHTNESS, ColorMode, LightEntity
13 from homeassistant.core import HomeAssistant, callback
14 from homeassistant.exceptions import HomeAssistantError
15 from homeassistant.helpers import config_validation as cv, entity_platform
16 from homeassistant.helpers.entity import Entity
17 from homeassistant.helpers.entity_platform import AddEntitiesCallback
18 
19 from . import BondConfigEntry
20 from .const import (
21  ATTR_POWER_STATE,
22  SERVICE_SET_LIGHT_BRIGHTNESS_TRACKED_STATE,
23  SERVICE_SET_LIGHT_POWER_TRACKED_STATE,
24 )
25 from .entity import BondEntity
26 from .models import BondData
27 from .utils import BondDevice
28 
29 _LOGGER = logging.getLogger(__name__)
30 
31 SERVICE_START_INCREASING_BRIGHTNESS = "start_increasing_brightness"
32 SERVICE_START_DECREASING_BRIGHTNESS = "start_decreasing_brightness"
33 SERVICE_STOP = "stop"
34 
35 ENTITY_SERVICES = [
36  SERVICE_START_INCREASING_BRIGHTNESS,
37  SERVICE_START_DECREASING_BRIGHTNESS,
38  SERVICE_STOP,
39 ]
40 
41 
43  hass: HomeAssistant,
44  entry: BondConfigEntry,
45  async_add_entities: AddEntitiesCallback,
46 ) -> None:
47  """Set up Bond light devices."""
48  data = entry.runtime_data
49  hub = data.hub
50 
51  platform = entity_platform.async_get_current_platform()
52  for service in ENTITY_SERVICES:
53  platform.async_register_entity_service(
54  service,
55  None,
56  f"async_{service}",
57  )
58 
59  fan_lights: list[Entity] = [
60  BondLight(data, device)
61  for device in hub.devices
62  if DeviceType.is_fan(device.type)
63  and device.supports_light()
64  and not (device.supports_up_light() and device.supports_down_light())
65  ]
66 
67  fan_up_lights: list[Entity] = [
68  BondUpLight(data, device, "up_light")
69  for device in hub.devices
70  if DeviceType.is_fan(device.type) and device.supports_up_light()
71  ]
72 
73  fan_down_lights: list[Entity] = [
74  BondDownLight(data, device, "down_light")
75  for device in hub.devices
76  if DeviceType.is_fan(device.type) and device.supports_down_light()
77  ]
78 
79  fireplaces: list[Entity] = [
80  BondFireplace(data, device)
81  for device in hub.devices
82  if DeviceType.is_fireplace(device.type)
83  ]
84 
85  fp_lights: list[Entity] = [
86  BondLight(data, device, "light")
87  for device in hub.devices
88  if DeviceType.is_fireplace(device.type) and device.supports_light()
89  ]
90 
91  lights: list[Entity] = [
92  BondLight(data, device)
93  for device in hub.devices
94  if DeviceType.is_light(device.type)
95  ]
96 
97  platform.async_register_entity_service(
98  SERVICE_SET_LIGHT_BRIGHTNESS_TRACKED_STATE,
99  {
100  vol.Required(ATTR_BRIGHTNESS): vol.All(
101  vol.Number(scale=0), vol.Range(0, 255)
102  )
103  },
104  "async_set_brightness_belief",
105  )
106 
107  platform.async_register_entity_service(
108  SERVICE_SET_LIGHT_POWER_TRACKED_STATE,
109  {vol.Required(ATTR_POWER_STATE): vol.All(cv.boolean)},
110  "async_set_power_belief",
111  )
112 
114  fan_lights + fan_up_lights + fan_down_lights + fireplaces + fp_lights + lights,
115  )
116 
117 
119  """Representation of a Bond light."""
120 
121  _attr_color_mode = ColorMode.ONOFF
122  _attr_supported_color_modes = {ColorMode.ONOFF}
123 
124  async def async_set_brightness_belief(self, brightness: int) -> None:
125  """Set the belief state of the light."""
126  if not self._device_device.supports_set_brightness():
127  raise HomeAssistantError("This device does not support setting brightness")
128  if brightness == 0:
129  await self.async_set_power_beliefasync_set_power_belief(False)
130  return
131  try:
132  await self._bond_bond.action(
133  self._device_id_device_id,
134  Action.set_brightness_belief(round((brightness * 100) / 255)),
135  )
136  except ClientResponseError as ex:
137  raise HomeAssistantError(
138  "The bond API returned an error calling set_brightness_belief for"
139  f" {self.entity_id}. Code: {ex.status} Message: {ex.message}"
140  ) from ex
141 
142  async def async_set_power_belief(self, power_state: bool) -> None:
143  """Set the belief state of the light."""
144  try:
145  await self._bond_bond.action(
146  self._device_id_device_id, Action.set_light_state_belief(power_state)
147  )
148  except ClientResponseError as ex:
149  raise HomeAssistantError(
150  "The bond API returned an error calling set_light_state_belief for"
151  f" {self.entity_id}. Code: {ex.status} Message: {ex.message}"
152  ) from ex
153 
154 
156  """Representation of a Bond light."""
157 
158  def __init__(
159  self,
160  data: BondData,
161  device: BondDevice,
162  sub_device: str | None = None,
163  ) -> None:
164  """Create HA entity representing Bond light."""
165  super().__init__(data, device, sub_device)
166  if device.supports_set_brightness():
167  self._attr_color_mode_attr_color_mode_attr_color_mode = ColorMode.BRIGHTNESS
168  self._attr_supported_color_modes_attr_supported_color_modes_attr_supported_color_modes = {ColorMode.BRIGHTNESS}
169 
170  def _apply_state(self) -> None:
171  state = self._device_device.state
172  self._attr_is_on_attr_is_on = state.get("light") == 1
173  brightness = state.get("brightness")
174  self._attr_brightness_attr_brightness = round(brightness * 255 / 100) if brightness else None
175 
176  async def async_turn_on(self, **kwargs: Any) -> None:
177  """Turn on the light."""
178  if brightness := kwargs.get(ATTR_BRIGHTNESS):
179  await self._bond_bond.action(
180  self._device_id_device_id,
181  Action.set_brightness(round((brightness * 100) / 255)),
182  )
183  else:
184  await self._bond_bond.action(self._device_id_device_id, Action.turn_light_on())
185 
186  async def async_turn_off(self, **kwargs: Any) -> None:
187  """Turn off the light."""
188  await self._bond_bond.action(self._device_id_device_id, Action.turn_light_off())
189 
190  @callback
191  def _async_has_action_or_raise(self, action: str) -> None:
192  """Raise HomeAssistantError if the device does not support an action."""
193  if not self._device_device.has_action(action):
194  raise HomeAssistantError(f"{self.entity_id} does not support {action}")
195 
196  async def async_start_increasing_brightness(self) -> None:
197  """Start increasing the light brightness."""
198  _LOGGER.warning(
199  "The bond.start_increasing_brightness service is deprecated and has been"
200  " replaced with a button; Call the button.press service instead"
201  )
202  self._async_has_action_or_raise_async_has_action_or_raise(Action.START_INCREASING_BRIGHTNESS)
203  await self._bond_bond.action(
204  self._device_id_device_id, Action(Action.START_INCREASING_BRIGHTNESS)
205  )
206 
207  async def async_start_decreasing_brightness(self) -> None:
208  """Start decreasing the light brightness."""
209  _LOGGER.warning(
210  "The bond.start_decreasing_brightness service is deprecated and has been"
211  " replaced with a button; Call the button.press service instead"
212  )
213  self._async_has_action_or_raise_async_has_action_or_raise(Action.START_DECREASING_BRIGHTNESS)
214  await self._bond_bond.action(
215  self._device_id_device_id, Action(Action.START_DECREASING_BRIGHTNESS)
216  )
217 
218  async def async_stop(self) -> None:
219  """Stop all actions and clear the queue."""
220  _LOGGER.warning(
221  "The bond.stop service is deprecated and has been replaced with a button;"
222  " Call the button.press service instead"
223  )
224  self._async_has_action_or_raise_async_has_action_or_raise(Action.STOP)
225  await self._bond_bond.action(self._device_id_device_id, Action(Action.STOP))
226 
227 
229  """Representation of a Bond light."""
230 
231  def _apply_state(self) -> None:
232  state = self._device_device.state
233  self._attr_is_on_attr_is_on = bool(state.get("down_light") and state.get("light"))
234 
235  async def async_turn_on(self, **kwargs: Any) -> None:
236  """Turn on the light."""
237  await self._bond_bond.action(self._device_id_device_id, Action(Action.TURN_DOWN_LIGHT_ON))
238 
239  async def async_turn_off(self, **kwargs: Any) -> None:
240  """Turn off the light."""
241  await self._bond_bond.action(self._device_id_device_id, Action(Action.TURN_DOWN_LIGHT_OFF))
242 
243 
245  """Representation of a Bond light."""
246 
247  def _apply_state(self) -> None:
248  state = self._device_device.state
249  self._attr_is_on_attr_is_on = bool(state.get("up_light") and state.get("light"))
250 
251  async def async_turn_on(self, **kwargs: Any) -> None:
252  """Turn on the light."""
253  await self._bond_bond.action(self._device_id_device_id, Action(Action.TURN_UP_LIGHT_ON))
254 
255  async def async_turn_off(self, **kwargs: Any) -> None:
256  """Turn off the light."""
257  await self._bond_bond.action(self._device_id_device_id, Action(Action.TURN_UP_LIGHT_OFF))
258 
259 
261  """Representation of a Bond-controlled fireplace."""
262 
263  _attr_color_mode = ColorMode.BRIGHTNESS
264  _attr_supported_color_modes = {ColorMode.BRIGHTNESS}
265  _attr_translation_key = "fireplace"
266 
267  def _apply_state(self) -> None:
268  state = self._device_device.state
269  power = state.get("power")
270  flame = state.get("flame")
271  self._attr_is_on_attr_is_on = power == 1
272  self._attr_brightness_attr_brightness = round(flame * 255 / 100) if flame else None
273 
274  async def async_turn_on(self, **kwargs: Any) -> None:
275  """Turn the fireplace on."""
276  _LOGGER.debug("Fireplace async_turn_on called with: %s", kwargs)
277 
278  if brightness := kwargs.get(ATTR_BRIGHTNESS):
279  flame = round((brightness * 100) / 255)
280  await self._bond_bond.action(self._device_id_device_id, Action.set_flame(flame))
281  else:
282  await self._bond_bond.action(self._device_id_device_id, Action.turn_on())
283 
284  async def async_turn_off(self, **kwargs: Any) -> None:
285  """Turn the fireplace off."""
286  _LOGGER.debug("Fireplace async_turn_off called with: %s", kwargs)
287 
288  await self._bond_bond.action(self._device_id_device_id, Action.turn_off())
289 
290  async def async_set_brightness_belief(self, brightness: int) -> None:
291  """Set the belief state of the light."""
292  if not self._device_device.supports_set_brightness():
293  raise HomeAssistantError("This device does not support setting brightness")
294  if brightness == 0:
295  await self.async_set_power_beliefasync_set_power_belief(False)
296  return
297  try:
298  await self._bond_bond.action(
299  self._device_id_device_id,
300  Action.set_brightness_belief(round((brightness * 100) / 255)),
301  )
302  except ClientResponseError as ex:
303  raise HomeAssistantError(
304  "The bond API returned an error calling set_brightness_belief for"
305  f" {self.entity_id}. Code: {ex.status} Message: {ex.message}"
306  ) from ex
307 
308  async def async_set_power_belief(self, power_state: bool) -> None:
309  """Set the belief state of the light."""
310  try:
311  await self._bond_bond.action(
312  self._device_id_device_id, Action.set_power_state_belief(power_state)
313  )
314  except ClientResponseError as ex:
315  raise HomeAssistantError(
316  "The bond API returned an error calling set_power_state_belief for"
317  f" {self.entity_id}. Code: {ex.status} Message: {ex.message}"
318  ) from ex
None async_set_power_belief(self, bool power_state)
Definition: light.py:142
None async_set_brightness_belief(self, int brightness)
Definition: light.py:124
None async_turn_on(self, **Any kwargs)
Definition: light.py:235
None async_turn_off(self, **Any kwargs)
Definition: light.py:239
None async_set_brightness_belief(self, int brightness)
Definition: light.py:290
None async_turn_on(self, **Any kwargs)
Definition: light.py:274
None async_set_power_belief(self, bool power_state)
Definition: light.py:308
None async_turn_off(self, **Any kwargs)
Definition: light.py:284
None async_turn_on(self, **Any kwargs)
Definition: light.py:176
None async_turn_off(self, **Any kwargs)
Definition: light.py:186
None _async_has_action_or_raise(self, str action)
Definition: light.py:191
None __init__(self, BondData data, BondDevice device, str|None sub_device=None)
Definition: light.py:163
None async_turn_on(self, **Any kwargs)
Definition: light.py:251
None async_turn_off(self, **Any kwargs)
Definition: light.py:255
None async_setup_entry(HomeAssistant hass, BondConfigEntry entry, AddEntitiesCallback async_add_entities)
Definition: light.py:46