### Quick Start Example Source: https://github.com/djelibeybi/lifx-async/blob/main/docs/user-guide/ceiling-lights.md Demonstrates basic initialization and setting colors for both downlight and uplight components. ```APIDOC ## Quick Start Example This example shows how to initialize a `CeilingLight` and set colors for its downlight and uplight. ```python from lifx import CeilingLight from lifx.color import HSBK async def main(): async with await CeilingLight.from_ip("192.168.1.100") as ceiling: # Set downlight to warm white await ceiling.set_downlight_colors( HSBK(hue=0, saturation=0, brightness=1.0, kelvin=3000) ) # Set uplight to a dim, warm ambient glow await ceiling.set_uplight_color( HSBK(hue=30, saturation=0.2, brightness=0.3, kelvin=2700) ) ``` ``` -------------------------------- ### Quick Start: Initialize and Control Ceiling Light Source: https://github.com/djelibeybi/lifx-async/blob/main/docs/user-guide/ceiling-lights.md Connect to a Ceiling Light by IP address and set initial colors for both the downlight and uplight components. Ensure the `lifx` library is installed and the device is reachable. ```python from lifx import CeilingLight from lifx.color import HSBK async def main(): async with await CeilingLight.from_ip("192.168.1.100") as ceiling: # Set downlight to warm white await ceiling.set_downlight_colors( HSBK(hue=0, saturation=0, brightness=1.0, kelvin=3000) ) # Set uplight to a dim, warm ambient glow await ceiling.set_uplight_color( HSBK(hue=30, saturation=0.2, brightness=0.3, kelvin=2700) ) ``` -------------------------------- ### Install lifx-async for Development Source: https://github.com/djelibeybi/lifx-async/blob/main/docs/index.md Steps to clone the repository and install dependencies for development using `uv`. ```bash git clone https://github.com/Djelibeybi/lifx-async.git cd lifx-async uv sync ``` -------------------------------- ### Install lifx-async with uv or pip Source: https://github.com/djelibeybi/lifx-async/blob/main/docs/index.md Instructions for installing the lifx-async library using either the `uv` package installer (recommended) or `pip`. ```bash # Using uv (recommended) uv pip install lifx-async # Or using pip pip install lifx-async ``` -------------------------------- ### Install lifx-async using uv Source: https://github.com/djelibeybi/lifx-async/blob/main/docs/getting-started/installation.md Use this command to install the lifx-async package with the uv package installer. Ensure uv is installed first. ```bash uv pip install lifx-async ``` -------------------------------- ### Install lifx-async using pip Source: https://github.com/djelibeybi/lifx-async/blob/main/docs/getting-started/installation.md Standard installation command for lifx-async using pip. ```bash pip install lifx-async ``` -------------------------------- ### Install lifx-async from source using uv Source: https://github.com/djelibeybi/lifx-async/blob/main/docs/getting-started/installation.md Installs the latest development version of lifx-async from its Git repository using uv. Requires git to be installed. ```bash git clone https://github.com/Djelibeybi/lifx-async.git cd lifx-async # Using uv (recommended) uv pip install -e . ``` -------------------------------- ### Install lifx-async with development dependencies using uv Source: https://github.com/djelibeybi/lifx-async/blob/main/docs/getting-started/installation.md Installs lifx-async along with development tools using uv. Recommended for contributors. ```bash git clone https://github.com/Djelibeybi/lifx-async.git cd lifx-async # Using uv (recommended) uv sync ``` -------------------------------- ### Install lifx-async from source using pip Source: https://github.com/djelibeybi/lifx-async/blob/main/docs/getting-started/installation.md Installs the latest development version of lifx-async from its Git repository using pip. Requires git to be installed. ```bash git clone https://github.com/Djelibeybi/lifx-async.git cd lifx-async # Or using pip pip install -e . ``` -------------------------------- ### Install lifx-async with development dependencies using pip Source: https://github.com/djelibeybi/lifx-async/blob/main/docs/getting-started/installation.md Installs lifx-async along with development tools using pip. Recommended for contributors. ```bash git clone https://github.com/Djelibeybi/lifx-async.git cd lifx-async # Or using pip pip install -e ".[dev]" ``` -------------------------------- ### Wave Effect Usage Source: https://github.com/djelibeybi/lifx-async/blob/main/docs/user-guide/effects-custom.md Example of how to use the WaveEffect. Instantiate the effect and start it with a conductor and a list of lights, calculating the total expected runtime. ```python conductor = Conductor() effect = WaveEffect(wave_count=3, wave_speed=0.4) await conductor.start(effect, lights) total_time = 3 * (len(lights) * 0.4 + 0.5) await asyncio.sleep(total_time + 1) ``` -------------------------------- ### Quick Example: Blink Lights with EffectPulse Source: https://github.com/djelibeybi/lifx-async/blob/main/docs/getting-started/effects.md This example demonstrates how to discover lights, create a DeviceGroup, and use the Conductor to run an EffectPulse to blink all lights 5 times. The conductor automatically restores the lights' original state after the effect completes. ```python import asyncio from lifx import discover, DeviceGroup from lifx.effects import Conductor, EffectPulse async def main(): devices = [] async for device in discover(): devices.append(device) group = DeviceGroup(devices) if not group.lights: print("No lights found") return # Create a conductor to manage effects conductor = Conductor() # Blink all lights 5 times effect = EffectPulse(mode='blink', cycles=5) await conductor.start(effect, group.lights) # Wait for effect to complete await asyncio.sleep(6) print("Done - lights restored to original state") asyncio.run(main()) ``` -------------------------------- ### Install uv package installer Source: https://github.com/djelibeybi/lifx-async/blob/main/docs/getting-started/installation.md Commands to install the uv package installer on macOS, Linux, or Windows. Alternatively, uv can be installed using pip. ```bash # On macOS and Linux curl -LsSf https://astral.sh/uv/install.sh | sh ``` ```powershell # On Windows powershell -c "irm https://astral.sh/uv/install.ps1 | iex" ``` ```bash # Or with pip pip install uv ``` -------------------------------- ### Verify lifx-async installation Source: https://github.com/djelibeybi/lifx-async/blob/main/docs/getting-started/installation.md Python code to check if the lifx-async library is installed correctly by printing its version. ```python import lifx print(lifx.__version__) ``` -------------------------------- ### Sync Dependencies with uv Source: https://github.com/djelibeybi/lifx-async/blob/main/CLAUDE.md Use `uv sync` to install all project dependencies, including development ones. Use `--no-dev` to install only the core library dependencies. ```bash uv sync ``` ```bash uv sync --no-dev ``` -------------------------------- ### Start Effect with Await Source: https://github.com/djelibeybi/lifx-async/blob/main/docs/user-guide/effects-troubleshooting.md Ensure effects are started correctly by using the `await` keyword. Missing `await` causes the start command to return immediately without effect. ```python # Wrong - missing await conductor.start(effect, lights) # Returns immediately, nothing happens # Correct await conductor.start(effect, lights) ``` -------------------------------- ### Start a Pulse Effect on Lights Source: https://github.com/djelibeybi/lifx-async/blob/main/docs/user-guide/effects.md Demonstrates how to discover lights, create a Conductor, instantiate an EffectPulse, and start it on a group of lights. Includes waiting for the effect to complete and automatic state restoration. ```python import asyncio from lifx import discover, DeviceGroup from lifx.effects import Conductor, EffectPulse async def main(): # Discover lights on your network devices = [] async for device in discover(): devices.append(device) group = DeviceGroup(devices) if not group.lights: print("No lights found") return # Create a conductor to manage effects conductor = Conductor() # Create a blink effect effect = EffectPulse(mode='blink', cycles=5) # Start the effect on all lights await conductor.start(effect, group.lights) # Wait for effect to complete (5 cycles * 1 second) await asyncio.sleep(6) print("Effect complete - lights restored to original state") asyncio.run(main()) ``` -------------------------------- ### Run Basic Animation with Profiling Source: https://github.com/djelibeybi/lifx-async/blob/main/examples/README.md Executes the basic animation example in profiling mode for synthetic benchmarks. No device is needed for this mode. ```bash uv run python examples/animation_basic.py --profile ``` -------------------------------- ### Check installed packages Source: https://github.com/djelibeybi/lifx-async/blob/main/docs/getting-started/installation.md Command to list installed packages and filter for lifx-async, useful for troubleshooting import errors. Works with both uv and pip. ```bash # Using uv uv pip list | grep lifx-async # Or using pip pip list | grep lifx-async ``` -------------------------------- ### Pattern 3 Usage Example Source: https://github.com/djelibeybi/lifx-async/blob/main/docs/user-guide/effects-custom.md Example of how to instantiate and run a continuous loop effect, then signal it to stop after a delay. ```python effect = RandomColorEffect(interval=2.0) await conductor.start(effect, lights) await asyncio.sleep(30) effect.stop() # Signal to stop ``` -------------------------------- ### Start a ColorLoop Effect on Lights Source: https://github.com/djelibeybi/lifx-async/blob/main/docs/user-guide/effects.md Shows how to set up and run an EffectColorloop, which creates a continuous rainbow effect. It includes discovering devices, initializing the Conductor, configuring the effect parameters (period, change, spread), starting the effect, and stopping it after a duration. ```python import asyncio from lifx import discover, DeviceGroup from lifx.effects import Conductor, EffectColorloop async def main(): devices = [] async for device in discover(): devices.append(device) group = DeviceGroup(devices) if not group.lights: print("No lights found") return conductor = Conductor() # Create a rainbow effect effect = EffectColorloop( period=30, # 30 seconds per full cycle change=20, # Change hue by 20 degrees each step spread=60 # Spread colors across devices ) # Start the effect await conductor.start(effect, group.lights) # Let it run for 2 minutes await asyncio.sleep(120) # Stop and restore lights to original state await conductor.stop(group.lights) asyncio.run(main()) ``` -------------------------------- ### Best Practice: Use DeviceGroup for Organization Source: https://github.com/djelibeybi/lifx-async/blob/main/docs/user-guide/effects.md Organize discovered devices using `DeviceGroup` for convenient access to collections of lights when starting effects. ```python from lifx import discover, DeviceGroup # Discover devices devices = [] async for device in discover(): devices.append(device) group = DeviceGroup(devices) conductor = Conductor() await conductor.start(effect, group.lights) ``` -------------------------------- ### Check Product Registry Source: https://github.com/djelibeybi/lifx-async/blob/main/docs/user-guide/troubleshooting.md Access and query the product registry to get information about known LIFX device models and their capabilities. ```python from lifx.products import get_product, get_registry # List all known products registry = get_registry() for product_id, product in registry.items(): print(f"{product_id}: {product.name}") # Check specific product product = get_product(27) # LIFX A19 if product: print(f"Name: {product.name}") print(f"Capabilities: {product.capabilities}") ``` -------------------------------- ### Find Devices by Label Source: https://github.com/djelibeybi/lifx-async/blob/main/docs/api/high-level.md Finds LIFX devices by their label. The first example finds devices with 'Living' in their label (substring match) and powers them on. The second example finds a device with the exact label 'Living Room', sets its color to warm, and stops searching. ```python from lifx import find_by_label, Colors async def main(): # Find all devices with "Living" in the label (substring match) async for device in find_by_label("Living"): # May match "Living Room", "Living Area", etc. await device.set_power(True) # Find device with exact label match async for device in find_by_label("Living Room", exact_match=True): await device.set_color(Colors.WARM) break # exact_match returns at most one device ``` -------------------------------- ### LIFX Effect Usage Example Source: https://context7.com/djelibeybi/lifx-async/llms.txt Demonstrates how to use both frame-based and imperative effects with the Conductor. This example shows starting and stopping effects, with a timed delay for the frame effect and a self-terminating behavior for the imperative effect. ```python async def main(): lights = [d async for d in discover()] conductor = Conductor() # Frame effect — runs until stopped effect = RollingRainbow(speed=90.0) await conductor.start(effect, lights) await asyncio.sleep(15) await conductor.stop(lights) # Imperative effect — self-terminating await conductor.start(AlertEffect(flashes=8), lights) await asyncio.sleep(3) asyncio.run(main()) ``` -------------------------------- ### Serve Documentation Locally Source: https://github.com/djelibeybi/lifx-async/blob/main/CLAUDE.md Serve the project's documentation locally with hot reload enabled by running `uv run zensical serve`. ```bash uv run zensical serve ``` -------------------------------- ### Flash Effect Usage Source: https://github.com/djelibeybi/lifx-async/blob/main/docs/user-guide/effects-custom.md Example of how to use the FlashEffect. Instantiate the effect and start it with a conductor and a list of lights. ```python conductor = Conductor() effect = FlashEffect(flash_count=10, duration=0.3) await conductor.start(effect, lights) await asyncio.sleep(4) ``` -------------------------------- ### Connect directly to a LIFX device by IP Source: https://github.com/djelibeybi/lifx-async/blob/main/docs/getting-started/installation.md Example of how to connect to a LIFX device directly if its IP address is known, bypassing network discovery. Replace with the actual IP address. ```python from lifx import Light light = Light.from_ip("192.168.1.100") ``` -------------------------------- ### Implement async_setup for Device Initialization Source: https://github.com/djelibeybi/lifx-async/blob/main/docs/user-guide/effects-custom.md Override `async_setup` in a `FrameEffect` subclass to fetch initial device states or perform setup before the effect runs. This is useful for effects that need to adapt to current device colors. ```python class AdaptiveEffect(FrameEffect): """Effect that adapts to current device colors.""" def __init__(self, power_on: bool = True): super().__init__(power_on=power_on, fps=15.0, duration=None) self._base_hues: list[float] = [] @property def name(self) -> str: return "adaptive" async def async_setup(self, participants: list[Light]) -> None: """Fetch initial colors from all devices.""" for light in self.participants: color = await self.fetch_light_color(light) self._base_hues.append(color.hue) def generate_frame(self, ctx: FrameContext) -> list[HSBK]: base_hue = self._base_hues[ctx.device_index] if self._base_hues else 0 hue = (base_hue + ctx.elapsed_s * 20) % 360 return [HSBK(hue=hue, saturation=1.0, brightness=0.8, kelvin=3500)] * ctx.pixel_count ``` -------------------------------- ### Usage of Minimal FlashEffect Source: https://github.com/djelibeybi/lifx-async/blob/main/docs/user-guide/effects-custom.md Example of how to instantiate and run the `FlashEffect` using a `Conductor`. This involves starting the effect and allowing it to run for a specified duration. ```python conductor = Conductor() effect = FlashEffect() await conductor.start(effect, lights) await asyncio.sleep(2) ``` -------------------------------- ### Build Documentation Source: https://github.com/djelibeybi/lifx-async/blob/main/CLAUDE.md Build static documentation files using `uv run zensical build` or `uv run llmstxt-standalone build`. ```bash uv run zensical build ``` ```bash uv run llmstxt-standalone build ``` -------------------------------- ### Good Practice: Using Context Managers Source: https://github.com/djelibeybi/lifx-async/blob/main/docs/api/index.md Illustrates the recommended way to manage device connections using async context managers for automatic cleanup, contrasting it with manual closing. ```python # ✅ Good - automatic cleanup async with await Light.from_ip("192.168.1.100") as light: await light.set_color(Colors.BLUE) # ❌ Bad - no context manager, no state initialization light = Light(serial="d073d5123456", ip="192.168.1.100") await light.set_color(Colors.BLUE) await light.connection.close() ``` -------------------------------- ### Using the Product Registry Source: https://github.com/djelibeybi/lifx-async/blob/main/docs/api/protocol.md Demonstrates how to use the product registry for device detection and capability information. ```APIDOC ### Using the Product Registry This section shows how to utilize the product registry to get device information. ```python from lifx.products import get_product, get_device_class_name # Get product info by product ID product_info = get_product(product_id=27) # Get appropriate device class name class_name = get_device_class_name(product_id=27) # Returns "Light", "MultiZoneLight", etc. ``` ``` -------------------------------- ### Color Manipulation Example Source: https://github.com/djelibeybi/lifx-async/blob/main/docs/api/colors.md Provides an example of how to manipulate color over time, specifically cycling through hues for a light. ```APIDOC ## Color Manipulation ```python from lifx import HSBK, Light async def cycle_hue(light: Light): """Cycle through the color spectrum""" for hue in range(0, 360, 10): color = HSBK(hue=float(hue), saturation=1.0, brightness=0.8, kelvin=3500) await light.set_color(color, duration=0.1) ``` ``` -------------------------------- ### Apply a Theme to LIFX Devices Source: https://github.com/djelibeybi/lifx-async/blob/main/docs/getting-started/themes.md Discover devices, group them, retrieve a theme by name, and apply it with optional power-on and duration settings. Requires an active async event loop. ```python from lifx import discover, DeviceGroup, ThemeLibrary devices = [] async for device in discover(): devices.append(device) group = DeviceGroup(devices) # Get a theme by name and apply it theme = ThemeLibrary.get("evening") await group.apply_theme(theme, power_on=True, duration=1.5) ``` -------------------------------- ### Install lifx-emulator-core Source: https://github.com/djelibeybi/lifx-async/blob/main/CLAUDE.md Installs the lifx-emulator-core as a development dependency. This is required for running integration tests that use the embedded emulator. ```bash uv sync # Installs lifx-emulator-core automatically ``` -------------------------------- ### Best Practice: Using Type Hints for Control Source: https://github.com/djelibeybi/lifx-async/blob/main/docs/api/index.md Demonstrates the use of type hints in function signatures for better code clarity and maintainability when controlling a light device. ```python from lifx import Light, HSBK async def control_light(light: Light) -> str: label: str = await light.get_label() return label ``` -------------------------------- ### Creating Colors Source: https://github.com/djelibeybi/lifx-async/blob/main/docs/api/colors.md Demonstrates how to create colors using built-in presets, custom HSBK values, and RGB values. Also shows how to convert HSBK colors to RGB. ```APIDOC ## Creating Colors ```python from lifx import HSBK, Colors # Use built-in color presets color = Colors.BLUE # Create custom colors custom = HSBK(hue=180.0, saturation=1.0, brightness=0.8, kelvin=3500) # Create from RGB (0.0-1.0) red = HSBK.from_rgb(1.0, 0.0, 0.0) # Convert to RGB (returns 0.0-1.0) r, g, b = Colors.BLUE.to_rgb() print(f"RGB: ({r:.2f}, {g:.2f}, {b:.2f})") ``` ``` -------------------------------- ### Check for Lights Before Starting Effect Source: https://github.com/djelibeybi/lifx-async/blob/main/docs/user-guide/effects-troubleshooting.md Prevent errors by checking if the `lights` list is empty before attempting to start an effect. ```python # Check you have lights if not lights: print("No lights to apply effect to") return await conductor.start(effect, lights) ``` -------------------------------- ### Discover Devices Source: https://github.com/djelibeybi/lifx-async/blob/main/docs/api/network.md This example demonstrates how to discover all LIFX devices on the local network using the `discover_devices` function. It prints the label, IP address, and serial number of each found device. ```APIDOC ## discover_devices ### Description Functions for discovering LIFX devices on the local network. ### Method ```python async def discover_devices(timeout: float = 5.0) ``` ### Parameters #### Query Parameters - **timeout** (float) - Optional - The duration in seconds to wait for device discovery responses. Defaults to 5.0 seconds. ### Response #### Success Response - **devices** (list[DiscoveredDevice]) - A list of DiscoveredDevice objects representing the found LIFX devices. ### Request Example ```python from lifx.network.discovery import discover_devices async def main(): # Discover all devices on the network devices = await discover_devices(timeout=3.0) for device in devices: print(f"Found: {device.label} at {device.ip}") print(f" Serial: {device.serial}") ``` ``` -------------------------------- ### Working with Serial Numbers Example Source: https://github.com/djelibeybi/lifx-async/blob/main/docs/api/protocol.md Example demonstrating the usage of the `Serial` dataclass for type-safe, immutable serial number handling. ```APIDOC ## Working with Serial Numbers The `Serial` dataclass provides type-safe, immutable serial number handling: ```python from lifx.protocol.models import Serial ``` -------------------------------- ### Query Product Registry Source: https://github.com/djelibeybi/lifx-async/blob/main/docs/api/protocol.md Demonstrates how to retrieve product information and device class names using the product registry by product ID. ```python from lifx.products import get_product, get_device_class_name # Get product info by product ID product_info = get_product(product_id=27) # Get appropriate device class name class_name = get_device_class_name(product_id=27) # Returns "Light", "MultiZoneLight", etc. ``` -------------------------------- ### Serve MkDocs Documentation Locally Source: https://github.com/djelibeybi/lifx-async/blob/main/conductor/tracks/_archive/review-docs_20260318/plan.md Serve the MkDocs documentation locally for manual spot-checking and verification. This command allows you to preview changes in a live environment. ```bash uv run mkdocs serve ``` -------------------------------- ### Sequential Effects on Same Devices Source: https://github.com/djelibeybi/lifx-async/blob/main/docs/architecture/effects-architecture.md Start one effect, wait for its duration, then start another on the same devices. State is automatically restored between effects. ```python # Effect 1 completes before Effect 2 starts await conductor.start(effect1, lights) await asyncio.sleep(duration1) await conductor.start(effect2, lights) # Captures new state ``` -------------------------------- ### Send and Request Protocol Packets Source: https://github.com/djelibeybi/lifx-async/blob/main/docs/api/protocol.md Shows how to establish a device connection, send a LightSetColor packet, and request a response with LightGet and LightState. ```python from lifx.network.connection import DeviceConnection from lifx.protocol.packets import LightSetColor, LightGet, LightState from lifx.protocol.protocol_types import LightHsbk from lifx.protocol.models import Serial async def main(): serial = Serial.from_string("d073d5123456") async with DeviceConnection(serial.to_string(), "192.168.1.100") as conn: # Create a packet packet = LightSetColor( reserved=0, color=LightHsbk( hue=240 * 182, saturation=65535, brightness=32768, kelvin=3500 ), duration=1000, # milliseconds ) # Send without waiting for response await conn.send_packet(packet) # Request with response response = await conn.request_response(LightGet(), LightState) print(f"Hue: {response.color.hue / 182}°") ``` -------------------------------- ### Basic Light Control Source: https://github.com/djelibeybi/lifx-async/blob/main/docs/api/devices.md Demonstrates how to turn on a light, set its color, and retrieve its label. ```APIDOC ## Basic Light Control ### Description Turn on a light, set its color to blue, and retrieve its label. ### Method ```python await light.set_power(True) await light.set_color(Colors.BLUE, duration=1.0) label = await light.get_label() ``` ### Parameters - `power` (bool): Whether to turn the light on or off. - `color` (Colors): The color to set the light to. - `duration` (float): The time in seconds over which to transition to the new color. ### Response - `label` (str): The label of the light. ``` -------------------------------- ### Establish and Use a Device Connection Source: https://github.com/djelibeybi/lifx-async/blob/main/docs/architecture/overview.md Shows how to instantiate a DeviceConnection with a serial number and IP address. The connection is established lazily upon the first request, and a response can be awaited. ```python from lifx.network.connection import DeviceConnection conn = DeviceConnection(serial="d073d5123456", ip="192.168.1.100") # Connection opens lazily on first request response = await conn.request(packet) ``` -------------------------------- ### Good Practice: Using Context Managers for Cleanup Source: https://github.com/djelibeybi/lifx-async/blob/main/docs/api/exceptions.md Demonstrates the use of `async with` context managers to ensure resources, such as device connections, are properly cleaned up even when exceptions occur. This prevents resource leaks. ```python # ✅ Good - resources cleaned up even on exception try: async with await Light.from_ip(ip) as light: await light.set_color(Colors.BLUE) except LifxError: print("Error occurred but connection was closed properly") ``` -------------------------------- ### Get All Color Zones Source: https://github.com/djelibeybi/lifx-async/blob/main/docs/architecture/effects-architecture.md Retrieves all zone colors for a MultiZoneLight device. This method automatically selects the most efficient way to get zone data based on device capabilities. ```python if isinstance(light, MultiZoneLight): # Get all zones using the convenience method # Automatically uses the best method based on capabilities zone_colors = await light.get_all_color_zones() ``` -------------------------------- ### Daily Lighting Schedule with Themes Source: https://github.com/djelibeybi/lifx-async/blob/main/docs/user-guide/themes.md Implements a daily lighting schedule by applying different themes at specific times. This example uses a hardcoded schedule and a demo delay; for production, integrate with a scheduler like APScheduler. ```python from lifx import discover, DeviceGroup, ThemeLibrary import asyncio async def daily_lighting_schedule(): devices = [] async for device in discover(): devices.append(device) group = DeviceGroup(devices) schedule = [ ("06:00", "energizing"), # Morning ("12:00", "focusing"), # Afternoon ("18:00", "evening"), # Early evening ("21:00", "relaxing"), # Night ("23:00", "peaceful"), # Bedtime ] for time_str, theme_name in schedule: theme = ThemeLibrary.get(theme_name) await group.apply_theme(theme, duration=2.0) # In production, schedule this with APScheduler or similar await asyncio.sleep(2.0) # Demo delay ``` -------------------------------- ### Start Independent Effects on Multiple Lights Source: https://github.com/djelibeybi/lifx-async/blob/main/docs/user-guide/effects-troubleshooting.md Avoid starting too many concurrent effects on individual lights, as this can lead to choppy or stuttering performance. Consider grouping devices if possible. ```python # 50 devices all running independent effects for light in lights: await conductor.start(effect, [light]) # Too many! ``` -------------------------------- ### Start a Rainbow Effect on Lights Source: https://github.com/djelibeybi/lifx-async/blob/main/docs/user-guide/effects.md Illustrates the use of EffectRainbow to create a scrolling 360-degree rainbow effect, particularly suited for multizone strips and matrix lights. It covers discovering devices, starting the effect with specified period and brightness, and stopping it. ```python import asyncio from lifx import discover, DeviceGroup from lifx.effects import Conductor, EffectRainbow async def main(): devices = [] async for device in discover(): devices.append(device) group = DeviceGroup(devices) if not group.lights: print("No lights found") return conductor = Conductor() # Rainbow that scrolls every 10 seconds effect = EffectRainbow(period=10, brightness=0.8) await conductor.start(effect, group.lights) await asyncio.sleep(30) await conductor.stop(group.lights) asyncio.run(main()) ``` -------------------------------- ### Example: Daytime Productivity Lighting Source: https://github.com/djelibeybi/lifx-async/blob/main/docs/user-guide/ceiling-lights.md Set up lighting for daytime productivity with bright, cool white downlights and the uplight turned off. This mode uses a 1-second transition for the downlights and also turns off the uplight with a 1-second transition. ```python async def daytime_mode(ip: str): async with await CeilingLight.from_ip(ip) as ceiling: # Bright cool downlight for task lighting await ceiling.set_downlight_colors( HSBK(hue=0, saturation=0, brightness=1.0, kelvin=5500), duration=1.0 ) # Turn off uplight during the day await ceiling.turn_uplight_off(duration=1.0) ``` -------------------------------- ### Best Practice: Exception Handling Source: https://github.com/djelibeybi/lifx-async/blob/main/docs/api/index.md Shows how to handle potential LIFX-specific errors using a try-except block. This ensures graceful failure when interacting with devices. ```python from lifx import discover, Colors, LifxError try: async for device in discover(): await device.set_color(Colors.GREEN) except LifxError as e: print(f"LIFX error: {e}") ``` -------------------------------- ### Pattern 2: Sequential Actions in Python Source: https://github.com/djelibeybi/lifx-async/blob/main/docs/user-guide/effects-custom.md Create sequential actions where devices act one after another, like a wave effect. This example lights up devices sequentially with a specified color and delay. ```python async def async_play(self) -> None: """Light up devices sequentially.""" for light in self.participants: await light.set_color(self.color, duration=0.5) await asyncio.sleep(self.delay) if self.conductor: await self.conductor.stop(self.participants) ``` -------------------------------- ### Apply Different Themes by Device Type Source: https://github.com/djelibeybi/lifx-async/blob/main/docs/user-guide/themes.md Applies themes differently based on device type (lights, multi-zone lights, tiles). Single-zone lights get a random color from the theme, while multi-zone lights and tiles get distributed or interpolated colors. ```python from lifx import discover, DeviceGroup, ThemeLibrary async def themed_lighting(): devices = [] async for device in discover(): devices.append(device) group = DeviceGroup(devices) theme = ThemeLibrary.get("christmas") # Single-zone lights get a random color for light in group.lights: await light.apply_theme(theme) # Multi-zone lights get distributed colors for strip in group.multizone_lights: await strip.apply_theme(theme) # Tile devices get smooth interpolation for tile in group.tiles: await tile.apply_theme(theme) ``` -------------------------------- ### Perform quick device discovery Source: https://github.com/djelibeybi/lifx-async/blob/main/docs/getting-started/installation.md An asynchronous Python script to discover LIFX devices on the local network and print their labels. Requires asyncio. ```python import asyncio from lifx import discover async def main(): async for device in discover(timeout=3.0): async with device: label = await device.get_label() print(f"Found: {label}") asyncio.run(main()) ``` -------------------------------- ### Multi-Tile Canvas Animation Example Source: https://github.com/djelibeybi/lifx-async/blob/main/docs/user-guide/animation.md Illustrates creating a unified canvas for devices with multiple tiles, allowing animations to span across them. The animator automatically calculates the canvas dimensions and tile regions based on device configuration. This example generates a horizontal gradient across 5 tiles. ```python async with await MatrixLight.from_ip("192.168.1.100") as device: animator = await Animator.for_matrix(device) # For 5 tiles arranged horizontally: # - canvas_width = 40 (5 tiles x 8 pixels) # - canvas_height = 8 # - pixel_count = 320 (40 x 8) print(f"Canvas: {animator.canvas_width}x{animator.canvas_height}") # Generate a gradient that flows across ALL tiles frame = [] for y in range(animator.canvas_height): for x in range(animator.canvas_width): # Hue varies from 0 to 65535 across the full width hue = int(x / animator.canvas_width * 65535) frame.append((hue, 65535, 65535, 3500)) animator.send_frame(frame) # Rainbow spans all 5 tiles! ``` -------------------------------- ### Apply Themes to LIFX Devices Source: https://context7.com/djelibeybi/lifx-async/llms.txt Demonstrates how to list, retrieve, and apply built-in or custom themes to LIFX devices using ThemeLibrary and get_theme(). Themes are applied optimally based on device type. ```python import asyncio from lifx import discover, DeviceGroup, ThemeLibrary from lifx.theme import get_theme, Theme async def main(): # List all available theme names all_themes = ThemeLibrary.get_available_themes() print(all_themes) # ['autumn', 'blissful', 'calaveras', 'christmas', ...] # Get by category seasonal = ThemeLibrary.get_by_category("seasonal") # Apply theme via ThemeLibrary devices = [d async for d in discover()] group = DeviceGroup(devices) theme = ThemeLibrary.get("autumn") await group.apply_theme(theme, power_on=True, duration=2.0) # Or use get_theme() shorthand xmas = get_theme("christmas") await group.apply_theme(xmas) # Build a custom theme from HSBK colors from lifx import HSBK, Colors custom = Theme([ Colors.DEEP_SKY_BLUE, Colors.CORAL, HSBK(hue=45, saturation=1.0, brightness=0.9, kelvin=3500), ]) await group.apply_theme(custom) asyncio.run(main()) ``` -------------------------------- ### Start an Effect with Lights Source: https://github.com/djelibeybi/lifx-async/blob/main/docs/user-guide/effects-troubleshooting.md Initiates an effect on a list of lights using the conductor. ```python await conductor.start(effect, lights) ``` -------------------------------- ### Run Benchmark Tests (Phase 1) Source: https://github.com/djelibeybi/lifx-async/blob/main/conductor/tracks/_archive/review-docs_20260318/plan.md Execute benchmark tests and save results for Phase 1 of the documentation review. Use this command to capture performance data related to documentation changes. ```bash uv run pytest tests/benchmarks/ -m benchmark --no-cov --benchmark-save=review-docs_20260318-Phase1 ``` -------------------------------- ### Usage of Notification Effect Source: https://github.com/djelibeybi/lifx-async/blob/main/docs/user-guide/effects-custom.md Demonstrates how to start the custom NotificationEffect with different levels using a Conductor. ```python conductor = Conductor() # Different notification levels await conductor.start(NotificationEffect(level='info'), lights) await asyncio.sleep(3) await conductor.start(NotificationEffect(level='warning'), lights) await asyncio.sleep(3) await conductor.start(NotificationEffect(level='error'), lights) await asyncio.sleep(3) ``` -------------------------------- ### Example SetColor Payload Source: https://github.com/djelibeybi/lifx-async/blob/main/docs/architecture/protocol-deep-dive.md Illustrates the structure of a SetColor payload, including reserved bytes, color information (HSBK), and duration. ```python # Example: SetColor payload (13 bytes) { 'reserved': 0, # 1 byte 'color': HSBK(...), # 8 bytes (4 × uint16) 'duration': 1000, # 4 bytes (uint32, milliseconds) } ``` -------------------------------- ### Run LIFX Effects in Background Source: https://github.com/djelibeybi/lifx-async/blob/main/examples/README.md Demonstrates that `conductor.start()` returns immediately, allowing effects to run in the background. Starts a colorloop, performs work for 10 seconds, then stops the effect. Discovers all lights on the network by default, with no parameters required. ```bash uv run python examples/effects_background.py ``` -------------------------------- ### Initialize Effect Registry Source: https://github.com/djelibeybi/lifx-async/blob/main/docs/api/effects.md Get the default effect registry, which is pre-populated with all built-in effects. It is lazily initialized on the first call. ```python from lifx import get_effect_registry, DeviceType, DeviceSupport registry = get_effect_registry() ``` -------------------------------- ### Using Built-in Color Presets Source: https://github.com/djelibeybi/lifx-async/blob/main/docs/getting-started/quickstart.md Demonstrates the use of predefined color constants for common colors like red, green, blue, and various white temperatures. ```python from lifx import Colors # Primary colors Colors.RED Colors.GREEN Colors.BLUE # White variants Colors.WARM Colors.COOL Colors.DAYLIGHT # Pastels Colors.PASTEL_BLUE Colors.PASTEL_PINK ``` -------------------------------- ### Get Current Effect on a Light Source: https://github.com/djelibeybi/lifx-async/blob/main/docs/api/effects.md Retrieve the effect currently running on a specific light. Returns None if the light is idle. ```python current_effect = conductor.effect(light) if current_effect: print(f"Running: {type(current_effect).__name__}") else: print("No effect running") ``` -------------------------------- ### Basic Animation for Matrix Devices Source: https://github.com/djelibeybi/lifx-async/blob/main/docs/user-guide/animation.md Demonstrates setting up an animator for matrix devices (Tiles, Candle, Path) and sending frames at 30 FPS. The animator is created using `Animator.for_matrix(device)` and frames are sent using `animator.send_frame()`. Ensure the animator is closed when done. ```python import asyncio from lifx import Animator, MatrixLight async def main(): async with await MatrixLight.from_ip("192.168.1.100") as device: # Create animator (queries device for tile info) animator = await Animator.for_matrix(device) # Device connection closed - animator sends via direct UDP print(f"Canvas: {animator.canvas_width}x{animator.canvas_height}") print(f"Total pixels: {animator.pixel_count}") try: # Animation loop for _ in range(100): # Generate frame (H, S, B, K as uint16) frame = [(65535, 65535, 65535, 3500)] * animator.pixel_count # send_frame() is synchronous for speed stats = animator.send_frame(frame) print(f"Sent {stats.packets_sent} packets") await asyncio.sleep(1 / 30) # 30 FPS finally: animator.close() asyncio.run(main()) ``` -------------------------------- ### Discover LIFX Devices via mDNS Source: https://github.com/djelibeybi/lifx-async/blob/main/examples/README.md Discovers devices using mDNS/DNS-SD instead of UDP broadcast. Demonstrates both high-level API (yielding device instances) and low-level API (yielding raw service records). No parameters are required. ```bash uv run python examples/discovery_mdns.py ``` -------------------------------- ### Power On Lights Before Effect Source: https://github.com/djelibeybi/lifx-async/blob/main/docs/user-guide/effects-troubleshooting.md Ensures all lights are powered on before starting an effect, which can resolve issues with state capture on older multizone devices. ```python for light in lights: await light.set_power(True) await asyncio.sleep(0.5) await conductor.start(effect, lights) ``` -------------------------------- ### Run NumPy Animation with Profiling Source: https://github.com/djelibeybi/lifx-async/blob/main/examples/README.md Executes the NumPy animation example in profiling mode for synthetic benchmarks. No device is needed for this mode. ```bash uv run python examples/animation_numpy.py --profile ``` -------------------------------- ### Simple Discovery Source: https://github.com/djelibeybi/lifx-async/blob/main/docs/api/high-level.md Discovers all LIFX devices on the network, sets their power to on, and changes their color to blue. ```APIDOC ## Simple Discovery ### Description Discovers all LIFX devices on the network, sets their power to on, and changes their color to blue. ### Usage ```python from lifx import discover, DeviceGroup, Colors async def main(): count: int = 0 async for device in discover(): count += 1 await device.set_power(True) await device.set_color(Colors.BLUE) print(f"Found {count} devices") ``` ``` -------------------------------- ### White Balance Presets Source: https://github.com/djelibeybi/lifx-async/blob/main/docs/api/colors.md Shows examples of creating different white balance temperatures using the HSBK model, from warm to cool. ```APIDOC ## White Balance ```python from lifx import HSBK # Warm white (sunset, candlelight) warm = HSBK(hue=0, saturation=0, brightness=1.0, kelvin=2500) # Neutral white (daylight) neutral = HSBK(hue=0, saturation=0, brightness=1.0, kelvin=4000) # Cool white (overcast, shade) cool = HSBK(hue=0, saturation=0, brightness=1.0, kelvin=6500) ``` ``` -------------------------------- ### Basic Light Control Source: https://github.com/djelibeybi/lifx-async/blob/main/docs/api/devices.md Control a standard LIFX light by setting its power state and color. This example shows how to connect to a light, turn it on, set a specific color with a duration, and retrieve the device's label. ```python from lifx import Light, Colors async def main(): async with await Light.from_ip("192.168.1.100") as light: # Turn on and set color await light.set_power(True) await light.set_color(Colors.BLUE, duration=1.0) # Get device info label = await light.get_label() print(f"Controlling: {label}") ``` -------------------------------- ### Get Power State Source: https://github.com/djelibeybi/lifx-async/blob/main/docs/architecture/effects-architecture.md Retrieve the power state of a light using `get_power()`. Returns an integer where 0 indicates off and 65535 indicates on. ```python power_level = await light.get_power() # Returns int (0 or 65535) is_on = power_level > 0 ``` -------------------------------- ### EffectRegistry Usage Source: https://github.com/djelibeybi/lifx-async/blob/main/docs/api/effects.md Demonstrates how to get the effect registry and query available effects for different device types or specific device instances. ```APIDOC ## 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 ```python from lifx import get_effect_registry, DeviceType, DeviceSupport registry = get_effect_registry() ``` ### `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 ```python @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 ``` ### Effect Support Matrix | Effect | Light | MultiZone | Matrix | |--------|-------|-----------|--------| | aurora | COMPATIBLE | RECOMMENDED | RECOMMENDED | | colorloop | RECOMMENDED | COMPATIBLE | COMPATIBLE | | cylon | COMPATIBLE | RECOMMENDED | — | | double_slit | — | RECOMMENDED | — | | embers | COMPATIBLE | RECOMMENDED | — | | fireworks | — | RECOMMENDED | — | | flame | RECOMMENDED | RECOMMENDED | RECOMMENDED | | jacobs_ladder | — | RECOMMENDED | — | | newtons_cradle | — | RECOMMENDED | — | | pendulum_wave | — | RECOMMENDED | — | | plasma | COMPATIBLE | RECOMMENDED | — | | plasma2d | — | — | RECOMMENDED | | progress | — | RECOMMENDED | — | | pulse | RECOMMENDED | RECOMMENDED | RECOMMENDED | | rainbow | COMPATIBLE | RECOMMENDED | RECOMMENDED | | ripple | — | RECOMMENDED | — | | rule30 | — | RECOMMENDED | — | | rule_trio | — | RECOMMENDED | — | | sine | COMPATIBLE | RECOMMENDED | — | | sonar | — | RECOMMENDED | — | | spectrum_sweep | COMPATIBLE | RECOMMENDED | — | | spin | COMPATIBLE | RECOMMENDED | — | | sunrise | — | — | RECOMMENDED | | sunset | — | — | RECOMMENDED | | twinkle | RECOMMENDED | RECOMMENDED | COMPATIBLE | | wave | COMPATIBLE | RECOMMENDED | — | ### Examples ```python 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}") ``` ``` -------------------------------- ### Good Practice: Catching Specific Exceptions First Source: https://github.com/djelibeybi/lifx-async/blob/main/docs/api/exceptions.md Illustrates the recommended practice of catching more specific LIFX exceptions before broader ones to allow for differentiated error handling. This example shows the correct order of `except` blocks. ```python # ✅ Good - specific to general try: await light.set_color(Colors.BLUE) except LifxTimeoutError: print("Timeout") except LifxConnectionError: print("Connection failed") except LifxError: print("Other LIFX error") # ❌ Bad - general exception catches everything try: await light.set_color(Colors.BLUE) except LifxError: print("Error") # Can't distinguish timeout from other errors ``` -------------------------------- ### Handling Large Matrix Tiles Source: https://github.com/djelibeybi/lifx-async/blob/main/examples/README.md Demonstrates handling matrix devices with more than 64 zones per tile, showing various patterns. The library automatically uses the frame buffer strategy for large tiles. Requires the IP address of the MatrixLight. ```bash uv run python examples/matrix_large_tiles.py --ip 192.168.1.100 ```