Feature-rich Raspberry Pi project for controlling an RGB LED strip light. Includes:
- Web-based REST API (Flask) for remote control (on/off, color, brightness, effects)
- Web-based interface for manual remote control
- Homebridge integration for Apple HomeKit and Siri voice control
- Command-line interface for scripting and manual control
- Multiple built-in LED effects (breathing, fade, rainbow, random, campfire, candle, aurora, heartbeat, lightning, and more)
- Time-based color profiles and scheduled automation (systemd, cron)
- Modular, testable Python codebase with hardware abstraction and full unit test suite
Easily automate, script, or integrate your LED strip with smart home platforms and custom workflows.
Hardware
- Raspberry Pi (tested on Pi Zero W Rev 1.1)
- LED strip light
The guide How to control a RGB LED Strip Light with a Raspberry Pi Zero W shows how to physically connect a 12 V RGB strip to a Raspberry Pi Zero W.
Software
- Python 3.13+
- pip dependencies:
flask,waitress,pigpio(see pyproject.toml)
graph TD
subgraph Clients
SIRI["Siri / HomeKit"]
WEBUI["Web Browser\n(index.html)"]
SHELL["Shell / Cron"]
end
subgraph Entry Points
HB["Homebridge\n(homebridge-http-rgb-push)"]
HTTP["http_server.py\n(Flask REST API)"]
CLI["run.py\n(CLI)"]
end
subgraph Config
CM["ConfigManager\n(config.toml)"]
PA["PinAssignment"]
PM["ProfileManager\n(time-based colors)"]
end
subgraph LED Control
GPIO["GPIOService\n(pigpio PWM)"]
CTRL["LEDStripLightController\n(color · brightness · thread)"]
ER["EffectRunner\n(effect dispatch)"]
EFX["effects.py\n(breathing · fade · campfire\ncandle · aurora · heartbeat · lightning\nrainbow · cycle · random)"]
end
HW["RGB LED Strip\n(hardware)"]
SIRI -->|"HomeKit protocol"| HB
HB -->|"HTTP"| HTTP
WEBUI -->|"HTTP"| HTTP
SHELL --> CLI
HTTP --> CTRL
CLI --> CTRL
CM --> PA
CM --> PM
PA --> GPIO
GPIO --> CTRL
CTRL --> ER
ER -->|"background thread"| EFX
PM --> ER
GPIO --> HW
Configure the application: config.toml
This project uses the pigpio library for PWM control of the GPIO pins. To install it on your Raspberry Pi:
sudo apt-get install pigpio
sudo systemctl enable pigpiod
sudo systemctl start pigpiodcd ~/raspberry/led-strip-light
# Create venv and install runtime dependencies
python3 -m venv --upgrade-deps .venv
.venv/bin/pip install .
# Install and start the systemd service
sudo cp deploy/systemd/ledstriplight-http-server.service /etc/systemd/system/
sudo systemctl daemon-reload
sudo systemctl enable ledstriplight-http-server.service
sudo systemctl start ledstriplight-http-server.serviceFor full deployment instructions see the READMEs in deploy/:
deploy/systemd/— systemd service installation and managementdeploy/cron/— scheduled automation with crondeploy/logrotate.d/— log rotation for the cron logdeploy/homebridge/— Apple HomeKit integration
# Create and activate virtual environment (from repo root)
python3 -m venv --upgrade-deps .venv
source .venv/bin/activate
# Install dependencies + test extras
pip install -e ".[dev]"The application supports multiple effects via command-line arguments:
# Basic profile effect (morning/evening colors based on time of the day)
./run.py profile
# Breathing effect with custom color and duration
./run.py breathing --color red --duration 3000
# Use hex colors
./run.py breathing --color "#FF6347"
# Color cycling through multiple colors
./run.py cycle --colors red,green,blue,yellow --duration 500
# Fade between two colors
./run.py fade --from black --to white --duration 5000
# Random color changes
./run.py random --interval 2000
# Campfire effect (dynamic warm flicker)
./run.py campfire --duration 60000 --base-color "#FF4E04"
# Candle effect (gentler, slower flicker)
./run.py candle --duration 60000
# Aurora drift (slow HSV wander, green↔violet by default)
./run.py aurora --duration 120000
# Heartbeat (double-pulse thump-thump-rest)
./run.py heartbeat --color red
# Rainbow sweep (continuous HSV hue rotation)
./run.py rainbow --period-ms 8000
# Lightning (random bright flashes with fast decay)
./run.py lightning --max-gap-ms 5000
# Get help
./run.py --helpThe project includes comprehensive unit tests with hardware mocking. Tests can be run from the repo root (pytest configuration is in pyproject.toml):
# Run all tests (from repo root)
pytest
# Run a specific test file
pytest tests/test_color.py
# Run tests with HTML coverage report
pytest --cov-report=htmlled-strip-light/
├── deploy/
│ ├── cron/ # Cron job for scheduled automation
│ ├── homebridge/ # Homebridge config for Apple HomeKit
│ │ ├── armv6/ # Pi Zero W (npm install method)
│ │ └── armv7/ # Pi Zero 2 W (apt install method)
│ ├── logrotate.d/ # Logrotate drop-in for the cron log
│ └── systemd/ # Systemd service files
├── docs/ # Documentation and wiring diagrams
├── src/
│ ├── cli/
│ │ └── cli_handler.py # Command-line interface handler
│ ├── config/
│ │ ├── color_profile.py
│ │ ├── config_manager.py # Reads config.toml
│ │ └── pin_assignment.py
│ ├── led/
│ │ ├── color.py
│ │ ├── effect_runner.py
│ │ ├── effects.py # LED effects (breathing, fade, campfire, aurora, …)
│ │ ├── gpio_service.py # pigpio PWM interface
│ │ ├── led_strip_light_controller.py
│ │ └── profile_manager.py # Time-based color profiles
│ ├── static/
│ │ └── index.html # Web UI
│ ├── utils/
│ │ └── graceful_shutdown.py
│ ├── config.toml # GPIO pins and color profiles
│ ├── http_server.py # Flask REST API entry point
│ └── run.py # CLI entry point
└── tests/ # Unit tests with mocked hardware
The project includes a Flask server for remote control via HTTP endpoints and a web-based control interface.
A responsive web interface is available for controlling the LED strip through your browser:
- Access: Navigate to
http://localhost:5000(orhttp://YOUR_PI_IP:5000from other devices) - Features:
- Power control (On/Off) with visual status indicators
- Color picker and preset color buttons (Red, Green, Blue, White, Yellow, Magenta, Cyan)
- Brightness slider with real-time adjustment
- Start/stop built‑in effects (breathing, campfire, candle, aurora, heartbeat, lightning, rainbow, random, fade) with parameter inputs
- Live status + active effect display and error handling
- Mobile-friendly responsive design
Endpoints:
Core control:
POST /on— Turn the light on (restores last color; warm yellow by default)POST /off— Turn the light off (black)GET /status— Get on/off state (1/0)GET /color— Get current color (hex with #)POST /color/<value>— Set color (6‑digit hex, with or without #)GET /brightness— Get current brightness (0–100)POST /brightness/<int:value>— Set brightness (0–100)
Effects management:
GET /effects— List available effects + currently activePOST /effects/stop— Stop any running effectPOST /effects/breathingJSON:{ "color": "FF0000", "duration": 2000 }POST /effects/campfire(optional JSON overrides: base_color, duration, update_hz, min_brightness, max_brightness, hue_jitter, saturation, spark_chance, spark_gain, tau_ms, gamma)POST /effects/candle(same override keys as campfire)POST /effects/aurora(optional JSON overrides: duration, update_hz, hue_min, hue_max, saturation, min_brightness, max_brightness, hue_step, brightness_step, tau_ms, gamma)POST /effects/heartbeat(optional JSON overrides: color, beat_ms, gap_ms, rest_ms, second_beat_scale)POST /effects/rainbow(optional JSON overrides: period_ms, duration, update_hz, saturation, brightness, gamma)POST /effects/lightning(optional JSON overrides: flash_color, background_color, min_gap_ms, max_gap_ms, flash_ms, intensity_min, intensity_max, aftershock_chance, max_aftershocks, duration, gamma)POST /effects/randomJSON:{ "interval": 2000 }POST /effects/cycleJSON:{ "duration": 2000, "colors": ["FF0000","00FF00","0000FF"] }POST /effects/fadeJSON:{ "from": "000000", "to": "FFFFFF", "duration": 5000 }POST /effects/profileJSON:{ "duration": 10000 }(fades from black to active profile color)
Starting the server:
cd src
./http_server.pyExample usage:
curl -X POST http://localhost:5000/on
curl -X POST http://localhost:5000/color/ff0000
curl -X POST http://localhost:5000/brightness/80
curl http://localhost:5000/status
# Start campfire effect
curl -X POST http://localhost:5000/effects/campfire
# Start candle effect for 30s
curl -X POST -H 'Content-Type: application/json' \
-d '{"duration":30000}' http://localhost:5000/effects/candle
# Start aurora drift with a narrower hue range (teal→violet)
curl -X POST -H 'Content-Type: application/json' \
-d '{"hue_min":0.45,"hue_max":0.78,"tau_ms":3000}' \
http://localhost:5000/effects/aurora
# Heartbeat in pink with a softer second beat
curl -X POST -H 'Content-Type: application/json' \
-d '{"color":"FF69B4","second_beat_scale":0.5}' \
http://localhost:5000/effects/heartbeat
# Rainbow sweep at half-brightness, 5s per rotation
curl -X POST -H 'Content-Type: application/json' \
-d '{"period_ms":5000,"brightness":0.5}' \
http://localhost:5000/effects/rainbow
# Lightning with cyan flashes and shorter gaps
curl -X POST -H 'Content-Type: application/json' \
-d '{"flash_color":"00FFFF","max_gap_ms":3000}' \
http://localhost:5000/effects/lightning
# Breathing effect: blue, 3s cycles
curl -X POST -H 'Content-Type: application/json' \
-d '{"color":"0000FF","duration":3000}' http://localhost:5000/effects/breathing
# Custom cycle effect
curl -X POST -H 'Content-Type: application/json' \
-d '{"colors":["FF0000","00FF00","0000FF","FFFF00"],"duration":800}' http://localhost:5000/effects/cycle
# Fade from black to warm white over 10s
curl -X POST -H 'Content-Type: application/json' \
-d '{"from":"000000","to":"FFC864","duration":10000}' http://localhost:5000/effects/fade
# Run current time-based profile color (10s fade in)
curl -X POST -H 'Content-Type: application/json' \
-d '{"duration":12000}' http://localhost:5000/effects/profile
# Stop current effect
curl -X POST http://localhost:5000/effects/stopYou can integrate the LED strip with Homebridge for Apple HomeKit support. All installation and configuration instructions, including example Homebridge accessory configuration, can be found in the deploy/homebridge/ directory of this repository.
See README.md for details on how to set up Homebridge integration and connect it to the Flask server endpoints.
| Symptom | Likely cause | Fix |
|---|---|---|
OSError: Cannot connect to pigpio daemon on startup |
pigpiod isn't running |
sudo systemctl enable --now pigpiod |
| App starts but the strip never lights up | Wrong GPIO pins, or wiring doesn't match config.toml |
Verify the [pins] BCM numbers against your wiring (see the wiring guide) |
BCM pin number N is out of range (0-27) |
A [pins] value uses a physical-header number instead of a BCM GPIO number |
Use BCM numbering (0–27) in config.toml |
No [profile.*] sections found / Duplicate profile start_hour values |
config.toml has no profiles, or two share a start_hour |
Define at least one [profile.NAME] and give each a distinct start_hour (0–23) |
POST /color or /effects/* returns 400 Unknown color |
Color name/hex isn't recognized | Use a known name or 6-digit hex (e.g. red, FF6347) |
POST /effects/* returns 503 previous effect is still stopping |
The prior effect hasn't stopped yet | Retry after a moment; the running effect exits on its next interrupt poll |
| Server unreachable from other devices | Bound to localhost, or blocked by the firewall | Set FLASK_HOST=0.0.0.0 and allow the port (see deploy/ufw/) |
LEDs stay lit after systemctl stop |
Old build without SIGTERM cleanup | Update to a build where http_server turns the strip off on shutdown |
Homebridge crashes with SIGILL on a Pi Zero W |
apt package ships an ARMv7+ Node.js binary | Use the ARMv6 npm install method in deploy/homebridge/armv6/ |
Found a bug or have an idea? Open an issue or send a PR.
Run pytest before submitting and keep changes focused.
MIT © Jan Rothen — see LICENSE for details.