#pragma once #include "wled.h" #include // Maximum number of lights supported #define MAX_WIZ_LIGHTS 15 WiFiUDP UDP; class WizLightsUsermod : public Usermod { private: unsigned long lastTime = 0; long updateInterval; long sendDelay; long forceUpdateMinutes; bool forceUpdate; bool useEnhancedWhite; long warmWhite; long coldWhite; IPAddress lightsIP[MAX_WIZ_LIGHTS]; // Stores Light IP addresses bool lightsValid[MAX_WIZ_LIGHTS]; // Stores Light IP address validity uint32_t colorsSent[MAX_WIZ_LIGHTS]; // Stores last color sent for each light public: // Send JSON blob to WiZ Light over UDP // RGB or C/W white // TODO: // Better utilize WLED existing white mixing logic void wizSendColor(IPAddress ip, uint32_t color) { UDP.beginPacket(ip, 38899); // If no LED color, turn light off. Note wiz light setting for "Off fade-out" will be applied by the light itself. if (color == 0) { UDP.print("{\"method\":\"setPilot\",\"params\":{\"state\":false}}"); // If color is WHITE, try and use the lights WHITE LEDs instead of mixing RGB LEDs } else if (color == 16777215 && useEnhancedWhite){ // set cold white light only if (coldWhite > 0 && warmWhite == 0){ UDP.print("{\"method\":\"setPilot\",\"params\":{\"c\":"); UDP.print(coldWhite) ;UDP.print("}}");} // set warm white light only if (warmWhite > 0 && coldWhite == 0){ UDP.print("{\"method\":\"setPilot\",\"params\":{\"w\":"); UDP.print(warmWhite) ;UDP.print("}}");} // set combination of warm and cold white light if (coldWhite > 0 && warmWhite > 0){ UDP.print("{\"method\":\"setPilot\",\"params\":{\"c\":"); UDP.print(coldWhite) ;UDP.print(",\"w\":"); UDP.print(warmWhite); UDP.print("}}");} // Send color as RGB } else { UDP.print("{\"method\":\"setPilot\",\"params\":{\"r\":"); UDP.print(R(color)); UDP.print(",\"g\":"); UDP.print(G(color)); UDP.print(",\"b\":"); UDP.print(B(color)); UDP.print("}}"); } UDP.endPacket(); } // Override definition so it compiles void setup() { } // TODO: Check millis() rollover void loop() { // Make sure we are connected first if (!WLED_CONNECTED) return; unsigned long ellapsedTime = millis() - lastTime; if (ellapsedTime > updateInterval) { bool update = false; for (uint8_t i = 0; i < MAX_WIZ_LIGHTS; i++) { if (!lightsValid[i]) { continue; } uint32_t newColor = strip.getPixelColor(i); if (forceUpdate || (newColor != colorsSent[i]) || (ellapsedTime > forceUpdateMinutes*60000)){ wizSendColor(lightsIP[i], newColor); colorsSent[i] = newColor; update = true; delay(sendDelay); } } if (update) lastTime = millis(); } } void addToConfig(JsonObject& root) { JsonObject top = root.createNestedObject("wizLightsUsermod"); top["Interval (ms)"] = updateInterval; top["Send Delay (ms)"] = sendDelay; top["Use Enhanced White *"] = useEnhancedWhite; top["* Warm White Value (0-255)"] = warmWhite; top["* Cold White Value (0-255)"] = coldWhite; top["Always Force Update"] = forceUpdate; top["Force Update Every x Minutes"] = forceUpdateMinutes; for (uint8_t i = 0; i < MAX_WIZ_LIGHTS; i++) { top[getJsonLabel(i)] = lightsIP[i].toString(); } } bool readFromConfig(JsonObject& root) { JsonObject top = root["wizLightsUsermod"]; bool configComplete = !top.isNull(); configComplete &= getJsonValue(top["Interval (ms)"], updateInterval, 1000); // How frequently to update the wiz lights configComplete &= getJsonValue(top["Send Delay (ms)"], sendDelay, 0); // Optional delay after sending each UDP message configComplete &= getJsonValue(top["Use Enhanced White *"], useEnhancedWhite, false); // When color is white use wiz white LEDs instead of mixing RGB configComplete &= getJsonValue(top["* Warm White Value (0-255)"], warmWhite, 0); // Warm White LED value for Enhanced White configComplete &= getJsonValue(top["* Cold White Value (0-255)"], coldWhite, 50); // Cold White LED value for Enhanced White configComplete &= getJsonValue(top["Always Force Update"], forceUpdate, false); // Update wiz light every loop, even if color value has not changed configComplete &= getJsonValue(top["Force Update Every x Minutes"], forceUpdateMinutes, 5); // Update wiz light if color value has not changed, every x minutes // Read list of IPs String tempIp; for (uint8_t i = 0; i < MAX_WIZ_LIGHTS; i++) { configComplete &= getJsonValue(top[getJsonLabel(i)], tempIp, "0.0.0.0"); lightsValid[i] = lightsIP[i].fromString(tempIp); // If the IP is not valid, force the value to be empty if (!lightsValid[i]){lightsIP[i].fromString("0.0.0.0");} } return configComplete; } // Create label for the usermod page (I cannot make it work with JSON arrays...) String getJsonLabel(uint8_t i) {return "WiZ Light IP #" + String(i+1);} uint16_t getId(){return USERMOD_ID_WIZLIGHTS;} };