Skip to main content

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/info in a browser; you should see firmware version, mac, and LED count.

Setup steps

  1. Find the WLED device IP from your router or the WLED iOS/Android app.
  2. Go to System → Devices → Add Device, choose the WLED (ESP LED Controller) driver (key wled), and enter the controller's IP in the IP Address / Host field. Leave Port at 80.
  3. If you've turned on Settings → Security → API access token in WLED, set the API Token (api_key) attribute on the device row. WLED only enforces the token on writes; the driver attaches it as the X-WLED-Token header (it's harmlessly included on reads too).
  4. Create one Zone per WLED segment you want to control independently, under the Lights subsystem (see the note below). Set the zone's Address to the integer segment id (0 for the main / only segment; most installs only have one). The driver does not auto-create zones or discover segments — you add each zone by hand, and the segment a command targets is taken from that zone's Address.
  5. Drive the strip with the on / off / set_level / set_color / set_effect / set_palette / set_preset commands directly, or wire them into scene macros.
Subsystem placement

WLED zones belong in the Lights subsystem. The driver hints lights, which exactly matches the default-seeded Lights subsystem, so the New Zone editor pre-selects it for you — just confirm the selection. If you've renamed or deleted that subsystem, pick the lighting subsystem manually; the driver never creates one.

Attribute reference

ScopeAttributeDirectionNotes
deviceiprequiredLAN IP or mDNS hostname.
deviceportoptionalDefault 80.
deviceapi_keyoptional, secureWLED API token (only set if Security is enabled).
devicestatus_intervaloptionalPoll cadence in ms. Default 10000. Set to 0 to disable polling and rely on write-only command flow.
devicetransitionoptionalDefault fade time sent on every write, in 100ms units. WLED default is 7 (~700 ms).
devicefirmware_versionread-onlyCaptured on connect.
devicedevice_nameread-onlyFriendly name set in WLED.
devicemacread-onlyController MAC.
deviceled_countread-onlyNumber of LEDs the controller is driving.
devicestateread-onlyon / off. Only written when no zones exist — segment 0 then stands in as device-level state.
devicelevelread-onlyBrightness 0-100. Same fallback as state: only written when no zones exist.
zonestateread-onlyon / off.
zonelevelread-onlyBrightness 0-100 (mapped from WLED's 0-255).
zonecolorread-onlyLast-reported foreground color in RRGGBB (or RRGGBBWW) hex.
zoneeffectread-onlyEffect id active on this segment.
zonepaletteread-onlyPalette id active on this segment.
zonepresetread-onlyActive preset id, if any.

All of these attribute names are cataloged, so they autocomplete in the Attribute editor's name picker and can drive attribute triggers — for example, fire a macro when a zone's state flips to on, or when level crosses a threshold.

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.

When you command a WLED zone, GEM passes that zone's Address through as the segment id automatically — you don't repeat it in the command. If a zone has no Address set, the driver falls back to segment 0.

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). Use get_effects to list the names supported by the connected firmware.
  • set_palette — palette id (integer). Use get_palettes to 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_effects once 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_effect like 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

SymptomLikely cause
Writes return 401 / nothing happensAPI security token enabled on the controller but api_key not set on the device row (or wrong value).
Polling silent, never reports statestatus_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 fadingtransition 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.
  • Zones — creating the per-segment zones and setting each zone's Address.
  • Subsystems — the Lights subsystem these zones live under.
  • Devices — the device editor, secure attributes (the API token), and Reload.
  • Commands — the command tester for running get_info / get_effects / get_palettes.