Reference
Protocols Tempolight uses
The wire details of every kind of light and beat source Tempolight talks to, for developers and network admins.
The wire details, for developers and network admins. How to set each kind of light up, step by step: connect-lights.md.
| Protocol | Port | Used for | Notes |
|---|---|---|---|
| DDP | UDP 4048 | Streaming pixels | Header: flags 0x40 (version 1), 0x41 on the last packet of a frame (push); sequence 1-15; type 0x0B (RGB, 8 bits); id 1; 32-bit byte offset; 16-bit length; up to 1,440 bytes (480 pixels) per packet |
| JSON API | HTTP 80 | Device info, segments, presets, power | GET /json/info, POST /json/state. Segment stop is exclusive |
| Audio sync | UDP 11988, multicast 239.0.0.1 | Letting WLED's own audio effects react | 44-byte "V2" packet, header 00002: raw and smoothed level, peak flag, 16 frequency bands (0-255), magnitude, loudest frequency |
| mDNS | UDP 5353 | Finding controllers | WLED announces _wled._tcp; Tempolight also scans the local /24 for /json/info |
| OSC | UDP 9000 (configurable) | Control from lighting desks, TouchOSC, Companion | Input only; addresses under /tempolight/ |
| E1.31 (sACN) / Art-Net | UDP 5568 / 6454 | WLED set to E1.31 or Art-Net, Falcon/FPP pixel controllers, DMX nodes | 170 pixels per universe; first universe set per device (E1.31 default 1, Art-Net 0) |
| Govee LAN (beta) | UDP 4001 (scan, multicast 239.255.255.250), 4002 (answers), 4003 (commands) | Govee lights with "LAN Control" on | One colour: colorwc about 10 times a second, only when it changes. Segments: the undocumented razer stream (0xBB 0x00 len 0xB0 0x01 count RGB… xor), 25 a second, on models that support DreamView; razer mode is switched on again every 10 s and after power on (the light drops it after about a minute without frames). At most 60 segments |
| OpenRGB SDK | TCP 6742 | PC lighting: RAM, fans, keyboards, motherboards, GPUs | Protocol version 0: ORGB header (device, packet id, size, little-endian). Lists devices (ids 0, 1), sets direct mode (1100), sends UPDATELEDS (1050) up to 40 a second, with exactly the device's LED count (OpenRGB ignores an update with more). One connection per server, closed when its last device is removed |
| Nanoleaf | HTTP 16021, UDP 60222 | Shapes, Canvas, Elements, Lines | Pair with POST /api/v1/new after holding the power button; layout from GET /api/v1/<token>; extControl v2 frames: panel count, then id, R, G, B, W, transition (big-endian) per panel, 30 a second |
| Philips Hue (basic) | HTTP 80 | Hue lights through the bridge | Pair with POST /api (generateclientkey: true, for fast mode) after pressing the link button; PUT /api/<user>/lights/<id>/state with xy and bri, about 10 commands a second per bridge in total (shared by every device on it), the light that changed most first |
| Philips Hue Entertainment (fast mode) | HTTPS 443 (CLIP v2), DTLS UDP 2100 | Hue lights in an entertainment area, up to 50 updates a second | Areas from GET /clip/v2/resource/entertainment_configuration (header hue-application-key); each channel's light from its member's entertainment service, that service's owner device and the device's light (id_v1). PUT .../entertainment_configuration/<id> {"action": "start"}, then DTLS 1.2 with TLS_PSK_WITH_AES_128_GCM_SHA256 (identity: the user name, key: the client key from pairing, hex), our own small DTLS client (dtls.js: cookie exchange, retransmission, AES-GCM records). HueStream v2: HueStream, 02 00, sequence, 2 reserved, colour space 00 (RGB), 1 reserved, the area id (36 ASCII), then per channel id + 16-bit R G B, big-endian; at most 20 channels. {"action": "stop"} on power off. Falls back to basic mode (and tries again every 30 s) when streaming can't start. Tested against our test server and OpenSSL, not yet a real bridge |
| LIFX LAN | UDP 56700 | LIFX bulbs, strips and beams | 36-byte little-endian header (protocol 1024, addressable, tagged when there's no target MAC). Discovery: GetService (2) broadcast, StateService (3); GetLabel/GetVersion for the name; GetExtendedColorZones (511) answered = multizone. SetColor (102, HSBK, kelvin 3500) for bulbs; strips SetExtendedColorZones (510), 82 zones a message, the last one applies. SetLightPower (117). At most 20 messages a second per light. Tiles and candles get one colour; strips on firmware without extended zones get one colour |
| WiZ | UDP 38899 | Philips WiZ and other WiZ Connected lights | JSON: registration broadcast (discovery), getSystemConfig (health), setPilot {state, r, g, b, dimming 10-100} (colour sent full scale, brightness as dimming, off below WiZ's minimum). At most 10 a second, only on change |
| TP-Link Kasa | TCP/UDP 9999 | Kasa bulbs (KL/LB) and KL400/420/430 strips | JSON with the XOR autokey (key 171); TCP has a 4-byte length in front. get_sysinfo broadcast (discovery) and over TCP (health); smartlife.iot.smartbulb.lightingservice.transition_light_state for bulbs, smartlife.iot.lightStrip.set_light_state for strips, over UDP, at most 10 a second. Per-zone strips (beta, unconfirmed on hardware): groups: [[first, last, hue, sat, bri, 0]]. Tapo and KLAP-firmware Kasa devices aren't supported (they need the TP-Link account) |
| Yeelight | UDP 1982 (multicast 239.255.255.250), TCP 55443 | Yeelight bulbs and strips with LAN Control on | Discovery M-SEARCH ... ST: wifi_bulb, answers in headers (Location: yeelight://ip:55443). JSON lines over TCP; the normal connection allows about 60 commands a minute, so Tempolight uses music mode: set_music [1, our ip, port], the light connects back to us and takes set_scene ["color", rgb, bright] without limit (sent up to 20 a second). Without it (a firewall), one colour a second, music mode tried again every 15 s |
| Twinkly | HTTP 80, UDP 7777, UDP 5555 (discovery) | Twinkly strings, curtains, Squares | POST /xled/v1/login (random challenge) and /verify for a token (about 4 hours, renewed); gestalt for the LED count and RGB/RGBW; led/layout/full for the mapped positions (placed as a points shape); led/mode {"mode":"rt"} every 30 s. Realtime protocol 3: 03, token (8 bytes), 00 00, fragment number, up to 900 bytes (R G B, or W R G B); protocol 2 for firmware before 2.4.14. About 25 frames a second. Discovery: \x01discover broadcast, answer: IP (reversed), OK, name |
| Pro DJ Link (input) | UDP 50001 | Beat grid from Pioneer CDJs/XDJs | Listens to beat packets (Qspt1WmJOL, type 0x28): track BPM at 0x5a (÷100), pitch at 0x55 (0x100000 = 0%), beat in bar at 0x5c. Never joins the network as a player |
| DMX fixtures (Art-Net / sACN) | UDP 6454 / 5568 | Pars, dimmers, strobes, moving heads, lasers, fog machines on a DMX node | One full 512-channel universe per DMX device (ArtDmx length 512; E1.31 property count 513), about 40 a second, sent even when the lights are off (nodes hold the last values); zeros when Tempolight stops. A node address can carry a port (192.168.1.60:6455) |
| Ableton Link (input, beta) | UDP 20808, multicast 224.76.78.75; unicast to each peer's measurement port | Tempo and beat from Ableton Live, Traktor, Bitwig and Link apps | Listen-only: never announces itself or changes the tempo. Discovery _asdp_v + 1: type (1 alive, 2 response, 3 bye-bye), ttl, group (uint16), node id (8), then entries (4-char key, uint32 size, value): tmln µs per beat, beat origin (µ-beats), time origin (µs, session clock), sess, stst, mep4 (IPv4 + port). Clock offset by _link_v + 1 ping (__ht, _pgt) / pong (sess, __gt, echo), median of ~100 samples, again every 30 s. Written from the open-source Link code; not yet checked against Live. Bars assume a quantum of 4 |
| MIDI clock (input, browser) | Web MIDI, then the WebSocket | Beat from DJ software or a drum machine | 24 clocks per beat (0xF8), Start 0xFA (next clock is beat 1 of a bar), Continue 0xFB, Stop 0xFC, Song Position Pointer 0xF2 (16ths). Tempo from a line fitted to the last 2 beats of clocks; browser timestamps are mapped to the server's clock with the smallest delay seen in 10 s |
| MQTT 3.1.1 | TCP 1883 | Home Assistant | Discovery under homeassistant/, QoS 0, retained config and state, last will on tempolight/availability |
When a stream stops, WLED waits a few seconds and then returns to its own effect, so Tempolight can hand a room back to WLED's presets (for example at night) simply by stopping.