WLED Central Controller
A web-based central controller for multiple WLED instances, allowing you to discover, manage, group, and schedule actions across your WLED devices.
Features
- Device Management: Add, edit, and monitor multiple WLED devices
- Grouping: Organize devices into logical groups (e.g., "Living Room", "Garden")
- Group Actions: Apply presets and playlists to individual devices or groups
- Scheduling: Automate preset/playlist changes with cron-based schedules
- UK Timezone Support: All times displayed in Europe/London timezone (dd/MM/yyyy HH:mm format)
- RESTful API: Complete backend API for integration with other systems
- Modern UI: Clean, responsive web interface built with React
Tech Stack
Backend
- Node.js v20+ with TypeScript
- Express.js for HTTP API
- SQLite via Prisma ORM
- node-cron for scheduling
- Zod for validation
Frontend
- React 18 with TypeScript
- Vite build tool
- React Router for navigation
- Luxon for date/time handling
Quick Start with Docker
The easiest way to run the WLED Controller is using Docker Compose:
# Clone the repository
cd wled-controller
# Start the services
docker-compose up -d
# Access the web UI
# Open http://localhost in your browser
The backend API will be available at http://localhost:3000/api.
Manual Setup
Backend Setup
cd backend
# Copy environment file
cp .env.example .env
# Install dependencies
npm install
# Generate Prisma Client
npm run prisma:generate
# Run database migrations
npm run prisma:migrate
# Development mode
npm run dev
# Production build
npm run build
npm start
Frontend Setup
cd frontend
# Copy environment file
cp .env.example .env
# Install dependencies
npm install
# Development mode
npm run dev
# Production build
npm run build
npm run preview
Configuration
Backend Environment Variables
Create a .env file in the backend directory:
PORT=3000
DATABASE_URL="file:./dev.db"
LOG_LEVEL=info
Frontend Environment Variables
Create a .env file in the frontend directory:
VITE_API_BASE_URL=http://localhost:3000/api
Usage Guide
1. Add Devices
- Navigate to the Devices page
- Click Add Device
- Enter device details:
- Name (e.g., "Kitchen Strip")
- IP Address (e.g., "192.168.1.50")
- Port (default: 80)
- Enabled checkbox
- Use Ping to verify connectivity
2. Create Groups
- Navigate to the Groups page
- Click Create Group
- Enter group name
- Select devices to include
- Save
3. Control Groups
- Click Control on any group
- Apply a preset:
- Enter preset ID
- Click Apply Preset
- Or apply a playlist:
- Enter comma-separated preset IDs
- Configure duration, transition, repeat options
- Click Apply Playlist
4. Schedule Actions
- Navigate to the Schedules page
- Click Create Schedule
- Configure:
- Name
- Group
- Type (Preset or Playlist)
- Cron expression (e.g.,
30 18 * * *for 6:30 PM daily) - Timezone (default: Europe/London)
- Action payload (preset ID or playlist config)
- Enable/disable schedules with the toggle
API Documentation
Devices
GET /api/devices- List all devicesPOST /api/devices- Create deviceGET /api/devices/:id- Get devicePUT /api/devices/:id- Update deviceDELETE /api/devices/:id- Delete devicePOST /api/devices/:id/ping- Ping device
Groups
GET /api/groups- List all groupsPOST /api/groups- Create groupGET /api/groups/:id- Get groupPUT /api/groups/:id- Update groupDELETE /api/groups/:id- Delete groupPOST /api/groups/:id/preset- Apply preset to groupPOST /api/groups/:id/playlist- Apply playlist to group
Schedules
GET /api/schedules- List all schedulesPOST /api/schedules- Create scheduleGET /api/schedules/:id- Get schedulePUT /api/schedules/:id- Update scheduleDELETE /api/schedules/:id- Delete schedule
WLED Integration
The controller communicates with WLED devices over HTTP using the JSON API:
/json/info- Device information/json/state- Device state and control
Preset Application
POST /json/state
{
"ps": 5
}
Playlist Application
POST /json/state
{
"playlist": {
"ps": [1, 2, 3],
"dur": [30, 30, 30],
"transition": 0,
"repeat": 0,
"end": 1
}
}
Cron Expression Format
Schedules use standard cron syntax:
* * * * *
┬ ┬ ┬ ┬ ┬
│ │ │ │ │
│ │ │ │ └─ day of week (0-7, 0 and 7 are Sunday)
│ │ │ └────── month (1-12)
│ │ └─────────── day of month (1-31)
│ └──────────────── hour (0-23)
└───────────────────── minute (0-59)
Examples
30 18 * * *- Every day at 6:30 PM0 9 * * 1-5- Weekdays at 9:00 AM*/15 * * * *- Every 15 minutes0 22 * * 0- Sundays at 10:00 PM
Development
Backend Tests
cd backend
npm test
Code Formatting
# Backend
cd backend
npm run format
# Frontend
cd frontend
npm run format
Linting
# Backend
cd backend
npm run lint
# Frontend
cd frontend
npm run lint
Deployment
Behind a Reverse Proxy
The application is designed to work behind HTTPS reverse proxies. Configure your reverse proxy to:
- Serve the frontend on your domain
- Proxy
/api/*requests to the backend - Set appropriate CORS headers if needed
Example Nginx configuration:
server {
listen 443 ssl;
server_name wled.example.com;
ssl_certificate /path/to/cert.pem;
ssl_certificate_key /path/to/key.pem;
location / {
proxy_pass http://localhost:80;
}
location /api {
proxy_pass http://localhost:3000;
}
}
Troubleshooting
Device Not Reachable
- Verify the device IP address is correct
- Ensure the device is on the same network
- Check firewall rules
- Use the Ping button to test connectivity
Schedule Not Triggering
- Verify the cron expression is correct
- Check the schedule is enabled
- Ensure the group has enabled devices
- Review backend logs for errors
Database Issues
cd backend
# Reset database
rm dev.db
npm run prisma:migrate
# View database
npm run prisma:studio
License
MIT
Contributing
Contributions welcome! Please open an issue or pull request.
Description
Languages
TypeScript
93.7%
CSS
3.9%
PowerShell
1.3%
Dockerfile
0.6%
HTML
0.3%
Other
0.2%