1 """Platform for Control4 Lights."""
3 from __future__
import annotations
6 from datetime
import timedelta
10 from pyControl4.error_handling
import C4Exception
11 from pyControl4.light
import C4Light
26 from .
import get_items_of_category
27 from .const
import CONF_DIRECTOR, CONTROL4_ENTITY_TYPE, DOMAIN
28 from .director_utils
import update_variables_for_config_entry
29 from .entity
import Control4Entity
31 _LOGGER = logging.getLogger(__name__)
33 CONTROL4_CATEGORY =
"lights"
34 CONTROL4_NON_DIMMER_VAR =
"LIGHT_STATE"
35 CONTROL4_DIMMER_VARS = [
"LIGHT_LEVEL",
"Brightness Percent"]
39 hass: HomeAssistant, entry: ConfigEntry, async_add_entities: AddEntitiesCallback
41 """Set up Control4 lights from a config entry."""
42 entry_data = hass.data[DOMAIN][entry.entry_id]
43 scan_interval = entry_data[CONF_SCAN_INTERVAL]
49 async
def async_update_data_non_dimmer() -> dict[int, dict[str, Any]]:
50 """Fetch data from Control4 director for non-dimmer lights."""
53 hass, entry, {CONTROL4_NON_DIMMER_VAR}
55 except C4Exception
as err:
56 raise UpdateFailed(f
"Error communicating with API: {err}")
from err
58 async
def async_update_data_dimmer() -> dict[int, dict[str, Any]]:
59 """Fetch data from Control4 director for dimmer lights."""
62 hass, entry, {*CONTROL4_DIMMER_VARS}
64 except C4Exception
as err:
65 raise UpdateFailed(f
"Error communicating with API: {err}")
from err
67 non_dimmer_coordinator = DataUpdateCoordinator[dict[int, dict[str, Any]]](
71 update_method=async_update_data_non_dimmer,
72 update_interval=
timedelta(seconds=scan_interval),
74 dimmer_coordinator = DataUpdateCoordinator[dict[int, dict[str, Any]]](
78 update_method=async_update_data_dimmer,
79 update_interval=
timedelta(seconds=scan_interval),
83 await non_dimmer_coordinator.async_refresh()
84 await dimmer_coordinator.async_refresh()
89 for item
in items_of_category:
91 if item[
"type"] == CONTROL4_ENTITY_TYPE:
92 item_name = item[
"name"]
94 item_parent_id = item[
"parentId"]
96 item_manufacturer =
None
97 item_device_name =
None
100 for parent_item
in items_of_category:
101 if parent_item[
"id"] == item_parent_id:
102 item_manufacturer = parent_item[
"manufacturer"]
103 item_device_name = parent_item[
"name"]
104 item_model = parent_item[
"model"]
109 "Unknown device properties received from Control4: %s",
114 if item_id
in dimmer_coordinator.data:
115 item_is_dimmer =
True
116 item_coordinator = dimmer_coordinator
117 elif item_id
in non_dimmer_coordinator.data:
118 item_is_dimmer =
False
119 item_coordinator = non_dimmer_coordinator
121 director = entry_data[CONF_DIRECTOR]
122 item_variables = await director.getItemVariables(item_id)
125 "Couldn't get light state data for %s, skipping setup. Available"
126 " variables from Control4: %s"
151 """Control4 light entity."""
153 _attr_has_entity_name =
True
158 coordinator: DataUpdateCoordinator[dict[int, dict[str, Any]]],
161 device_name: str |
None,
162 device_manufacturer: str |
None,
163 device_model: str |
None,
167 """Initialize Control4 light entity."""
187 """Create a pyControl4 device object.
189 This exists so the director token used is always the latest one, without needing to re-init the entire entity.
191 return C4Light(self.
entry_dataentry_data[CONF_DIRECTOR], self.
_idx_idx)
195 """Return whether this light is on or off."""
197 for var
in CONTROL4_DIMMER_VARS:
198 if var
in self.coordinator.data[self.
_idx_idx]:
199 return self.coordinator.data[self.
_idx_idx][var] > 0
200 raise RuntimeError(
"Dimmer Variable Not Found")
201 return self.coordinator.data[self.
_idx_idx][CONTROL4_NON_DIMMER_VAR] > 0
205 """Return the brightness of this light between 0..255."""
207 for var
in CONTROL4_DIMMER_VARS:
208 if var
in self.coordinator.data[self.
_idx_idx]:
209 return round(self.coordinator.data[self.
_idx_idx][var] * 2.55)
214 """Flag supported features."""
216 return LightEntityFeature.TRANSITION
220 """Turn the entity on."""
223 if ATTR_TRANSITION
in kwargs:
224 transition_length = kwargs[ATTR_TRANSITION] * 1000
226 transition_length = 0
227 if ATTR_BRIGHTNESS
in kwargs:
228 brightness = (kwargs[ATTR_BRIGHTNESS] / 255) * 100
231 await c4_light.rampToLevel(brightness, transition_length)
233 transition_length = 0
234 await c4_light.setLevel(100)
235 if transition_length == 0:
236 transition_length = 1000
237 delay_time = (transition_length / 1000) + 0.7
238 _LOGGER.debug(
"Delaying light update by %s seconds", delay_time)
239 await asyncio.sleep(delay_time)
240 await self.coordinator.async_request_refresh()
243 """Turn the entity off."""
246 if ATTR_TRANSITION
in kwargs:
247 transition_length = kwargs[ATTR_TRANSITION] * 1000
249 transition_length = 0
250 await c4_light.rampToLevel(0, transition_length)
252 transition_length = 0
253 await c4_light.setLevel(0)
254 if transition_length == 0:
255 transition_length = 1500
256 delay_time = (transition_length / 1000) + 0.7
257 _LOGGER.debug(
"Delaying light update by %s seconds", delay_time)
258 await asyncio.sleep(delay_time)
259 await self.coordinator.async_request_refresh()
LightEntityFeature supported_features(self)
_attr_supported_color_modes
def _create_api_object(self)
None async_turn_off(self, **Any kwargs)
None __init__(self, dict entry_data, DataUpdateCoordinator[dict[int, dict[str, Any]]] coordinator, str name, int idx, str|None device_name, str|None device_manufacturer, str|None device_model, int device_id, bool is_dimmer)
None async_turn_on(self, **Any kwargs)
dict[int, dict[str, Any]] update_variables_for_config_entry(HomeAssistant hass, ConfigEntry entry, set[str] variable_names)
None async_setup_entry(HomeAssistant hass, ConfigEntry entry, AddEntitiesCallback async_add_entities)
def get_items_of_category(HomeAssistant hass, ConfigEntry entry, str category)