diff --git a/wled00/WS2812FX.cpp b/wled00/WS2812FX.cpp index e25a93f31..eb3b0ae7d 100644 --- a/wled00/WS2812FX.cpp +++ b/wled00/WS2812FX.cpp @@ -1816,6 +1816,11 @@ void WS2812FX::setFastUpdateMode(bool y) if (_mode_index == 0) _mode_delay = 20; } +void WS2812FX::setReverseMode(bool b) +{ + _reverseMode = b; +} + void WS2812FX::driverModeCronixie(bool b) { _cronixieMode = b; @@ -1940,6 +1945,7 @@ void WS2812FX::setPixelColorRaw(uint16_t i, uint8_t r, uint8_t g, uint8_t b, uin void WS2812FX::setPixelColor(uint16_t i, uint8_t r, uint8_t g, uint8_t b, uint8_t w) { + if (_reverseMode) i = _led_count - 1 -i; if (!_cronixieMode) { #ifdef RGBW diff --git a/wled00/WS2812FX.h b/wled00/WS2812FX.h index fdd997ae3..e3a56f4e9 100644 --- a/wled00/WS2812FX.h +++ b/wled00/WS2812FX.h @@ -213,6 +213,7 @@ class WS2812FX : public NeoPixelBrightnessBus { _counter_mode_step = 0; _counter_cc_step = 0; _fastStandard = false; + _reverseMode = false; _locked = new boolean[n]; _cronixieDigits = new uint8_t[6]; } @@ -247,6 +248,7 @@ class WS2812FX : public NeoPixelBrightnessBus { setBrightness(uint8_t b), increaseBrightness(uint8_t s), decreaseBrightness(uint8_t s), + setReverseMode(bool b), driverModeCronixie(bool b), setCronixieDigits(uint8_t* d), setCronixieBacklight(bool b), @@ -360,6 +362,7 @@ class WS2812FX : public NeoPixelBrightnessBus { boolean _triggered, _fastStandard, + _reverseMode, _cronixieMode, _cronixieBacklightEnabled, _cc_fs, diff --git a/wled00/data/settings_leds.htm b/wled00/data/settings_leds.htm index 14d21096d..4dd33b0a8 100644 Binary files a/wled00/data/settings_leds.htm and b/wled00/data/settings_leds.htm differ diff --git a/wled00/data/settings_sync.htm b/wled00/data/settings_sync.htm index 94d96227c..3cd71500f 100644 Binary files a/wled00/data/settings_sync.htm and b/wled00/data/settings_sync.htm differ diff --git a/wled00/data/settings_time.htm b/wled00/data/settings_time.htm index 391682b1b..5ec9d5335 100644 Binary files a/wled00/data/settings_time.htm and b/wled00/data/settings_time.htm differ diff --git a/wled00/data/settings_ui.htm b/wled00/data/settings_ui.htm index 851c9ef78..4bf51c1a9 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 eb783a1a7..498776306 100644 --- a/wled00/htmls00.h +++ b/wled00/htmls00.h @@ -7,7 +7,7 @@ const char PAGE_index0[] PROGMEM = R"=====( -WLED 0.5.1 +WLED 0.6.0_dev )====="; diff --git a/wled00/htmls01.h b/wled00/htmls01.h index ad6285f45..5cbada9ca 100644 --- a/wled00/htmls01.h +++ b/wled00/htmls01.h @@ -116,7 +116,7 @@ Default Duration: Default Target brightness:
Fade down:

Advanced

-Default overlay ID:
+Reverse LED order (rotate 180):
WARLS offset:
@@ -154,7 +154,7 @@ Color Theme: - + @@ -193,12 +193,13 @@ On/Off button enabled:

WLED Broadcast

UDP Port:
Receive Brightness, Color, and Effects
-Send notifications on direct change:
-Send notifications on button press:
-Send Alexa notifications:
+Send notifications on direct change:
+Send notifications on button press:
+Send Alexa notifications:
Send Philips Hue change notifications: +Send notifications twice:

Alexa Voice Assistant

-Emulate Alexa device:
+Emulate Alexa device:
Alexa invocation name:

Philips Hue

You can find the bridge IP and the light number in the 'About' section of the hue app.
@@ -239,9 +240,9 @@ Get time from NTP server:
Time zone:
Hour/Min offset:
--> Current local time is unknown. @@ -331,7 +332,7 @@ HTTP traffic is not encrypted. An attacker in the same network could intercept f
Enable ArduinoOTA:

About

-WLED version 0.5.1
+WLED version 0.6.0_dev
(c) 2016-2018 Christian Schwinne
Licensed under the MIT license

Uses libraries:
diff --git a/wled00/src/dependencies/time/Time.cpp b/wled00/src/dependencies/time/Time.cpp index 5ca132775..6b1df7c5f 100644 --- a/wled00/src/dependencies/time/Time.cpp +++ b/wled00/src/dependencies/time/Time.cpp @@ -281,9 +281,9 @@ void setTime(time_t t) { nextSyncTime = (uint32_t)t + syncInterval; Status = timeSet; prevMillis = millis(); // restart counting from now (thanks to Korman for this fix) -} +} -void setTime(int hr,int min,int sec,int dy, int mnth, int yr){ +time_t getUnixTime(int hr,int min,int sec,int dy, int mnth, int yr){ // year can be given as full four digit year or two digts (2010 or 10 for 2010); //it is converted to years since 1970 if( yr > 99) @@ -296,7 +296,11 @@ void setTime(int hr,int min,int sec,int dy, int mnth, int yr){ tm.Hour = hr; tm.Minute = min; tm.Second = sec; - setTime(makeTime(tm)); + return makeTime(tm); +} + +void setTime(int hr,int min,int sec,int dy, int mnth, int yr){ + setTime(getUnixTime(hr,min,sec,dy,mnth,yr)); } void adjustTime(long adjustment) { diff --git a/wled00/src/dependencies/time/TimeLib.h b/wled00/src/dependencies/time/TimeLib.h index ddb166850..a1f3ce389 100644 --- a/wled00/src/dependencies/time/TimeLib.h +++ b/wled00/src/dependencies/time/TimeLib.h @@ -120,6 +120,7 @@ int year(time_t t); // the year for the given time time_t now(); // return the current time as seconds since Jan 1 1970 void setTime(time_t t); void setTime(int hr,int min,int sec,int day, int month, int yr); +void getUnixTime(int hr,int min,int sec,int day, int month, int yr); //added by Aircoookie to get epoch time void adjustTime(long adjustment); /* date strings */ diff --git a/wled00/src/dependencies/timezone/Timezone.h b/wled00/src/dependencies/timezone/Timezone.h index e0581ee37..c55d0c467 100644 --- a/wled00/src/dependencies/timezone/Timezone.h +++ b/wled00/src/dependencies/timezone/Timezone.h @@ -27,12 +27,11 @@ enum month_t {Jan=1, Feb, Mar, Apr, May, Jun, Jul, Aug, Sep, Oct, Nov, Dec}; //or when standard time begins. struct TimeChangeRule { - char abbrev[6]; //five chars max uint8_t week; //First, Second, Third, Fourth, or Last week of the month uint8_t dow; //day of week, 1=Sun, 2=Mon, ... 7=Sat uint8_t month; //1=Jan, 2=Feb, ... 12=Dec uint8_t hour; //0-23 - int offset; //offset from UTC in minutes + int16_t offset; //offset from UTC in minutes }; class Timezone diff --git a/wled00/wled00.ino b/wled00/wled00.ino index 1350114a4..8051d06c6 100644 --- a/wled00/wled00.ino +++ b/wled00/wled00.ino @@ -3,7 +3,7 @@ */ /* * @title WLED project sketch - * @version 0.5.1 + * @version 0.6.0_dev * @author Christian Schwinne */ @@ -32,8 +32,8 @@ #include "WS2812FX.h" //version in format yymmddb (b = daily build) -#define VERSION 1802273 -const String versionString = "0.5.1"; +#define VERSION 1803061 +const String versionString = "0.6.0_dev"; //AP and OTA default passwords (change them!) String appass = "wled1234"; @@ -42,16 +42,10 @@ String otapass = "wledota"; //If you have an RGBW strip, also uncomment first line in WS2812FX.h! bool useRGBW = false; -//overlays, needed for clocks etc. -#define USEOVERLAYS - -//support for the CRONIXIE clock by Diamex (disable overlays!) -//#define CRONIXIE - //spiffs FS only useful for debug (only ESP8266) //#define USEFS -//to toggle usb serial debug (un)comment following line +//to toggle usb serial debug (un)comment following line(s) //#define DEBUG //Hardware-settings (only changeble via code) @@ -61,39 +55,14 @@ uint8_t auxPin = 15; //use e.g. for external relay uint8_t auxDefaultState = 0; //0: input 1: high 2: low uint8_t auxTriggeredState = 0; //0: input 1: high 2: low -TimeChangeRule CEST = {"CEST", Last, Sun, Mar, 2, 120}; //Central European Summer Time -TimeChangeRule CET = {"CET ", Last, Sun, Oct, 3, 60}; //Central European Standard Time -Timezone TZ(CEST, CET); -TimeChangeRule *tcr; //pointer to the time change rule, use to get the TZ abbrev -time_t local; - -//cronixie defaults -#ifdef CRONIXIE -#undef LEDCOUNT -#define LEDCOUNT 60 -uint8_t ledcount = 6; -String apssid = "CRONIXIE-AP"; -String alexaInvocationName = "Clock"; -char cronixieDefault[] = "HHMMSS"; -long cronixieRefreshMs = 497; -unsigned long cronixieRefreshedTime; -byte dP[]{0,0,0,0,0,0}; -bool cronixieUseAMPM = false; -bool cronixieBacklight = true; -bool cronixieCountdown = false; -bool ntpEnabled = true; -#endif - //Default CONFIG String serverDescription = versionString; uint8_t currentTheme = 0; String clientssid = "Your_Network_Here"; String clientpass = "Dummy_Pass"; String cmdns = "led"; -#ifndef CRONIXIE -uint8_t ledcount = 100; -String apssid = "WLED-AP"; -#endif +uint8_t ledcount = 10; //lowered to prevent accidental overcurrent +String apssid = ""; //AP off by default (unless setup) uint8_t apchannel = 1; uint8_t aphide = 0; uint8_t apWaitTimeSecs = 32; @@ -114,11 +83,12 @@ uint8_t nightlightTargetBri = 0, bri_nl_t; bool fadeTransition = true; bool sweepTransition = false, sweepDirection = true; uint16_t transitionDelay = 1200; +bool reverseMode = false; bool otaLock = false, wifiLock = false; bool aOtaEnabled = true; bool onlyAP = false; bool buttonEnabled = true; -bool notifyDirect = true, notifyButton = true, notifyDirectDefault = true, alexaNotify = false, macroNotify = false; +bool notifyDirect = true, notifyButton = true, notifyDirectDefault = true, alexaNotify = false, macroNotify = false, notifyTwice = false; bool receiveNotifications = true, receiveNotificationBrightness = true, receiveNotificationColor = true, receiveNotificationEffects = true; uint8_t briMultiplier = 100; uint8_t nightlightDelayMins = 60; @@ -128,9 +98,7 @@ uint8_t effectDefault = 0; uint8_t effectSpeedDefault = 75; uint8_t effectIntensityDefault = 128; //NTP stuff -#ifndef CRONIXIE boolean ntpEnabled = false; -#endif IPAddress ntpServerIP; const char* ntpServerName = "pool.ntp.org"; //custom chase @@ -144,11 +112,10 @@ uint8_t cc_start = 0; //alexa boolean alexaEnabled = true; -#ifndef CRONIXIE String alexaInvocationName = "Light"; -#endif -uint8_t alexaOnMacro = 255, alexaOffMacro = 255; -uint8_t buttonMacro = 255, countdownMacro = 255; +uint8_t alexaOnMacro = 0, alexaOffMacro = 0; +uint8_t buttonMacro = 0, countdownMacro = 0; +uint8_t bootMacro = 0; unsigned long countdownTime = 1514764800L; @@ -191,6 +158,9 @@ byte bri_last = 127; boolean transitionActive = false; boolean buttonPressedBefore = false; long buttonPressedTime = 0; +long notificationSentTime = 0; +uint8_t notificationSentCallMode = 0; +bool notificationTwoRequired = false; boolean nightlightActive = false; boolean nightlightActive_old = false; int nightlightDelayMs; @@ -209,30 +179,34 @@ const int NTP_PACKET_SIZE = 48; byte ntpPacketBuffer[NTP_PACKET_SIZE]; unsigned long ntpLastSyncTime = 999000000L; unsigned long ntpPacketSentTime = 999000000L; -const unsigned long seventyYears = 2208988800UL; +uint8_t currentTimezone = 0; +time_t local; +int utcOffsetSecs = 0; //overlay stuff uint8_t overlayDefault = 0; uint8_t overlayCurrent = 0; -#ifdef USEOVERLAYS int overlayMin = 0, overlayMax = 79; //bb: 35, 46, t: 0, 79 int analogClock12pixel = 25; //bb: 41, t: 25 -bool overlayDimBg = true; boolean analogClockSecondsTrail = false; boolean analogClock5MinuteMarks = false; -boolean nixieClockDisplaySeconds = false; -boolean nixieClock12HourFormat = false; -boolean overlayReverse = true; uint8_t overlaySpeed = 200; long overlayRefreshMs = 200; unsigned long overlayRefreshedTime; int overlayArr[6]; -int overlayDur[6]; -int overlayPauseDur[6]; +uint16_t overlayDur[6]; +uint16_t overlayPauseDur[6]; int nixieClockI = -1; boolean nixiePause; -#endif +uint8_t countdownYear=19, countdownMonth=1, countdownDay=1, countdownHour=0, countdownMin=0, countdownSec=0; //year is actual year -2000 bool countdownOverTriggered = true; +//cronixie +String cronixieDisplay = "HHMMSS"; +byte dP[]{0,0,0,0,0,0}; +bool useAMPM = false; +bool cronixieBacklight = true; +bool overlayCountdown = false; +bool cronixieInit = false; int arlsTimeoutMillis = 2500; boolean arlsTimeout = false; @@ -338,17 +312,12 @@ void loop() { handleButton(); handleNetworkTime(); if (!otaLock && aOtaEnabled) ArduinoOTA.handle(); - #ifdef CRONIXIE - handleCronixie(); - #endif handleAlexa(); + handleOverlays(); if (!arlsTimeout) //block stuff if WARLS is enabled { handleHue(); handleNightlight(); - #ifdef USEOVERLAYS - handleOverlays(); - #endif if (bri_t) strip.service(); //do not update strip if off, prevents flicker on ESP32 } diff --git a/wled00/wled01_eeprom.ino b/wled00/wled01_eeprom.ino index e75c3b2df..fb8b25b59 100644 --- a/wled00/wled01_eeprom.ino +++ b/wled00/wled01_eeprom.ino @@ -12,7 +12,7 @@ //2 -> 0.4p 1711302 and up //3 -> 0.4 1712121 and up //4 -> 0.5.0 and up -//5 -> 0.5.1 and up +//5 -> 0.6.0_dev and up void clearEEPROM() { @@ -61,7 +61,7 @@ void saveSettingsToEEPROM() EEPROM.write(228, aphide); EEPROM.write(229, ledcount); EEPROM.write(230, notifyButton); - //231 was notifyNightlight + EEPROM.write(231, notifyTwice); EEPROM.write(232, buttonEnabled); //233 reserved for first boot flag EEPROM.write(234, staticip[0]); @@ -82,6 +82,7 @@ void saveSettingsToEEPROM() EEPROM.write(249, bri_s); EEPROM.write(250, receiveNotificationBrightness); EEPROM.write(251, fadeTransition); + EEPROM.write(252, reverseMode); EEPROM.write(253, (transitionDelay >> 0) & 0xFF); EEPROM.write(254, (transitionDelay >> 8) & 0xFF); EEPROM.write(255, briMultiplier); @@ -102,8 +103,8 @@ void saveSettingsToEEPROM() EEPROM.write(325, effectSpeedDefault); EEPROM.write(326, effectIntensityDefault); EEPROM.write(327, ntpEnabled); - //328 reserved for timezone setting - //329 reserved for dst setting + EEPROM.write(328, currentTimezone); + EEPROM.write(329, useAMPM); EEPROM.write(330, useGammaCorrectionBri); EEPROM.write(331, useGammaCorrectionRGB); EEPROM.write(332, overlayDefault); @@ -140,6 +141,9 @@ void saveSettingsToEEPROM() EEPROM.write(391, receiveNotificationColor); EEPROM.write(392, receiveNotificationEffects); EEPROM.write(393, wifiLock); + EEPROM.write(394, (abs(utcOffsetSecs) >> 0) & 0xFF); + EEPROM.write(395, (abs(utcOffsetSecs) >> 8) & 0xFF); + EEPROM.write(396, (utcOffsetSecs<0)); //is negative for (int k=0;k<6;k++){ int in = 900+k*8; @@ -225,7 +229,7 @@ void loadSettingsFromEEPROM(bool first) if (aphide > 1) aphide = 1; ledcount = EEPROM.read(229); if (ledcount > LEDCOUNT) ledcount = LEDCOUNT; notifyButton = EEPROM.read(230); - //231 was notifyNightlight + notifyTwice = EEPROM.read(231); buttonEnabled = EEPROM.read(232); staticip[0] = EEPROM.read(234); staticip[1] = EEPROM.read(235); @@ -249,6 +253,7 @@ void loadSettingsFromEEPROM(bool first) } receiveNotificationBrightness = EEPROM.read(250); fadeTransition = EEPROM.read(251); + reverseMode = EEPROM.read(252); transitionDelay = ((EEPROM.read(253) << 0) & 0xFF) + ((EEPROM.read(254) << 8) & 0xFF00); briMultiplier = EEPROM.read(255); otapass = ""; @@ -269,6 +274,8 @@ void loadSettingsFromEEPROM(bool first) effectDefault = EEPROM.read(324); effectCurrent = effectDefault; effectSpeedDefault = EEPROM.read(325); effectSpeed = effectSpeedDefault; ntpEnabled = EEPROM.read(327); + currentTimezone = EEPROM.read(328); + useAMPM = EEPROM.read(329); useGammaCorrectionBri = EEPROM.read(330); useGammaCorrectionRGB = EEPROM.read(331); overlayDefault = EEPROM.read(332); @@ -348,6 +355,8 @@ void loadSettingsFromEEPROM(bool first) 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 //favorite setting memory (25 slots/ each 20byte) //400 - 899 reserved @@ -442,15 +451,25 @@ void savePreset(uint8_t index) EEPROM.commit(); } -void applyMacro(uint8_t index) +String loadMacro(uint8_t index) { - if (index > 15) return; - String mc="win&"; + index-=1; + String m=""; + if (index > 15) return m; for (int i = 1024+64*index; i < 1088+64*index; i++) { if (EEPROM.read(i) == 0) break; - mc += char(EEPROM.read(i)); + m += char(EEPROM.read(i)); } + return m; +} + +void applyMacro(uint8_t index) +{ + index-=1; + if (index > 15) return; + String mc="win&"; + mc += loadMacro(index+1); mc += "&IN"; //internal, no XML response if (!macroNotify) mc += "&NN"; String forbidden = "&M="; //dont apply if called by the macro itself to prevent loop @@ -465,6 +484,7 @@ void applyMacro(uint8_t index) void saveMacro(uint8_t index, String mc) { + index-=1; if (index > 15) return; int s = 1024+index*64; for (int i = s; i < s+64; i++) diff --git a/wled00/wled02_xml.ino b/wled00/wled02_xml.ino index e7d5d0042..5432495a2 100644 --- a/wled00/wled02_xml.ino +++ b/wled00/wled02_xml.ino @@ -70,6 +70,7 @@ String getSettings(uint8_t subPage) String v = ".value="; String c = ".checked="; String ih = ".innerHTML="; + String si = ".selectedIndex="; if (subPage == 1) { resp += ds + "CSSID" + v + "\"" + clientssid + "\";"; @@ -164,7 +165,7 @@ String getSettings(uint8_t subPage) resp += ds + "TLBRI" + v + nightlightTargetBri +";"; resp += ds + "TLDUR" + v + nightlightDelayMins +";"; resp += ds + "TLFDE" + c + nightlightFade +";"; - resp += ds + "OLDEF" + v + overlayDefault +";"; + resp += ds + "LEDRV" + c + reverseMode +";"; resp += ds + "WOFFS" + v + arlsOffset +";"; } @@ -172,7 +173,7 @@ String getSettings(uint8_t subPage) { resp += ds + "DESC" + v + "\"" + serverDescription + "\";"; resp += ds + "COLMD" + c + useHSBDefault + ";"; - resp += ds + "THEME.selectedIndex=" + String(currentTheme) + ";"; + resp += ds + "THEME" + si + String(currentTheme) + ";"; for(int i=0;i<6;i++) resp += ds + "CCOL" + i + v + "\"" + cssCol[i] + "\";"; resp += ds + "CFONT" + v + "\"" + cssFont + "\";"; @@ -188,6 +189,7 @@ String getSettings(uint8_t subPage) resp += ds + "NSDIR" + c + notifyDirectDefault +";"; resp += ds + "NSBTN" + c + notifyButton +";"; resp += ds + "NSHUE" + c + notifyHue +";"; + resp += ds + "NS2XS" + c + notifyTwice +";"; resp += ds + "ALEXA" + c + alexaEnabled +";"; resp += ds + "AINVN" + v + "\"" + alexaInvocationName + "\";"; resp += ds + "NSALX" + c + alexaNotify +";"; @@ -207,7 +209,36 @@ String getSettings(uint8_t subPage) if (subPage == 5) { resp += ds + "NTPON" + c + ntpEnabled +";"; + resp += ds + "CL24H" + c + !useAMPM +";"; + resp += ds + "TZONE" + si + String(currentTimezone) + ";"; + resp += ds + "UTCOS" + v + utcOffsetSecs +";"; resp += dg + "(\"times\")[0]" + ih + "\"" + getTimeString() + "\";"; + resp += ds + "OLMDE" + si + String(currentOverlay) + ";"; + resp += ds + "OLIN1" + v + overlayMin +";"; + resp += ds + "OLIN2" + v + overlayMax +";"; + resp += ds + "OLINM" + v + analogClock12pixel +";"; + resp += ds + "OLSTR" + c + analogClockSecondsTrail +";"; + resp += ds + "OL5MI" + c + analogClock5MinuteMarks +";"; + resp += ds + "CRONX" + v + "\"" + cronixieDisplay + "\";"; + resp += ds + "CROBL" + c + cronixieBacklight +";"; + resp += ds + "CLCND" + c + overlayCountdown +";"; + resp += ds + "CDGYR" + v + countdownYear +";"; + resp += ds + "CDGMN" + v + countdownMonth +";"; + resp += ds + "CDGDY" + v + countdownDay +";"; + resp += ds + "CDGHR" + v + countdownHours +";"; + resp += ds + "CDGMI" + v + countdownMin +";"; + resp += ds + "CDGSC" + v + countdownSec +";"; + for (int i=1;i<17;i++) + { + resp += ds + "MC" + String(i) + v + "\"" + loadMacro(i) + "\";"; + } + resp += ds + "MCRBT" + v + macroBoot +";"; + resp += ds + "MCA0I" + v + macroAlexaOn +";"; + resp += ds + "MCA0O" + v + macroAlexaOff +";"; + resp += ds + "MCB0D" + v + macroButton +";"; + resp += ds + "MCB0L" + v + macroLongPress +";"; + resp += ds + "MCNTD" + v + macroCountdown +";"; + resp += ds + "MCLNO" + v + macroNightlight +";"; } if (subPage == 6) diff --git a/wled00/wled03_set.ino b/wled00/wled03_set.ino index 56ca9d749..2b5be7f01 100644 --- a/wled00/wled03_set.ino +++ b/wled00/wled03_set.ino @@ -230,11 +230,7 @@ void handleSettingsSet(uint8_t subPage) if (i > 0) nightlightDelayMins = i; } nightlightFade = server.hasArg("TLFDE"); - if (server.hasArg("OLDEF")) - { - int i = server.arg("OLDEF").toInt(); - if (i >= 0 && i <= 255) overlayDefault = i; - } + reverseMode = server.hasArg("LEDRV"); if (server.hasArg("WOFFS")) { int i = server.arg("WOFFS").toInt(); @@ -278,6 +274,7 @@ void handleSettingsSet(uint8_t subPage) notifyDirectDefault = server.hasArg("NSDIR"); notifyDirect = notifyDirectDefault; notifyButton = server.hasArg("NSBTN"); + notifyTwice = server.hasArg("NS2XS"); alexaEnabled = server.hasArg("ALEXA"); if (server.hasArg("AINVN")) alexaInvocationName = server.arg("AINVN"); alexaNotify = server.hasArg("NSALX"); @@ -319,6 +316,11 @@ void handleSettingsSet(uint8_t subPage) { ntpEnabled = server.hasArg("NTPON"); if (ntpEnabled && WiFi.status() == WL_CONNECTED && !ntpConnected) ntpConnected = ntpUdp.begin(ntpLocalPort); //start if not already connected + if (server.hasArg("OLDEF")) + { + int i = server.arg("OLDEF").toInt(); + if (i >= 0 && i <= 255) overlayDefault = i; + } } //SECURITY @@ -712,17 +714,19 @@ boolean handleSet(String req) applyPreset(req.substring(pos + 3).toInt(), false, false, true); effectUpdated = true; } - #ifdef CRONIXIE + + //cronixie pos = req.indexOf("NX="); //sets digits to code if (pos > 0) { - setCronixie(req.substring(pos + 3, pos + 9).c_str()); + cronixieDisplay = req.substring(pos + 3, pos + 9); + setCronixie(); } pos = req.indexOf("NM="); //mode, 1 countdown if (pos > 0) { - cronixieCountdown = true; + overlayCountdown = true; if (req.indexOf("NM=0") > 0) { - cronixieCountdown = false; + overlayCountdown = false; } } if (req.indexOf("NB=") > 0) //sets backlight @@ -732,10 +736,10 @@ boolean handleSet(String req) { cronixieBacklight = false; } - strip.setCronixieBacklight(cronixieBacklight); - cronixieRefreshedTime = 0; + if (overlayCurrent == 4) strip.setCronixieBacklight(cronixieBacklight); + overlayRefreshedTime = 0; } - #endif + //internal call, does not send XML response pos = req.indexOf("IN"); if (pos < 1) XML_response(); diff --git a/wled00/wled05_init.ino b/wled00/wled05_init.ino index 3776ee71a..0dd5246d5 100644 --- a/wled00/wled05_init.ino +++ b/wled00/wled05_init.ino @@ -212,16 +212,6 @@ void wledInit() info += "rgbw: false\r\n"; #endif info += "max-leds: " + (String)LEDCOUNT + "\r\n"; - #ifdef USEOVERLAYS - info += "overlays: true\r\n"; - #else - info += "overlays: false\r\n"; - #endif - #ifdef CRONIXIE - info += "cronixie: true\r\n"; - #else - info += "cronixie: false\r\n"; - #endif #ifdef USEFS info += "spiffs: true\r\n"; #else @@ -308,16 +298,13 @@ void wledInit() // Initialize NeoPixel Strip strip.init(); strip.setLedCount(ledcount); + strip.setReverseMode(reverseMode); strip.setColor(0); strip.setBrightness(255); strip.start(); pinMode(buttonPin, INPUT_PULLUP); - #ifdef CRONIXIE - strip.driverModeCronixie(true); - strip.setCronixieBacklight(cronixieBacklight); - setCronixie(cronixieDefault); - #endif + if (bootPreset>0) applyPreset(bootPreset, turnOnAtBoot, true, true); colorUpdated(0); if(digitalRead(buttonPin) == LOW) buttonEnabled = false; //disable button if it is "pressed" unintentionally @@ -325,11 +312,7 @@ void wledInit() void initAP(){ String save = apssid; - #ifdef CRONIXIE - if (apssid.length() <1) apssid = "CRONIXIE-AP"; - #else - if (apssid.length() <1) apssid = "WLED-AP"; - #endif + if (apssid.length() <1) apssid = "WLED-AP"; WiFi.softAP(apssid.c_str(), appass.c_str(), apchannel, aphide); apssid = save; } @@ -370,6 +353,7 @@ void buildCssColorString() case 8: cs[0]="0ac"; cs[1]="124"; cs[2]="224"; cs[3]="003eff"; cs[4]="003eff"; cs[5]="003eff"; break;//air case 9: cs[0]="f70"; cs[1]="421"; cs[2]="221"; cs[3]="a50"; cs[4]="f70"; cs[5]="f70"; break;//nixie case 10: cs[0]="2d2"; cs[1]="010"; cs[2]="121"; cs[3]="060"; cs[4]="040"; cs[5]="3f3"; break; //terminal + case 11: cs[0]="867ADE"; cs[1]="4033A3"; cs[2]="483AAA"; cs[3]="483AAA"; cs[4]=""; cs[5]="867ADE"; break; //c64 case 14: cs[0]="fc7"; cs[1]="49274a"; cs[2]="94618e"; cs[3]="f4decb"; cs[4]="0008"; cs[5]="f4decb"; break; //end case 15: for (int i=0;i<6;i++)cs[i]=cssCol[i];//custom } diff --git a/wled00/wled07_notify.ino b/wled00/wled07_notify.ino index f82a618b2..11eb4a766 100644 --- a/wled00/wled07_notify.ino +++ b/wled00/wled07_notify.ino @@ -4,7 +4,7 @@ #define WLEDPACKETSIZE 24 -void notify(uint8_t callMode) +void notify(uint8_t callMode, bool followUp=false) { if (!udpConnected) return; switch (callMode) @@ -41,10 +41,17 @@ void notify(uint8_t callMode) notifierUdp.beginPacket(broadcastIp, udpPort); notifierUdp.write(udpOut, WLEDPACKETSIZE); notifierUdp.endPacket(); + notificationSentCallMode = callMode; + notificationSentTime = millis(); + notificationTwoRequired = (followUp)? false:notifyTwice; } void handleNotifications() { + if(udpConnected && notificationTwoRequired && millis()-notificationSentTime > 250){ + notify(notificationSentCallMode,true); + } + if(udpConnected && receiveNotifications){ int packetSize = notifierUdp.parsePacket(); if(packetSize && notifierUdp.remoteIP() != WiFi.localIP()) //don't process broadcasts we send ourselves diff --git a/wled00/wled09_button.ino b/wled00/wled09_button.ino index 98b64239d..83f21b41e 100644 --- a/wled00/wled09_button.ino +++ b/wled00/wled09_button.ino @@ -10,27 +10,34 @@ void handleButton() { buttonPressedTime = millis(); buttonPressedBefore = true; - if (buttonMacro == 255) - { - if (bri == 0) - { - bri = bri_last; - } else - { - bri_last = bri; - bri = 0; - } - colorUpdated(2); - } else { - applyMacro(buttonMacro); - } } else if (digitalRead(buttonPin) == HIGH && buttonPressedBefore) { delay(15); //debounce if (digitalRead(buttonPin) == HIGH) { - if (millis() - buttonPressedTime > 7000) initAP(); + if (millis() - buttonPressedTime > 7000) {initAP();} + else if (millis() - buttonPressedTime > 700) + { + if (buttonLongPressMacro != 0) {applyMacro(buttonLongPressMacro);} + else _setRandomColor(false); + } + else { + if (buttonMacro == 0) + { + if (bri == 0) + { + bri = bri_last; + } else + { + bri_last = bri; + bri = 0; + } + colorUpdated(2); + } else { + applyMacro(buttonMacro); + } + } buttonPressedBefore = false; } } diff --git a/wled00/wled10_ntp.ino b/wled00/wled10_ntp.ino index 4c24e4ad7..f1ff30c6f 100644 --- a/wled00/wled10_ntp.ino +++ b/wled00/wled10_ntp.ino @@ -2,6 +2,55 @@ * Acquires time from NTP server */ +TimeChangeRule UTCr = {Last, Sun, Mar, 1, 0}; // UTC +Timezone tzUTC(UTCr, UTCr); + +TimeChangeRule BST = {Last, Sun, Mar, 1, 60}; // British Summer Time +TimeChangeRule GMT = {Last, Sun, Oct, 2, 0}; // Standard Time +Timezone tzUK(BST, GMT); + +TimeChangeRule CEST = {Last, Sun, Mar, 2, 120}; //Central European Summer Time +TimeChangeRule CET = {Last, Sun, Oct, 3, 60}; //Central European Standard Time +Timezone tzEUCentral(CEST, CET); + +TimeChangeRule EEST = {Last, Sun, Mar, 3, 180}; //Central European Summer Time +TimeChangeRule EET = {Last, Sun, Oct, 4, 120}; //Central European Standard Time +Timezone tzEUEastern(EEST, EET); + +TimeChangeRule EDT = {Second, Sun, Mar, 2, -240 }; //Daylight time = UTC - 4 hours +TimeChangeRule EST = {First, Sun, Nov, 2, -300 }; //Standard time = UTC - 5 hours +Timezone tzUSEastern(EDT, EST); + +TimeChangeRule CDT = {Second, Sun, Mar, 2, -300 }; //Daylight time = UTC - 5 hours +TimeChangeRule CST = {First, Sun, Nov, 2, -360 }; //Standard time = UTC - 6 hours +Timezone tzUSCentral(CDT, CST); + +TimeChangeRule MDT = {Second, Sun, Mar, 2, -360 }; //Daylight time = UTC - 6 hours +TimeChangeRule MST = {First, Sun, Nov, 2, -420 }; //Standard time = UTC - 7 hours +Timezone tzUSMountain(MDT, MST); + +Timezone tzUSArizona(MST, MST); //Mountain without DST + +TimeChangeRule PDT = {Second, Sun, Mar, 2, -420 }; //Daylight time = UTC - 7 hours +TimeChangeRule PST = {First, Sun, Nov, 2, -480 }; //Standard time = UTC - 8 hours +Timezone tzUSPacific(PDT, PST); + +TimeChangeRule ChST = {Last, Sun, Mar, 1, 480}; // China Standard Time = UTC + 8 hours +Timezone tzChina(ChST, ChST); + +TimeChangeRule JST = {Last, Sun, Mar, 1, 540}; // Japan Standard Time = UTC + 9 hours +Timezone tzJapan(JST, JST); + +TimeChangeRule AEDT = {Second, Sun, Oct, 2, 660 }; //Daylight time = UTC + 11 hours +TimeChangeRule AEST = {First, Sun, Apr, 3, 600 }; //Standard time = UTC + 10 hours +Timezone tzAUEastern(AEDT, AEST); + +TimeChangeRule NZDT = {Second, Sun, Sep, 2, 780 }; //Daylight time = UTC + 13 hours +TimeChangeRule NZST = {First, Sun, Apr, 3, 720 }; //Standard time = UTC + 12 hours +Timezone tzNZ(NZDT, NZST); + +Timezone* timezones[] = { &tzUTC, &tzUK, &tzEUCentral, &tzEUEastern, &tzUSEastern, &tzUSCentral, &tzUSMountain, &tzUSArizona, &tzUSPacific, &tzChina, &tzJapan, &tzAUEastern, &tzNZ}; + void handleNetworkTime() { if (ntpEnabled && ntpConnected && millis() - ntpLastSyncTime > 50000000L && WiFi.status() == WL_CONNECTED) @@ -56,7 +105,7 @@ boolean checkNTPResponse() unsigned long secsSince1900 = highWord << 16 | lowWord; DEBUG_PRINT("Unix time = "); - unsigned long epoch = secsSince1900 - seventyYears; + unsigned long epoch = secsSince1900 - 2208988800UL; //subtract 70 years setTime(epoch); DEBUG_PRINTLN(epoch); if (countdownTime - now() > 0) countdownOverTriggered = false; @@ -65,25 +114,41 @@ boolean checkNTPResponse() return false; } +void updateLocalTime() +{ + unsigned long tmc = now()+ (utcOffsetSign)? -utcOffsetSecs:utcOffsetSecs; + local = timezones[currentTimezone]->toLocal(tmc); +} + String getTimeString() { - local = TZ.toLocal(now(), &tcr); + updateLocalTime(); String ret = monthStr(month(local)); ret = ret + " "; ret = ret + day(local); ret = ret + " "; ret = ret + year(local); ret = ret + ", "; - ret = ret + hour(local); + ret += (useAMPM)? hour(local)%12:hour(local); ret = ret + ":"; if (minute(local) < 10) ret = ret + "0"; ret = ret + minute(local); ret = ret + ":"; if (second(local) < 10) ret = ret + "0"; ret = ret + second(local); + if (useAMPM) + { + ret += (hour(local) > 11)? " PM":" AM"; + } return ret; } +void setCountdown() +{ + countdownTime = timezones[currentTimezone]->toUTC(getUnixTime(countdownHour, countdownMin, countdownSec, countdownDay, countdownMonth, countdownYear)); + if (countdownTime - now() > 0) countdownOverTriggered = false; +} + //returns true if countdown just over bool checkCountdown() { @@ -91,7 +156,7 @@ bool checkCountdown() local = abs(diff); if (diff <0 && !countdownOverTriggered) { - applyMacro(countdownMacro); + if (countdownMacro != 0) applyMacro(countdownMacro); countdownOverTriggered = true; return true; } diff --git a/wled00/wled11_ol.ino b/wled00/wled11_ol.ino index da7757986..79bdf9858 100644 --- a/wled00/wled11_ol.ino +++ b/wled00/wled11_ol.ino @@ -1,7 +1,21 @@ /* - * The Overlay function is over a year old, largely untested and not configurable during runtime. Consider it as deprecated for now, it might get either removed/simplified/reworked. + * Used to draw clock overlays over the strip */ -#ifdef USEOVERLAYS +void initCronixie() +{ + if (overlayCurrent == 7 && !cronixieInit) + { + strip.driverModeCronixie(true); + strip.setCronixieBacklight(cronixieBacklight); + setCronixie(cronixieDefault); + cronixieInit = true; + } else if (cronixieInit && overlayCurrent != 7) + { + strip.driverModeCronixie(false); + cronixieInit = false; + } +} + void _nixieDisplay(int num[], int dur[], int pausedur[], int cnt) { strip.setRange(overlayMin, overlayMax, 0); @@ -84,8 +98,6 @@ void _nixieNumber(int number, int dur) if (overlayArr[i] != -1) { overlayArr[i] = overlayArr[i] + overlayMin; - if (overlayReverse) - overlayArr[i] = overlayMax - overlayArr[i]; } } for (int i = 0; i <6; i++) @@ -106,38 +118,39 @@ void _nixieNumber(int number, int dur) void handleOverlays() { - //properties: range, (color) - //0 no overlay - //1 solid color (NI) - //2 analog clock - //3 digital nixie-style clock one digit - //4 just static hour (NI) - //5 analog countdown - //6 digital one digit countdown + if (overlayCurrent == 0) return; + if (millis() - overlayRefreshedTime > overlayRefreshMs) { - overlayRefreshedTime = millis(); + initCronixie(); + updateLocalTime(); switch (overlayCurrent) { + case 1: _overlaySolid(); break;//solid secondary color case 2: _overlayAnalogClock(); break;//2 analog clock case 3: _overlayNixieClock(); break;//nixie 1-digit - case 5: _overlayAnalogCountdown(); break;//a.countdown - case 6: _overlayNixieCountdown(); break;//d. + case 4: _overlayCronixie();//Diamex cronixie clock kit } + overlayRefreshedTime = millis(); } } +void _overlaySolid() +{ + uint32_t cls = (useGammaCorrectionRGB)? gamma8[white*16777216] + gamma8[col[0]]*65536 + gamma8[col[1]]*256 + gamma8[col[2]]:white*16777216 + col[0]*65536 + col[1]*256 + col[2]; + strip.setRange(overlayMin,overlayMax,cls); + overlayRefreshMs = 1902; +} + void _overlayAnalogClock() { int overlaySize = overlayMax - overlayMin +1; strip.unlockAll(); - if (overlayDimBg) + if (overlayCountdown) { - uint32_t ct = (white>>1)*16777216 + (col[0]>>1)*65536 + (col[1]>>1)*256 + (col[2]>>1); - if (useGammaCorrectionRGB) ct = (gamma8[white]>>1)*16777216 + (gamma8[col[0]]>>1)*65536 + (gamma8[col[1]]>>1)*256 + (gamma8[col[2]]>>1); - strip.setRange(overlayMin, overlayMax, ct); + _overlayAnalogCountdown(); return; } - local = TZ.toLocal(now(), &tcr); + _overlaySolid(); double hourP = ((double)(hour(local)%12))/12; double minuteP = ((double)minute(local))/60; hourP = hourP + minuteP/12; @@ -160,7 +173,14 @@ void _overlayAnalogClock() } if (analogClockSecondsTrail) { - strip.setRange(analogClock12pixel, secondPixel, 0xFF0000); + if (secondPixel < analogClock12pixel) + { + strip.setRange(analogClock12pixel, secondPixel, 0xFF0000); + strip.setRange(secondPixel, overlayMax, 0xFF0000); + } else + { + strip.setRange(analogClock12pixel, secondPixel, 0xFF0000); + } } else { strip.setIndividual(secondPixel, 0xFF0000); @@ -172,14 +192,14 @@ void _overlayAnalogClock() void _overlayNixieClock() { + if (overlayCountdown) + { + _overlayNixieCountdown(); return; + } if (nixieClockI < 0) { - local = TZ.toLocal(now(), &tcr); overlayArr[0] = hour(local); - if (nixieClock12HourFormat && overlayArr[0] > 12) - { - overlayArr[0] = overlayArr[0]%12; - } + if (useAMPM) overlayArr[0] = overlayArr[0]%12; overlayArr[1] = -1; if (overlayArr[0] > 9) { @@ -191,7 +211,7 @@ void _overlayNixieClock() overlayArr[2] = overlayArr[2]/10; overlayArr[4] = -1; overlayArr[5] = -1; - if (nixieClockDisplaySeconds) + if (analogClockSecondsTrail) { overlayArr[4] = second(local); overlayArr[5] = overlayArr[4]%10; @@ -202,8 +222,6 @@ void _overlayNixieClock() if (overlayArr[i] != -1) { overlayArr[i] = overlayArr[i] + overlayMin; - if (overlayReverse) - overlayArr[i] = overlayMax - overlayArr[i]; } } overlayDur[0] = 12 + 12*(255 - overlaySpeed); @@ -331,5 +349,5 @@ void _overlayNixieCountdown() } _nixieNumber(diff, 800); } + overlayRefreshMs = 998; } -#endif diff --git a/wled00/wled12_alexa.ino b/wled00/wled12_alexa.ino index f460ed46b..47ec3dfdc 100644 --- a/wled00/wled12_alexa.ino +++ b/wled00/wled12_alexa.ino @@ -46,7 +46,7 @@ void handleAlexa() void alexaOn() { - if (alexaOnMacro == 255) + if (alexaOnMacro == 0) { handleSet((alexaNotify)?"win&T=1&IN":"win&T=1&NN&IN"); } else @@ -64,7 +64,7 @@ void alexaOn() void alexaOff() { - if (alexaOffMacro == 255) + if (alexaOffMacro == 0) { handleSet((alexaNotify)?"win&T=0&IN":"win&T=0&NN&IN"); } else diff --git a/wled00/wled13_cronixie.ino b/wled00/wled13_cronixie.ino index f5d7112ef..5c79a0d87 100644 --- a/wled00/wled13_cronixie.ino +++ b/wled00/wled13_cronixie.ino @@ -1,7 +1,6 @@ /* * Support for the Cronixie clock */ -#ifdef CRONIXIE uint8_t getSameCodeLength(char code, int index, char const digits[]) { uint8_t counter = 0; @@ -18,8 +17,9 @@ uint8_t getSameCodeLength(char code, int index, char const digits[]) return counter; } -void setCronixie(char const digits[]) +void setCronixie() { + char digits[] = cronixieDisplay.substring(0,6); /* * digit purpose index * 0-9 | 0-9 (incl. random) @@ -86,7 +86,7 @@ void setCronixie(char const digits[]) DEBUG_PRINT("cset "); DEBUG_PRINTLN(digits); - cronixieRefreshMs = 1997; //Only refresh every 2secs if no seconds are displayed + overlayRefreshMs = 1997; //Only refresh every 2secs if no seconds are displayed for (int i = 0; i < 6; i++) { @@ -107,8 +107,8 @@ void setCronixie(char const digits[]) case 'a': dP[i] = 58; i++; break; case 'm': dP[i] = 74 + getSameCodeLength('m',i,digits); i = i+dP[i]-74; break; case 'M': dP[i] = 24 + getSameCodeLength('M',i,digits); i = i+dP[i]-24; break; - case 's': dP[i] = 80 + getSameCodeLength('s',i,digits); i = i+dP[i]-80; cronixieRefreshMs = 497; break; //refresh more often bc. of secs - case 'S': dP[i] = 30 + getSameCodeLength('S',i,digits); i = i+dP[i]-30; cronixieRefreshMs = 497; break; + case 's': dP[i] = 80 + getSameCodeLength('s',i,digits); i = i+dP[i]-80; overlayRefreshMs = 497; break; //refresh more often bc. of secs + case 'S': dP[i] = 30 + getSameCodeLength('S',i,digits); i = i+dP[i]-30; overlayRefreshMs = 497; break; case 'Y': dP[i] = 36 + getSameCodeLength('Y',i,digits); i = i+dP[i]-36; break; case 'y': dP[i] = 86 + getSameCodeLength('y',i,digits); i = i+dP[i]-86; break; case 'I': dP[i] = 39 + getSameCodeLength('I',i,digits); i = i+dP[i]-39; break; //Month. Don't ask me why month and minute both start with M. @@ -139,16 +139,12 @@ void setCronixie(char const digits[]) } DEBUG_PRINTLN((int)dP[5]); - cronixieRefreshedTime = 0; //refresh immediately + _overlayCronixie(); //refresh } -void handleCronixie() +void _overlayCronixie() { - if (millis() - cronixieRefreshedTime > cronixieRefreshMs) - { - cronixieRefreshedTime = millis(); - local = TZ.toLocal(now(), &tcr); - if (cronixieCountdown) checkCountdown(); + if (overlayCountdown) checkCountdown(); uint8_t h = hour(local); uint8_t h0 = h; uint8_t m = minute(local); @@ -159,7 +155,7 @@ void handleCronixie() //this has to be changed in time for 22nd century y -= 2000; if (y<0) y += 30; //makes countdown work - if (cronixieUseAMPM && !cronixieCountdown) + if (useAMPM && !overlayCountdown) { if (h>12) h-=12; else if (h==0) h+=12; @@ -213,6 +209,4 @@ void handleCronixie() } strip.setCronixieDigits(_digitOut); //strip.trigger(); //this has a drawback, no effects slower than RefreshMs. advantage: Quick update, not dependant on effect time - } } -#endif diff --git a/wled00/wled14_colors.ino b/wled00/wled14_colors.ino index eb2d60d92..165053eea 100644 --- a/wled00/wled14_colors.ino +++ b/wled00/wled14_colors.ino @@ -86,16 +86,14 @@ void colorXYtoRGB(float x, float y, uint8_t* rgb) //coordinates to rgb (https:// b = b / r; r = 1.0f; } - } - else if (g > b && g > r) { + } else if (g > b && g > r) { // green is biggest if (g > 1.0f) { r = r / g; b = b / g; g = 1.0f; } - } - else if (b > r && b > g) { + } else if (b > r && b > g) { // blue is biggest if (b > 1.0f) { r = r / b; @@ -117,4 +115,25 @@ void colorRGBtoXY(uint8_t* rgb, float* xy) //rgb to coordinates (https://www.dev xy[1] = Y / (X + Y + Z); } -void colorRGBtoRGBW(uint8_t* rgb, uint8_t* rgbw){} //rgb to rgbw, not imlemented yet +/*//For some reason min and max are not declared here + +float minf (float v, float w) +{ + if (w > v) return v; + return w; +} + +float maxf (float v, float w) +{ + if (w > v) return w; + return v; +} + +void colorRGBtoRGBW(uint8_t* rgb, uint8_t* wht) //rgb to rgbw, untested and currently unused +{ + *wht = (float)minf(rgb[0],minf(rgb[1],rgb[2]))*0.95; + rgb[0]-=wht; + rgb[1]-=wht; + rgb[2]-=wht; +}*/ + diff --git a/wled00/wled15_hue.ino b/wled00/wled15_hue.ino index 1c10faa77..9a6c63c2e 100644 --- a/wled00/wled15_hue.ino +++ b/wled00/wled15_hue.ino @@ -45,7 +45,7 @@ bool sendHuePoll(bool sAuth) { bool st; hueClient.setReuse(true); - hueClient.setTimeout(250); + hueClient.setTimeout(450); String hueURL = "http://"; hueURL += hueIP.toString(); hueURL += "/api/";