A Python-based HTTP server for controlling WS2812B (NeoPixel) RGB LED strips or Ring LEDs via SPI interface on nearly any Single Board Computer (SBC) / eSBC / DevBoard / EvalBoard / ESB running Linux, including Busybox/Buildroot!
Tested on Luckfox Pico Ultra W with the Buildroot image and a MIS5001 Camera
- π Web Interface - Modern, responsive control panel with Solarized theme
- π¨ Color Picker - Click the color preview for a visual color picker
- π Dark Mode - Automatic dark mode with manual toggle and cookie persistence
- π REST API - Control LEDs programmatically via HTTP requests
- π‘ Individual LED Control - Update single LEDs via API
- π Health Monitoring - Real-time system stats and status endpoint
- π§΅ Thread-Safe - Proper locking for concurrent access
- π‘οΈ Error Handling - Graceful error handling and recovery
- π¨ Startup Animation - Ring animation on startup to verify LEDs
- π API Documentation - Built-in interactive documentation page
- π― Hex Editing - Click hex values to edit colors directly
- SBC (any model with SPI support)
- WS2812B LED strip (NeoPixels)
- Appropriate power supply for your LED strip
- Proper level shifting (3.3V to 5V) if needed
- Python 3.10+ (uses native standard library only!)
- SPI enabled on your SBC
spidevPython package (Linux only, see requirements.txt)- Works on minimal Linux distributions like Buildroot
sudo raspi-config
# Navigate to: Interface Options -> SPI -> Enablesudo luckfox-config
# Navigate to: Advanced -> SPI -> [Choose your port] -> enableNote: You may need to disable RGB and PWM5
Example Luckfox Pico Ultra W /etc/luckfox.cfg
SPI0_M0_CS_ENABLE=0
SPI0_M0_MODE=1
RGB_ENABLE=0
TS_ENABLE=0
CSI_ENABLE=1
PWM5_M2_STATUS=0
SPI0_M0_STATUS=1
SPI0_M0_MISO_ENABLE=0
SPI0_M0_SPEED=2400000
USB_MODE=peripheral
git clone https://github.com/platima/Python-WS2812B
cd Python-WS2812B# On Raspberry Pi OS or similar
pip install -r requirements.txt
# On Buildroot or minimal systems, spidev may already be included
# or you may need to install it via your package managerEdit the constants at the top of ws.py:
PORT = 8080 # HTTP server port
NUM_LEDS = 16 # Number of LEDs in your strip
DEFAULT_BRIGHTNESS = 64 # Default brightness (0-255)
RING_SPEED = 0.03 # Startup animation speedpython ws.pyYou should see:
β SPI initialized successfully
Running startup animation...
β Initialized 16 LEDs
==================================================
π WS2812B LED Controller Started
==================================================
Control Panel: http://localhost:8080
API Docs: http://localhost:8080/api/docs
Health Check: http://localhost:8080/health
LEDs: 16 connected
==================================================
Press Ctrl+C to stop the server
GET /
Interactive web interface with:
- RGB sliders with synchronized number inputs
- Visual color picker (click the color preview box)
- Dark/light mode toggle with cookie persistence
- Real-time color preview showing
rgb()and hex values - Clickable hex values for direct editing
GET /update
Update LED colors via query parameters.
Query Parameters:
r- Red value (0-255, optional)g- Green value (0-255, optional)b- Blue value (0-255, optional)
Examples:
# Set all LEDs to red
curl "http://localhost:8080/update?r=255&g=0&b=0"
# Set all LEDs to purple
curl "http://localhost:8080/update?r=128&g=0&b=128"
# Turn off all LEDs
curl "http://localhost:8080/update?r=0&g=0&b=0"GET /update_led
Update a single LED color via query parameters.
Query Parameters:
index- LED index (0 to NUM_LEDS-1, required)r- Red value (0-255, required)g- Green value (0-255, required)b- Blue value (0-255, required)
Examples:
# Set first LED to red
curl "http://localhost:8080/update_led?index=0&r=255&g=0&b=0"
# Set LED 5 to green
curl "http://localhost:8080/update_led?index=5&r=0&g=255&b=0"
# Turn off last LED (index 15 for 16 LEDs)
curl "http://localhost:8080/update_led?index=15&r=0&g=0&b=0"GET /health
Returns system status and statistics in JSON format.
Example Response:
{
"status": "ok",
"server_uptime_seconds": 3600.52,
"server_uptime": "1h 0m 0s",
"updates_processed": 142,
"num_leds": 16,
"current_color": {
"r": 128,
"g": 64,
"b": 255
},
"system": {
"platform": "Linux",
"platform_release": "5.10.17-v7l+",
"python_version": "3.10.2",
"cpu_count": 4,
"memory": {
"total_mb": 3906.3,
"available_mb": 2453.1,
"used_percent": 37.2
},
"load_average": [0.45, 0.52, 0.48],
"cpu_temp_c": 42.8,
"system_uptime": "5h 23m"
}
}Note: System stats use native Python and /proc filesystem (Linux only). Available stats will vary by platform.
GET /api/docs
Interactive API documentation with examples.
SBC WS2812B LED Strip
------------ -----------------
MOSI GPIO ----------> Data In (DIN)
GND ----------------> GND
+5V (from separate power supply)
Important:
- Use a separate 5V power supply for the LEDs (don't power from Pi)
- Consider using a level shifter for the data line (3.3V β 5V)
- Add a 300-470Ξ© resistor in series with the data line
- Add a 1000ΞΌF capacitor across the LED strip power supply
- Bus: 0
- Device: 0
- Speed: 2.4 MHz
- Encoding: Each bit is represented as 3 SPI bits
0bit β0b100(high-low-low)1bit β0b110(high-high-low)
- All SPI operations are protected by a threading lock
- LED state updates are atomic
- Safe for concurrent HTTP requests
- SPI initialization failure detection
- Graceful error handling for LED updates
- Automatic cleanup on exit (using atexit)
- Detailed error messages
β Failed to initialize SPI: [Errno 2] No such file or directory: '/dev/spidev0.0'
Solution: Enable SPI via sudo raspi-config
β Failed to initialize SPI: [Errno 13] Permission denied: '/dev/spidev0.0'
Solution: Add your user to the SPI group:
sudo usermod -a -G spi $USER
# Log out and back in- Check wiring (MOSI to DIN)
- Verify power supply voltage (should be 5V)
- Try adjusting SPI speed (2.4 MHz works for most)
- Check if your LEDs are WS2812B (not WS2811 or SK6812)
- Check power supply
- Verify SPI is enabled
- Check first LED isn't damaged
- Ensure proper ground connection
# TODO: Add tests
python -m pytest tests/The code includes:
- Comprehensive docstrings
- Type hints where applicable
- Error handling
- Thread safety measures
- Resource cleanup
See LICENSE file for details.
Pull requests are welcome! Please ensure:
- Code follows existing style
- Docstrings are included
- Error handling is appropriate
- Thread safety is maintained
- β¨ Added visual color picker (click color preview box)
- β¨ Solarized dark/light theme with system preference detection
- β¨ Manual theme toggle with cookie persistence
- β¨ RGB and hex value display in status bar
- β¨ Clickable hex editing for direct color input
- β¨ Synchronized sliders and number inputs
- β¨ Individual LED control API endpoint (
/update_led) - β¨ Footer with GitHub link and theme toggle
- π§ Improved startup messages with IP address detection
- β Fixed race condition in LED state updates
- β Added comprehensive error handling
- β Improved resource management with atexit
- β Added health check endpoint with system stats
- β Added API documentation endpoint
- β Enhanced logging and status messages
- β Native Python system monitoring (no external deps needed!)
- β Improved thread safety
- β Buildroot compatible (minimal dependencies)
- Initial release
- Basic web interface
- SPI control of WS2812B LEDs
- Startup animation