218 lines
6.8 KiB
Markdown
218 lines
6.8 KiB
Markdown
# 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.
|