Add Celebright holiday-lights integration
Home Assistant custom integration for Celebright (CLC-03) holiday-lights controllers, plus a standalone reference client. Local-only, reverse-engineered from the device's WebSocket protocol — talks directly to the controller on the LAN with no vendor cloud. - select entity exposes the device's saved scenes plus an off option - firmware-v2 protocol (savedScenes); getSystemState drives availability and the active scene, scene library fetched best-effort and cached - WS connect/recv/send wrapped in asyncio timeouts so a silent device can't blow past HA's setup deadline - config flow prompts for the controller IP; no credentials involved - docs/PROTOCOL.md: full v2 WebSocket protocol and device behaviors Migrated from the private dfritz/celebright with history dropped and internal site references removed. MIT-licensed. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01F6B8b3iYNv6QUftK2FDfYb
This commit is contained in:
@@ -0,0 +1,217 @@
|
||||
# Celebright Controller
|
||||
|
||||
Python-based controller for Celebright holiday lights systems.
|
||||
This implementation is based on reverse-engineering the network protocol from packet capture analysis.
|
||||
|
||||
## Project Components
|
||||
|
||||
This repository contains two main components:
|
||||
|
||||
1. **Home Assistant Integration** (`custom_components/celebright/`) — the maintained, **firmware-v2** custom component. This is the supported implementation.
|
||||
2. **Standalone Python Controller** (`celebright_controller.py`) — the original **v1** reverse-engineering reference/demo. It does **not** work against firmware 2.x (the `getPresetsAndEventsPaginated`/`loadPreset` topics it uses were removed); kept for historical reference.
|
||||
|
||||
> **Full protocol & operations reference: [`docs/PROTOCOL.md`](docs/PROTOCOL.md)** — v2 WebSocket topics, device behaviors, deploy, and access gotchas.
|
||||
|
||||
## Features
|
||||
|
||||
### Standalone Controller
|
||||
|
||||
- **Discovery**: Automatically discovers Celebright controllers on the local network via UDP broadcast
|
||||
- **WebSocket Communication**: Establishes WebSocket connection for real-time control
|
||||
- **Scene Management**: Lists and selects available lighting scenes/presets
|
||||
- **Power Control**: Turn off lights and disable schedules
|
||||
|
||||
### Home Assistant Integration
|
||||
|
||||
- **Automatic Discovery**: Finds controllers on your network automatically
|
||||
- **Select Entity**: Drop-down selector for choosing presets
|
||||
- **Native Integration**: Full Home Assistant device integration
|
||||
- **Automation Support**: Use in automations, scripts, and scenes
|
||||
|
||||
## Requirements
|
||||
|
||||
- Python 3.7+
|
||||
- `websockets` library
|
||||
|
||||
## Installation
|
||||
|
||||
```bash
|
||||
pip install -r requirements.txt
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
### Basic Usage
|
||||
|
||||
Run the main script to execute a complete demo sequence:
|
||||
|
||||
```bash
|
||||
python3 celebright_controller.py
|
||||
```
|
||||
|
||||
This will:
|
||||
1. Discover the Celebright controller on your network
|
||||
2. Establish a WebSocket connection
|
||||
3. List all available scenes
|
||||
4. Load a couple of example scenes
|
||||
5. Turn off the system
|
||||
6. Disconnect
|
||||
|
||||
### Using as a Library
|
||||
|
||||
```python
|
||||
import asyncio
|
||||
from celebright_controller import CelebrightController
|
||||
|
||||
async def control_lights():
|
||||
controller = CelebrightController()
|
||||
|
||||
# Discover controller
|
||||
device_info = controller.discover_controller()
|
||||
if not device_info:
|
||||
print("Controller not found")
|
||||
return
|
||||
|
||||
# Connect
|
||||
await controller.connect()
|
||||
|
||||
# Get available presets
|
||||
presets = await controller.get_presets()
|
||||
|
||||
# Load a specific preset
|
||||
if presets:
|
||||
await controller.load_preset(presets[0]['preset_uuid'])
|
||||
|
||||
# Turn off
|
||||
await controller.turn_off()
|
||||
|
||||
# Disconnect
|
||||
await controller.disconnect()
|
||||
|
||||
asyncio.run(control_lights())
|
||||
```
|
||||
|
||||
### Home Assistant Integration
|
||||
|
||||
For detailed Home Assistant integration instructions, see [custom_components/celebright/README.md](custom_components/celebright/README.md).
|
||||
|
||||
#### Quick Start
|
||||
|
||||
1. Copy the `custom_components/celebright` folder to your Home Assistant's `custom_components` directory
|
||||
2. Restart Home Assistant
|
||||
3. Go to Settings > Devices & Services > Add Integration
|
||||
4. Search for "Celebright"
|
||||
5. Follow the configuration flow
|
||||
|
||||
#### Deployment via Makefile
|
||||
|
||||
The project includes a Makefile for easy deployment to Home Assistant:
|
||||
|
||||
```bash
|
||||
make deploy
|
||||
```
|
||||
|
||||
This will:
|
||||
- Set up the remote directory with correct permissions
|
||||
- Deploy the integration to your Home Assistant instance
|
||||
- Remind you to restart Home Assistant
|
||||
|
||||
Configure the Makefile variables for your environment:
|
||||
- `REMOTE_HOST`: Your Home Assistant hostname or IP
|
||||
- `REMOTE_PATH`: Path to Home Assistant's custom_components directory
|
||||
- `REMOTE_USER`: SSH user for deployment
|
||||
|
||||
## Protocol Details
|
||||
|
||||
> The current **firmware-v2** protocol is documented in full in
|
||||
> [`docs/PROTOCOL.md`](docs/PROTOCOL.md). The sections below describe the
|
||||
> **original v1** protocol the standalone controller targets, retained for
|
||||
> historical reference.
|
||||
|
||||
Based on packet capture analysis of `celebright-full.pcapng`:
|
||||
|
||||
### Discovery Process
|
||||
- **Client sends**: UDP broadcast to port 49999 (discovery request with empty payload)
|
||||
- **Client listens**: On port 51234 for responses
|
||||
- **Controller responds**: From port 49999 to client's port 51234 with JSON payload containing:
|
||||
- Model name
|
||||
- Device ID
|
||||
- Firmware version
|
||||
- Number of LEDs
|
||||
- LED configuration
|
||||
|
||||
### WebSocket Communication
|
||||
- **Endpoint**: `ws://<device_ip>:80/ws`
|
||||
- **Message Format**: JSON with `topic` and `message` fields
|
||||
|
||||
```json
|
||||
{
|
||||
"topic": "command_name",
|
||||
"message": {
|
||||
// command parameters
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Available Commands
|
||||
|
||||
| Topic | Description | Parameters |
|
||||
|-------|-------------|------------|
|
||||
| `getPresetsAndEventsPaginated` | Get list of available scenes | None |
|
||||
| `loadPreset` | Load/activate a specific scene | `presetUuid`: UUID of preset |
|
||||
| `setTurnOffAndDisableSchedule` | Turn off lights and disable schedule | None |
|
||||
| `getSystemState` | Get current system state | None |
|
||||
|
||||
## Example Output
|
||||
|
||||
```
|
||||
============================================================
|
||||
STEP 1: DISCOVERY
|
||||
============================================================
|
||||
[Discovery] Listening for Celebright controller on UDP port 51234...
|
||||
[Discovery] Found controller at 192.168.1.50
|
||||
[Discovery] Model: CLC-03
|
||||
[Discovery] Device ID: 123456789
|
||||
[Discovery] Firmware: 1.41
|
||||
[Discovery] Number of LEDs: 296
|
||||
|
||||
============================================================
|
||||
STEP 2: WEBSOCKET CONNECTION
|
||||
============================================================
|
||||
[Connect] Connecting to ws://192.168.1.50:80/ws...
|
||||
[Connect] WebSocket connection established
|
||||
|
||||
============================================================
|
||||
STEP 3: LIST AVAILABLE SCENES
|
||||
============================================================
|
||||
[Presets] Requesting preset list...
|
||||
[Receive] Response topic: presetsPage
|
||||
[Presets] Found 12 presets:
|
||||
1. Halloween Twinkle - Orange, Purple and Green twinkle
|
||||
UUID: 3956e504-aafa-4f1c-8ad7-b00fb2381baa
|
||||
2. Warm White Solid - Warm White lights
|
||||
UUID: 6d2bdc6e-b015-4903-b8e5-5f7fc28c156a
|
||||
...
|
||||
```
|
||||
|
||||
## Network Requirements
|
||||
|
||||
- The controller must be on the same local network
|
||||
- UDP port 49999 must be accessible for sending discovery broadcasts
|
||||
- UDP port 51234 must be accessible for receiving discovery responses
|
||||
- TCP port 80 must be accessible for WebSocket communication
|
||||
|
||||
## Limitations
|
||||
|
||||
- The discovery process requires the ability to send UDP broadcasts on the local network
|
||||
- Broadcast discovery may not work across network segments or VLANs without proper routing
|
||||
- If broadcast discovery fails, you may need to specify the controller IP directly (feature could be added)
|
||||
- The script currently only handles the basic protocol commands observed in the packet capture
|
||||
|
||||
## License
|
||||
|
||||
MIT — see [LICENSE](LICENSE).
|
||||
|
||||
This is an unofficial, reverse-engineered implementation based on local network
|
||||
traffic analysis of the vendor device. It is not affiliated with or endorsed by
|
||||
Celebright. Use at your own risk.
|
||||
Reference in New Issue
Block a user