light.py 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  1. """Light setup for our Integration."""
  2. from datetime import timedelta
  3. import logging
  4. from typing import Any
  5. import voluptuous as vol
  6. from homeassistant.components.light import ATTR_BRIGHTNESS, ColorMode, LightEntity
  7. from homeassistant.core import HomeAssistant
  8. from homeassistant.helpers import config_validation as cv, entity_platform
  9. from homeassistant.helpers.entity_platform import AddEntitiesCallback
  10. from . import MyConfigEntry
  11. from .base import ExampleBaseEntity
  12. from .const import CONF_OFF_TIME, SET_OFF_TIMER_ENTITY_SERVICE_NAME
  13. from .coordinator import ExampleCoordinator
  14. _LOGGER = logging.getLogger(__name__)
  15. async def async_setup_entry(
  16. hass: HomeAssistant,
  17. config_entry: MyConfigEntry,
  18. async_add_entities: AddEntitiesCallback,
  19. ):
  20. """Set up the Binary Sensors."""
  21. # This gets the data update coordinator from the config entry runtime data as specified in your __init__.py
  22. coordinator: ExampleCoordinator = config_entry.runtime_data.coordinator
  23. # ----------------------------------------------------------------------------
  24. # Here we are going to add some lights entities for the lights in our mock data.
  25. # We have an on/off light and a dimmable light in our mock data, so add each
  26. # specific class based on the light type.
  27. # ----------------------------------------------------------------------------
  28. lights = []
  29. # On/Off lights
  30. lights.extend(
  31. [
  32. ExampleOnOffLight(coordinator, device, "state")
  33. for device in coordinator.data
  34. if device.get("device_type") == "ON_OFF_LIGHT"
  35. ]
  36. )
  37. # Dimmable lights
  38. lights.extend(
  39. [
  40. ExampleDimmableLight(coordinator, device, "state")
  41. for device in coordinator.data
  42. if device.get("device_type") == "DIMMABLE_LIGHT"
  43. ]
  44. )
  45. # Create the lights.
  46. async_add_entities(lights)
  47. # ----------------------------------------------------------------------------
  48. # Add an Entity Service
  49. #
  50. # This example creates a service to set an off timer for our mock device.
  51. # You can have your schema as anything you need and must relate to the entry
  52. # in services.yaml. Best to set your target filters in serivces.yaml to match
  53. # what this can be called on, so your users cannot pick inappropriate entities.
  54. # If an entity is supplied that does not support this service, nothing will
  55. # happen.
  56. #
  57. # The function async_set_off_timer has to be part of your entity class and
  58. # is shown below.
  59. #
  60. # You will see the off timer sensor on a light update to reflect the time you
  61. # set.
  62. # ----------------------------------------------------------------------------
  63. platform = entity_platform.async_get_current_platform()
  64. platform.async_register_entity_service(
  65. SET_OFF_TIMER_ENTITY_SERVICE_NAME,
  66. {
  67. vol.Required(CONF_OFF_TIME): cv.time_period,
  68. },
  69. "async_set_off_timer",
  70. )
  71. class ExampleOnOffLight(ExampleBaseEntity, LightEntity):
  72. """Implementation of an on/off light.
  73. This inherits our ExampleBaseEntity to set common properties.
  74. See base.py for this class.
  75. https://developers.home-assistant.io/docs/core/entity/light/
  76. """
  77. _attr_supported_color_modes = {ColorMode.ONOFF}
  78. _attr_color_mode = ColorMode.ONOFF
  79. @property
  80. def is_on(self) -> bool | None:
  81. """Return if the binary sensor is on."""
  82. # This needs to enumerate to true or false
  83. return (
  84. self.coordinator.get_device_parameter(self.device_id, self.parameter)
  85. == "ON"
  86. )
  87. async def async_turn_on(self, **kwargs: Any) -> None:
  88. """Turn the entity on."""
  89. await self.hass.async_add_executor_job(
  90. self.coordinator.api.set_data, self.device_id, self.parameter, "ON"
  91. )
  92. # ----------------------------------------------------------------------------
  93. # Use async_refresh on the DataUpdateCoordinator to perform immediate update.
  94. # Using self.async_update or self.coordinator.async_request_refresh may delay update due
  95. # to trying to batch requests.
  96. # ----------------------------------------------------------------------------
  97. await self.coordinator.async_refresh()
  98. async def async_turn_off(self, **kwargs: Any) -> None:
  99. """Turn the entity off."""
  100. await self.hass.async_add_executor_job(
  101. self.coordinator.api.set_data, self.device_id, self.parameter, "OFF"
  102. )
  103. # ----------------------------------------------------------------------------
  104. # Use async_refresh on the DataUpdateCoordinator to perform immediate update.
  105. # Using self.async_update or self.coordinator.async_request_refresh may delay update due
  106. # to trying to batch requests.
  107. # ----------------------------------------------------------------------------
  108. await self.coordinator.async_refresh()
  109. async def async_set_off_timer(self, off_time: timedelta) -> None:
  110. """Handle the set off timer service call.
  111. Important here to have your service parameters included in your
  112. function as they are passed as named parameters.
  113. """
  114. await self.hass.async_add_executor_job(
  115. self.coordinator.api.set_data,
  116. self.device_id,
  117. "off_timer",
  118. ":".join(str(off_time).split(":")[:2]),
  119. )
  120. # We have made a change to our device, so call a refresh to get updated data.
  121. # We use async_request_refresh here to batch the updates in case you select
  122. # multiple entities.
  123. await self.coordinator.async_request_refresh()
  124. class ExampleDimmableLight(ExampleOnOffLight):
  125. """Implementation of a dimmable light."""
  126. _attr_supported_color_modes = {ColorMode.BRIGHTNESS}
  127. _attr_color_mode = ColorMode.BRIGHTNESS
  128. @property
  129. def brightness(self) -> int:
  130. """Return the brightness of this light between 0..255."""
  131. # Our light is in range 0..100, so convert
  132. return int(
  133. self.coordinator.get_device_parameter(self.device_id, "brightness")
  134. * (255 / 100)
  135. )
  136. async def async_turn_on(self, **kwargs: Any) -> None:
  137. """Turn the entity on."""
  138. if ATTR_BRIGHTNESS in kwargs:
  139. brightness = int(kwargs[ATTR_BRIGHTNESS] * (100 / 255))
  140. await self.hass.async_add_executor_job(
  141. self.coordinator.api.set_data, self.device_id, "brightness", brightness
  142. )
  143. else:
  144. await self.hass.async_add_executor_job(
  145. self.coordinator.api.set_data, self.device_id, self.parameter, "ON"
  146. )
  147. # ----------------------------------------------------------------------------
  148. # Use async_refresh on the DataUpdateCoordinator to perform immediate update.
  149. # Using self.async_update or self.coordinator.async_request_refresh may delay update due
  150. # to trying to batch requests and cause wierd UI behaviour.
  151. # ----------------------------------------------------------------------------
  152. await self.coordinator.async_refresh()