REST output: sending HTTP requests
PixDrive Studio sends HTTP requests to WLED, Philips Hue or any other HTTP API – from a REST device or straight from your Lua effects.
Updated
Paste the guide into an AI chat, then describe what the script should do.
Besides Art-Net, sACN and TPM2.Net, PixDrive Studio can send HTTP requests. Use them to control anything with an HTTP API: a WLED controller, a Philips Hue bridge, a Shelly, a media server or your own webhook.
There are two ways, and you can combine them:
- A REST device gets pixels like any other device. A small Lua script turns their colors into a request. Use this when an HTTP device should simply light up along with the show.
- Effect scripts send requests themselves, with
rest_get("WLED", "/path")orhttp_get(url). Use this when you need full control: requests on the beat, at specific points in a show, or with any data you like.
This page covers requests that PixDrive sends. To control PixDrive itself over HTTP, see External control API (REST & OSC).
Adding a REST device
- Click Add Device in the device list.
- Choose REST (HTTP) as the protocol.
- Enter a name, for example
WLED, and the base URL in the address field, for examplehttp://192.168.178.52. There is no port field for REST; put a non-standard port in the URL. - Click Add.
Select the device in the list and the Properties panel on the right shows all REST settings. At the top it shows how to address the device from an effect script, for example rest_get("WLED", "/path").
Settings
- Base URL: the device’s address. A
pathfrom the script is appended.https://works too. - Method: GET, POST, PUT, PATCH or DELETE. Used when the script doesn’t set its own method.
- Timeout (ms): how long PixDrive waits for a response (100 to 60,000 ms).
- Mode: Stream (on color change) sends whenever the colors change. One-shot (on trigger) sends only when you click Send now or an MCP client triggers it.
- Max. rate (Hz): upper limit in stream mode, 0.1 to 60 requests per second. 10 Hz works well for WLED; a Hue bridge handles only about 10 requests per second in total.
- Headers: sent with every request, for example
Authorization: Bearer ….
Every request carries User-Agent: PixDrive-Studio/<version> unless you set your own User-Agent.
The request script
Whenever the REST device has something to send, it calls build_request(pixels, fixtures) in its script. The function gets the current colors of this device’s fixtures and returns what to send.
pixels[i] is a table with the channels of the LED type, each 0 to 255 (gamma-corrected, the same values Art-Net would send):
| LED type | Fields |
|---|---|
| RGB | r, g, b |
| RGBW | r, g, b, w |
| RGBCCT | r, g, b, ww, cw |
| CCT | bri, ct |
fixtures[i] describes the fixtures in device order: id, name, start (index of the first pixel in pixels) and count.
The script returns nil or {} to send nothing, one request table, or a list of them (64 at most). All fields are optional:
method: overrides the device’s methodpath: appended to the base URL, orurlfor a different full addressheaders: a table such as{ ["X-Key"] = "abc" }, adds to or replaces the device’s headersbody: a string is sent as is, a table as JSON (the headerContent-Type: application/jsonis then added automatically)
json_encode(value) turns a table into a JSON string. Tables with the keys 1 to n become arrays, an empty table becomes {}.
This script sets a WLED controller to the color of the first pixel through its HTTP API:
function build_request(pixels, fixtures)
local p = pixels[1]
if p == nil then return nil end
return {
method = "GET",
path = string.format("/win&A=255&R=%d&G=%d&B=%d", p.r, p.g, p.b),
}
end
The script runs in the same sandbox as effect scripts: no file access, no system commands, and a time limit of 250 ms per call. A script that doesn’t load can’t be applied; the error message shows the line.
Templates
Insert template above the editor loads a ready-made script:
- Generic JSON sends the first pixel’s color as
{ "r": …, "g": …, "b": … }. - WLED (JSON API) colors one WLED segment per fixture through
/json/state. - Philips Hue sets one lamp per fixture through API v1. The base URL is then
http://<bridge-ip>/api/<username>, and each fixture is named after its lamp’s ID, for example3.
Changes in the editor take effect after Apply script.
Preview and testing
Preview request shows the method, URL, headers and body of the requests for the current colors without sending anything. Below that are counters for sent and failed requests and the last error. Send now sends the current colors immediately, in either mode.
A REST device sends from its own background thread, so a slow or unreachable target doesn’t hold up the preview or the other outputs. In stream mode there is never more than one request in flight; colors that arrive in the meantime are merged instead of queued.
Requests from effect scripts
These functions are available in every effect script:
| Function | Purpose |
|---|---|
rest_get(device, path [, headers]) |
GET to the REST device’s base URL plus path |
rest_post(device, path, body [, headers]) |
POST, body as a string or table (JSON) |
rest_put(device, path, body [, headers]) |
PUT |
rest_request(device, { method, path, headers, body }) |
any method, otherwise the device’s |
http_get(url [, headers]) |
GET to a full URL |
http_post(url, body [, headers]), http_put(…) |
POST and PUT to a full URL |
http_request{ method, url, headers, body } |
any method |
json_encode(value) |
table as a JSON string |
The rest_* functions address a REST device by its name and use its base URL and headers. If the IP address changes, you update it in the device only, not in every script. A REST device without fixtures acts as an address book and sends nothing on its own. The name is case-sensitive. With an unknown name, for example after renaming a device, the function sends nothing and returns false. The effect keeps running, and the log gets a warning listing the existing REST devices.
The http_* functions don’t need a device; the full URL is in the script instead.
Rules
- The functions send in the background and don’t wait for a response. They return
trueif the request was queued andfalseotherwise. The script never sees the response. - Requests are only sent when the frame actually goes out: for live effects and while the sequencer plays. In the timeline’s hover preview, while dragging the playhead, when paused and when exporting, the script runs but sends nothing.
- Each effect sends at most 20 requests per second; anything above that is dropped.
render()runs 60 times a second, so never call the functions unconditionally every frame, only when something changes. - In scripts with
parallel = trueonly the first worker sends. - An invalid URL or method is a script error and shows up in the preview already.
Example: WLED follows the effect
This script colors the LEDs and sends the same color to the REST device WLED, at most ten times a second and only on change. sent is only updated once the request actually went out; otherwise a preview frame would swallow the first real request.
local sent, sent_at = nil, -1
function render()
local r = (sin(time) * 0.5 + 0.5)
for i = 0, led_count - 1 do set_led_rgb(i, r, 0.0, 0.0) end
local path = string.format("/win&A=255&R=%d&G=0&B=0", math.floor(r * 255))
if time < sent_at then sent_at = -1 end -- segment restarted in a loop
if path ~= sent and time - sent_at >= 0.1 and rest_get("WLED", path) then
sent, sent_at = path, time
end
end
Example: one request per beat
local was_beat = false
function render()
if audio_beat and not was_beat then
http_post("http://10.0.0.5/api/trigger", { scene = "flash" })
end
was_beat = audio_beat
end
In the sequencer and presets
Put effect scripts that use rest_get or http_get on the timeline as segments or save them as presets, like any other script. A preset can then also be fired as a cue through the external control API.
Don’t let segments that send to the same device overlap. Each script sends its own color, so a crossfade between two segments would make the device flicker. Fades in the timeline only affect the preview and the pixels, not the values a script sends over HTTP.
Through MCP
Through the MCP server an AI assistant can set up and test REST output:
add_devicewithprotocol: "Rest";ipmay be a full base URLset_rest_configsets URL, method, headers, timeout, mode, rate and scriptpreview_rest_requestshows the requests for the current colors without sendingsend_rest_devicesends immediately, also in one-shot modeadd_segmentwithlua_sourceputs a custom script on the timeline, for example one that usesrest_get
Notes and limits
- Responses are not evaluated. Status codes of 400 and above and connection errors count as failed and are written to the log (
app.log) at most every 5 seconds per device. - REST devices are not part of the exports (
.scn,.artnet, TPM2, WLED) and don’t appear in the export dialog’s device list. - A fixture’s color order doesn’t apply to REST; the script addresses channels by name.
- If two REST devices share a name,
rest_getuses the one added last. - WLED may apply its own gamma correction on top. If dark tones look too dark, raise them in the script.