22c3ac5be3
* Add usermode to control Wiz lights (#1) * Fix inclusion in usermods list Co-authored-by: Christian Schwinne <dev.aircoookie@gmail.com>
142 lines
4.7 KiB
C++
142 lines
4.7 KiB
C++
#pragma once
|
|
|
|
#include "wled.h"
|
|
#include <WiFiUdp.h>
|
|
|
|
// Maximum number of lights supported
|
|
#define MAX_WIZ_LIGHTS 10
|
|
|
|
// UDP object, to send messages
|
|
WiFiUDP UDP;
|
|
|
|
// Function to send a color to a light
|
|
void sendColor(IPAddress ip, uint32_t color) {
|
|
UDP.beginPacket(ip, 38899);
|
|
if (color == 0) {
|
|
UDP.print("{\"method\":\"setPilot\",\"params\":{\"state\":false}}");
|
|
} else {
|
|
UDP.print("{\"method\":\"setPilot\",\"params\":{\"state\":true, \"r\":");
|
|
UDP.print(R(color));
|
|
UDP.print(",\"g\":");
|
|
UDP.print(G(color));
|
|
UDP.print(",\"b\":");
|
|
UDP.print(B(color));
|
|
UDP.print("}}");
|
|
}
|
|
UDP.endPacket();
|
|
}
|
|
|
|
// Create label for the usermode page (I cannot make it work with JSON arrays...)
|
|
String getJsonLabel(uint8_t i) {
|
|
return "ip_light_" + String(i);
|
|
}
|
|
|
|
class WizLightsUsermod : public Usermod {
|
|
private:
|
|
// Keep track of the last time the lights were updated
|
|
unsigned long lastTime = 0;
|
|
|
|
// Specify how often WLED sends data to the Wiz lights
|
|
long updateInterval;
|
|
|
|
// Save the IP of the lights
|
|
IPAddress lightsIP[MAX_WIZ_LIGHTS];
|
|
bool lightsValid[MAX_WIZ_LIGHTS];
|
|
|
|
// Variable that keeps track of RBG values for the lights
|
|
uint32_t colorsSent[MAX_WIZ_LIGHTS];
|
|
|
|
public:
|
|
//Functions called by WLED
|
|
|
|
/*
|
|
* loop() is called continuously. Here you can check for events, read sensors, etc.
|
|
*/
|
|
void loop() {
|
|
// Calculate how long since the last update
|
|
unsigned long ellapsedTime = millis() - lastTime;
|
|
|
|
if (ellapsedTime > updateInterval) {
|
|
// Keep track of whether we are updating any of the lights
|
|
bool update = false;
|
|
|
|
// Loop through the lights
|
|
for (uint8_t i = 0; i < MAX_WIZ_LIGHTS; i++) {
|
|
// Check if we have a valid IP
|
|
if (!lightsValid[i]) { continue; }
|
|
|
|
// Get the first colors in the strip
|
|
uint32_t new_color = strip.getPixelColor(i);
|
|
|
|
// Check if the color has changed from the last one sent
|
|
// Force an update every 5 minutes, in case the colors don't change
|
|
// (the lights could have been reset by turning off and on)
|
|
if ((new_color != colorsSent[i]) | (ellapsedTime > 5*60000)) {
|
|
// It has changed, send the new color to the light
|
|
update = true;
|
|
sendColor(lightsIP[i], new_color);
|
|
colorsSent[i] = new_color;
|
|
}
|
|
}
|
|
|
|
// We sent an update, wait until we do this again
|
|
if (update) {
|
|
lastTime = millis();
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
* addToConfig() can be used to add custom persistent settings to the cfg.json file in the "um" (usermod) object.
|
|
* It will be called by WLED when settings are actually saved (for example, LED settings are saved)
|
|
* If you want to force saving the current state, use serializeConfig() in your loop().
|
|
*/
|
|
void addToConfig(JsonObject& root)
|
|
{
|
|
JsonObject top = root.createNestedObject("wizLightsUsermod");
|
|
top["interval_ms"] = updateInterval;
|
|
for (uint8_t i = 0; i < MAX_WIZ_LIGHTS; i++) {
|
|
top[getJsonLabel(i)] = lightsIP[i].toString();
|
|
}
|
|
}
|
|
|
|
/*
|
|
* readFromConfig() can be used to read back the custom settings you added with addToConfig().
|
|
* This is called by WLED when settings are loaded (currently this only happens immediately after boot, or after saving on the Usermod Settings page)
|
|
*/
|
|
bool readFromConfig(JsonObject& root)
|
|
{
|
|
// default settings values could be set here (or below using the 3-argument getJsonValue()) instead of in the class definition or constructor
|
|
// setting them inside readFromConfig() is slightly more robust, handling the rare but plausible use case of single value being missing after boot (e.g. if the cfg.json was manually edited and a value was removed)
|
|
|
|
JsonObject top = root["wizLightsUsermod"];
|
|
|
|
bool configComplete = !top.isNull();
|
|
|
|
// Read interval to update the lights
|
|
configComplete &= getJsonValue(top["interval_ms"], updateInterval, 1000);
|
|
|
|
// 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;
|
|
}
|
|
|
|
/*
|
|
* getId() allows you to optionally give your V2 usermod an unique ID (please define it in const.h!).
|
|
* This could be used in the future for the system to determine whether your usermod is installed.
|
|
*/
|
|
uint16_t getId()
|
|
{
|
|
return USERMOD_ID_WIZLIGHTS;
|
|
}
|
|
}; |