WLED (ESP LED Controller)
Local control of LED strips driven by WLED firmware on ESP8266 / ESP32 boards (QuinLED, Athom, Dig-Quad, custom). Uses the on-device HTTP/JSON API — no cloud account, no MQTT broker, no Home Assistant in the middle.
Prerequisites
- WLED 0.13 or newer recommended. Older builds work but lack a few segment fields.
- Device on the same LAN as GEM. Static DHCP reservation strongly recommended — WLED defaults to DHCP and the IP can drift.
- Verify the API with
http://<wled-ip>/json/infoin a browser; you should see firmware version, mac, and LED count.
Setup steps
- Find the WLED device IP from your router or the WLED iOS/Android app.
- Add a Device row in System → Devices with driver
wledand the IP. Port stays at 80. - If you've turned on Settings → Security → API access token in WLED, set the
api_keyattribute on the device row. Reads are unauthenticated by design; writes will include the token in theX-WLED-Tokenheader. - Add one Zone per WLED segment you want to control independently.
zone.addressis the integer segment id (0for the main / only segment; most installs only have one). - Use the
set_color,set_effect,set_palette, andset_presetcommands directly or wire them into scene macros.
Attribute reference
| Scope | Attribute | Direction | Notes |
|---|---|---|---|
| device | ip | required | LAN IP or mDNS hostname. |
| device | port | optional | Default 80. |
| device | api_key | optional, secure | WLED API token (only set if Security is enabled). |
| device | status_interval | optional | Poll cadence in ms. Default 10000. Set to 0 to disable polling and rely on write-only command flow. |
| device | transition | optional | Default fade time sent on every write, in 100ms units. WLED default is 7 (~700 ms). |
| device | firmware_version | read-only | Captured on connect. |
| device | device_name | read-only | Friendly name set in WLED. |
| device | mac | read-only | Controller MAC. |
| device | led_count | read-only | Number of LEDs the controller is driving. |
| zone | state | read-only | on / off. |
| zone | level | read-only | Brightness 0-100 (mapped from WLED's 0-255). |
| zone | color | read-only | Last-reported foreground color in RRGGBB (or RRGGBBWW) hex. |
| zone | effect | read-only | Effect id active on this segment. |
| zone | palette | read-only | Palette id active on this segment. |
| zone | preset | read-only | Active preset id, if any. |
Zone address format
Integer segment id. WLED supports multiple software-defined segments per physical strip (set up in the WLED Web UI under Segments). Address 0 = the first segment. If you only have one continuous strip you only need one zone with address 0.
If you omit zone.address the driver will default to segment 0 for commands.
Commands
on/off/toggle— per-segment power.set_level— brightness 0-100, mapped to WLED's bri 0-255.set_color— RRGGBB hex (ff8800) or RRGGBBWW hex (ffaa00ff) for RGBW strips.set_effect— effect id (integer). Useget_effectsto list the names supported by the connected firmware.set_palette— palette id (integer). Useget_palettesto list.set_speed/set_intensity— fx parameters 0-255.set_preset— activate a stored preset by id (whole device).get_info,get_state,get_effects,get_palettes— diagnostic reads.
Known limitations
- Effect / palette ids are firmware-version specific. WLED 0.14 ships ~187 effects; older 0.10 had ~118. The driver passes the id through; the controller is the source of truth. The recommended pattern is to call
get_effectsonce during integration and pick the id you want. - Live audio sync (Sound Reactive) and 2D matrix effects are not separately modeled — they're just effect ids that WLED reports. Choose them via
set_effectlike any other. - DDP / E1.31 streaming is out of scope — for ArtNet / sACN flows use a dedicated lighting console rather than the JSON API.
- Per-segment color order and mapping is set in the WLED UI, not via this driver. If colors look swapped, fix the RGB order in WLED Settings → LED Preferences.
Troubleshooting
| Symptom | Likely cause |
|---|---|
| Writes return 401 / nothing happens | API security token enabled on the controller but api_key not set on the device row (or wrong value). |
| Polling silent, never reports state | status_interval set to 0 (write-only mode) or no zones created yet — the driver leaves device-level state populated but doesn't fan out per segment. |
| Brightness "snaps" instead of fading | transition attribute set to 0. Default WLED behavior is ~700 ms; set it to 7 (or higher) to restore the fade. |
set_color returns "invalid color" | Color string must be 6 or 8 hex characters (RRGGBB or RRGGBBWW). Leading # is accepted; spaces / parentheses / decimal are not. |
| Colors look wrong (red vs. green swapped) | LED color order misconfigured in WLED itself — fix under Settings → LED Preferences → Color Order, not here. |