lifx-async 4.4.0__py3-none-any.whl → 4.4.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- lifx/devices/matrix.py +73 -21
- lifx/theme/generators.py +8 -2
- {lifx_async-4.4.0.dist-info → lifx_async-4.4.1.dist-info}/METADATA +1 -1
- {lifx_async-4.4.0.dist-info → lifx_async-4.4.1.dist-info}/RECORD +6 -6
- {lifx_async-4.4.0.dist-info → lifx_async-4.4.1.dist-info}/WHEEL +0 -0
- {lifx_async-4.4.0.dist-info → lifx_async-4.4.1.dist-info}/licenses/LICENSE +0 -0
lifx/devices/matrix.py
CHANGED
|
@@ -14,7 +14,6 @@ Terminology:
|
|
|
14
14
|
|
|
15
15
|
from __future__ import annotations
|
|
16
16
|
|
|
17
|
-
import asyncio
|
|
18
17
|
import logging
|
|
19
18
|
import time
|
|
20
19
|
from dataclasses import asdict, dataclass
|
|
@@ -544,6 +543,57 @@ class MatrixLight(Light):
|
|
|
544
543
|
|
|
545
544
|
return result
|
|
546
545
|
|
|
546
|
+
async def get_all_tile_colors(self) -> list[list[HSBK]]:
|
|
547
|
+
"""Get colors for all tiles in the chain.
|
|
548
|
+
|
|
549
|
+
Fetches colors from each tile in the device chain and returns them
|
|
550
|
+
as a list of color lists (one per tile). This is the matrix equivalent
|
|
551
|
+
of MultiZoneLight's get_all_color_zones().
|
|
552
|
+
|
|
553
|
+
Always fetches from device. Tiles are queried sequentially to avoid
|
|
554
|
+
overwhelming the device with concurrent requests.
|
|
555
|
+
|
|
556
|
+
Returns:
|
|
557
|
+
List of color lists, one per tile. Each inner list contains
|
|
558
|
+
the colors for that tile (typically 64 for 8x8 tiles).
|
|
559
|
+
|
|
560
|
+
Raises:
|
|
561
|
+
LifxDeviceNotFoundError: If device is not connected
|
|
562
|
+
LifxTimeoutError: If device does not respond
|
|
563
|
+
LifxUnsupportedCommandError: If device doesn't support this command
|
|
564
|
+
|
|
565
|
+
Example:
|
|
566
|
+
```python
|
|
567
|
+
# Get colors for all tiles
|
|
568
|
+
all_colors = await matrix.get_all_tile_colors()
|
|
569
|
+
print(f"Device has {len(all_colors)} tiles")
|
|
570
|
+
for i, tile_colors in enumerate(all_colors):
|
|
571
|
+
print(f"Tile {i}: {len(tile_colors)} colors")
|
|
572
|
+
|
|
573
|
+
# Flatten to single list if needed
|
|
574
|
+
flat_colors = [c for tile in all_colors for c in tile]
|
|
575
|
+
```
|
|
576
|
+
"""
|
|
577
|
+
# Get device chain (use cached if available)
|
|
578
|
+
if self._device_chain is None:
|
|
579
|
+
device_chain = await self.get_device_chain()
|
|
580
|
+
else:
|
|
581
|
+
device_chain = self._device_chain
|
|
582
|
+
|
|
583
|
+
# Fetch colors from each tile sequentially
|
|
584
|
+
all_colors: list[list[HSBK]] = []
|
|
585
|
+
for tile in device_chain:
|
|
586
|
+
tile_colors = await self.get64(tile_index=tile.tile_index)
|
|
587
|
+
all_colors.append(tile_colors)
|
|
588
|
+
|
|
589
|
+
# Update state if it exists (flatten for state storage)
|
|
590
|
+
if self._state is not None and hasattr(self._state, "tile_colors"):
|
|
591
|
+
flat_colors = [c for tile_colors in all_colors for c in tile_colors]
|
|
592
|
+
self._state.tile_colors = flat_colors
|
|
593
|
+
self._state.last_updated = time.time()
|
|
594
|
+
|
|
595
|
+
return all_colors
|
|
596
|
+
|
|
547
597
|
async def set64(
|
|
548
598
|
self,
|
|
549
599
|
tile_index: int,
|
|
@@ -993,8 +1043,13 @@ class MatrixLight(Light):
|
|
|
993
1043
|
canvas = Canvas()
|
|
994
1044
|
for tile in tiles:
|
|
995
1045
|
canvas.add_points_for_tile((int(tile.user_x), int(tile.user_y)), theme)
|
|
996
|
-
|
|
997
|
-
|
|
1046
|
+
|
|
1047
|
+
# Shuffle and blur ONCE after all points are added
|
|
1048
|
+
# (Previously these were inside the loop, causing earlier tiles' points
|
|
1049
|
+
# to be shuffled/blurred multiple times, displacing them from their
|
|
1050
|
+
# intended positions and losing theme color variety)
|
|
1051
|
+
canvas.shuffle_points()
|
|
1052
|
+
canvas.blur_by_distance()
|
|
998
1053
|
|
|
999
1054
|
# Create tile canvas and fill in gaps for smooth interpolation
|
|
1000
1055
|
tile_canvas = Canvas()
|
|
@@ -1068,7 +1123,7 @@ class MatrixLight(Light):
|
|
|
1068
1123
|
async def refresh_state(self) -> None:
|
|
1069
1124
|
"""Refresh matrix light state from hardware.
|
|
1070
1125
|
|
|
1071
|
-
Fetches color, tiles, tile colors, and effect.
|
|
1126
|
+
Fetches color, tiles, tile colors for all tiles, and effect.
|
|
1072
1127
|
|
|
1073
1128
|
Raises:
|
|
1074
1129
|
RuntimeError: If state has not been initialized
|
|
@@ -1077,15 +1132,12 @@ class MatrixLight(Light):
|
|
|
1077
1132
|
"""
|
|
1078
1133
|
await super().refresh_state()
|
|
1079
1134
|
|
|
1080
|
-
# Fetch all matrix light state
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
effect_task = tg.create_task(self.get_effect())
|
|
1084
|
-
|
|
1085
|
-
tile_colors = colors_task.result()
|
|
1086
|
-
effect = effect_task.result()
|
|
1135
|
+
# Fetch all matrix light state sequentially to avoid overwhelming device
|
|
1136
|
+
all_tile_colors = await self.get_all_tile_colors()
|
|
1137
|
+
effect = await self.get_effect()
|
|
1087
1138
|
|
|
1088
|
-
|
|
1139
|
+
# Flatten tile colors for state storage
|
|
1140
|
+
self._state.tile_colors = [c for tile in all_tile_colors for c in tile]
|
|
1089
1141
|
self._state.effect = effect.effect_type
|
|
1090
1142
|
|
|
1091
1143
|
async def _initialize_state(self) -> MatrixLightState:
|
|
@@ -1103,24 +1155,24 @@ class MatrixLight(Light):
|
|
|
1103
1155
|
"""
|
|
1104
1156
|
light_state = await super()._initialize_state()
|
|
1105
1157
|
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
tile_colors_task = tg.create_task(self.get64())
|
|
1109
|
-
effect_task = tg.create_task(self.get_effect())
|
|
1110
|
-
|
|
1111
|
-
chain = chain_task.result()
|
|
1158
|
+
# Fetch matrix-specific state sequentially to avoid overwhelming device
|
|
1159
|
+
chain = await self.get_device_chain()
|
|
1112
1160
|
tile_orientations = {
|
|
1113
1161
|
index: tile.nearest_orientation for index, tile in enumerate(chain)
|
|
1114
1162
|
}
|
|
1115
|
-
|
|
1116
|
-
|
|
1163
|
+
# get_all_tile_colors uses cached chain from above
|
|
1164
|
+
all_tile_colors = await self.get_all_tile_colors()
|
|
1165
|
+
effect = await self.get_effect()
|
|
1166
|
+
|
|
1167
|
+
# Flatten tile colors for state storage
|
|
1168
|
+
flat_tile_colors = [c for tile in all_tile_colors for c in tile]
|
|
1117
1169
|
|
|
1118
1170
|
# Create state instance with matrix fields
|
|
1119
1171
|
self._state = MatrixLightState.from_light_state(
|
|
1120
1172
|
light_state,
|
|
1121
1173
|
chain=chain,
|
|
1122
1174
|
tile_orientations=tile_orientations,
|
|
1123
|
-
tile_colors=
|
|
1175
|
+
tile_colors=flat_tile_colors,
|
|
1124
1176
|
effect=effect.effect_type,
|
|
1125
1177
|
)
|
|
1126
1178
|
|
lifx/theme/generators.py
CHANGED
|
@@ -165,10 +165,16 @@ class MatrixGenerator:
|
|
|
165
165
|
shuffled_theme = theme.shuffled()
|
|
166
166
|
shuffled_theme.ensure_color()
|
|
167
167
|
|
|
168
|
+
# Add points for all tiles first
|
|
168
169
|
for (left_x, top_y), (width, height) in self.coords_and_sizes:
|
|
169
170
|
canvas.add_points_for_tile((left_x, top_y), shuffled_theme)
|
|
170
|
-
|
|
171
|
-
|
|
171
|
+
|
|
172
|
+
# Shuffle and blur ONCE after all points are added
|
|
173
|
+
# (Previously these were inside the loop, causing earlier tiles' points
|
|
174
|
+
# to be shuffled/blurred multiple times, displacing them from their
|
|
175
|
+
# intended positions and losing theme color variety)
|
|
176
|
+
canvas.shuffle_points()
|
|
177
|
+
canvas.blur_by_distance()
|
|
172
178
|
|
|
173
179
|
# Create tile canvas and fill gaps
|
|
174
180
|
tile_canvas = Canvas()
|
|
@@ -9,7 +9,7 @@ lifx/devices/base.py,sha256=x2RlGeCv60QLKklP6kA9wbCc3rmcHHhmvkSJHqTow5s,63151
|
|
|
9
9
|
lifx/devices/hev.py,sha256=T5hvt2q_vdgPBvThx_-M7n5pZu9pL0y9Fs3Zz_KL0NM,15588
|
|
10
10
|
lifx/devices/infrared.py,sha256=ePk9qxX_s-hv5gQMvio1Vv8FYiCd68HF0ySbWgSrvuU,8130
|
|
11
11
|
lifx/devices/light.py,sha256=gk92lhViUWINGaxDWbs4qn8Stnn2fGCfRkC5Kk0Q-hI,34087
|
|
12
|
-
lifx/devices/matrix.py,sha256=
|
|
12
|
+
lifx/devices/matrix.py,sha256=8Z0FbBGUzRhvqs3h9fL9ZQ691C9mAoA6kuOrhe89Qwk,41061
|
|
13
13
|
lifx/devices/multizone.py,sha256=8OJ6zP5xgSCmlMQDj2mLUZ352EMkbYMbDZ1X-Cux7AU,32786
|
|
14
14
|
lifx/effects/__init__.py,sha256=4DF31yp7RJic5JoltMlz5dCtF5KQobU6NOUtLUKkVKE,1509
|
|
15
15
|
lifx/effects/base.py,sha256=YO0Hbg2VYHKPtfYnWxmrtzYoPGOi9BUXhn8HVFKv5IM,10283
|
|
@@ -37,10 +37,10 @@ lifx/protocol/protocol_types.py,sha256=m15A82zVrwAXomTqo-GfNmAIynVRDSV94UqHDkWgi
|
|
|
37
37
|
lifx/protocol/serializer.py,sha256=Cl87-Y8_LnvqFANjorJK2CMoRtBGksB_Eq07xHMTqH0,10387
|
|
38
38
|
lifx/theme/__init__.py,sha256=dg4Y25dYq22EemFyxQ1fyb3D_bP2hhxGCd9BE1g_hvk,1320
|
|
39
39
|
lifx/theme/canvas.py,sha256=4h7lgN8iu_OdchObGDgbxTqQLCb-FRKC-M-YCWef_i4,8048
|
|
40
|
-
lifx/theme/generators.py,sha256=
|
|
40
|
+
lifx/theme/generators.py,sha256=nq3Yvntq_h-eFHbmmow3LcAdA_hEbRRaP5mv9Bydrjk,6435
|
|
41
41
|
lifx/theme/library.py,sha256=tKlKZNqJp8lRGDnilWyDm_Qr1vCRGGwuvWVS82anNpQ,21326
|
|
42
42
|
lifx/theme/theme.py,sha256=qMEx_8E41C0Cc6f083XHiAXEglTv4YlXW0UFsG1rQKg,5521
|
|
43
|
-
lifx_async-4.4.
|
|
44
|
-
lifx_async-4.4.
|
|
45
|
-
lifx_async-4.4.
|
|
46
|
-
lifx_async-4.4.
|
|
43
|
+
lifx_async-4.4.1.dist-info/METADATA,sha256=GPXITqP1r-6RIp91S1SuabkN4ie0cJxMvM498v3AKwg,2609
|
|
44
|
+
lifx_async-4.4.1.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
|
|
45
|
+
lifx_async-4.4.1.dist-info/licenses/LICENSE,sha256=eBz48GRA3gSiWn3rYZAz2Ewp35snnhV9cSqkVBq7g3k,1832
|
|
46
|
+
lifx_async-4.4.1.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|