Skip to main content

A Python client for the dLight smart lamp API.

Project description

python-dlight-client - Async Python Client for dLight API

PyPI version Python Versions

This Python package provides an asynchronous client library (asyncio) for interacting with the dLight smart lamp API, based on the documentation dated 2023-01-04. It allows discovering dLight devices using UDP broadcasts and controlling them over a local Wi-Fi network using TCP commands.

The library has been refactored for better organization:

  • dlightclient.client: Contains the AsyncDLightClient for TCP control.
  • dlightclient.discovery: Provides the discover_devices function for UDP discovery.
  • dlightclient.exceptions: Defines custom error types.
  • dlightclient.constants: Holds shared constants.
  • dlightclient.cli: Offers a basic command-line interface.

Features

  • Asynchronous: Built with asyncio for non-blocking network operations.
  • Discover Devices: Find dLight devices on the local network via UDP broadcast (discover_devices).
  • Control Light State:
    • Turn On/Off (AsyncDLightClient.set_light_state)
    • Set Brightness (0-100%) (AsyncDLightClient.set_brightness)
    • Set Color Temperature (2600K-6000K) (AsyncDLightClient.set_color_temperature)
  • Query Device:
    • Get current state (AsyncDLightClient.query_device_state).
    • Get device information (AsyncDLightClient.query_device_info).
  • Wi-Fi Provisioning: Support for sending Wi-Fi credentials (AsyncDLightClient.connect_to_wifi - typically used when device is in SoftAP mode).
  • Robust Communication: Handles the specific dLight TCP response format (4-byte length prefix + JSON payload) and includes timeouts.
  • Error Handling: Custom exceptions for specific error conditions (e.g., DLightError, DLightTimeoutError, DLightConnectionError).
  • Command-Line Tool: A basic CLI (cli.py) for discovery and interaction.

Prerequisites

  • A dLight device connected to your local Wi-Fi network (or in SoftAP mode for initial setup).
  • Python 3.9+ (due to asyncio features used)

Installation

pip install dlight-client

Usage

You can use this package as a library in your Python projects or via the included command-line tool.As a LibraryFirst, discover your dLight device(s) to get their IP address and Device ID. Then, use these details to send commands via an AsyncDLightClient instance within an async function.import asyncio

import logging
import time # For delays in example

# Import the public interface
from dlightclient import (
    AsyncDLightClient,
    discover_devices,
    DLightError,
    DLightTimeoutError,
    DLightConnectionError
)

# Configure logging
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s')
log = logging.getLogger(__name__)

async def run_example():
    log.info("--- Async dLight Python Client Example ---")

    log.info("\n--- Discovering Devices (3 seconds) ---")
    try:
        # Use the discover_devices function directly
        devices = await discover_devices(discovery_duration=3.0)
    except Exception as e:
         log.exception(f"Discovery failed with an unexpected error: {e}")
         devices = []

    if not devices:
        log.warning("\nNo dLight devices found on the network.")
        log.warning("Ensure dLight is powered on and connected to the same network.")
        # Add Wi-Fi connect example if needed (see cli.py or client.py for details)
        return

    # --- Interact with the first discovered device ---
    target_device = devices[0]
    target_ip = target_device.get('ip_address')
    # Handle potential case difference for deviceId from discovery
    device_id = target_device.get('deviceId') or target_device.get('deviceid')

    if not target_ip or not device_id:
        log.error(f"Could not get IP address or Device ID from discovered device: {target_device}")
        return

    log.info(f"\n--- Interacting with: {device_id} at {target_ip} ---")
    client = AsyncDLightClient(default_timeout=5.0) # Adjust timeout if needed

    try:
        # Query Info
        log.info("\nQuerying Device Info...")
        info = await client.query_device_info(target_ip, device_id)
        log.info(f"  Info: {info}")

        # Query State
        log.info("\nQuerying Device State...")
        state_resp = await client.query_device_state(target_ip, device_id)
        current_state = state_resp.get('states', {})
        log.info(f"  Current State: {current_state}")

        # Turn On
        log.info("\nTurning Light ON...")
        await client.set_light_state(target_ip, device_id, True)
        await asyncio.sleep(0.5) # Give device time to react

        # Set Brightness
        log.info("\nSetting Brightness to 60%...")
        await client.set_brightness(target_ip, device_id, 60)
        await asyncio.sleep(0.5)

        # Set Color Temperature
        log.info("\nSetting Color Temperature to 4500K...")
        await client.set_color_temperature(target_ip, device_id, 4500)
        await asyncio.sleep(0.5)

        # Query State Again
        log.info("\nQuerying Device State Again...")
        state_resp = await client.query_device_state(target_ip, device_id)
        new_state = state_resp.get('states', {})
        log.info(f"  New State: {new_state}")

        # Turn Off
        log.info("\nTurning Light OFF...")
        await client.set_light_state(target_ip, device_id, False)

    except (DLightTimeoutError, DLightConnectionError) as e:
        log.error(f"\n--- Network Error during interaction ---")
        log.error(e)
    except DLightError as e:
        log.error(f"\n--- A dLight error occurred during interaction ---")
        log.error(e)
    except ValueError as e:
         log.error(f"\n--- Invalid value provided during interaction ---")
         log.error(e)
    except Exception as e:
         log.exception(f"\n--- An unexpected error occurred during interaction ---")


if __name__ == "__main__":
    try:
        asyncio.run(run_example())
    except KeyboardInterrupt:
        print("Example stopped.")

Using the Command-Line Tool (cli.py)

The package includes a basic command-line tool for common operations. You can run it as a module:

python -m dlightclient.cli [OPTIONS]

Common Commands:

  • Discover devices:
    • python -m dlightclient.cli --discover
    • python -m dlightclient.cli --discover --discover-duration <DURATION>
  • Interact with a device (requires IP and ID):
    • Replace <IP_ADDRESS> and <DEVICE_ID> with actual values
    • python -m dlightclient.cli --ip <IP_ADDRESS> --id <DEVICE_ID>
  • Send Wi-Fi credentials (for setup):
    • Warning: Use this only when the device is in SoftAP mode and your computer is connected to its network.
    •   # Replace <DEVICE_ID>, <YOUR_WIFI_SSID>, <YOUR_WIFI_PASSWORD>
        python -m dlightclient.cli --connect-wifi --id <DEVICE_ID> --ssid "<YOUR_WIFI_SSID>" --password "<YOUR_WIFI_PASSWORD>"
      
  • Get Help:
    • python -m dlightclient.cli --help
  • Increase Verbosity:
    • Use -v for INFO level logging, -vv for DEBUG level.# Discover with DEBUG logging
    • python -m dlightclient.cli --discover -vv

Interact with DEBUG logging

python -m dlightclient.cli --ip <IP_ADDRESS> --id <DEVICE_ID> -vv

API Details

  • TCP Commands: Sent to device IP on port 3333 (default). Handled by AsyncDLightClient.
  • UDP Discovery: Broadcast sent to 255.255.255.255 (default) on port 9478. Responses listened for on port 9487. Handled by discover_devices.

Development and Testing

  1. Setup Virtual Environment:
python -m venv .venv
source .venv/bin/activate  # or .\.venv\Scripts\activate on Windows
  1. Install Dependencies (if any beyond standard library):
# Add requirements-dev.txt if needed for linters, pytest, etc.
# pip install -r requirements-dev.txt
  1. Install in Editable Mode:
pip install -e .

Testing

Note: The test suite (tests/test_dlight.py) needs to be updated to reflect the refactored code structure (module paths for patching, imports, etc.).Once updated, you can run tests using:python -m unittest discover -s tests/ -p 'test_*.py'

Or potentially targeting the specific test file if structure changed:

python -m unittest tests.test_dlight

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

dlight_client-1.2.0.tar.gz (33.0 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

dlight_client-1.2.0-py3-none-any.whl (25.9 kB view details)

Uploaded Python 3

File details

Details for the file dlight_client-1.2.0.tar.gz.

File metadata

  • Download URL: dlight_client-1.2.0.tar.gz
  • Upload date:
  • Size: 33.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.9.5

File hashes

Hashes for dlight_client-1.2.0.tar.gz
Algorithm Hash digest
SHA256 83dc77107e2301705380051e8a9e35f11a0a818297e54c95b555fce8cfbdb95b
MD5 7841c73da602874ab3451194e67f571f
BLAKE2b-256 c49de424b369b339345503ba6b497ca27fd2e9cf50c64d3b1bc5300adb043475

See more details on using hashes here.

File details

Details for the file dlight_client-1.2.0-py3-none-any.whl.

File metadata

  • Download URL: dlight_client-1.2.0-py3-none-any.whl
  • Upload date:
  • Size: 25.9 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.9.5

File hashes

Hashes for dlight_client-1.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 a16d2aa0666dfb4964b0281cf90da8b033cc8a03c75fce568fcd29f9eed3b179
MD5 b7a000a6b26d148d53d3366a1ff0d01e
BLAKE2b-256 5f615cb619bf23dc76e9fd44508de9e9fedb6e021e050ca15c242d64c0ce616d

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page