HSD Love Light CLI & SDK
Control your HSD Love Light BLE speaker-lamp from the command line — lighting, music, alarms, and more.
This project provides two layers:
- SDK (
hsd_light.protocol+hsd_light.device) — integrate directly into any Python project - CLI (
hsdcommand) — one-liner terminal control for the device
Requirements
- Python >= 3.10
- Bluetooth adapter with BLE support
- Windows / macOS / Linux
Installation
From PyPI (recommended):
pip install hsd-light
Or from source (for development):
cd cli
pip install -e .
The hsd command will be available after installation.
CLI Usage
Global Options
hsd [OPTIONS] COMMAND
| Option | Description |
|---|---|
-a, --address TEXT |
BLE MAC address (skip scanning) |
-t, --timeout FLOAT |
Scan / connection timeout in seconds (default: 10) |
-v, --verbose |
Enable debug logging |
Scan for Device
hsd scan
# Found: HSD Love Light [AA:BB:CC:DD:EE:FF]
After the first successful scan, the device address is cached in ~/.config/hsd-light/config.json. Subsequent commands will skip scanning and connect directly.
Light Control
# Preset colours
hsd light color red # red / green / blue / white
# Custom RGB
hsd light rgb 255 0 128
hsd light rgb 255 100 0 --white 50 --brightness 80
# Brightness (0-100)
hsd light brightness 60
# Effects
hsd light effect gradient # gradient / flow / dither
Music Control
hsd music send play # play / pause (toggle)
hsd music send next # next track
hsd music send prev # previous track
hsd music send volume-up # volume up
hsd music send volume-down # volume down
hsd music send eq # cycle EQ modes
hsd music send source # toggle BT / TF source
hsd music send mute # mute
Alarm
hsd alarm set 07:30 # set and enable alarm
hsd alarm set 22:00 --disable # set but keep disabled
Time Sync & Device Query
hsd sync # sync system time to the device
hsd query # query current device state
Specifying a Device Address
Manually specify a MAC address (takes priority over cached address):
hsd -a AA:BB:CC:DD:EE:FF light color blue
Clearing Cached Address
Clear the cached device address to force a re-scan on next use:
hsd forget
SDK Usage
Quick Start
import asyncio
from hsd_light import HSDDevice, Command
from hsd_light.protocol import MusicAction, ColorPreset, Effect
async def main():
async with HSDDevice() as dev:
# Set red, 80% brightness
await dev.send(Command.color_preset(ColorPreset.RED))
await dev.send(Command.brightness(80))
# Custom colour
await dev.send(Command.custom_color(r=255, g=0, b=128, w=0, brightness=100))
# Gradient effect
await dev.send(Command.effect(Effect.GRADIENT))
# Music: play, next track
await dev.send(Command.music(MusicAction.PLAY_PAUSE))
await dev.send(Command.music(MusicAction.NEXT_TRACK))
# Set alarm at 07:30
await dev.send(Command.timer(7, 30, enabled=True))
asyncio.run(main())
Specifying a Device Address
async with HSDDevice(address="AA:BB:CC:DD:EE:FF") as dev:
await dev.send(Command.brightness(50))
Listening for Device Notifications
async with HSDDevice() as dev:
dev.on_notify = lambda data: print("Received:", data.hex())
await dev.send(Command.query_params())
await asyncio.sleep(2) # wait for response
Manual Connection Management
dev = HSDDevice()
await dev.connect() # scan + connect + auto time-sync
await dev.send(Command.brightness(100))
await dev.disconnect()
BLE Protocol Overview
All commands are binary packets with the following format:
[0x69, 0x96, <length>, <cmd_type>, <payload...>]
────────── ──────── ────────── ───────────
header payload command command
length type data
| Command | Type | Payload | Description |
|---|---|---|---|
| COLOR_MODE | 1 | [preset] |
Preset colour / effect (1–7) |
| TIME_SYNC | 2 | [year_hi, year_lo, month, day, hour, min, sec] |
Sync clock |
| CUSTOM_RGB | 3 | [R, G, B, W, brightness] |
Custom RGBW colour |
| TIMER | 4 | [hour, min, mode] |
Alarm setting |
| MUSIC | 8 | [action] |
Music control (2–10) |
| QUERY | 15 | — | Query device state |
| BRIGHTNESS | 17 | [value] |
Brightness (0–100) |
Project Structure
cli/
├── pyproject.toml
├── README.md # Chinese documentation
├── README_EN.md # English documentation
└── hsd_light/
├── __init__.py # Exports Command, HSDDevice
├── __main__.py # python -m hsd_light
├── protocol.py # Protocol layer — pure command builders, no dependencies
├── device.py # Device layer — BLE connection management via bleak
├── config.py # Config layer — device address caching (~/.config/hsd-light/)
└── cli.py # CLI layer — click-based command-line tool
License
MIT
Metadata
Release files for hsd-light 1.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| hsd_light-1.1.0.tar.gz | 14.0 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| hsd_light-1.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 26.6 kB
Release files / hsd_light-1.1.0.tar.gz
| Download URL | hsd_light-1.1.0.tar.gz |
|---|---|
| Size | 14.0 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
754e4e5b3bee079eae4d8db27b7809c99f8deac3f269356dff6f978fd2aee6ba
|
|
BLAKE2b-256 checksum How to use checksums |
ade4db28d5b9386c152ca3104d46d15fea112dd5d78c2d5d2be3d01b4264fe70
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Apr 7, 2026.
Transparency logRelease files / hsd_light-1.1.0-py3-none-any.whl
| Download URL | hsd_light-1.1.0-py3-none-any.whl |
|---|---|
| Size | 12.6 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
5365ba70f48b0ced8e1d98ba1f1cf001615f991d9f9f53ce005506f7386f6ce8
|
|
BLAKE2b-256 checksum How to use checksums |
fde56ca96a852d4194e2bc149d11c0dc670d8966d75e15a18136e52bde87c54a
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Apr 7, 2026.
Transparency log