Skip to content

Commit ec5991b

Browse files
authored
Add support for LIFX 26"x13" Ceiling (home-assistant#148459)
Signed-off-by: Avi Miller <[email protected]>
1 parent 87aecf0 commit ec5991b

File tree

5 files changed

+1437
-1
lines changed

5 files changed

+1437
-1
lines changed

homeassistant/components/lifx/const.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@
7070
}
7171

7272
LIFX_CEILING_PRODUCT_IDS = {176, 177, 201, 202}
73+
LIFX_128ZONE_CEILING_PRODUCT_IDS = {201, 202}
7374

7475
_LOGGER = logging.getLogger(__package__)
7576

homeassistant/components/lifx/coordinator.py

Lines changed: 49 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
DEFAULT_ATTEMPTS,
4242
DOMAIN,
4343
IDENTIFY_WAVEFORM,
44+
LIFX_128ZONE_CEILING_PRODUCT_IDS,
4445
MAX_ATTEMPTS_PER_UPDATE_REQUEST_MESSAGE,
4546
MAX_UPDATE_TIME,
4647
MESSAGE_RETRIES,
@@ -183,6 +184,11 @@ def is_matrix(self) -> bool:
183184
"""Return true if this is a matrix device."""
184185
return bool(lifx_features(self.device)["matrix"])
185186

187+
@cached_property
188+
def is_128zone_matrix(self) -> bool:
189+
"""Return true if this is a 128-zone matrix device."""
190+
return bool(self.device.product in LIFX_128ZONE_CEILING_PRODUCT_IDS)
191+
186192
async def diagnostics(self) -> dict[str, Any]:
187193
"""Return diagnostic information about the device."""
188194
features = lifx_features(self.device)
@@ -216,6 +222,16 @@ async def diagnostics(self) -> dict[str, Any]:
216222
"last_result": self.device.last_hev_cycle_result,
217223
}
218224

225+
if features["matrix"] is True:
226+
device_data["matrix"] = {
227+
"effect": self.device.effect,
228+
"chain": self.device.chain,
229+
"chain_length": self.device.chain_length,
230+
"tile_devices": self.device.tile_devices,
231+
"tile_devices_count": self.device.tile_devices_count,
232+
"tile_device_width": self.device.tile_device_width,
233+
}
234+
219235
if features["infrared"] is True:
220236
device_data["infrared"] = {"brightness": self.device.infrared_brightness}
221237

@@ -291,6 +307,37 @@ def _wrapped_callback(
291307

292308
return calls
293309

310+
@callback
311+
def _async_build_get64_update_requests(self) -> list[Callable]:
312+
"""Build one or more get64 update requests."""
313+
if self.device.tile_device_width == 0:
314+
return []
315+
316+
calls: list[Callable] = []
317+
calls.append(
318+
partial(
319+
self.device.get64,
320+
tile_index=0,
321+
length=1,
322+
x=0,
323+
y=0,
324+
width=self.device.tile_device_width,
325+
)
326+
)
327+
if self.is_128zone_matrix:
328+
# For 128-zone ceiling devices, we need another get64 request for the next set of zones
329+
calls.append(
330+
partial(
331+
self.device.get64,
332+
tile_index=0,
333+
length=1,
334+
x=0,
335+
y=4,
336+
width=self.device.tile_device_width,
337+
)
338+
)
339+
return calls
340+
294341
async def _async_update_data(self) -> None:
295342
"""Fetch all device data from the api."""
296343
device = self.device
@@ -312,9 +359,9 @@ async def _async_update_data(self) -> None:
312359
[
313360
self.device.get_tile_effect,
314361
self.device.get_device_chain,
315-
self.device.get64,
316362
]
317363
)
364+
methods.extend(self._async_build_get64_update_requests())
318365
if self.is_extended_multizone:
319366
methods.append(self.device.get_extended_color_zones)
320367
elif self.is_legacy_multizone:
@@ -339,6 +386,7 @@ async def _async_update_data(self) -> None:
339386

340387
if self.is_matrix or self.is_extended_multizone or self.is_legacy_multizone:
341388
self.active_effect = FirmwareEffect[self.device.effect.get("effect", "OFF")]
389+
342390
if self.is_legacy_multizone and num_zones != self.get_number_of_zones():
343391
# The number of zones has changed so we need
344392
# to update the zones again. This happens rarely.

tests/components/lifx/__init__.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,17 @@ def _mocked_ceiling() -> Light:
199199
return bulb
200200

201201

202+
def _mocked_128zone_ceiling() -> Light:
203+
bulb = _mocked_bulb()
204+
bulb.product = 201 # LIFX 26"x13" Ceiling
205+
bulb.effect = {"effect": "OFF"}
206+
bulb.get_tile_effect = MockLifxCommand(bulb)
207+
bulb.set_tile_effect = MockLifxCommand(bulb)
208+
bulb.get64 = MockLifxCommand(bulb)
209+
bulb.get_device_chain = MockLifxCommand(bulb)
210+
return bulb
211+
212+
202213
def _mocked_bulb_old_firmware() -> Light:
203214
bulb = _mocked_bulb()
204215
bulb.host_firmware_version = "2.77"

0 commit comments

Comments
 (0)