Skip to content

Commit 9237b7e

Browse files
committed
Transform from DMX output to WLED JSON API output
Replace the DMX512/ArtNet output subsystem with HTTP-based WLED device control. Each configured light now maps to a WLED device on the network instead of a DMX address range. New modules: - wled_output: sends HTTP POST to /json/state with color, brightness, and power state; tracks last-sent state to avoid redundant calls - wled_discovery: mDNS scan for WLED devices with /json/info metadata query (name, LED count, RGBW capability, firmware version) Config changes: - LightConfig stores wledHost/wledPort instead of dmxStartAddr/channelMap - Removed OutputConfig, OutputMode, DmxChannelMap structs entirely - NVS namespace changed from zbdmx to zbwled Web UI changes: - Replaced Output Settings card with WLED device discovery panel - Light modal shows host/port fields with network scan button - Discovered devices shown as selectable cards with auto-fill - AP name changed to ZigbeeWLED-Setup Zigbee stack unchanged — all Hue pairing requirements preserved.
1 parent 4acedb2 commit 9237b7e

14 files changed

Lines changed: 609 additions & 715 deletions

include/config_store.h

Lines changed: 7 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
11
/*
2-
* Zigbee DMX Bridge - Configuration Storage
2+
* Zigbee WLED Bridge - Configuration Storage
33
*
4-
* Stores light definitions, output mode, and WiFi credentials in NVS (Preferences).
5-
* Each light has: name, type (RGB/RGBW), DMX start address,
6-
* and channel-to-offset mapping.
4+
* Stores light definitions and WiFi credentials in NVS (Preferences).
5+
* Each light has: name, type (RGB/RGBW), and a WLED device host/port.
76
*/
87

98
#pragma once
@@ -16,43 +15,20 @@
1615
#define MAX_LIGHTS 16
1716
#endif
1817

19-
// Channel mapping: which DMX offset corresponds to which color channel
20-
struct DmxChannelMap {
21-
uint8_t red; // offset from start address for red (0-based)
22-
uint8_t green; // offset for green
23-
uint8_t blue; // offset for blue
24-
uint8_t white; // offset for white (only used if type == RGBW)
25-
};
26-
2718
enum LightType : uint8_t {
2819
LIGHT_TYPE_RGB = 3,
2920
LIGHT_TYPE_RGBW = 4,
3021
};
3122

32-
enum OutputMode : uint8_t {
33-
OUTPUT_MODE_WIRED_DMX = 0,
34-
OUTPUT_MODE_ARTNET = 1,
35-
};
36-
37-
struct OutputConfig {
38-
OutputMode mode = OUTPUT_MODE_WIRED_DMX;
39-
// Wired DMX settings
40-
int8_t txPin = 2; // GPIO for DMX TX (default GPIO2)
41-
int8_t enPin = 4; // GPIO for RS-485 enable (default GPIO4, -1 = not used)
42-
// ArtNet settings
43-
uint16_t artnetUniverse = 0; // ArtNet universe (0-32767)
44-
char artnetTargetIp[16] = {}; // Target IP for unicast, empty/"" = subnet broadcast
45-
};
46-
4723
struct LightConfig {
4824
bool active;
4925
char name[32];
5026
LightType type;
51-
uint16_t dmxStartAddr; // 1-512
52-
DmxChannelMap channelMap;
27+
char wledHost[64]; // IP address or hostname of WLED device
28+
uint16_t wledPort; // HTTP port (default 80)
5329
};
5430

55-
// Current state of a light (set by Zigbee, read by DMX output)
31+
// Current state of a light (set by Zigbee, read by WLED output)
5632
struct LightState {
5733
bool powerOn;
5834
uint8_t brightness; // 0-254 (Zigbee scale)
@@ -83,12 +59,8 @@ class ConfigStore {
8359
const LightConfig& getLight(uint8_t index) const { return lights[index]; }
8460
LightConfig& getLightMut(uint8_t index) { return lights[index]; }
8561

86-
// Output configuration
87-
const OutputConfig& getOutputConfig() const { return outputCfg; }
88-
void setOutputConfig(const OutputConfig& cfg) { outputCfg = cfg; }
89-
9062
// Add a light with defaults, returns index or -1 if full
91-
int addLight(const char* name, LightType type, uint16_t dmxAddr);
63+
int addLight(const char* name, LightType type, const char* wledHost, uint16_t wledPort = 80);
9264

9365
// Remove a light by index, shifts remaining lights down
9466
bool removeLight(uint8_t index);
@@ -115,7 +87,6 @@ class ConfigStore {
11587
Preferences prefs;
11688
uint8_t lightCount = 0;
11789
LightConfig lights[MAX_LIGHTS] = {};
118-
OutputConfig outputCfg;
11990
};
12091

12192
extern ConfigStore configStore;

include/dmx_output.h

Lines changed: 0 additions & 75 deletions
This file was deleted.

include/web_ui.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
/*
2-
* Zigbee DMX Bridge - Web UI & WiFi Manager
2+
* Zigbee WLED Bridge - Web UI & WiFi Manager
33
*
44
* Handles:
55
* - Initial WiFi configuration via captive portal (AP mode)
6-
* - Web-based configuration UI for defining lights
6+
* - Web-based configuration UI for WLED light definitions
77
* - REST API for light configuration CRUD
8+
* - WLED device discovery via mDNS
89
* - Status page showing Zigbee pairing state
910
*/
1011

include/wled_discovery.h

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
/*
2+
* Zigbee WLED Bridge - WLED Device Discovery
3+
*
4+
* Discovers WLED devices on the local network using mDNS.
5+
* WLED devices advertise as _http._tcp with hostname typically "wled-XXXXXX".
6+
* After mDNS discovery, queries each device's /json/info endpoint to get
7+
* device name, LED count, RGBW capability, MAC address, etc.
8+
*/
9+
10+
#pragma once
11+
12+
#include <Arduino.h>
13+
#include <vector>
14+
15+
struct WledDeviceInfo {
16+
char name[64]; // WLED device name (from /json/info)
17+
char host[64]; // IP address as string
18+
uint16_t port; // HTTP port (usually 80)
19+
char mac[18]; // MAC address (from /json/info)
20+
uint16_t ledCount; // Number of LEDs
21+
bool isRGBW; // Has white channel
22+
char version[16]; // WLED firmware version
23+
};
24+
25+
/**
26+
* Scan the local network for WLED devices via mDNS.
27+
* Queries each discovered device's /json/info for metadata.
28+
*
29+
* @param results Vector to fill with discovered devices
30+
* @param timeoutMs mDNS scan timeout in milliseconds (default 5000)
31+
* @return Number of devices found
32+
*/
33+
int wledDiscover(std::vector<WledDeviceInfo>& results, uint32_t timeoutMs = 5000);

include/wled_output.h

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
/*
2+
* Zigbee WLED Bridge - WLED Output
3+
*
4+
* Controls WLED devices via their JSON API over HTTP.
5+
* Each configured light maps to a WLED device on the network.
6+
* Sends HTTP POST to /json/state to set color, brightness, and on/off.
7+
*
8+
* Rate limited to ~2Hz per device to avoid flooding under
9+
* WiFi/Zigbee coexistence constraints.
10+
*/
11+
12+
#pragma once
13+
14+
#include <Arduino.h>
15+
#include "config_store.h"
16+
17+
class WledOutput {
18+
public:
19+
/**
20+
* Initialize the output subsystem.
21+
* Call after configStore.begin() and WiFi is available.
22+
*/
23+
void begin();
24+
25+
/**
26+
* Update all WLED devices from light states.
27+
* Called at a fixed rate from the main loop (~2Hz).
28+
* Only sends updates for lights whose state has changed.
29+
*/
30+
void update(const LightConfig* lights, const LightState* states, uint8_t count);
31+
32+
/**
33+
* Stop all output and release resources.
34+
*/
35+
void stop();
36+
37+
/**
38+
* Return true if the output subsystem is initialized and active.
39+
*/
40+
bool isRunning() const { return initialized; }
41+
42+
private:
43+
bool initialized = false;
44+
45+
// Track last-sent state per light to avoid redundant HTTP calls
46+
struct SentState {
47+
bool valid; // true if we've sent at least once
48+
bool powerOn;
49+
uint8_t brightness;
50+
uint8_t red;
51+
uint8_t green;
52+
uint8_t blue;
53+
uint8_t white;
54+
};
55+
SentState lastSent[MAX_LIGHTS] = {};
56+
57+
// Send state to a single WLED device via HTTP POST
58+
bool sendToWled(const LightConfig& cfg, const LightState& state);
59+
60+
// Check if state has changed since last send
61+
bool stateChanged(uint8_t index, const LightState& state) const;
62+
};
63+
64+
extern WledOutput wledOutput;

include/zigbee_manager.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Zigbee DMX Bridge - Zigbee Manager
2+
* Zigbee WLED Bridge - Zigbee Manager
33
*
44
* Manages the Zigbee stack running as End Device(s).
55
* Creates one Zigbee HA Color Dimmable Light endpoint per configured light.

platformio.ini

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
; PlatformIO Project Configuration
2-
; Zigbee DMX Bridge - ESP32-C6
3-
; Presents configurable RGB/RGBW lights as Zigbee HA Color Dimmable Lights
4-
; (Hue-compatible) and outputs via DMX512.
2+
; Zigbee WLED Bridge - ESP32-C6
3+
; Presents WLED devices as Zigbee HA Extended Color Lights (Hue-compatible)
4+
; and controls them via the WLED JSON API over HTTP.
55

66
[env]
77
platform = https://github.com/pioarduino/platform-espressif32/releases/download/55.03.37/platform-espressif32.zip
@@ -12,7 +12,7 @@ board_build.filesystem = littlefs
1212
monitor_speed = 115200
1313

1414
; --- OTA upload support ---
15-
; To upload via OTA: pio run -t upload --upload-port zigbeedmx.local
15+
; To upload via OTA: pio run -t upload --upload-port zigbeewled.local
1616
; Or specify IP directly: pio run -t upload --upload-port 192.168.x.x
1717

1818
; --- Dependencies ---

0 commit comments

Comments
 (0)