2022-03-23 16:20:18 +01:00
# pragma once
# include "wled.h"
# include <WiFiUdp.h>
// Maximum number of lights supported
2022-05-03 12:18:21 +02:00
# define MAX_WIZ_LIGHTS 15
2022-03-23 16:20:18 +01:00
WiFiUDP UDP ;
2022-05-03 12:18:21 +02:00
2022-03-23 16:20:18 +01:00
class WizLightsUsermod : public Usermod {
2022-05-03 12:18:21 +02:00
2022-03-23 16:20:18 +01:00
private :
unsigned long lastTime = 0 ;
long updateInterval ;
2022-05-03 12:18:21 +02:00
long sendDelay ;
2022-03-23 16:20:18 +01:00
2022-05-03 12:18:21 +02:00
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
2022-03-23 16:20:18 +01:00
public :
2022-05-03 12:18:21 +02:00
// 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 ( ) ;
}
2022-12-13 05:04:25 +01:00
// Override definition so it compiles
void setup ( ) {
}
2022-05-03 12:18:21 +02:00
// TODO: Check millis() rollover
2022-03-23 16:20:18 +01:00
void loop ( ) {
2022-05-03 12:18:21 +02:00
// Make sure we are connected first
if ( ! WLED_CONNECTED ) return ;
2022-03-23 16:20:18 +01:00
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 ; }
2022-05-03 12:18:21 +02:00
uint32_t newColor = strip . getPixelColor ( i ) ;
if ( forceUpdate | | ( newColor ! = colorsSent [ i ] ) | | ( ellapsedTime > forceUpdateMinutes * 60000 ) ) {
wizSendColor ( lightsIP [ i ] , newColor ) ;
colorsSent [ i ] = newColor ;
2022-03-23 16:20:18 +01:00
update = true ;
2022-05-03 12:18:21 +02:00
delay ( sendDelay ) ;
}
2022-03-23 16:20:18 +01:00
}
2022-05-03 12:18:21 +02:00
if ( update ) lastTime = millis ( ) ;
2022-03-23 16:20:18 +01:00
}
}
2022-05-03 12:18:21 +02:00
2022-03-23 16:20:18 +01:00
void addToConfig ( JsonObject & root )
{
JsonObject top = root . createNestedObject ( " wizLightsUsermod " ) ;
2022-05-03 12:18:21 +02:00
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 ;
2022-03-23 16:20:18 +01:00
for ( uint8_t i = 0 ; i < MAX_WIZ_LIGHTS ; i + + ) {
top [ getJsonLabel ( i ) ] = lightsIP [ i ] . toString ( ) ;
}
}
2022-05-03 12:18:21 +02:00
2022-03-23 16:20:18 +01:00
bool readFromConfig ( JsonObject & root )
{
JsonObject top = root [ " wizLightsUsermod " ] ;
bool configComplete = ! top . isNull ( ) ;
2022-05-03 12:18:21 +02:00
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
2022-03-23 16:20:18 +01:00
// 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
2022-05-03 12:18:21 +02:00
if ( ! lightsValid [ i ] ) { lightsIP [ i ] . fromString ( " 0.0.0.0 " ) ; }
2022-03-23 16:20:18 +01:00
}
return configComplete ;
}
2022-05-03 12:18:21 +02:00
// 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 ; }
} ;