Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
93 changes: 93 additions & 0 deletions flux_led/aiodevice.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,12 @@
STATE_GREEN,
STATE_RED,
STATE_WARM_WHITE,
ExtendedCustomEffectDirection,
ExtendedCustomEffectOption,
ExtendedCustomEffectPattern,
MultiColorEffects,
ScribbleEffect,
ScribbleLED,
)
from .protocol import (
POWER_RESTORE_BYTES_TO_POWER_RESTORE,
Expand Down Expand Up @@ -422,6 +427,94 @@ async def async_set_custom_pattern(
self._generate_custom_patterm(rgb_list, speed, transition_type)
)

async def async_set_extended_custom_effect(
self,
pattern_id: ExtendedCustomEffectPattern | int,
colors: list[tuple[int, int, int]],
speed: int = 50,
density: int = 50,
direction: ExtendedCustomEffectDirection | int = 0x01,
option: ExtendedCustomEffectOption | int = 0x00,
) -> None:
"""Set an extended custom effect on the device.

Only supported on devices using the extended protocol (e.g., 0xB6).

Args:
pattern_id: Pattern ID (1-22 or 101-102). See ExtendedCustomEffectPattern.
colors: List of 1-8 RGB color tuples
speed: Animation speed 0-100 (default 50)
density: Pattern density 0-100 (default 50)
direction: Animation direction (0x01=L->R, 0x02=R->L)
option: Pattern-specific option (default 0)
"""
if not self.supports_extended_custom_effects:
raise ValueError("device does not support extended custom effects")
await self._async_send_msg(
self._generate_extended_custom_effect(
pattern_id, colors, speed, density, direction, option
)
)

async def async_set_custom_segment_colors(
self,
segments: list[tuple[int, int, int] | None],
) -> None:
"""Set custom colors for each segment on the device.

Only supported on devices using the extended protocol (e.g., 0xB6).
Sets static HSV colors for each of 20 segments on the light strip.

Args:
segments: List of up to 20 segment colors. Each is (R, G, B) or None for off.
"""
if not self.supports_extended_custom_effects:
raise ValueError("device does not support extended custom effects")
await self._async_send_msg(self._generate_custom_segment_colors(segments))

async def async_set_scribble(
self,
leds: list[ScribbleLED],
effect: ScribbleEffect | int = ScribbleEffect.STATIC,
direction: ExtendedCustomEffectDirection | int = (
ExtendedCustomEffectDirection.LEFT_TO_RIGHT
),
density: int = 80,
speed: int = 100,
enter_mode: bool = True,
) -> None:
"""Set a per-LED ('scribble') configuration on a 0xB6 device.

Renders every LED via grouped E1 26 paints (one per color/blink group),
covering all N LEDs including an (0,0,0) group for off bulbs. Per-LED
blink/color come from each ScribbleLED. ``effect`` is a ScribbleEffect or
a raw int id 0x00-0x08 (ids 3,4,6,7 are valid effects with no UI name).
When enter_mode is True, first sends one all-zero E1 23 to guarantee
scribble-mode entry from another mode (E1 26 alone also works when
already in scribble). E1 23 does NOT render -- all colors render through
E1 26 (verified on hardware).

Only supported on devices using the extended protocol (e.g., 0xB6).
"""
if not self.supports_scribble:
raise ValueError("device does not support scribble")
num_leds = self.led_count if self.led_count is not None else len(leds)
direction_val = (
direction.value
if isinstance(direction, ExtendedCustomEffectDirection)
else int(direction)
)
# Build (and validate) the paint messages up front so an invalid call
# raises before any network send -- otherwise the E1 23 init would leave
# the device in scribble-init mode with nothing rendered.
paint_msgs = self._scribble_paint_groups(
leds, effect, direction_val, density, speed, num_leds
)
if enter_mode:
await self._async_send_msg(self._generate_scribble_init(num_leds))
for msg in paint_msgs:
await self._async_send_msg(msg)

async def async_set_effect(
self, effect: str, speed: int, brightness: int = 100
) -> None:
Expand Down
Loading
Loading