CLI tool & SDK for controlling HSD Love Light BLE device
Project description
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
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]
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
If you already know the MAC address, skip scanning for a faster connection:
hsd -a AA:BB:CC:DD:EE:FF light color blue
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
└── cli.py # CLI layer — click-based command-line tool
License
MIT
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file hsd_light-1.0.0.tar.gz.
File metadata
- Download URL: hsd_light-1.0.0.tar.gz
- Upload date:
- Size: 12.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ecf3dd3776fd4aa7da5f58aca2051d28caf6b88c70c5e19504d9687c3f421e01
|
|
| MD5 |
36b152957ab9e33ff38ca082bd7de409
|
|
| BLAKE2b-256 |
9d043982793aa143c86d88a655813ebd50a4f85785d267284e8baeef4ef2d05f
|
Provenance
The following attestation bundles were made for hsd_light-1.0.0.tar.gz:
Publisher:
publish.yml on yearliny/hsd-light
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
hsd_light-1.0.0.tar.gz -
Subject digest:
ecf3dd3776fd4aa7da5f58aca2051d28caf6b88c70c5e19504d9687c3f421e01 - Sigstore transparency entry: 1243600162
- Sigstore integration time:
-
Permalink:
yearliny/hsd-light@b11d64796568425597d0e89dcb88b17f79b8b15c -
Branch / Tag:
refs/tags/v1.0.0 - Owner: https://github.com/yearliny
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@b11d64796568425597d0e89dcb88b17f79b8b15c -
Trigger Event:
push
-
Statement type:
File details
Details for the file hsd_light-1.0.0-py3-none-any.whl.
File metadata
- Download URL: hsd_light-1.0.0-py3-none-any.whl
- Upload date:
- Size: 11.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b0dffb9eba0a7012503808c2df5d9a6cae2109929fa239b9a26d72705dedf618
|
|
| MD5 |
c88f480d47e310feeab15f31781eb3d4
|
|
| BLAKE2b-256 |
fd56dbe95ec31197a114e1083c64d9e99089a0afe38c8721ba852f8857bbd447
|
Provenance
The following attestation bundles were made for hsd_light-1.0.0-py3-none-any.whl:
Publisher:
publish.yml on yearliny/hsd-light
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
hsd_light-1.0.0-py3-none-any.whl -
Subject digest:
b0dffb9eba0a7012503808c2df5d9a6cae2109929fa239b9a26d72705dedf618 - Sigstore transparency entry: 1243600172
- Sigstore integration time:
-
Permalink:
yearliny/hsd-light@b11d64796568425597d0e89dcb88b17f79b8b15c -
Branch / Tag:
refs/tags/v1.0.0 - Owner: https://github.com/yearliny
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@b11d64796568425597d0e89dcb88b17f79b8b15c -
Trigger Event:
push
-
Statement type: