diff --git a/readme.md b/readme.md index ea7a0266..51a14402 100644 --- a/readme.md +++ b/readme.md @@ -2,29 +2,28 @@ WLED is a fast and (relatively) secure implementation of an ESP8266/ESP32 webserver to control NeoPixel (WS2812B) LEDs! -### Features: (V0.6.4) +### Features: (V0.7.0) - RGB, HSB, and brightness sliders +- All new, mobile-friendly web UI! - Settings page - configuration over network - Access Point and station mode - automatic failsafe AP -- WS2812FX library integrated for over 50 special effects! +- WS2812FX library integrated for over 50 special effects (+Custom Theater Chase)! - Secondary color support lets you use even more effect combinations - Alexa smart home device server (including dimming) - Beta syncronization to Philips hue lights - Support for RGBW strips -- 25 user presets! Save your favorite colors and effects and apply them easily! Now supports cycling through them. +- 25 user presets! Save colors and effects and apply them easily! Supports cycling through them. - HTTP request API for simple integration - Macro functions to automatically execute API calls - Nightlight function (gradually dims down) - Notifier function (multiple ESPs sync color via UDP broadcast) - Support for power pushbutton -- Custom Theater Chase - Support for the Adalight serial ambilight protocol! - Full OTA software update capability (HTTP and ArduinoOTA) - Password protected OTA page for added security (OTA lock) - NTP and configurable analog clock function - Support for the Cronixie Clock kit by Diamex -- Realtime UDP Packet Control (WARLS, DRGB, DRGBW) possible -- Client HTML UI controlled, customizable themes +- Realtime UDP Packet Control (Hyperion, WARLS, DRGB, DRGBW) ### Quick start guide and documentation: diff --git a/wled00/WS2812FX.cpp b/wled00/WS2812FX.cpp index 60e1d548..9b2e0e74 100644 --- a/wled00/WS2812FX.cpp +++ b/wled00/WS2812FX.cpp @@ -37,8 +37,8 @@ #define CALL_MODE(n) (this->*_mode[n])(); -void WS2812FX::init(bool supportWhite, uint16_t countPixels, uint8_t pin) { - begin(supportWhite,countPixels,pin); +void WS2812FX::init(bool supportWhite, uint16_t countPixels, uint8_t pin,bool skipFirst) { + begin(supportWhite,countPixels,pin,skipFirst); for (int i=0; i < _led_count; i++) _locked[i] = false; WS2812FX::setBrightness(_brightness); show(); @@ -2032,6 +2032,7 @@ void WS2812FX::setPixelColor(uint16_t i, byte r, byte g, byte b, byte w) if (_reverseMode) i = _led_count - 1 -i; if (!_cronixieMode) { + if (_skipFirstMode) {i++;if(i==1)setPixelColorRaw(0,0,0,0,0);} if (_rgbwMode) { bus->SetPixelColor(i, RgbwColor(r,g,b,w)); @@ -2050,27 +2051,27 @@ void WS2812FX::setPixelColor(uint16_t i, byte r, byte g, byte b, byte w) byte wCorr = (int)(((double)((_color_sec>>24) & 0xFF))*_cronixieSecMultiplier); for (int j=o; j< o+19; j++) { - setPixelColorRaw(j,rCorr,gCorr,bCorr,wCorr); + setPixelColorRaw((_skipFirstMode)?j+1:j,rCorr,gCorr,bCorr,wCorr); } } else { for (int j=o; j< o+19; j++) { - setPixelColorRaw(j,0,0,0,0); + setPixelColorRaw((_skipFirstMode)?j+1:j,0,0,0,0); } } switch(_cronixieDigits[i]) { - case 0: setPixelColorRaw(o+5,r,g,b,w); break; - case 1: setPixelColorRaw(o+0,r,g,b,w); break; - case 2: setPixelColorRaw(o+6,r,g,b,w); break; - case 3: setPixelColorRaw(o+1,r,g,b,w); break; - case 4: setPixelColorRaw(o+7,r,g,b,w); break; - case 5: setPixelColorRaw(o+2,r,g,b,w); break; - case 6: setPixelColorRaw(o+8,r,g,b,w); break; - case 7: setPixelColorRaw(o+3,r,g,b,w); break; - case 8: setPixelColorRaw(o+9,r,g,b,w); break; - case 9: setPixelColorRaw(o+4,r,g,b,w); break; + case 0: setPixelColorRaw((_skipFirstMode)?o+6:o+5,r,g,b,w); break; + case 1: setPixelColorRaw((_skipFirstMode)?o+1:o+0,r,g,b,w); break; + case 2: setPixelColorRaw((_skipFirstMode)?o+7:o+6,r,g,b,w); break; + case 3: setPixelColorRaw((_skipFirstMode)?o+2:o+1,r,g,b,w); break; + case 4: setPixelColorRaw((_skipFirstMode)?o+8:o+7,r,g,b,w); break; + case 5: setPixelColorRaw((_skipFirstMode)?o+3:o+2,r,g,b,w); break; + case 6: setPixelColorRaw((_skipFirstMode)?o+9:o+8,r,g,b,w); break; + case 7: setPixelColorRaw((_skipFirstMode)?o+4:o+3,r,g,b,w); break; + case 8: setPixelColorRaw((_skipFirstMode)?o+10:o+9,r,g,b,w); break; + case 9: setPixelColorRaw((_skipFirstMode)?o+5:o+4,r,g,b,w); break; default: break; } } @@ -2134,17 +2135,19 @@ void WS2812FX::clear() bus->ClearTo(RgbColor(0)); } -void WS2812FX::begin(bool supportWhite, uint16_t countPixels, uint8_t pin) +void WS2812FX::begin(bool supportWhite, uint16_t countPixels, uint8_t pin, bool skipFirst) { if (supportWhite == _rgbwMode && countPixels == _led_count && _locked != NULL) return; _rgbwMode = supportWhite; + _skipFirstMode = skipFirst; _led_count = countPixels; _cc_i2 = _led_count -1; + if (_skipFirstMode) _led_count++; uint8_t ty = 1; if (supportWhite) ty =2; - bus->Begin((NeoPixelType)ty, countPixels, pin); + bus->Begin((NeoPixelType)ty, _led_count, pin); if (_locked != NULL) delete _locked; - _locked = new bool[countPixels]; + _locked = new bool[_led_count]; } //For some reason min and max are not declared here diff --git a/wled00/WS2812FX.h b/wled00/WS2812FX.h index 7a9ae891..2ea09e4f 100644 --- a/wled00/WS2812FX.h +++ b/wled00/WS2812FX.h @@ -199,6 +199,7 @@ class WS2812FX { _counter_ccStep = 0; _fastStandard = false; _reverseMode = false; + _skipFirstMode = false; _locked = NULL; _cronixieDigits = new byte[6]; bus = new NeoPixelWrapper(); @@ -208,7 +209,7 @@ class WS2812FX { show(void), setPixelColor(uint16_t i, byte r, byte g, byte b), setPixelColor(uint16_t i, byte r, byte g, byte b, byte w), - init(bool supportWhite, uint16_t countPixels, uint8_t pin), + init(bool supportWhite, uint16_t countPixels, uint8_t pin, bool skipFirst), service(void), start(void), stop(void), @@ -277,7 +278,7 @@ class WS2812FX { NeoPixelWrapper *bus; void - begin(bool supportWhite, uint16_t countPixels, uint8_t pin), + begin(bool supportWhite, uint16_t countPixels, uint8_t pin, bool skipFirst), clear(void), setPixelColor(uint16_t i, uint32_t c), setPixelColorRaw(uint16_t i, byte r, byte g, byte b, byte w), @@ -348,6 +349,7 @@ class WS2812FX { bool _triggered, _rgbwMode, + _skipFirstMode, _fastStandard, _reverseMode, _cronixieMode, diff --git a/wled00/data/index.htm b/wled00/data/index.htm index c79496a8..e395b3ad 100644 --- a/wled00/data/index.htm +++ b/wled00/data/index.htm @@ -1,8 +1,8 @@ - + - WLED 0.6.4 + WLED 0.7.0 + + +
+
Loading WLED UI...
+
+
+

WLED

+ + + +
+
+

FX 2nd Color

+
+ +
+

Sync Lights

+
+ +
+
+
+
+
+

White Channel

+
+
+

Master Brightness



+
+
+
 
+
 
+
 
+
 

+
 
+
 
+
 
+
 
+
+
+
+

Edit Presets

+
+ +
+
+

Presets

+
1
+
2
+
3
+
4

+
5
+
6
+
7
+
8

+
9
+
10
+
11
+
12

+
13
+
14
+
15
+
16
+
+
+

Cycle Mode

+
+ +
+
+

Cycle Range

+
+ +
+
+ +
+

Preset Duration

+
+
+

Color Transition

+
+
+
+

FX Speed

+
+
+

FX Intensity

+
+
+ + + + \ No newline at end of file diff --git a/wled00/data/msg.htm b/wled00/data/msg.htm index 5475635f..2b5bf7c3 100644 --- a/wled00/data/msg.htm +++ b/wled00/data/msg.htm @@ -9,7 +9,7 @@ window.location = "/settings"; } function RP() { - top.location.href=top.location.href; + top.location.href="/"; } + - + +
diff --git a/wled00/data/settings_leds.htm b/wled00/data/settings_leds.htm index a8931e63..83a84271 100644 Binary files a/wled00/data/settings_leds.htm and b/wled00/data/settings_leds.htm differ diff --git a/wled00/data/settings_sec.htm b/wled00/data/settings_sec.htm index 482e2d95..c02bcd39 100644 Binary files a/wled00/data/settings_sec.htm and b/wled00/data/settings_sec.htm differ diff --git a/wled00/data/settings_sync.htm b/wled00/data/settings_sync.htm index 5be3944e..54a1db9b 100644 Binary files a/wled00/data/settings_sync.htm and b/wled00/data/settings_sync.htm differ diff --git a/wled00/data/settings_ui.htm b/wled00/data/settings_ui.htm index 24649e4c..172b01aa 100644 Binary files a/wled00/data/settings_ui.htm and b/wled00/data/settings_ui.htm differ diff --git a/wled00/htmls00.h b/wled00/htmls00.h index ac7efc71..b3de4829 100644 --- a/wled00/htmls00.h +++ b/wled00/htmls00.h @@ -1,14 +1,65 @@ /* - * Index html + * Mobile UI by StormPie html +*/ +#ifndef WLED_FLASH_512K_MODE +const char PAGE_indexM[] PROGMEM = R"=====( +WLED 0.7.0
Loading WLED UI...

WLED

FX 2nd Color

Sync Lights

White Channel

Master Brightness



 
 
 
 

 
 
 
 

Edit Presets

Presets

1
2
3
4

5
6
7
8

9
10
11
12

13
14
15
16

Cycle Mode

Cycle Range

Preset Duration

Color Transition

FX Speed

FX Intensity

+)====="; +#else +const char PAGE_indexM[] PROGMEM = R"=====( +The Mobile UI is not supported due to limited flash storage. Please go to IP/settings/ui and change the UI mode to "Classic". +)====="; +#endif + +/* + * Classic UI Index html */ //head0 (js) const char PAGE_index0[] PROGMEM = R"=====( - + -WLED 0.6.4 - +WLED 0.7.0 + )====="; //head1 (css) diff --git a/wled00/htmls01.h b/wled00/htmls01.h index 0f542507..aea78045 100644 --- a/wled00/htmls01.h +++ b/wled00/htmls01.h @@ -7,15 +7,15 @@ body{font-family:var(--cFn),sans-serif;text-align:center;background:var(--cCol); const char PAGE_settings0[] PROGMEM = R"=====( - - -WLED Settings +WLED Settings )====="; const char PAGE_settings1[] PROGMEM = R"=====( -body{text-align:center;background:var(--cCol);height:100%;margin:0;background-attachment:fixed}button{background:var(--bCol);color:var(--tCol);font-family:var(--cFn),sans-serif;border:.3ch solid var(--bCol);display:inline-block;filter:drop-shadow(-5px -5px 5px var(--sCol));font-size:8vmin;height:13.86vh;width:95%;margin-top:2.4vh} +body{text-align:center;background:var(--cCol);height:100%;margin:0;background-attachment:fixed}html{--h:11.55vh}button{background:var(--bCol);color:var(--tCol);font-family:var(--cFn),Helvetica,sans-serif;border:.3ch solid var(--bCol);display:inline-block;filter:drop-shadow(-5px -5px 5px var(--sCol));font-size:8vmin;height:var(--h);width:95%;margin-top:2.4vh} + - + +
@@ -28,8 +28,7 @@ body{text-align:center;background:var(--cCol);height:100%;margin:0;background-at const char PAGE_settings_wifi0[] PROGMEM = R"=====( - - + WiFi Settings + )====="; const char PAGE_msg1[] PROGMEM = R"=====( button{background:var(--bCol);color:var(--tCol);font-family:var(--cFn),sans-serif;border:.3ch solid var(--bCol);display:inline-block;filter:drop-shadow(-5px -5px 5px var(--sCol));font-size:20px;margin:8px;margin-top:12px}body{font-family:var(--cFn),sans-serif;text-align:center;background:var(--cCol);color:var(--tCol);line-height:200%;margin:0;background-attachment:fixed} diff --git a/wled00/src/dependencies/webserver/WebServer.cpp b/wled00/src/dependencies/webserver/WebServer.cpp index 8b825e67..83785bef 100644 --- a/wled00/src/dependencies/webserver/WebServer.cpp +++ b/wled00/src/dependencies/webserver/WebServer.cpp @@ -90,8 +90,8 @@ WebServer::~WebServer() { void WebServer::begin() { _currentStatus = HC_NONE; _server.begin(); - if(!_headerKeysCount) - collectHeaders(0, 0); + //if(!_headerKeysCount) + //collectHeaders(0, 0); } bool WebServer::authenticate(const char * username, const char * password){ @@ -408,15 +408,13 @@ String WebServer::header(String name) { return String(); } -void WebServer::collectHeaders(const char* headerKeys[], const size_t headerKeysCount) { - _headerKeysCount = headerKeysCount + 1; - if (_currentHeaders) - delete[]_currentHeaders; - _currentHeaders = new RequestArgument[_headerKeysCount]; +//Modified by Aircoookie to work for WLED +void WebServer::collectHeaders(String headerKey) { + _headerKeysCount = 2; + if (_currentHeaders) delete[]_currentHeaders; + _currentHeaders = new RequestArgument[2]; _currentHeaders[0].key = AUTHORIZATION_HEADER; - for (int i = 1; i < _headerKeysCount; i++){ - _currentHeaders[i].key = headerKeys[i-1]; - } + _currentHeaders[1].key = headerKey; } String WebServer::header(int i) { diff --git a/wled00/src/dependencies/webserver/WebServer.h b/wled00/src/dependencies/webserver/WebServer.h index 40807867..5a9ed0de 100644 --- a/wled00/src/dependencies/webserver/WebServer.h +++ b/wled00/src/dependencies/webserver/WebServer.h @@ -105,7 +105,7 @@ public: String argName(int i); // get request argument name by number int args(); // get arguments count bool hasArg(String name); // check if argument exists - void collectHeaders(const char* headerKeys[], const size_t headerKeysCount); // set the request headers to collect + void collectHeaders(String headerKey); // set the request headers to collect String header(String name); // get request header value by name String header(int i); // get request header value by number String headerName(int i); // get request header name by number diff --git a/wled00/wled00.ino b/wled00/wled00.ino index 43b66f28..30108e70 100644 --- a/wled00/wled00.ino +++ b/wled00/wled00.ino @@ -3,10 +3,14 @@ */ /* * @title WLED project sketch - * @version 0.6.4 + * @version 0.7.0 * @author Christian Schwinne */ +//ESP8266-01 got too little storage space to work with all features of WLED. To use it, you must use ESP8266 Arduino Core v2.3.0 and the setting 512K(64K SPIFFS). +//Uncomment the following line to disable some features (currently Mobile UI) to compile for ESP8266-01 +//#define WLED_FLASH_512K_MODE + #include #ifdef ARDUINO_ARCH_ESP32 #include @@ -33,8 +37,8 @@ #include "WS2812FX.h" //version in format yymmddb (b = daily build) -#define VERSION 1804151 -const String versionString = "0.6.4"; +#define VERSION 1806240 +const String versionString = "0.7.0"; //AP and OTA default passwords (change them!) String apPass = "wled1234"; @@ -54,8 +58,9 @@ byte auxDefaultState = 0; //0: input 1: high 2: low byte auxTriggeredState = 0; //0: input 1: high 2: low //Default CONFIG -String serverDescription = versionString; +String serverDescription = "WLED Light"; byte currentTheme = 0; +byte uiConfiguration = 0; //0: auto 1: classic 2: mobile String clientSSID = "Your_Network"; String clientPass = ""; String cmDNS = "led"; @@ -69,9 +74,9 @@ IPAddress staticIP(0, 0, 0, 0); IPAddress staticGateway(0, 0, 0, 0); IPAddress staticSubnet(255, 255, 255, 0); IPAddress staticDNS(8, 8, 8, 8); //only for NTP -bool useHSB = true, useHSBDefault = true, useRGBW = false; +bool useHSB = true, useHSBDefault = true, useRGBW = false, autoRGBtoRGBW = false; bool turnOnAtBoot = true; -bool initLedsLast = false; +bool initLedsLast = false, skipFirstLed = false; byte bootPreset = 0; byte colS[]{255, 159, 0}; byte colSecS[]{0, 0, 0}; @@ -81,6 +86,7 @@ byte briS = 127; byte nightlightTargetBri = 0; bool fadeTransition = true; bool sweepTransition = false, sweepDirection = true; +bool disableSecTransition = true; uint16_t transitionDelay = 1200, transitionDelayDefault = transitionDelay; bool reverseMode = false; bool otaLock = false, wifiLock = false; @@ -91,7 +97,7 @@ bool receiveNotifications = true, receiveNotificationBrightness = true, receiveN byte briMultiplier = 100; byte nightlightDelayMins = 60; bool nightlightFade = true; -uint16_t udpPort = 21324; +uint16_t udpPort = 21324, udpRgbPort = 19446; byte effectDefault = 0; byte effectSpeedDefault = 75; byte effectIntensityDefault = 128; @@ -126,15 +132,19 @@ IPAddress hueIP = (0,0,0,0); bool notifyHue = true; bool hueApplyOnOff = true, hueApplyBri = true, hueApplyColor = true; +uint16_t userVar0 = 0, userVar1 = 0; + //Internal vars byte col[]{0, 0, 0}; byte colOld[]{0, 0, 0}; byte colT[]{0, 0, 0}; byte colIT[]{0, 0, 0}; byte colSec[]{0, 0, 0}; +byte colSecT[]{0, 0, 0}; +byte colSecOld[]{0, 0, 0}; byte colSecIT[]{0, 0, 0}; byte white, whiteOld, whiteT, whiteIT; -byte whiteSec, whiteSecIT; +byte whiteSec, whiteSecOld, whiteSecT, whiteSecIT; byte lastRandomIndex = 0; uint16_t transitionDelayTemp = transitionDelay; unsigned long transitionStartTime; @@ -153,20 +163,20 @@ byte notificationSentCallMode = 0; bool notificationTwoRequired = false; bool nightlightActive = false; bool nightlightActiveOld = false; -uint32_t nightlightDelayMs; -byte briNlT; +uint32_t nightlightDelayMs = 10; +byte briNlT = 0; byte effectCurrent = 0; byte effectSpeed = 75; byte effectIntensity = 128; bool onlyAP = false; -bool udpConnected = false; +bool udpConnected = false, udpRgbConnected = false; String cssCol[]={"","","","","",""}; String cssFont="Verdana"; String cssColorString=""; //NTP stuff bool ntpConnected = false; byte currentTimezone = 0; -time_t local; +time_t local = 0; int utcOffsetSecs = 0; //hue @@ -207,15 +217,17 @@ bool presetCyclingEnabled = false; byte presetCycleMin = 1, presetCycleMax = 5; uint16_t presetCycleTime = 1250; unsigned long presetCycledTime = 0; byte presetCycCurr = presetCycleMin; -bool presetCycleBri, presetCycleCol, presetCycleFx; +bool presetApplyBri = true, presetApplyCol = true, presetApplyFx = true; +bool saveCurrPresetCycConf = false; uint32_t arlsTimeoutMillis = 2500; bool arlsTimeout = false; -bool receiveDirect = true; -unsigned long arlsTimeoutTime; +bool receiveDirect = true, enableRealtimeUI = false; +IPAddress realtimeIP = (0,0,0,0); +unsigned long arlsTimeoutTime = 0; byte auxTime = 0; -unsigned long auxStartTime; -bool auxActive, auxActiveBefore; +unsigned long auxStartTime = 0; +bool auxActive = false, auxActiveBefore = false; bool showWelcomePage = false; bool useGammaCorrectionBri = false; @@ -240,7 +252,7 @@ ESP8266WebServer server(80); #endif HTTPClient hueClient; ESP8266HTTPUpdateServer httpUpdater; -WiFiUDP notifierUdp; +WiFiUDP notifierUdp, rgbUdp; WiFiUDP ntpUdp; IPAddress ntpServerIP; unsigned int ntpLocalPort = 2390; @@ -294,14 +306,6 @@ String txd = "Please disable OTA Lock in security settings!"; void serveMessage(int,String,String,int=255); -void down() -{ - briT = 0; - setAllLeds(); - DEBUG_PRINTLN("MODULE TERMINATED"); - while (1) {delay(1000);} -} - void reset() { briT = 0; @@ -323,7 +327,7 @@ void loop() { yield(); handleButton(); handleNetworkTime(); - if (!otaLock && aOtaEnabled) ArduinoOTA.handle(); + if (aOtaEnabled) ArduinoOTA.handle(); handleAlexa(); handleOverlays(); if (!arlsTimeout) //block stuff if WARLS/Adalight is enabled diff --git a/wled00/wled01_eeprom.ino b/wled00/wled01_eeprom.ino index 37743c06..a156efa3 100644 --- a/wled00/wled01_eeprom.ino +++ b/wled00/wled01_eeprom.ino @@ -148,6 +148,7 @@ void saveSettingsToEEPROM() EEPROM.write(396, (utcOffsetSecs<0)); //is negative EEPROM.write(397, initLedsLast); EEPROM.write(398, (ledCount >> 8) & 0xFF); + EEPROM.write(399, disableSecTransition); for (int k=0;k<6;k++){ int in = 900+k*8; @@ -208,6 +209,25 @@ void saveSettingsToEEPROM() EEPROM.write(2179, macroLongPress); EEPROM.write(2180, macroCountdown); EEPROM.write(2181, macroNl); + + EEPROM.write(2200,!receiveDirect); + EEPROM.write(2201,enableRealtimeUI); + EEPROM.write(2202,uiConfiguration); + EEPROM.write(2203,autoRGBtoRGBW); + EEPROM.write(2204,skipFirstLed); + + if (saveCurrPresetCycConf) + { + EEPROM.write(2205,presetCyclingEnabled); + EEPROM.write(2206,(presetCycleTime >> 0) & 0xFF); + EEPROM.write(2207,(presetCycleTime >> 8) & 0xFF); + EEPROM.write(2208,presetCycleMin); + EEPROM.write(2209,presetCycleMax); + EEPROM.write(2210,presetApplyBri); + EEPROM.write(2211,presetApplyCol); + EEPROM.write(2212,presetApplyFx); + saveCurrPresetCycConf = false; + } EEPROM.commit(); } @@ -260,7 +280,7 @@ void loadSettingsFromEEPROM(bool first) if (apChannel > 13 || apChannel < 1) apChannel = 1; apHide = EEPROM.read(228); if (apHide > 1) apHide = 1; - ledCount = ((EEPROM.read(229) << 0) & 0xFF) + ((EEPROM.read(398) << 8) & 0xFF00); if (ledCount > 1200) ledCount = 10; + ledCount = ((EEPROM.read(229) << 0) & 0xFF) + ((EEPROM.read(398) << 8) & 0xFF00); if (ledCount > 1200 || ledCount == 0) ledCount = 10; notifyButton = EEPROM.read(230); notifyTwice = EEPROM.read(231); buttonEnabled = EEPROM.read(232); @@ -416,14 +436,37 @@ void loadSettingsFromEEPROM(bool first) macroCountdown = EEPROM.read(2180); macroNl = EEPROM.read(2181); } + receiveDirect = !EEPROM.read(2200); + enableRealtimeUI = EEPROM.read(2201); + uiConfiguration = EEPROM.read(2202); + + #ifdef WLED_FLASH_512K_MODE + uiConfiguration = 1; + //force default UI since mobile is unavailable + #endif + + autoRGBtoRGBW = EEPROM.read(2203); + skipFirstLed = EEPROM.read(2204); + + if (EEPROM.read(2210) || EEPROM.read(2211) || EEPROM.read(2212)) + { + presetCyclingEnabled = EEPROM.read(2205); + presetCycleTime = ((EEPROM.read(2206) << 0) & 0xFF) + ((EEPROM.read(2207) << 8) & 0xFF00); + presetCycleMin = EEPROM.read(2208); + presetCycleMax = EEPROM.read(2209); + presetApplyBri = EEPROM.read(2210); + presetApplyCol = EEPROM.read(2211); + presetApplyFx = EEPROM.read(2212); + } bootPreset = EEPROM.read(389); wifiLock = EEPROM.read(393); utcOffsetSecs = ((EEPROM.read(394) << 0) & 0xFF) + ((EEPROM.read(395) << 8) & 0xFF00); if (EEPROM.read(396)) utcOffsetSecs = -utcOffsetSecs; //negative initLedsLast = EEPROM.read(397); + disableSecTransition = EEPROM.read(399); - //favorite setting memory (25 slots/ each 20byte) + //favorite setting (preset) memory (25 slots/ each 20byte) //400 - 899 reserved currentTheme = EEPROM.read(948); diff --git a/wled00/wled02_xml.ino b/wled00/wled02_xml.ino index 310e4a4c..7cefdd11 100644 --- a/wled00/wled02_xml.ino +++ b/wled00/wled02_xml.ino @@ -142,6 +142,7 @@ String getSettings(byte subPage) resp += ds + "CB" + v + colS[2] +";"; resp += ds + "CA" + v + briS +";"; resp += ds + "EW" + c + useRGBW +";"; + resp += ds + "AW" + c + autoRGBtoRGBW +";"; resp += ds + "CW" + v + whiteS +";"; resp += ds + "SR" + v + colSecS[0] +";"; resp += ds + "SG" + v + colSecS[1] +";"; @@ -158,6 +159,7 @@ String getSettings(byte subPage) resp += ds + "TS" + c + sweepTransition +";"; resp += ds + "TI" + c + !sweepDirection +";"; resp += ds + "TD" + v + transitionDelay +";"; + resp += ds + "T2" + c + !disableSecTransition +";"; resp += ds + "BF" + v + briMultiplier +";"; resp += ds + "TB" + v + nightlightTargetBri +";"; resp += ds + "TL" + v + nightlightDelayMins +";"; @@ -165,10 +167,12 @@ String getSettings(byte subPage) resp += ds + "RV" + c + reverseMode +";"; resp += ds + "EI" + c + initLedsLast +";"; resp += ds + "WO" + v + arlsOffset +";"; + resp += ds + "SL" + c + skipFirstLed +";"; } if (subPage == 3) { + resp += ds + "UI" + si + String(uiConfiguration) + ";"; resp += ds + "DS" + v + "\"" + serverDescription + "\";"; resp += ds + "MD" + c + useHSBDefault + ";"; resp += ds + "TH" + si + String(currentTheme) + ";"; @@ -188,6 +192,8 @@ String getSettings(byte subPage) resp += ds + "SB" + c + notifyButton +";"; resp += ds + "SH" + c + notifyHue +";"; resp += ds + "S2" + c + notifyTwice +";"; + resp += ds + "RD" + c + receiveDirect +";"; + resp += ds + "RU" + c + enableRealtimeUI +";"; resp += ds + "AL" + c + alexaEnabled +";"; resp += ds + "AI" + v + "\"" + alexaInvocationName + "\";"; resp += ds + "SA" + c + alexaNotify +";"; diff --git a/wled00/wled03_set.ino b/wled00/wled03_set.ino index 966eb8b6..fa0c6fa2 100644 --- a/wled00/wled03_set.ino +++ b/wled00/wled03_set.ino @@ -121,7 +121,9 @@ void handleSettingsSet(byte subPage) if (ledCount > 600) ledCount = 600; #endif } + ccIndex2 = ledCount -1; useRGBW = server.hasArg("EW"); + autoRGBtoRGBW = server.hasArg("AW"); if (server.hasArg("IS")) //ignore settings and save current brightness, colors and fx as default { colS[0] = col[0]; @@ -193,6 +195,7 @@ void handleSettingsSet(byte subPage) if (i >= 0 && i <= 255) effectIntensityDefault = i; } } + saveCurrPresetCycConf = server.hasArg("PC"); turnOnAtBoot = server.hasArg("BO"); if (server.hasArg("BP")) { @@ -211,6 +214,7 @@ void handleSettingsSet(byte subPage) transitionDelay = i; } } + disableSecTransition = !server.hasArg("T2"); if (server.hasArg("TB")) { nightlightTargetBri = server.arg("TB").toInt(); @@ -229,6 +233,7 @@ void handleSettingsSet(byte subPage) int i = server.arg("WO").toInt(); if (i >= -255 && i <= 255) arlsOffset = i; } + skipFirstLed = server.hasArg("SL"); if (server.hasArg("BF")) { int i = server.arg("BF").toInt(); @@ -239,6 +244,7 @@ void handleSettingsSet(byte subPage) //UI if (subPage == 3) { + if (server.hasArg("UI")) uiConfiguration = server.arg("UI").toInt(); if (server.hasArg("DS")) serverDescription = server.arg("DS"); useHSBDefault = server.hasArg("MD"); useHSB = useHSBDefault; @@ -267,6 +273,8 @@ void handleSettingsSet(byte subPage) notifyDirect = notifyDirectDefault; notifyButton = server.hasArg("SB"); notifyTwice = server.hasArg("S2"); + receiveDirect = server.hasArg("RD"); + enableRealtimeUI = server.hasArg("RU"); alexaEnabled = server.hasArg("AL"); if (server.hasArg("AI")) alexaInvocationName = server.arg("AI"); alexaNotify = server.hasArg("SA"); @@ -381,7 +389,7 @@ void handleSettingsSet(byte subPage) } } saveSettingsToEEPROM(); - if (subPage == 2) strip.init(useRGBW,ledCount,PIN); + if (subPage == 2) strip.init(useRGBW,ledCount,PIN,skipFirstLed); } bool handleSet(String req) @@ -703,6 +711,8 @@ bool handleSet(String req) } } } + //deactivate nightlight if target brightness is reached + if (bri == nightlightTargetBri) nightlightActive = false; //set time (unix timestamp) pos = req.indexOf("ST="); if (pos > 0) { @@ -729,6 +739,12 @@ bool handleSet(String req) if (_cc_updated) strip.setCustomChase(ccIndex1, ccIndex2, ccStart, ccNumPrimary, ccNumSecondary, ccStep, ccFromStart, ccFromEnd); //set presets + pos = req.indexOf("P1="); //sets first preset for cycle + if (pos > 0) presetCycleMin = req.substring(pos + 3).toInt(); + + pos = req.indexOf("P2="); //sets last preset for cycle + if (pos > 0) presetCycleMax = req.substring(pos + 3).toInt(); + if (req.indexOf("CY=") > 0) //preset cycle { presetCyclingEnabled = true; @@ -736,61 +752,36 @@ bool handleSet(String req) { presetCyclingEnabled = false; } - bool all = true; - if (req.indexOf("&PA") > 0) - { - presetCycleBri = true; - all = false; - } - if (req.indexOf("&PC") > 0) - { - presetCycleCol = true; - all = false; - } - if (req.indexOf("&PX") > 0) - { - presetCycleFx = true; - all = false; - } - if (all) - { - presetCycleBri = true; - presetCycleCol = true; - presetCycleFx = true; - } + presetCycCurr = presetCycleMin; } pos = req.indexOf("PT="); //sets cycle time in ms if (pos > 0) { int v = req.substring(pos + 3).toInt(); if (v > 49) presetCycleTime = v; } - pos = req.indexOf("P1="); //sets first preset for cycle - if (pos > 0) presetCycleMin = req.substring(pos + 3).toInt(); - - pos = req.indexOf("P2="); //sets last preset for cycle - if (pos > 0) presetCycleMax = req.substring(pos + 3).toInt(); - + if (req.indexOf("PA=") > 0) //apply brightness from preset + { + presetApplyBri = true; + if (req.indexOf("PA=0") > 0) presetApplyBri = false; + } + if (req.indexOf("PC=") > 0) //apply color from preset + { + presetApplyCol = true; + if (req.indexOf("PC=0") > 0) presetApplyCol = false; + } + if (req.indexOf("PX=") > 0) //apply effects from preset + { + presetApplyFx = true; + if (req.indexOf("PX=0") > 0) presetApplyFx = false; + } pos = req.indexOf("PS="); //saves current in preset if (pos > 0) { savePreset(req.substring(pos + 3).toInt()); } pos = req.indexOf("PL="); //applies entire preset if (pos > 0) { - applyPreset(req.substring(pos + 3).toInt(), true, true, true); - effectUpdated = true; - } - pos = req.indexOf("PA="); //applies brightness from preset - if (pos > 0) { - applyPreset(req.substring(pos + 3).toInt(), true, false, false); - } - pos = req.indexOf("PC="); //applies color from preset - if (pos > 0) { - applyPreset(req.substring(pos + 3).toInt(), false, true, false); - } - pos = req.indexOf("PX="); //applies effects from preset - if (pos > 0) { - applyPreset(req.substring(pos + 3).toInt(), false, false, true); - effectUpdated = true; + applyPreset(req.substring(pos + 3).toInt(), presetApplyBri, presetApplyCol, presetApplyFx); + if (presetApplyFx) effectUpdated = true; } //cronixie @@ -817,7 +808,16 @@ bool handleSet(String req) if (overlayCurrent == 4) strip.setCronixieBacklight(cronixieBacklight); overlayRefreshedTime = 0; } - + pos = req.indexOf("U0="); //user var 0 + if (pos > 0) { + userVar0 = req.substring(pos + 3).toInt(); + } + pos = req.indexOf("U1="); //user var 1 + if (pos > 0) { + userVar1 = req.substring(pos + 3).toInt(); + } + //you can add more if you need + //internal call, does not send XML response pos = req.indexOf("IN"); if (pos < 1) XML_response(); diff --git a/wled00/wled04_file.ino b/wled00/wled04_file.ino index a873b67e..f6d2b71d 100644 --- a/wled00/wled04_file.ino +++ b/wled00/wled04_file.ino @@ -13,7 +13,7 @@ void handleSerial() strip.setMode(0); } arlsTimeout = true; - arlsTimeoutTime = millis() + 4900; + arlsTimeoutTime = millis() + 5200; delay(1); byte hi = Serial.read(); byte ledc = Serial.read(); diff --git a/wled00/wled05_init.ino b/wled00/wled05_init.ino index 4d1a2278..2e230e7a 100644 --- a/wled00/wled05_init.ino +++ b/wled00/wled05_init.ino @@ -5,12 +5,12 @@ void wledInit() { EEPROM.begin(EEPSIZE); - ledCount = ((EEPROM.read(229) << 0) & 0xFF) + ((EEPROM.read(398) << 8) & 0xFF00); if (ledCount > 1200) ledCount = 10; + ledCount = ((EEPROM.read(229) << 0) & 0xFF) + ((EEPROM.read(398) << 8) & 0xFF00); if (ledCount > 1200 || ledCount == 0) ledCount = 10; //RMT eats up too much RAM #ifdef ARDUINO_ARCH_ESP32 if (ledCount > 600) ledCount = 600; #endif - if (!EEPROM.read(397)) strip.init(EEPROM.read(372),ledCount,PIN); //quick init + if (!EEPROM.read(397)) strip.init(EEPROM.read(372),ledCount,PIN,EEPROM.read(2204)); //quick init Serial.begin(115200); Serial.setTimeout(50); @@ -39,17 +39,11 @@ void wledInit() hueIP[1] = WiFi.localIP()[1]; hueIP[2] = WiFi.localIP()[2]; } - - // Set up mDNS responder: - if (cmDNS != NULL && !onlyAP && !MDNS.begin(cmDNS.c_str())) { - DEBUG_PRINTLN("Error setting up MDNS responder!"); - down(); - } - DEBUG_PRINTLN("mDNS responder started"); if (udpPort > 0 && udpPort != ntpLocalPort && WiFi.status() == WL_CONNECTED) { udpConnected = notifierUdp.begin(udpPort); + if (udpConnected && udpRgbPort != udpPort) udpRgbConnected = rgbUdp.begin(udpRgbPort); } if (ntpEnabled && WiFi.status() == WL_CONNECTED) ntpConnected = ntpUdp.begin(ntpLocalPort); @@ -170,16 +164,18 @@ void wledInit() server.on("/freeheap", HTTP_GET, [](){ server.send(200, "text/plain", (String)ESP.getFreeHeap()); }); - - server.on("/pdebug", HTTP_GET, [](){ - server.send(200, "text/plain", (String)presetCycleTime); - }); server.on("/power", HTTP_GET, [](){ String val = (String)(int)strip.getPowerEstimate(ledCount,strip.getColor(),strip.getBrightness()); val += "mA currently"; serveMessage(200,val,"This is just an estimate (does not take into account several factors like effects and wire resistance). It is NOT an accurate measurement!",254); }); + + server.on("/u", HTTP_GET, [](){ + server.setContentLength(strlen_P(PAGE_usermod)); + server.send(200, "text/html", ""); + server.sendContent_P(PAGE_usermod); + }); server.on("/teapot", HTTP_GET, [](){ serveMessage(418, "418. I'm a teapot.","(Tangible Embedded Advanced Project Of Twinkling)",254); @@ -199,8 +195,6 @@ void wledInit() server.on("/edit", HTTP_POST, [](){ server.send(200, "text/plain", ""); }, handleFileUpload); server.on("/list", HTTP_GET, handleFileList); #endif - server.on("/down", HTTP_GET, down); - server.on("/cleareeprom", HTTP_GET, clearEEPROM); //init ota page httpUpdater.setup(&server); } else @@ -208,12 +202,6 @@ void wledInit() server.on("/edit", HTTP_GET, [](){ serveMessage(500, "Access Denied", txd, 254); }); - server.on("/down", HTTP_GET, [](){ - serveMessage(500, "Access Denied", txd, 254); - }); - server.on("/cleareeprom", HTTP_GET, [](){ - serveMessage(500, "Access Denied", txd, 254); - }); server.on("/update", HTTP_GET, [](){ serveMessage(500, "Access Denied", txd, 254); }); @@ -231,14 +219,21 @@ void wledInit() server.send(404, "text/plain", "Not Found"); } }); + + #ifndef ARDUINO_ARCH_ESP32 + const char * headerkeys[] = {"User-Agent"}; + server.collectHeaders(headerkeys,sizeof(char*)); + #else + String ua = "User-Agent"; + server.collectHeaders(ua); + #endif + if (!initLedsLast) strip.service(); //init Alexa hue emulation if (alexaEnabled) alexaInit(); server.begin(); DEBUG_PRINTLN("HTTP server started"); - // Add service to MDNS - MDNS.addService("http", "tcp", 80); //init ArduinoOTA if (aOtaEnabled) @@ -249,9 +244,20 @@ void wledInit() #endif DEBUG_PRINTLN("Start ArduinoOTA"); }); + if (cmDNS.length() > 0) ArduinoOTA.setHostname(cmDNS.c_str()); ArduinoOTA.begin(); } + if (!initLedsLast) strip.service(); + // Set up mDNS responder: + if (cmDNS.length() > 0 && !onlyAP) + { + MDNS.begin(cmDNS.c_str()); + DEBUG_PRINTLN("mDNS responder started"); + // Add service to MDNS + MDNS.addService("http", "tcp", 80); + } + if (initLedsLast) initStrip(); userBegin(); if (macroBoot>0) applyMacro(macroBoot); @@ -261,13 +267,15 @@ void wledInit() void initStrip() { // Initialize NeoPixel Strip and button - if (initLedsLast) strip.init(useRGBW,ledCount,PIN); + if (initLedsLast) strip.init(useRGBW,ledCount,PIN,skipFirstLed); strip.setReverseMode(reverseMode); strip.setColor(0); strip.setBrightness(255); strip.start(); pinMode(buttonPin, INPUT_PULLUP); + pinMode(4,OUTPUT); //this is only needed in special cases + digitalWrite(4,LOW); if (bootPreset>0) applyPreset(bootPreset, turnOnAtBoot, true, true); colorUpdated(0); @@ -305,7 +313,13 @@ void initCon() } int fail_count = 0; if (clientSSID.length() <1 || clientSSID.equals("Your_Network")) fail_count = apWaitTimeSecs*2; + #ifndef ARDUINO_ARCH_ESP32 + WiFi.hostname(serverDescription); + #endif WiFi.begin(clientSSID.c_str(), clientPass.c_str()); + #ifdef ARDUINO_ARCH_ESP32 + WiFi.setHostname(serverDescription.c_str()); + #endif unsigned long lastTry = 0; bool con = false; while(!con) @@ -386,19 +400,46 @@ void serveIndexOrWelcome() } } +void serveRealtimeError(bool settings) +{ + String mesg = "The "; + mesg += (settings)?"settings":"WLED"; + mesg += " UI is not available while receiving real-time data (UDP from "; + mesg += realtimeIP[0]; + for (int i = 1; i < 4; i++) + { + mesg += "."; + mesg += realtimeIP[i]; + } + mesg += ")."; + server.send(200, "text/plain", mesg); +} + void serveIndex() { - if (!arlsTimeout) //do not serve while receiving realtime + bool serveMobile = false; + if (uiConfiguration == 0) serveMobile = checkClientIsMobile(server.header("User-Agent")); + else if (uiConfiguration == 2) serveMobile = true; + + if (!arlsTimeout || enableRealtimeUI) //do not serve while receiving realtime { - server.setContentLength(strlen_P(PAGE_index0) + cssColorString.length() + strlen_P(PAGE_index1) + strlen_P(PAGE_index2) + strlen_P(PAGE_index3)); - server.send(200, "text/html", ""); - server.sendContent_P(PAGE_index0); - server.sendContent(cssColorString); - server.sendContent_P(PAGE_index1); - server.sendContent_P(PAGE_index2); - server.sendContent_P(PAGE_index3); + if (serveMobile) + { + server.setContentLength(strlen_P(PAGE_indexM)); + server.send(200, "text/html", ""); + server.sendContent_P(PAGE_indexM); + } else + { + server.setContentLength(strlen_P(PAGE_index0) + cssColorString.length() + strlen_P(PAGE_index1) + strlen_P(PAGE_index2) + strlen_P(PAGE_index3)); + server.send(200, "text/html", ""); + server.sendContent_P(PAGE_index0); + server.sendContent(cssColorString); + server.sendContent_P(PAGE_index1); + server.sendContent_P(PAGE_index2); + server.sendContent_P(PAGE_index3); + } } else { - server.send(200, "text/plain", "The WLED UI is not available while receiving real-time data."); + serveRealtimeError(false); } } @@ -436,7 +477,7 @@ void serveMessage(int code, String headl, String subl="", int optionType) void serveSettings(byte subPage) { //0: menu 1: wifi 2: leds 3: ui 4: sync 5: time 6: sec 255: welcomepage - if (!arlsTimeout) //do not serve while receiving realtime + if (!arlsTimeout || enableRealtimeUI) //do not serve while receiving realtime { int pl0, pl1; switch (subPage) @@ -483,7 +524,7 @@ void serveSettings(byte subPage) default: server.sendContent_P(PAGE_settings1); } } else { - server.send(200, "text/plain", "The settings are not available while receiving real-time data."); + serveRealtimeError(true); } } @@ -518,5 +559,14 @@ String getBuildInfo() return info; } +bool checkClientIsMobile(String useragent) +{ + //to save complexity this function is not comprehensive + if (useragent.indexOf("Android") >= 0) return true; + if (useragent.indexOf("iPhone") >= 0) return true; + if (useragent.indexOf("iPod") >= 0) return true; + return false; +} + diff --git a/wled00/wled06_usermod.ino b/wled00/wled06_usermod.ino index f60d2e4f..1c75ad1d 100644 --- a/wled00/wled06_usermod.ino +++ b/wled00/wled06_usermod.ino @@ -4,9 +4,11 @@ * EEPROM bytes 2944 to 3071 are reserved for your custom use case. */ +//Use userVar0 and userVar1 (API calls &U0=,&U1=, uint16_t) + void userBeginPreConnection() { - + } void userBegin() @@ -18,4 +20,3 @@ void userLoop() { } - diff --git a/wled00/wled07_notify.ino b/wled00/wled07_notify.ino index 924779b7..72965575 100644 --- a/wled00/wled07_notify.ino +++ b/wled00/wled07_notify.ino @@ -50,14 +50,60 @@ void notify(byte callMode, bool followUp=false) notificationTwoRequired = (followUp)? false:notifyTwice; } +void arlsLock(uint32_t timeoutMs) +{ + if (!arlsTimeout){ + strip.setRange(0, ledCount-1, 0); + strip.setMode(0); + } + arlsTimeout = true; + arlsTimeoutTime = millis() + timeoutMs; +} + void handleNotifications() { + //send second notification if enabled if(udpConnected && notificationTwoRequired && millis()-notificationSentTime > 250){ notify(notificationSentCallMode,true); } - + + //unlock strip when realtime UDP times out + if (arlsTimeout && millis() > arlsTimeoutTime) + { + strip.unlockAll(); + if (bri == 0) strip.setBrightness(0); + arlsTimeout = false; + strip.setMode(effectCurrent); + } + + //receive UDP notifications if(udpConnected && (receiveNotifications || receiveDirect)){ uint16_t packetSize = notifierUdp.parsePacket(); + + //hyperion / raw RGB + if (!packetSize && udpRgbConnected) { + packetSize = rgbUdp.parsePacket(); + if (!receiveDirect) return; + realtimeIP = rgbUdp.remoteIP(); + if (packetSize > 1026 || packetSize < 3) return; + byte udpIn[packetSize]; + rgbUdp.read(udpIn, packetSize); + arlsLock(5200); + uint16_t id = 0; + for (uint16_t i = 0; i < packetSize -2; i += 3) + { + if (useGammaCorrectionRGB) + { + strip.setPixelColor(id, gamma8[udpIn[i]], gamma8[udpIn[i+1]], gamma8[udpIn[i+2]]); + } else { + strip.setPixelColor(id, udpIn[i], udpIn[i+1], udpIn[i+2]); + } + id++; if (id >= ledCount) break; + } + strip.show(); + return; + } + if (packetSize > 1026) return; if(packetSize && notifierUdp.remoteIP() != WiFi.localIP()) //don't process broadcasts we send ourselves { @@ -107,23 +153,19 @@ void handleNotifications() if (receiveNotificationBrightness) bri = udpIn[2]; colorUpdated(3); } - } else if (udpIn[0] > 0 && udpIn[0] < 4) //1 warls //2 drgb //3 drgbw + } else if (udpIn[0] > 0 && udpIn[0] < 4 && receiveDirect) //1 warls //2 drgb //3 drgbw { + realtimeIP = notifierUdp.remoteIP(); if (packetSize > 1) { if (udpIn[1] == 0) { arlsTimeout = false; } else { - if (!arlsTimeout){ - strip.setRange(0, ledCount-1, 0); - strip.setMode(0); - } - arlsTimeout = true; - arlsTimeoutTime = millis() + 1000*udpIn[1]; + arlsLock(udpIn[1]*1000); } if (udpIn[0] == 1) //warls { - for (int i = 2; i < packetSize -3; i += 4) + for (uint16_t i = 2; i < packetSize -3; i += 4) { if (udpIn[i] + arlsOffset < ledCount && udpIn[i] + arlsOffset >= 0) if (useGammaCorrectionRGB) @@ -133,10 +175,10 @@ void handleNotifications() strip.setPixelColor(udpIn[i] + arlsOffset, udpIn[i+1], udpIn[i+2], udpIn[i+3]); } } - } else if (udpIn[0] == 2 && receiveDirect) //drgb + } else if (udpIn[0] == 2) //drgb { - int id = 0; - for (int i = 2; i < packetSize -2; i += 3) + uint16_t id = 0; + for (uint16_t i = 2; i < packetSize -2; i += 3) { if (useGammaCorrectionRGB) { @@ -146,10 +188,10 @@ void handleNotifications() } id++; if (id >= ledCount) break; } - } else if (udpIn[0] == 3 && receiveDirect) //drgbw + } else if (udpIn[0] == 3) //drgbw { - int id = 0; - for (int i = 2; i < packetSize -3; i += 4) + uint16_t id = 0; + for (uint16_t i = 2; i < packetSize -3; i += 4) { if (useGammaCorrectionRGB) { @@ -165,13 +207,6 @@ void handleNotifications() } } } - if (arlsTimeout && millis() > arlsTimeoutTime) - { - strip.unlockAll(); - if (bri == 0) strip.setBrightness(0); - arlsTimeout = false; - strip.setMode(effectCurrent); - } } diff --git a/wled00/wled08_led.ino b/wled00/wled08_led.ino index 7abea58a..f4e83cc9 100644 --- a/wled00/wled08_led.ino +++ b/wled00/wled08_led.ino @@ -12,28 +12,44 @@ void setAllLeds() { } else { strip.setBrightness(val); } + if (disableSecTransition) + { + for (byte i = 0; i<3; i++) + { + colSecT[i] = colSec[i]; + } + whiteSecT = whiteSec; + } + if (autoRGBtoRGBW) + { + colorRGBtoRGBW(colT,&whiteT); + colorRGBtoRGBW(colSecT,&whiteSecT); + } if (useGammaCorrectionRGB) { strip.setColor(gamma8[colT[0]], gamma8[colT[1]], gamma8[colT[2]], gamma8[whiteT]); - strip.setSecondaryColor(gamma8[colSec[0]], gamma8[colSec[1]], gamma8[colSec[2]], gamma8[whiteSec]); + strip.setSecondaryColor(gamma8[colSecT[0]], gamma8[colSecT[1]], gamma8[colSecT[2]], gamma8[whiteSecT]); } else { strip.setColor(colT[0], colT[1], colT[2], whiteT); - strip.setSecondaryColor(colSec[0], colSec[1], colSec[2], whiteSec); + strip.setSecondaryColor(colSecT[0], colSecT[1], colSecT[2], whiteSecT); } } void setLedsStandard() { - colOld[0] = col[0]; - colOld[1] = col[1]; - colOld[2] = col[2]; + for (byte i = 0; i<3; i++) + { + colOld[i] = col[i]; + colT[i] = col[i]; + colSecOld[i] = colSec[i]; + colSecT[i] = colSec[i]; + } whiteOld = white; briOld = bri; - colT[0] = col[0]; - colT[1] = col[1]; - colT[2] = col[2]; + whiteSecOld = whiteSec; whiteT = white; briT = bri; + whiteSecT = whiteSec; setAllLeds(); } @@ -86,6 +102,10 @@ void colorUpdated(int callMode) colOld[1] = colT[1]; colOld[2] = colT[2]; whiteOld = whiteT; + colSecOld[0] = colSecT[0]; + colSecOld[1] = colSecT[1]; + colSecOld[2] = colSecT[2]; + whiteSecOld = whiteSecT; briOld = briT; tperLast = 0; } @@ -120,10 +140,13 @@ void handleTransitions() tperLast = tper; if (fadeTransition) { - colT[0] = colOld[0]+((col[0] - colOld[0])*tper); - colT[1] = colOld[1]+((col[1] - colOld[1])*tper); - colT[2] = colOld[2]+((col[2] - colOld[2])*tper); + for (byte i = 0; i<3; i++) + { + colT[i] = colOld[i]+((col[i] - colOld[i])*tper); + colSecT[i] = colSecOld[i]+((colSec[i] - colSecOld[i])*tper); + } whiteT = whiteOld +((white - whiteOld )*tper); + whiteSecT = whiteSecOld +((whiteSec - whiteSecOld )*tper); briT = briOld +((bri - briOld )*tper); } if (sweepTransition) @@ -181,7 +204,7 @@ void handleNightlight() //also handle preset cycle here if (presetCyclingEnabled && (millis() - presetCycledTime > presetCycleTime)) { - applyPreset(presetCycCurr,presetCycleBri,presetCycleCol,presetCycleFx); + applyPreset(presetCycCurr,presetApplyBri,presetApplyCol,presetApplyFx); presetCycCurr++; if (presetCycCurr > presetCycleMax) presetCycCurr = presetCycleMin; if (presetCycCurr > 25) presetCycCurr = 1; colorUpdated(8); diff --git a/wled00/wled14_colors.ino b/wled00/wled14_colors.ino index 533cccc6..6f882299 100644 --- a/wled00/wled14_colors.ino +++ b/wled00/wled14_colors.ino @@ -115,8 +115,6 @@ void colorRGBtoXY(byte* rgb, float* xy) //rgb to coordinates (https://www.develo xy[1] = Y / (X + Y + Z); } -/*//For some reason min and max are not declared here - float minf (float v, float w) { if (w > v) return v; @@ -129,11 +127,12 @@ float maxf (float v, float w) return v; } -void colorRGBtoRGBW(byte* rgb, byte* wht) //rgb to rgbw, untested and currently unused +void colorRGBtoRGBW(byte* rgb, byte* wht) //rgb to rgbw (http://codewelt.com/rgbw) { - *wht = (float)minf(rgb[0],minf(rgb[1],rgb[2]))*0.95; - rgb[0]-=wht; - rgb[1]-=wht; - rgb[2]-=wht; -}*/ + float low = minf(rgb[0],minf(rgb[1],rgb[2])); + float high = maxf(rgb[0],maxf(rgb[1],rgb[2])); + if (high < 0.1f) return; + float sat = 255.0f * ((high - low) / high); + *wht = (byte)((255.0f - sat) / 255.0f * (rgb[0] + rgb[1] + rgb[2]) / 3); +}