Skip to content

Advanced Features

Busylight Core provides extensive functionality for controlling USB status lights programmatically.

Device Discovery and Management

Automatic Device Detection

Busylight Core automatically detects and recognizes supported devices:

from busylight_core import Light, Hardware

# Low-level hardware discovery
hardware_devices = Hardware.enumerate()
print(f"Found {len(hardware_devices)} hardware devices")

# High-level light discovery
lights = Light.available()
print(f"Recognized {len(lights)} busylights")

Device Information

Get detailed information about connected devices:

for light in Light.available():
    print(f"Vendor: {light.vendor}")
    print(f"Model: {light.name}")
    print(f"Device ID: {light.device_id}")
    print(f"Connection Type: {light.hardware.device_type}")
    print(f"USB Path: {light.hardware.path}")

Color Management

Color Formats

Busylight Core supports multiple color formats:

light = Light.first_light()

# RGB tuples (0-255)
light.on((255, 0, 0))      # Red
light.on((0, 255, 0))      # Green
light.on((0, 0, 255))      # Blue

# Hexadecimal strings
light.on("#FF0000")        # Red
light.on("#00FF00")        # Green
light.on("#0000FF")        # Blue

# Named colors (if supported)
light.on("red")
light.on("green")
light.on("blue")

Color Utilities

Use built-in color utilities for advanced color manipulation:

from busylight_core.mixins import ColorableMixin

# Color interpolation
start_color = (255, 0, 0)    # Red
end_color = (0, 0, 255)      # Blue
steps = 10

for i in range(steps):
    ratio = i / (steps - 1)
    interpolated = ColorableMixin.interpolate_color(start_color, end_color, ratio)
    light.on(interpolated)
    time.sleep(0.1)

Advanced Device Features

Multi-LED Devices

Control devices with multiple LEDs individually:

from busylight_core import BlinkStick

blinksticks = [l for l in Light.available() if isinstance(l, BlinkStick)]
if blinksticks:
    stick = blinksticks[0]

    # Set individual LEDs
    for i in range(8):  # BlinkStick Strip has 8 LEDs
        color = (255 * i // 7, 0, 255 - (255 * i // 7))  # Red to blue gradient
        stick.set_led(i, color)

    # Set all LEDs at once
    stick.set_all((255, 255, 255))  # All white

Audio-Enabled Devices

Control sound features on supported devices:

from busylight_core import Blynclight

blynclights = [l for l in Light.available() if isinstance(l, Blynclight)]
if blynclights:
    blight = blynclights[0]

    # Play sound with light
    blight.on((255, 0, 0), sound=True)

    # Sound-only operations
    blight.play_sound()
    blight.mute()
    blight.unmute()

    # Check mute status
    if blight.is_muted():
        print("Device is muted")

Button Input Devices

Handle button input on interactive devices:

from busylight_core import MuteMe, Luxafor

# Find devices with button input
input_devices = []
for light in Light.available():
    if isinstance(light, (MuteMe, Luxafor)) and hasattr(light, 'button_pressed'):
        input_devices.append(light)

if input_devices:
    device = input_devices[0]

    # Poll button state
    while True:
        if device.button_pressed():
            device.on((255, 0, 0))  # Red when pressed
        else:
            device.on((0, 255, 0))  # Green when not pressed
        time.sleep(0.1)

Asynchronous Programming

Built-in Task Management

Every Light instance includes async task management:

import asyncio
from busylight_core import Light

async def breathing_animation(light_instance):
    """Breathing effect animation"""
    while True:
        # Fade in
        for brightness in range(0, 256, 5):
            color = (brightness, 0, 0)  # Red
            light_instance.on(color)
            await asyncio.sleep(0.02)

        # Fade out
        for brightness in range(255, -1, -5):
            color = (brightness, 0, 0)
            light_instance.on(color)
            await asyncio.sleep(0.02)

# Use task management
light = Light.first_light()
if light:
    # Start animation task
    task = light.add_task("breathing", breathing_animation)

    # Let it run for 10 seconds
    await asyncio.sleep(10)

    # Stop the animation
    light.cancel_task("breathing")
    light.off()

Custom Async Patterns

Create complex lighting patterns with async/await:

async def police_lights(light):
    """Police car style red/blue flashing"""
    while True:
        # Red flash
        for _ in range(3):
            light.on((255, 0, 0))
            await asyncio.sleep(0.1)
            light.off()
            await asyncio.sleep(0.1)

        await asyncio.sleep(0.2)

        # Blue flash
        for _ in range(3):
            light.on((0, 0, 255))
            await asyncio.sleep(0.1)
            light.off()
            await asyncio.sleep(0.1)

        await asyncio.sleep(0.5)

# Run the pattern
light = Light.first_light()
if light:
    await police_lights(light)

Configuration and Settings

Environment Variables

Configure Busylight Core behavior via environment variables:

import os

# Set default behavior
os.environ['BUSYLIGHT_CORE_DEBUG'] = 'true'
os.environ['BUSYLIGHT_CORE_DEFAULT_BRIGHTNESS'] = '128'
os.environ['BUSYLIGHT_CORE_AUTO_DISCOVER'] = 'true'

# Use configuration
from busylight_core import Light
lights = Light.available()  # Uses configured settings

Programmatic Configuration

Configure devices programmatically:

from busylight_core.settings import Settings

# Access global settings
settings = Settings()
settings.debug = True
settings.default_color = (255, 255, 0)  # Yellow

# Device-specific configuration
light = Light.first_light()
if light:
    light.brightness = 0.5  # 50% brightness
    light.default_flash_count = 5

Error Handling and Debugging

Exception Hierarchy

Busylight Core provides specific exceptions for different error conditions:

from busylight_core import (
    Light, 
    NoLightsFound, 
    LightUnavailable, 
    LightUnsupported,
    InvalidHardwareInfo
)

try:
    light = Light.first_light()
    if not light:
        raise NoLightsFound("No devices found")

    light.on((255, 0, 0))

except NoLightsFound:
    print("Please connect a busylight device")
except LightUnavailable as e:
    print(f"Device unavailable: {e}")
except LightUnsupported as e:
    print(f"Device not supported: {e}")
except InvalidHardwareInfo as e:
    print(f"Hardware error: {e}")

Debug Logging

Enable comprehensive debug logging:

import logging
from loguru import logger

# Enable debug logging
logger.remove()
logger.add(lambda msg: print(msg), level="DEBUG")

# Now all operations will show debug information
from busylight_core import Light
lights = Light.available()  # Will show detailed discovery process

Hardware Troubleshooting

Diagnose hardware detection issues:

from busylight_core import Hardware, Light

def diagnose_hardware():
    """Comprehensive hardware diagnosis"""
    print("=== Hardware Diagnosis ===")

    # Check raw hardware detection
    hardware = Hardware.enumerate()
    print(f"Found {len(hardware)} hardware devices:")

    for hw in hardware:
        print(f"  VID:PID = {hw.vendor_id:04x}:{hw.product_id:04x}")
        print(f"  Manufacturer: {hw.manufacturer_string}")
        print(f"  Product: {hw.product_string}")
        print(f"  Serial: {hw.serial_number}")
        print(f"  Path: {hw.path}")
        print()

    # Check light recognition
    lights = Light.available()
    print(f"Recognized {len(lights)} as busylights:")

    for light in lights:
        print(f"  {light.vendor} {light.name}")
        print(f"  Class: {light.__class__.__name__}")
        print(f"  Supports: {', '.join(light.capabilities())}")
        print()

    # Check for unrecognized devices
    light_hardware = {light.hardware for light in lights}
    unrecognized = [hw for hw in hardware if hw not in light_hardware]

    if unrecognized:
        print(f"Unrecognized devices ({len(unrecognized)}):")
        for hw in unrecognized:
            print(f"  {hw.vendor_id:04x}:{hw.product_id:04x} - {hw.product_string}")

# Run diagnosis
diagnose_hardware()

Performance Optimization

Efficient Device Access

Optimize performance for applications that frequently access devices:

from busylight_core import Light

class LightManager:
    def __init__(self):
        self._lights_cache = None
        self._last_scan = 0
        self.scan_interval = 5.0  # Rescan every 5 seconds

    @property
    def lights(self):
        import time
        now = time.time()

        if (self._lights_cache is None or 
            now - self._last_scan > self.scan_interval):
            self._lights_cache = Light.available()
            self._last_scan = now

        return self._lights_cache

    def refresh(self):
        """Force refresh of device list"""
        self._lights_cache = None

# Usage
manager = LightManager()
for light in manager.lights:  # Cached access
    light.on((255, 0, 0))

Batch Operations

Perform batch operations efficiently:

def set_all_lights(color, flash=False):
    """Set all connected lights to the same color"""
    lights = Light.available()

    for light in lights:
        try:
            if flash:
                light.flash(color, count=2)
            else:
                light.on(color)
        except Exception as e:
            print(f"Failed to control {light.name}: {e}")

# Set all lights to green
set_all_lights((0, 255, 0))

# Flash all lights red
set_all_lights((255, 0, 0), flash=True)

Examples

For complete usage examples and real-world scenarios, see the Examples page.

Next Steps