From 745c1d7bc14660bf844006e44147487bbb1b7d61 Mon Sep 17 00:00:00 2001 From: cschwinne Date: Thu, 28 Dec 2017 00:37:13 +0100 Subject: [PATCH] Started implementing Macro function (not functional yet) Added Cronixie countdown function (min. and sec. works) Fixed analog clock not working if overlayMin >0 --- wled00/wled00.ino | 21 ++++++++++++------- wled00/wled01_eeprom.ino | 39 +++++++++++++++++++++++++++++++++- wled00/wled03_set.ino | 43 ++++++++++++++++++++++++++++++++------ wled00/wled05_init.ino | 2 +- wled00/wled09_button.ino | 21 ++++++++++++------- wled00/wled11_ol.ino | 26 ++++++++++++++--------- wled00/wled12_alexa.ino | 20 ++++++++++++------ wled00/wled13_cronixie.ino | 13 ++++++++++-- 8 files changed, 143 insertions(+), 42 deletions(-) diff --git a/wled00/wled00.ino b/wled00/wled00.ino index 90402a047..64b30f09e 100644 --- a/wled00/wled00.ino +++ b/wled00/wled00.ino @@ -25,7 +25,7 @@ #include "WS2812FX.h" //version in format yymmddb (b = daily build) -#define VERSION 1712200 +#define VERSION 1712272 //AP and OTA default passwords (change them!) String appass = "wled1234"; @@ -34,10 +34,10 @@ String otapass = "wledota"; //If you have an RGBW strip, uncomment first line in WS2812FX.h! //overlays, needed for clocks etc. -#define USEOVERLAYS +//#define USEOVERLAYS -//support for the CRONIXIE clock by Diamex -//#define CRONIXIE +//support for the CRONIXIE clock by Diamex (disable overlays!) +#define CRONIXIE //spiffs FS only useful for debug //#define USEFS @@ -74,6 +74,7 @@ unsigned long cronixieRefreshedTime; byte dP[]{0,0,0,0,0,0}; bool cronixieUseAMPM = false; bool cronixieBacklight = true; +bool cronixieCountdown = false; bool ntpEnabled = true; #endif @@ -109,7 +110,7 @@ uint16_t transitionDelay = 1200; boolean otaLock = true; boolean onlyAP = false; boolean buttonEnabled = true; -boolean notifyDirect = true, notifyButton = true, notifyDirectDefault = true; +boolean notifyDirect = true, notifyButton = true, notifyDirectDefault = true, alexaNotify = false, macroNotify = false; boolean receiveNotifications = true, receiveNotificationsDefault = true; uint8_t bri_n = 100; uint8_t nightlightDelayMins = 60; @@ -137,7 +138,10 @@ boolean alexaEnabled = true; #ifndef CRONIXIE String alexaInvocationName = "Light"; #endif -boolean alexaNotify = false; +uint8_t alexaOnMacro = 255, alexaOffMacro = 255; +uint8_t buttonMacro = 255, countdownMacro = 255; + +unsigned long countdownTime = 1514764800L; double transitionResolution = 0.011; @@ -183,8 +187,9 @@ uint8_t overlayCurrent = 0; #ifdef USEOVERLAYS int overlayMin = 0, overlayMax = 79; int analogClock12pixel = 25; +bool overlayDimBg = true; boolean analogClockSecondsTrail = false; -boolean analogClock5MinuteMarks = true; +boolean analogClock5MinuteMarks = false; boolean nixieClockDisplaySeconds = false; boolean nixieClock12HourFormat = false; boolean overlayReverse = true; @@ -196,8 +201,8 @@ int overlayDur[6]; int overlayPauseDur[6]; int nixieClockI = -1; boolean nixiePause; -unsigned long countdownTime = 1514764800L; #endif +bool countdownOverTriggered = true; int arlsTimeoutMillis = 2500; boolean arlsTimeout = false; diff --git a/wled00/wled01_eeprom.ino b/wled00/wled01_eeprom.ino index 72b0ab7c9..92d31be77 100644 --- a/wled00/wled01_eeprom.ino +++ b/wled00/wled01_eeprom.ino @@ -2,9 +2,11 @@ * Methods to handle saving and loading to non-volatile memory */ +#define EEPSIZE 2048 + void clearEEPROM() { - for (int i = 0; i < 1024; i++) + for (int i = 0; i < EEPSIZE; i++) { EEPROM.write(i, 0); } @@ -261,6 +263,9 @@ void loadSettingsFromEEPROM(bool first) //favorite setting memory (25 slots/ each 20byte) //400 - 899 reserved + + //custom macro memory (16 slots/ each 64byte) + //1024-2047 reserved useHSB = useHSBDefault; @@ -333,3 +338,35 @@ void savePreset(uint8_t index) EEPROM.commit(); } +void applyMacro(uint8_t index) +{ + if (index > 15) return; + String mc="win&"; + for (int i = 1024+64*index; i < 1088+64*index; i++) + { + if (EEPROM.read(i) == 0) break; + mc += char(EEPROM.read(i)); + } + mc += "&IN"; //internal, no XML response + if (!macroNotify) mc += "&NN"; + String forbidden = "&M="; //dont apply if called by the macro itself to prevent loop + /* + * NOTE: loop is still possible if you call a different macro from a macro, which then calls the first macro again. + * To prevent that, but also disable calling macros within macros, comment the next line out. + */ + forbidden = forbidden + index; + if (mc.indexOf(forbidden) >= 0) return; + handleSet(mc); +} + +void saveMacro(uint8_t index, String mc) +{ + if (index > 15) return; + int s = 1024+index*64; + for (int i = s; i < s+64; i++) + { + EEPROM.write(i, mc.charAt(i-s)); + } + EEPROM.commit(); +} + diff --git a/wled00/wled03_set.ino b/wled00/wled03_set.ino index 6b9079b11..7ee57cb84 100644 --- a/wled00/wled03_set.ino +++ b/wled00/wled03_set.ino @@ -262,6 +262,25 @@ boolean handleSet(String req) return false; } int pos = 0; + + //save macro, requires &MS=,"" format + pos = req.indexOf("&MS="); + if (pos > 0) { + int i = req.substring(pos + 4).toInt(); + pos = req.substring(pos + 4).indexOf('"') +1; + if (pos > 0) { + int en = pos+ req.substring(pos).indexOf('"'); + String mc = req.substring(pos); + if (en > 0) mc = req.substring(pos, en); + saveMacro(i, mc); + } + + pos = req.indexOf("IN"); + if (pos < 1) XML_response(); + return true; + //if you save a macro in one request, other commands in that request are ignored due to unwanted behavior otherwise + } + //set brigthness pos = req.indexOf("&A="); if (pos > 0) { @@ -425,6 +444,11 @@ boolean handleSet(String req) } } } + //apply macro + pos = req.indexOf("&M="); + if (pos > 0) { + applyMacro(req.substring(pos + 3).toInt()); + } //toggle send UDP direct notifications if (req.indexOf("SN=") > 0) { @@ -507,6 +531,12 @@ boolean handleSet(String req) if (pos > 0) { setTime(req.substring(pos+3).toInt()); } + //set countdown goal (unix timestamp) + pos = req.indexOf("CT="); + if (pos > 0) { + countdownTime = req.substring(pos+3).toInt(); + countdownOverTriggered = false; + } //set custom chase data bool _cc_updated = false; pos = req.indexOf("C0="); if (pos > 0) {cc_start = (req.substring(pos + 3).toInt()); _cc_updated = true;} @@ -547,9 +577,13 @@ boolean handleSet(String req) if (pos > 0) { setCronixie(req.substring(pos + 3, pos + 9).c_str()); } - pos = req.indexOf("NM="); //mode, NI + pos = req.indexOf("NM="); //mode, 1 countdown if (pos > 0) { - + cronixieCountdown = true; + if (req.indexOf("NM=0") > 0) + { + cronixieCountdown = false; + } } if (req.indexOf("NB=") > 0) //sets backlight { @@ -564,10 +598,7 @@ boolean handleSet(String req) #endif //internal call, does not send XML response pos = req.indexOf("IN"); - if (pos < 1) - { - XML_response(); - } + if (pos < 1) XML_response(); //do not send UDP notifications this time pos = req.indexOf("NN"); if (pos > 0) diff --git a/wled00/wled05_init.ino b/wled00/wled05_init.ino index ac6b037c7..ace3bd4e9 100644 --- a/wled00/wled05_init.ino +++ b/wled00/wled05_init.ino @@ -22,7 +22,7 @@ void wledInit() #endif DEBUG_PRINTLN("Init EEPROM"); - EEPROM.begin(1024); + EEPROM.begin(EEPSIZE); loadSettingsFromEEPROM(true); DEBUG_PRINT("CC: SSID: "); DEBUG_PRINT(clientssid); diff --git a/wled00/wled09_button.ino b/wled00/wled09_button.ino index b5ddf6940..d157fb308 100644 --- a/wled00/wled09_button.ino +++ b/wled00/wled09_button.ino @@ -9,19 +9,24 @@ void handleButton() if (digitalRead(buttonPin) == LOW && !buttonPressedBefore) { buttonPressedBefore = true; - if (bri == 0) + if (buttonMacro == 255) { - bri = bri_last; - } else - { - bri_last = bri; - bri = 0; + if (bri == 0) + { + bri = bri_last; + } else + { + bri_last = bri; + bri = 0; + } + colorUpdated(2); + } else { + applyMacro(buttonMacro); } - colorUpdated(2); } else if (digitalRead(buttonPin) == HIGH && buttonPressedBefore) { - delay(15); + delay(15); //debounce if (digitalRead(buttonPin) == HIGH) { buttonPressedBefore = false; diff --git a/wled00/wled11_ol.ino b/wled00/wled11_ol.ino index deffd1f0a..b6e21bc53 100644 --- a/wled00/wled11_ol.ino +++ b/wled00/wled11_ol.ino @@ -131,17 +131,23 @@ void _overlayAnalogClock() { int overlaySize = overlayMax - overlayMin +1; strip.unlockAll(); + if (overlayDimBg) + { + 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); + } local = TZ.toLocal(now(), &tcr); double hourP = ((double)(hour(local)%12))/12; double minuteP = ((double)minute(local))/60; hourP = hourP + minuteP/12; double secondP = ((double)second(local))/60; - int hourPixel = floor(overlayMin + analogClock12pixel + overlaySize*hourP); - if (hourPixel > overlayMax) hourPixel = hourPixel - overlayMax; - int minutePixel = floor(overlayMin + analogClock12pixel + overlaySize*minuteP); - if (minutePixel > overlayMax) minutePixel = minutePixel - overlayMax; - int secondPixel = floor(overlayMin + analogClock12pixel + overlaySize*secondP); - if (secondPixel > overlayMax) secondPixel = secondPixel - overlayMax; + int hourPixel = floor(analogClock12pixel + overlaySize*hourP); + if (hourPixel > overlayMax) hourPixel = overlayMin -1 + hourPixel - overlayMax; + int minutePixel = floor(analogClock12pixel + overlaySize*minuteP); + if (minutePixel > overlayMax) minutePixel = overlayMin -1 + minutePixel - overlayMax; + int secondPixel = floor(analogClock12pixel + overlaySize*secondP); + if (secondPixel > overlayMax) secondPixel = overlayMin -1 + secondPixel - overlayMax; if (analogClock5MinuteMarks) { int pix; @@ -154,13 +160,13 @@ void _overlayAnalogClock() } if (analogClockSecondsTrail) { - strip.setRange(analogClock12pixel, secondPixel, 0x0000FF); + strip.setRange(analogClock12pixel, secondPixel, 0x00FF00); } else { - strip.setIndividual(secondPixel, 0x0000FF); + strip.setIndividual(secondPixel, 0x00FF00); } - strip.setIndividual(minutePixel, 0x00FF00); - strip.setIndividual(hourPixel, 0xFF0000); + strip.setIndividual(minutePixel, 0xEEEEEE); + strip.setIndividual(hourPixel, 0x0000FF); overlayRefreshMs = 998; } diff --git a/wled00/wled12_alexa.ino b/wled00/wled12_alexa.ino index 7bd870722..1aac35307 100644 --- a/wled00/wled12_alexa.ino +++ b/wled00/wled12_alexa.ino @@ -1,5 +1,6 @@ void alexaOn(); void alexaOff(); +void alexaDim(); void alexaInit() { @@ -22,23 +23,30 @@ void handleAlexa() void alexaOn() { - if (alexaNotify) + if (alexaOnMacro == 255) { - handleSet("win&T=1&IN"); + handleSet((alexaNotify)?"win&T=1&IN":"win&T=1&NN&IN"); } else { - handleSet("win&T=1&NN&IN"); + applyMacro(alexaOnMacro); } } void alexaOff() { - if (alexaNotify) + if (alexaOffMacro == 255) { - handleSet("win&T=0&IN"); + handleSet((alexaNotify)?"win&T=0&IN":"win&T=0&NN&IN"); } else { - handleSet("win&T=0&NN&IN"); + applyMacro(alexaOffMacro); } } +void alexaDim(uint8_t bri) +{ + String ct = (alexaNotify)?"win&IN&A=":"win&NN&IN&A="; + ct = ct + bri; + handleSet(ct); +} + diff --git a/wled00/wled13_cronixie.ino b/wled00/wled13_cronixie.ino index 26678925a..b5d539c45 100644 --- a/wled00/wled13_cronixie.ino +++ b/wled00/wled13_cronixie.ino @@ -145,6 +145,16 @@ void handleCronixie() { cronixieRefreshedTime = millis(); local = TZ.toLocal(now(), &tcr); + if (cronixieCountdown) + { + long diff = countdownTime - now(); + local = abs(diff); + if (diff <0 && !countdownOverTriggered) + { + applyMacro(countdownMacro); + countdownOverTriggered = true; + } + } uint8_t h = hour(local); uint8_t h0 = h; uint8_t m = minute(local); @@ -152,9 +162,8 @@ void handleCronixie() uint8_t d = day(local); uint8_t mi = month(local); int y = year(local); - uint8_t woy = //this has to be changed in time for 22nd century - y -= 2000; if (y<0) y = 99; + y -= 2000; if (y<0) y += 30; //makes countdown work if (cronixieUseAMPM) {