159 lines
5.5 KiB
C++
159 lines
5.5 KiB
C++
#pragma once
|
|
|
|
#include "wled.h"
|
|
#include <WiFiUdp.h>
|
|
|
|
// 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;}
|
|
};
|