Effects Reference¶
This reference guide provides comprehensive documentation for all built-in effect classes in the Light Effects Framework.
Table of Contents¶
- Conductor
- EffectPulse
- EffectColorloop
- EffectRainbow
- EffectFlame
- EffectAurora
- EffectProgress
- EffectSunrise
- EffectSunset
- EffectRegistry
- FrameEffect (Base Class)
- LIFXEffect (Base Class)
Conductor¶
The Conductor class is the central orchestrator for managing light effects across multiple devices.
Class Definition¶
Methods¶
effect(light: Light) -> LIFXEffect | None¶
Return the effect currently running on a device, or None if idle.
Parameters:
light(Light): The device to check
Returns:
LIFXEffect | None: Currently running effect instance, or None
Example:
current_effect = conductor.effect(light)
if current_effect:
print(f"Running: {type(current_effect).__name__}")
else:
print("No effect running")
start(effect: LIFXEffect, participants: list[Light]) -> None¶
Start an effect on one or more lights.
Captures current light state, powers on if needed, and launches the effect. State is automatically restored when effect completes or stop() is called.
Parameters:
effect(LIFXEffect): The effect instance to executeparticipants(list[Light]): List of Light instances to apply effect to
Raises:
LifxTimeoutError: If light state capture times outLifxDeviceNotFoundError: If light becomes unreachable
Example:
stop(lights: list[Light]) -> None¶
Stop effects and restore light state.
Halts any running effects on the specified lights and restores them to their pre-effect state (power, color, zones).
Parameters:
lights(list[Light]): List of lights to stop
Example:
# Stop specific lights
await conductor.stop([light1, light2])
# Stop all lights in a group
await conductor.stop(group.lights)
add_lights(effect: LIFXEffect, lights: list[Light]) -> None¶
Add lights to a running effect without restarting it. Captures state, creates animators (for FrameEffects), and registers lights as participants. Incompatible or already-running lights are skipped.
Parameters:
effect(LIFXEffect): The effect to add lights to (must already be running)lights(list[Light]): List of lights to add
Example:
remove_lights(lights: list[Light], restore_state: bool = True) -> None¶
Remove lights from their running effect without stopping other participants. Closes animators, optionally restores state, and deregisters lights. If the last participant is removed, cancels the background task.
Parameters:
lights(list[Light]): List of lights to removerestore_state(bool): Whether to restore pre-effect state (defaultTrue)
Example:
# Remove and restore state
await conductor.remove_lights([light1])
# Remove without restoring
await conductor.remove_lights([light2], restore_state=False)
get_last_frame(light: Light) -> list[HSBK] | None¶
Return the most recent HSBK frame sent to a device. For frame-based effects, returns the list of HSBK colors from the most recent generate_frame() call. Returns None if no frame-based effect is running on the device.
Parameters:
light(Light): The device to query
Returns:
list[HSBK] | None: Most recent frame colors, or None
Example:
colors = conductor.get_last_frame(light)
if colors:
avg_brightness = sum(c.brightness for c in colors) / len(colors)
print(f"Average brightness: {avg_brightness:.1%}")
State Management¶
The conductor automatically handles:
- State Capture: Power state, current color (HSBK), and multizone colors (if applicable)
- Power Management: Powers on devices if needed for effect visibility
- Effect Execution: Runs effect logic on all participants
- State Restoration: Restores all captured state after effect completes
Timing Considerations¶
- State capture: <1 second per device (mostly network I/O)
- State restoration: 0.6-1.0 seconds per device (includes required 0.3s delays)
- All operations use concurrent execution for multiple devices
EffectPulse¶
Pulse/blink/breathe effects using LIFX waveform modes. Supports five distinct modes with configurable timing and colors.
Class Definition¶
from lifx import EffectPulse, HSBK
effect = EffectPulse(
power_on=True,
mode='blink',
period=None,
cycles=None,
hsbk=None
)
Parameters¶
power_on (bool, default: True)¶
Whether to power on devices during effect. If True, devices that are off will be powered on before the effect starts.
mode (str, default: 'blink')¶
Pulse mode to use. Must be one of:
'blink': Standard on/off toggle'strobe': Rapid flashing'breathe': Smooth breathing effect'ping': Single pulse with asymmetric duty cycle'solid': Minimal brightness variation
period (float | None, default: mode-dependent)¶
Effect period in seconds. If not specified, uses mode default:
'strobe': 0.1 seconds- All others: 1.0 second
cycles (int | None, default: mode-dependent)¶
Number of cycles to execute. If not specified, uses mode default:
'strobe': 10 cycles- All others: 1 cycle
hsbk (HSBK | None, default: None)¶
Optional color override. If provided, this color is used instead of automatic color selection. If None, the effect intelligently selects colors based on mode and device capabilities.
Pulse Modes¶
Blink Mode¶
Standard on/off toggle effect.
Defaults:
- Period: 1.0 second
- Cycles: 1
- Waveform: PULSE
- Behavior: Toggles between current color and off
Example:
# Basic blink - 5 cycles
effect = EffectPulse(mode='blink', cycles=5)
await conductor.start(effect, lights)
await asyncio.sleep(6) # 5 cycles * 1s + buffer
Best for: Notifications, alerts, attention-getting
Strobe Mode¶
Rapid flashing effect.
Defaults:
- Period: 0.1 second
- Cycles: 10
- Waveform: PULSE
- Behavior: Rapid flashing from dark (cold white)
Example:
# Rapid strobe - 20 flashes
effect = EffectPulse(mode='strobe', cycles=20)
await conductor.start(effect, lights)
await asyncio.sleep(3) # 20 * 0.1s + buffer
Best for: Emergency notifications, dramatic effects
Note: Strobe mode starts from dark (0 brightness, cold white) for maximum impact.
Breathe Mode¶
Smooth, gentle breathing effect using SINE waveform.
Defaults:
- Period: 1.0 second
- Cycles: 1
- Waveform: SINE (smooth)
- Behavior: Smooth fade in and out
Example:
# Slow breathing effect
effect = EffectPulse(mode='breathe', period=2.0, cycles=5)
await conductor.start(effect, lights)
await asyncio.sleep(11) # 5 * 2s + buffer
Best for: Relaxation, meditation, ambient effects
Ping Mode¶
Single pulse with asymmetric duty cycle.
Defaults:
- Period: 1.0 second
- Cycles: 1
- Waveform: PULSE
- Skew: 0.1 (10% on, 90% off)
- Behavior: Quick flash followed by longer off period
Example:
# Quick ping notification
red = HSBK.from_rgb(255, 0, 0)
effect = EffectPulse(mode='ping', color=red)
await conductor.start(effect, lights)
await asyncio.sleep(2)
Best for: Quick notifications, heartbeat effects
Solid Mode¶
Minimal brightness variation, almost solid color.
Defaults:
- Period: 1.0 second
- Cycles: 1
- Waveform: PULSE
- Skew: 0.0 (minimum variation)
- Behavior: Very subtle brightness change
Example:
# Subtle solid pulse
green = HSBK.from_rgb(0, 255, 0)
effect = EffectPulse(mode='solid', period=3.0, cycles=2, color=green)
await conductor.start(effect, lights)
await asyncio.sleep(7)
Best for: Subtle ambient effects, status indicators
Color Selection¶
With color Parameter¶
When you provide a color parameter, that exact color is used:
Without color Parameter (Automatic)¶
The effect intelligently selects colors based on mode and device:
- Strobe mode: Starts from dark (cold white, 0 brightness)
- Other modes: Preserves current device color
- Color devices: Full HSBK color used
- Monochrome devices: Brightness toggled, kelvin preserved
Device Type Behavior¶
Color Lights¶
All modes work as expected with full color support.
Multizone Lights¶
Pulse effects apply to entire device, not individual zones. All zones pulse together.
Tile Devices¶
Pulse effects apply to all tiles uniformly.
Monochrome/White Lights¶
Effects adapt to brightness changes only:
- Color components are ignored
- Brightness is toggled or faded
- Kelvin temperature is preserved
Examples¶
Custom Color Pulse¶
from lifx import HSBK
# Purple breathe effect
purple = HSBK.from_rgb(128, 0, 128)
effect = EffectPulse(
mode='breathe',
period=2.0,
cycles=3,
hsbk=purple
)
await conductor.start(effect, lights)
await asyncio.sleep(7)
Emergency Alert¶
# Rapid red strobe
red = HSBK.from_rgb(255, 0, 0)
effect = EffectPulse(
mode='strobe',
period=0.1,
cycles=30,
hsbk=red
)
await conductor.start(effect, lights)
await asyncio.sleep(4)
Meditation Breathing¶
# Slow blue breathing
blue = HSBK.from_rgb(0, 50, 200)
effect = EffectPulse(
mode='breathe',
period=4.0, # 4 second cycle
cycles=10,
hsbk=blue
)
await conductor.start(effect, lights)
await asyncio.sleep(42) # 10 * 4s + buffer
Performance Notes¶
- Effect starts within 100ms
- Duration is precisely
period * cycles - State restoration adds 0.6-1.0 seconds after completion
- Multiple devices execute concurrently
EffectColorloop¶
Continuous color rotation effect cycling through the hue spectrum. Runs indefinitely until manually stopped.
Class Definition¶
from lifx import EffectColorloop
effect = EffectColorloop(
power_on=True,
period=60,
change=20,
spread=30,
brightness=None,
saturation_min=0.8,
saturation_max=1.0,
synchronized=False
)
EffectColorloop is a FrameEffect that uses the animation module for high-performance direct UDP frame delivery. The Conductor automatically creates Animators for each participant device (Light, MultiZoneLight, or MatrixLight) and drives the frame loop.
Parameters¶
power_on (bool, default: True)¶
Whether to power on devices if they're off.
period (float, default: 60)¶
Seconds per full 360-degree hue cycle. Lower values = faster color changes.
Range: Must be positive
Examples:
period=60: One full rainbow per minute (slow)period=30: Two full rainbows per minute (medium)period=15: Four full rainbows per minute (fast)
change (float, default: 20)¶
Hue degrees to shift per iteration. Larger values = larger color jumps.
Range: 0-360 degrees
Examples:
change=10: Small, smooth color transitionschange=20: Medium color steps (default)change=45: Large, dramatic color jumps
Calculation: iterations_per_cycle = 360 / change
spread (float, default: 30)¶
Hue degrees spread across devices. Creates rainbow effect across multiple lights.
Range: 0-360 degrees
Examples:
spread=0: All lights same colorspread=30: Slight color variation (default)spread=60: Rainbow spread across devicesspread=120: Wide spectrum spread
brightness (float | None, default: None)¶
Fixed brightness level. If None, preserves current brightness for each device.
Range: 0.0-1.0
Examples:
brightness=None: Keeps original brightness (default)brightness=0.5: Locks to 50% brightnessbrightness=1.0: Full brightness
saturation_min (float, default: 0.8)¶
Minimum saturation for random saturation selection.
Range: 0.0-1.0
Must be ≤ saturation_max
saturation_max (float, default: 1.0)¶
Maximum saturation for random saturation selection.
Range: 0.0-1.0
Must be ≥ saturation_min
Note: Each iteration randomly selects saturation within this range.
synchronized (bool, default: False)¶
If True, all lights display the same color simultaneously with consistent transitions. When False, lights are spread across the hue spectrum based on the spread parameter.
Examples:
synchronized=False: Lights show different colors based on spread (default)synchronized=True: All lights change together in unison
transition (float | None, default: None)¶
Deprecated. This parameter is accepted for backward compatibility but has no effect. Frame timing is now handled automatically by the animation module, which calculates smooth firmware-level interpolation between frames based on the effect's FPS.
Behavior¶
Continuous Operation¶
ColorLoop effects run indefinitely until explicitly stopped:
effect = EffectColorloop(period=30)
await conductor.start(effect, lights)
# Runs forever until you call:
await conductor.stop(lights)
Random Elements¶
For visual variety, ColorLoop randomizes:
- Initial direction: Forward or backward through hue spectrum
- Saturation: Random value between saturation_min and saturation_max (spread mode only; synchronized mode uses midpoint)
Hue Calculation¶
Hue rotation is time-based, computed from elapsed time:
degrees_rotated = (elapsed_s / period) * 360.0 * direction
# Spread mode (per device):
new_hue = (base_hue + degrees_rotated + device_index * spread) % 360
# Synchronized mode (all devices):
new_hue = (base_hue + degrees_rotated) % 360
The FPS is automatically calculated from period and change: fps = max(1.0, (360 / change) / period)
Device Type Behavior¶
As a FrameEffect, ColorLoop works across all device types via the animation module:
Color Lights¶
Full color cycling with all parameters supported. Uses LightPacketGenerator for direct UDP delivery.
Multizone Lights¶
Entire device cycles as one unit (all zones set to same color per frame). Uses MultiZonePacketGenerator.
Matrix Lights (Tile/Candle/Path)¶
All pixels cycle together with same color per frame. Uses MatrixPacketGenerator for multi-tile canvas delivery.
Monochrome/White Lights¶
- Filtered out by
is_light_compatible()— ColorLoop requires color capability - Recommendation: Don't use ColorLoop on monochrome devices
Examples¶
Classic Rainbow¶
# Slow rainbow across multiple lights
effect = EffectColorloop(
period=60, # Full rainbow per minute
change=20, # Smooth color steps
spread=60 # Spread colors across devices
)
await conductor.start(effect, lights)
await asyncio.sleep(120) # Run for 2 minutes
await conductor.stop(lights)
Fast Party Mode¶
# Fast, dramatic color changes
effect = EffectColorloop(
period=15, # Fast rotation
change=45, # Large color jumps
spread=120, # Wide spread
brightness=0.8, # Fixed brightness
saturation_min=0.9, # High saturation only
)
await conductor.start(effect, lights)
await asyncio.sleep(60)
await conductor.stop(lights)
Ambient Pastels¶
# Subtle pastel color cycling
effect = EffectColorloop(
period=90, # Very slow
change=15, # Small steps
spread=30, # Slight variation
brightness=0.4, # Dim
saturation_min=0.3, # Low saturation (pastels)
saturation_max=0.6,
)
await conductor.start(effect, lights)
# Let it run indefinitely
Stopping ColorLoop¶
Always explicitly stop ColorLoop effects:
# Start effect
effect = EffectColorloop(period=30)
await conductor.start(effect, lights)
# Do other things...
await asyncio.sleep(60)
# Must stop manually
await conductor.stop(lights)
The conductor.stop() call will:
- Signal the effect to stop
- Wait for current iteration to complete
- Restore all lights to pre-effect state (power, color, zones)
Prestate Inheritance¶
ColorLoop effects support state inheritance optimization. If you start a ColorLoop while another ColorLoop is already running, the new effect inherits the existing prestate instead of resetting:
# Start first colorloop
effect1 = EffectColorloop(period=30, change=20)
await conductor.start(effect1, lights)
await asyncio.sleep(10)
# Switch to different colorloop - no reset, seamless transition
effect2 = EffectColorloop(period=20, change=30)
await conductor.start(effect2, lights) # Inherits state, no flash
This prevents the lights from briefly returning to their original state between consecutive ColorLoop effects.
Performance Notes¶
- Frame interval:
1 / fpswherefps = max(1.0, (360 / change) / period) - Frame delivery: Direct UDP via animation module (no connection overhead)
- Smooth transitions: Firmware interpolates between frames using
duration_ms = 1000 / fps - State capture: <1 second per device
- Effect startup: <100ms
- Multiple devices update concurrently
- No cycle limit - runs until stopped
EffectRainbow¶
Animated rainbow effect that spreads a full 360-degree rainbow across device pixels and scrolls it over time. Best on multizone strips and matrix lights where per-pixel variation creates a beautiful scrolling rainbow. Runs indefinitely until stopped.
Class Definition¶
from lifx import EffectRainbow
effect = EffectRainbow(
power_on=True,
period=10.0,
brightness=0.8,
saturation=1.0,
spread=0.0
)
EffectRainbow is a FrameEffect that generates per-pixel rainbow colors.
Parameters¶
| Parameter | Type | Default | Description |
|---|---|---|---|
power_on |
bool |
True |
Power on devices if off |
period |
float |
10.0 |
Seconds per full rainbow scroll. Must be positive. |
brightness |
float |
0.8 |
Fixed brightness 0.0-1.0 |
saturation |
float |
1.0 |
Fixed saturation 0.0-1.0 |
spread |
float |
0.0 |
Hue degrees offset between devices 0-360 |
Device Compatibility¶
- Color Lights: Cycles through hue (similar to a simpler colorloop)
- Multizone Lights: Full rainbow spread across all zones, scrolling
- Matrix Lights: Full rainbow spread across all pixels, scrolling
Requires color capability. Monochrome lights are filtered out by is_light_compatible().
Examples¶
# Slow rainbow on a strip
effect = EffectRainbow(period=20, brightness=0.6)
await conductor.start(effect, lights)
# Multiple devices offset by 90 degrees
effect = EffectRainbow(period=10, spread=90)
await conductor.start(effect, lights)
await asyncio.sleep(60)
await conductor.stop(lights)
EffectFlame¶
Fire/candle flicker effect using layered sine waves for organic brightness variation. Produces warm colors from deep red to yellow. On matrix devices, applies vertical brightness falloff so bottom rows glow hotter. Runs indefinitely until stopped.
Class Definition¶
from lifx import EffectFlame
effect = EffectFlame(
power_on=True,
intensity=0.7,
speed=1.0,
kelvin_min=1500,
kelvin_max=2500,
brightness=0.8
)
Parameters¶
| Parameter | Type | Default | Description |
|---|---|---|---|
power_on |
bool |
True |
Power on devices if off |
intensity |
float |
0.7 |
Flicker intensity 0.0-1.0. Higher values create more dramatic variation. |
speed |
float |
1.0 |
Animation speed multiplier. Must be positive. |
kelvin_min |
int |
1500 |
Minimum color temperature (>= 1500) |
kelvin_max |
int |
2500 |
Maximum color temperature (<= 9000, >= kelvin_min) |
brightness |
float |
0.8 |
Base brightness 0.0-1.0 |
Device Compatibility¶
- Color Lights: Flickering candle effect (single pixel)
- Multizone Lights: Fire along the strip with per-zone variation
- Matrix Lights: 2D fire with vertical gradient — bottom rows are hotter
Requires color capability.
Examples¶
# Gentle candle on a single bulb
effect = EffectFlame(intensity=0.5, speed=0.8)
await conductor.start(effect, lights)
# Intense bonfire on matrix tiles
effect = EffectFlame(intensity=1.0, speed=2.0, brightness=1.0)
await conductor.start(effect, [tile_light])
await asyncio.sleep(60)
await conductor.stop(lights)
EffectAurora¶
Northern lights simulation with flowing colored bands. Uses palette interpolation and sine waves to create flowing aurora-like patterns. Best on multizone strips and matrix lights. Runs indefinitely until stopped.
Class Definition¶
from lifx import EffectAurora
effect = EffectAurora(
power_on=True,
speed=1.0,
brightness=0.8,
palette=None, # defaults to green/cyan/blue/purple/magenta
spread=0.0
)
Parameters¶
| Parameter | Type | Default | Description |
|---|---|---|---|
power_on |
bool |
True |
Power on devices if off |
speed |
float |
1.0 |
Animation speed multiplier. Must be positive. |
brightness |
float |
0.8 |
Base brightness 0.0-1.0 |
palette |
list[int] \| None |
None |
List of hue values (0-360) defining aurora colors. Must have >= 2 entries. Default: [120, 160, 200, 260, 290] (green/cyan/blue/purple/magenta). |
spread |
float |
0.0 |
Hue degrees offset between devices 0-360 |
Device Compatibility¶
- Color Lights: Slow color drift (underwhelming on single pixel)
- Multizone Lights: Flowing colored bands across the strip
- Matrix Lights: Flowing bands with vertical brightness gradient (brightest in middle rows, like aurora hanging from the sky)
Requires color capability.
Examples¶
# Default aurora
effect = EffectAurora()
await conductor.start(effect, lights)
# Custom warm palette (magenta/pink tones)
effect = EffectAurora(palette=[280, 300, 320, 340])
await conductor.start(effect, lights)
# Multi-device with spread
effect = EffectAurora(spread=45, brightness=0.6)
await conductor.start(effect, lights)
await asyncio.sleep(120)
await conductor.stop(lights)
EffectProgress¶
Animated progress bar for multizone lights (strips/beams). Displays a filled/unfilled bar where the filled region has a traveling bright spot. The position attribute is mutable — update it at any time and the bar grows/shrinks on the next frame. Runs indefinitely until stopped.
Multizone only — requires has_multizone capability.
Class Definition¶
from lifx import EffectProgress, HSBK, Colors
effect = EffectProgress(
power_on=True,
start_value=0.0,
end_value=100.0,
position=0.0,
foreground=Colors.GREEN,
background=HSBK(0, 0.0, 0.05, 3500),
spot_brightness=1.0,
spot_width=0.15,
spot_speed=1.0
)
Parameters¶
| Parameter | Type | Default | Description |
|---|---|---|---|
power_on |
bool |
True |
Power on devices if off |
start_value |
float |
0.0 |
Start of value range (must be < end_value) |
end_value |
float |
100.0 |
End of value range (must be > start_value) |
position |
float |
0.0 |
Initial progress position (mutable at runtime) |
foreground |
HSBK \| list[HSBK] \| None |
Colors.GREEN |
Color or gradient of filled region. Pass a single HSBK for solid, or a list of >= 2 HSBK stops for a gradient. |
background |
HSBK \| None |
dim neutral | Color of unfilled region |
spot_brightness |
float |
1.0 |
Peak brightness of traveling spot 0.0-1.0 |
spot_width |
float |
0.15 |
Spot width as fraction of bar 0.0-1.0 |
spot_speed |
float |
1.0 |
Spot oscillation speed in cycles/sec. Must be positive. |
Dynamic Position Update¶
Since generate_frame() reads self.position each frame, changes are picked up immediately (asyncio single-threaded safety):
effect = EffectProgress(foreground=Colors.BLUE, end_value=100)
await conductor.start(effect, [strip])
# Update from your application
effect.position = 45.0 # 45% complete
await asyncio.sleep(5)
effect.position = 80.0 # 80% complete
Gradient Foreground¶
Pass a list of HSBK stops for a gradient that reveals progressively as the bar grows:
gradient = [
HSBK(hue=240, saturation=1.0, brightness=0.8, kelvin=3500), # blue
HSBK(hue=120, saturation=1.0, brightness=0.8, kelvin=3500), # green
HSBK(hue=0, saturation=1.0, brightness=0.8, kelvin=3500), # red
]
effect = EffectProgress(foreground=gradient, end_value=100)
Device Compatibility¶
- Multizone Lights: Full progress bar with traveling spot
- Color Lights / Matrix Lights: Not supported
EffectSunrise¶
Sunrise effect that transitions from night to daylight over a configurable duration. Simulates a radial sun expansion from a configurable origin point, progressing through night, dawn, golden hour, morning, and daylight phases.
Matrix only — requires has_matrix capability (tiles, candles, Ceiling lights).
Class Definition¶
from lifx import EffectSunrise
effect = EffectSunrise(
power_on=True,
duration=60.0,
brightness=1.0,
origin="bottom"
)
Parameters¶
| Parameter | Type | Default | Description |
|---|---|---|---|
power_on |
bool |
True |
Power on devices if off |
duration |
float |
60.0 |
Effect duration in seconds. Must be positive. |
brightness |
float |
1.0 |
Peak brightness at full daylight 0.0-1.0 |
origin |
SunOrigin |
"bottom" |
Sun origin point — "bottom" for center of bottom row (rectangular tiles) or "center" for middle of canvas (round/oval Ceiling lights) |
Behavior¶
- Duration-based: Completes automatically after
durationseconds - No state restoration: Light stays at daylight after completion (the whole point of a sunrise)
- Color phases: Night (deep navy) → Dawn (purple/magenta) → Golden hour (orange/gold) → Morning (yellow) → Daylight (warm white)
- Radial wavefront: Pixels near the origin transition first, creating a sun expanding outward
Origin Parameter¶
The origin parameter controls where the sun rises from:
"bottom"(default): Center of the bottom row. Ideal for rectangular tile arrays where the sun rises from the horizon."center": Middle of the canvas. Ideal for round or oval LIFX Ceiling lights where the sun expands outward from the center.
Examples¶
# 30-minute sunrise for rectangular tiles
effect = EffectSunrise(duration=1800, brightness=1.0)
await conductor.start(effect, [tile_light])
# Sunrise from center for Ceiling lights
effect = EffectSunrise(duration=1800, origin="center")
await conductor.start(effect, [ceiling_light])
EffectSunset¶
Sunset effect that transitions from daylight to night over a configurable duration. Reverses the sunrise progression — daylight through golden hour to night. Optionally powers off the light when complete.
Matrix only — requires has_matrix capability.
Class Definition¶
from lifx import EffectSunset
effect = EffectSunset(
power_on=False,
duration=60.0,
brightness=1.0,
power_off=True,
origin="bottom"
)
Parameters¶
| Parameter | Type | Default | Description |
|---|---|---|---|
power_on |
bool |
False |
Power on devices if off (default False — light should already be on) |
duration |
float |
60.0 |
Effect duration in seconds. Must be positive. |
brightness |
float |
1.0 |
Starting brightness at daylight 0.0-1.0 |
power_off |
bool |
True |
Power off lights when sunset completes |
origin |
SunOrigin |
"bottom" |
Sun origin point — "bottom" or "center" |
Behavior¶
- Duration-based: Completes automatically after
durationseconds - Power off: When
power_off=True, all participant lights are powered off after the last frame - State restoration: Skipped when
power_off=True(light is off). Whenpower_off=False, state is restored normally. - Color phases: Daylight → Morning → Golden hour → Dusk → Night
Examples¶
# 30-minute sunset that powers off the light
effect = EffectSunset(duration=1800, power_off=True)
await conductor.start(effect, [tile_light])
# Sunset from center for Ceiling lights, no power off
effect = EffectSunset(duration=1800, origin="center", power_off=False)
await conductor.start(effect, [ceiling_light])
EffectRegistry¶
Central registry for discovering and querying available effects. Enables consumers like Home Assistant to dynamically find and present available effects based on device type.
Usage¶
get_effect_registry() -> EffectRegistry¶
Returns the default registry pre-populated with all built-in effects. Lazily initialized on first call.
EffectRegistry Methods¶
effects -> list[EffectInfo]¶
Property returning all registered effects.
get_effect(name: str) -> EffectInfo | None¶
Look up an effect by name.
get_effects_for_device(device: Light) -> list[tuple[EffectInfo, DeviceSupport]]¶
Get effects compatible with a specific device instance. Classifies the device automatically and returns RECOMMENDED + COMPATIBLE entries, sorted with RECOMMENDED first.
get_effects_for_device_type(device_type: DeviceType) -> list[tuple[EffectInfo, DeviceSupport]]¶
Get effects compatible with a device type category.
DeviceType Enum¶
| Value | Description |
|---|---|
LIGHT |
Single bulb (Light, InfraredLight, HevLight) |
MULTIZONE |
Strip/beam (MultiZoneLight) |
MATRIX |
Tile/candle/ceiling (MatrixLight, CeilingLight) |
DeviceSupport Enum¶
| Value | Description |
|---|---|
RECOMMENDED |
Optimal visual experience for this device type |
COMPATIBLE |
Works, but may not showcase the effect's full potential |
NOT_SUPPORTED |
Filtered out (not useful on this device type) |
EffectInfo Dataclass¶
@dataclass(frozen=True)
class EffectInfo:
name: str # e.g. "flame"
effect_class: type[LIFXEffect] # e.g. EffectFlame
description: str # Human-readable one-liner
device_support: dict[DeviceType, DeviceSupport] # Per-type support
Built-in Effect Support Matrix¶
| Effect | Light | MultiZone | Matrix |
|---|---|---|---|
| pulse | RECOMMENDED | RECOMMENDED | RECOMMENDED |
| colorloop | RECOMMENDED | COMPATIBLE | COMPATIBLE |
| rainbow | COMPATIBLE | RECOMMENDED | RECOMMENDED |
| flame | RECOMMENDED | RECOMMENDED | RECOMMENDED |
| aurora | COMPATIBLE | RECOMMENDED | RECOMMENDED |
| progress | NOT_SUPPORTED | RECOMMENDED | NOT_SUPPORTED |
| sunrise | NOT_SUPPORTED | NOT_SUPPORTED | RECOMMENDED |
| sunset | NOT_SUPPORTED | NOT_SUPPORTED | RECOMMENDED |
Examples¶
from lifx import get_effect_registry, DeviceType
registry = get_effect_registry()
# List all effects
for info in registry.effects:
print(f"{info.name}: {info.description}")
# Get effects for multizone strips
for info, support in registry.get_effects_for_device_type(DeviceType.MULTIZONE):
print(f"{info.name} ({support.value})")
# Get effects for a specific device
for info, support in registry.get_effects_for_device(my_light):
print(f"{info.name}: {support.value}")
FrameEffect (Base Class)¶
Abstract base class for frame-generator effects. Extends LIFXEffect with a frame loop driven by the animation module. Subclass this to create effects that generate color frames at a fixed FPS.
Class Definition¶
from lifx import FrameEffect, FrameContext, HSBK
class MyEffect(FrameEffect):
def __init__(self, power_on: bool = True):
super().__init__(power_on=power_on, fps=30.0, duration=None)
@property
def name(self) -> str:
return "my_effect"
def generate_frame(self, ctx: FrameContext) -> list[HSBK]:
# Return pixel_count colors
hue = (ctx.elapsed_s * 60) % 360
return [HSBK(hue=hue, saturation=1.0, brightness=0.8, kelvin=3500)] * ctx.pixel_count
Parameters¶
power_on (bool, default: True)¶
Whether to power on devices during effect.
fps (float, default: 30.0)¶
Frames per second. Must be positive. Higher FPS means smoother animation but more network traffic. The Conductor passes duration_ms = 1500 / fps to the Animator so devices smoothly interpolate between frames.
duration (float | None, default: None)¶
Effect duration in seconds. If None, runs indefinitely until stopped. Must be positive if set.
FrameContext¶
Frozen dataclass passed to generate_frame() with timing and layout info:
@dataclass(frozen=True)
class FrameContext:
elapsed_s: float # Seconds since effect started
device_index: int # Index in participants list
pixel_count: int # Number of pixels (1 for light, N for zones, W*H for matrix)
canvas_width: int # Width (pixel_count for 1D, W for matrix)
canvas_height: int # Height (1 for 1D, H for matrix)
Methods¶
generate_frame(ctx: FrameContext) -> list[HSBK] (abstract)¶
Generate a frame of colors for one device. Called once per device per frame. Override this in subclasses.
Parameters:
ctx(FrameContext): Frame context with timing and layout info
Returns:
list[HSBK]: Colors matchingctx.pixel_count
async_setup(participants: list[Light]) -> None¶
Optional hook called before the frame loop starts. Override to perform async setup like fetching initial colors.
async_play() -> None¶
Runs the frame loop. Do not override — implement generate_frame() instead.
stop() -> None¶
Signal the frame loop to stop.
close_animators() -> None¶
Close all animators and clear the list. Called by the Conductor during cleanup.
Device Type Support¶
FrameEffect works across all device types via the animation module:
- Light:
Animator.for_light()— 1 pixel via SetColor packets - MultiZoneLight:
Animator.for_multizone()— N pixels via SetExtendedColorZones - MatrixLight:
Animator.for_matrix()— W×H pixels via Set64 packets
Creating Custom FrameEffects¶
See the Custom Effects Guide for detailed instructions.
LIFXEffect (Base Class)¶
Abstract base class for all light effects. Subclass this to create custom effects.
Class Definition¶
from lifx import LIFXEffect
class MyEffect(LIFXEffect):
def __init__(self, power_on: bool = True):
super().__init__(power_on=power_on)
async def async_play(self) -> None:
# Custom effect logic here
pass
Attributes¶
power_on (bool)¶
Whether to power on devices during effect.
conductor (Conductor | None)¶
Reference to the conductor managing this effect. Set automatically by conductor.
participants (list[Light])¶
List of lights participating in the effect. Set automatically by conductor.
Methods¶
async_perform(participants: list[Light]) -> None¶
Perform common setup and play the effect. Called by conductor.
Do not override this method. Override async_play() instead.
async_play() -> None (abstract)¶
Play the effect logic. Override this in subclasses.
This is where you implement your custom effect behavior.
Example:
async def async_play(self) -> None:
# Flash all lights 3 times
for _ in range(3):
await asyncio.gather(*[
light.set_brightness(1.0) for light in self.participants
])
await asyncio.sleep(0.3)
await asyncio.gather(*[
light.set_brightness(0.0) for light in self.participants
])
await asyncio.sleep(0.3)
# Restore via conductor
if self.conductor:
await self.conductor.stop(self.participants)
from_poweroff_hsbk(light: Light) -> HSBK¶
Return startup color when light is powered off.
Override this to customize the color used when powering on a light.
Default behavior: Returns random hue, full saturation, zero brightness, neutral white.
Example:
async def from_poweroff_hsbk(self, light: Light) -> HSBK:
# Always start with red
return HSBK.from_rgb(255, 0, 0, kelvin=KELVIN_NEUTRAL)
inherit_prestate(other: LIFXEffect) -> bool¶
Whether this effect can skip device state restoration.
Override this if your effect can run without resetting when following certain other effects.
Default behavior: Returns False (always reset)
Example:
def inherit_prestate(self, other: LIFXEffect) -> bool:
# Can inherit from same effect type
return type(self) == type(other)
Creating Custom Effects¶
See the Custom Effects Guide for detailed instructions on creating your own effects.
See Also¶
- Getting Started - Basic usage and common patterns
- Custom Effects - Creating your own effects
- Architecture - How the system works
- Troubleshooting - Common issues and solutions