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 (asyncio) client library for discovering and controlling dLight smart lamps over a local Wi-Fi network. It allows you to find dLight devices using UDP broadcasts and control them using TCP commands.

Table of Contents

Features

  • Asynchronous: Built with asyncio for efficient, non-blocking network operations.
  • Device Discovery: Find dLight devices on your local network using UDP broadcast (discover_devices).
  • High-Level Device Control: An easy-to-use DLightDevice class for object-oriented control of a specific lamp.
  • Performance Optimized:
    • Persistent TCP Connections: Reuse connections for sequential commands to reduce latency (persistent=True).
    • Connection Concurrency Safety: Automatic per-device locking ensures multiple concurrent tasks can share a client safely.
    • Idle Timeout: Stale connections are automatically closed and refreshed after a period of inactivity (default 60s).
    • State Caching & Optimistic Updates: Internal cache in DLightDevice reduces redundant network queries and provides immediate feedback.
  • Automatic Retries: Opt-in retries with exponential backoff (max_retries, retry_backoff) for transient network failures. Protocol errors are never retried.
  • Optional TLS: Pass ssl=True or a custom ssl.SSLContext to encrypt the TCP channel (CLI: --ssl, --insecure).
  • Developer Friendly:
    • Structured Models: Use TypedDict models (DeviceState, DeviceInfo, etc.) for better IDE support and type safety.
  • State Control:
    • Turn On/Off
    • Set Brightness (0-100%)
    • Set Color Temperature (2600K-6000K)
  • Device Query:
    • Get the current state (power, brightness, color).
    • Get device information (model, firmware version, etc.).
  • Wi-Fi Provisioning: Send Wi-Fi credentials to a device in SoftAP mode for initial setup.
  • Robust Communication: Handles the dLight TCP protocol (4-byte length prefix + JSON payload) and includes timeouts.
  • Custom Error Handling: Specific exceptions for network and device errors (e.g., DLightTimeoutError, DLightResponseError).
  • Command-Line Tool: A convenient CLI for quick discovery and interaction.

Prerequisites

  • A dLight device connected to your local Wi-Fi network (or in SoftAP mode for initial setup).
  • Python 3.9 through 3.13 (officially supported).

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 Library

Using the library typically involves two steps: discovering devices to get their IP address and ID, and then creating a DLightDevice instance to interact with a specific lamp.

1. Discovering Devices

First, use the discover_devices function to find lamps on your network.

import asyncio
from dlightclient import discover_devices

async def find_devices():
    print("--- Discovering Devices ---")
    devices = await discover_devices(discovery_duration=3.0)

    for i, device_info in enumerate(devices):
        ip = device_info.get('ip_address')
        dev_id = device_info.get('deviceId')
        print(f"  Device {i+1}: ID={dev_id}, IP={ip}")

if __name__ == "__main__":
    asyncio.run(find_devices())

2. Controlling a Device

Once you have the ip_address and deviceId, you can use the high-level DLightDevice class for intuitive control.

import asyncio
from dlightclient import AsyncDLightClient, DLightDevice

async def run_example():
    # The client handles the underlying TCP communication
    client = AsyncDLightClient()

    # The device object is the high-level interface
    device = DLightDevice(ip_address="192.168.1.123", device_id="DL12345", client=client)

    # Simple control commands
    await device.turn_on()
    await device.set_brightness(75)
    
    # State caching: get_state() returns cached value by default
    state = await device.get_state() 
    print(f"Current Brightness (cached): {state.get('brightness')}%")

if __name__ == "__main__":
    asyncio.run(run_example())

3. Performance Optimization

For applications that need to send many commands in a row, use Persistent Connections to eliminate connection setup overhead.

Persistence is enabled by the persistent=True constructor argument. The context manager does not enable it; it only guarantees that all pooled connections are closed on exit.

Option A: Context Manager (recommended)

from dlightclient import AsyncDLightClient, DLightDevice

async with AsyncDLightClient(persistent=True) as client:
    device = DLightDevice(ip_address="192.168.1.123", device_id="DL12345", client=client)
    # Both commands reuse the same TCP connection
    await device.turn_on()
    await device.set_brightness(50)
# All connections are closed when the block exits

Option B: Manual Lifecycle

client = AsyncDLightClient(persistent=True)
try:
    ...  # perform operations
finally:
    await client.close()  # Explicitly close when finished

Changed in 1.6.0: async with AsyncDLightClient() no longer implicitly enables persistence; pass persistent=True explicitly.

For lossy Wi-Fi environments, enable retries — they apply only to transient network errors (timeouts, connection failures), never to protocol errors:

client = AsyncDLightClient(max_retries=2, retry_backoff=0.5)  # waits 0.5s, then 1.0s

Using the Command-Line Tool (CLI)

The package includes a basic CLI for common operations.

# Discover all devices on the network
python -m dlightclient.cli --discover

# Interact with a specific device using a test sequence
python -m dlightclient.cli --ip 192.168.1.100 --id DL12345

API Overview

  • dlightclient.discovery.discover_devices: Uses UDP broadcast to find devices on the network.
  • dlightclient.client.AsyncDLightClient: The low-level TCP client. Supports persistent=True.
  • dlightclient.device.DLightDevice: High-level class. Includes state caching automatically.
  • dlightclient.exceptions: Custom exceptions hierarchy rooted in DLightError.

Architecture

For a deep dive into the library's layering, data flow, concurrency model, and wire protocol — aimed at contributors — see docs/ARCHITECTURE.md.

Development and Testing

  1. Set up a virtual environment:

    python -m venv .venv
    source .venv/bin/activate
    
  2. Install in editable mode:

    pip install -e .
    
  3. Run tests:

    python -m unittest discover tests/
    

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.6.1.tar.gz (37.6 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.6.1-py3-none-any.whl (26.7 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: dlight_client-1.6.1.tar.gz
  • Upload date:
  • Size: 37.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for dlight_client-1.6.1.tar.gz
Algorithm Hash digest
SHA256 eece3d0d3e517b0ae914c709a08a8b6cbd974689ad21c793e9dce231b0905d25
MD5 8c28961cdd8662b6fb67b2b6eed07f36
BLAKE2b-256 65ab408f79951678a991b2a4addfa03b8a3f15eae0193b9228145f05b57a3f39

See more details on using hashes here.

Provenance

The following attestation bundles were made for dlight_client-1.6.1.tar.gz:

Publisher: python-publish.yml on Irishsmurf/dlight-client

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

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

File metadata

  • Download URL: dlight_client-1.6.1-py3-none-any.whl
  • Upload date:
  • Size: 26.7 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for dlight_client-1.6.1-py3-none-any.whl
Algorithm Hash digest
SHA256 05d75b8e591715782a4ce98d72b23768bada8d68f642e8f8967edec6a448e165
MD5 abd53494ca96c9d5baa507cf81bafbc7
BLAKE2b-256 ec699221c66af5e4248c6cfa0915ebbcc9d5de717d1ba2b73fb977693c5ae2b2

See more details on using hashes here.

Provenance

The following attestation bundles were made for dlight_client-1.6.1-py3-none-any.whl:

Publisher: python-publish.yml on Irishsmurf/dlight-client

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

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