Started implementing Macro function (not functional yet)

Added Cronixie countdown function (min. and sec. works)
Fixed analog clock not working if overlayMin >0
This commit is contained in:
cschwinne 2017-12-28 00:37:13 +01:00
parent a3b3ddf930
commit 745c1d7bc1
8 changed files with 143 additions and 42 deletions

View File

@ -25,7 +25,7 @@
#include "WS2812FX.h" #include "WS2812FX.h"
//version in format yymmddb (b = daily build) //version in format yymmddb (b = daily build)
#define VERSION 1712200 #define VERSION 1712272
//AP and OTA default passwords (change them!) //AP and OTA default passwords (change them!)
String appass = "wled1234"; String appass = "wled1234";
@ -34,10 +34,10 @@ String otapass = "wledota";
//If you have an RGBW strip, uncomment first line in WS2812FX.h! //If you have an RGBW strip, uncomment first line in WS2812FX.h!
//overlays, needed for clocks etc. //overlays, needed for clocks etc.
#define USEOVERLAYS //#define USEOVERLAYS
//support for the CRONIXIE clock by Diamex //support for the CRONIXIE clock by Diamex (disable overlays!)
//#define CRONIXIE #define CRONIXIE
//spiffs FS only useful for debug //spiffs FS only useful for debug
//#define USEFS //#define USEFS
@ -74,6 +74,7 @@ unsigned long cronixieRefreshedTime;
byte dP[]{0,0,0,0,0,0}; byte dP[]{0,0,0,0,0,0};
bool cronixieUseAMPM = false; bool cronixieUseAMPM = false;
bool cronixieBacklight = true; bool cronixieBacklight = true;
bool cronixieCountdown = false;
bool ntpEnabled = true; bool ntpEnabled = true;
#endif #endif
@ -109,7 +110,7 @@ uint16_t transitionDelay = 1200;
boolean otaLock = true; boolean otaLock = true;
boolean onlyAP = false; boolean onlyAP = false;
boolean buttonEnabled = true; 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; boolean receiveNotifications = true, receiveNotificationsDefault = true;
uint8_t bri_n = 100; uint8_t bri_n = 100;
uint8_t nightlightDelayMins = 60; uint8_t nightlightDelayMins = 60;
@ -137,7 +138,10 @@ boolean alexaEnabled = true;
#ifndef CRONIXIE #ifndef CRONIXIE
String alexaInvocationName = "Light"; String alexaInvocationName = "Light";
#endif #endif
boolean alexaNotify = false; uint8_t alexaOnMacro = 255, alexaOffMacro = 255;
uint8_t buttonMacro = 255, countdownMacro = 255;
unsigned long countdownTime = 1514764800L;
double transitionResolution = 0.011; double transitionResolution = 0.011;
@ -183,8 +187,9 @@ uint8_t overlayCurrent = 0;
#ifdef USEOVERLAYS #ifdef USEOVERLAYS
int overlayMin = 0, overlayMax = 79; int overlayMin = 0, overlayMax = 79;
int analogClock12pixel = 25; int analogClock12pixel = 25;
bool overlayDimBg = true;
boolean analogClockSecondsTrail = false; boolean analogClockSecondsTrail = false;
boolean analogClock5MinuteMarks = true; boolean analogClock5MinuteMarks = false;
boolean nixieClockDisplaySeconds = false; boolean nixieClockDisplaySeconds = false;
boolean nixieClock12HourFormat = false; boolean nixieClock12HourFormat = false;
boolean overlayReverse = true; boolean overlayReverse = true;
@ -196,8 +201,8 @@ int overlayDur[6];
int overlayPauseDur[6]; int overlayPauseDur[6];
int nixieClockI = -1; int nixieClockI = -1;
boolean nixiePause; boolean nixiePause;
unsigned long countdownTime = 1514764800L;
#endif #endif
bool countdownOverTriggered = true;
int arlsTimeoutMillis = 2500; int arlsTimeoutMillis = 2500;
boolean arlsTimeout = false; boolean arlsTimeout = false;

View File

@ -2,9 +2,11 @@
* Methods to handle saving and loading to non-volatile memory * Methods to handle saving and loading to non-volatile memory
*/ */
#define EEPSIZE 2048
void clearEEPROM() void clearEEPROM()
{ {
for (int i = 0; i < 1024; i++) for (int i = 0; i < EEPSIZE; i++)
{ {
EEPROM.write(i, 0); EEPROM.write(i, 0);
} }
@ -261,6 +263,9 @@ void loadSettingsFromEEPROM(bool first)
//favorite setting memory (25 slots/ each 20byte) //favorite setting memory (25 slots/ each 20byte)
//400 - 899 reserved //400 - 899 reserved
//custom macro memory (16 slots/ each 64byte)
//1024-2047 reserved
useHSB = useHSBDefault; useHSB = useHSBDefault;
@ -333,3 +338,35 @@ void savePreset(uint8_t index)
EEPROM.commit(); 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();
}

View File

@ -262,6 +262,25 @@ boolean handleSet(String req)
return false; return false;
} }
int pos = 0; int pos = 0;
//save macro, requires &MS=<slot>,"<macro>" 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 //set brigthness
pos = req.indexOf("&A="); pos = req.indexOf("&A=");
if (pos > 0) { 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 //toggle send UDP direct notifications
if (req.indexOf("SN=") > 0) if (req.indexOf("SN=") > 0)
{ {
@ -507,6 +531,12 @@ boolean handleSet(String req)
if (pos > 0) { if (pos > 0) {
setTime(req.substring(pos+3).toInt()); 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 //set custom chase data
bool _cc_updated = false; bool _cc_updated = false;
pos = req.indexOf("C0="); if (pos > 0) {cc_start = (req.substring(pos + 3).toInt()); _cc_updated = true;} 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) { if (pos > 0) {
setCronixie(req.substring(pos + 3, pos + 9).c_str()); 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) { if (pos > 0) {
cronixieCountdown = true;
if (req.indexOf("NM=0") > 0)
{
cronixieCountdown = false;
}
} }
if (req.indexOf("NB=") > 0) //sets backlight if (req.indexOf("NB=") > 0) //sets backlight
{ {
@ -564,10 +598,7 @@ boolean handleSet(String req)
#endif #endif
//internal call, does not send XML response //internal call, does not send XML response
pos = req.indexOf("IN"); pos = req.indexOf("IN");
if (pos < 1) if (pos < 1) XML_response();
{
XML_response();
}
//do not send UDP notifications this time //do not send UDP notifications this time
pos = req.indexOf("NN"); pos = req.indexOf("NN");
if (pos > 0) if (pos > 0)

View File

@ -22,7 +22,7 @@ void wledInit()
#endif #endif
DEBUG_PRINTLN("Init EEPROM"); DEBUG_PRINTLN("Init EEPROM");
EEPROM.begin(1024); EEPROM.begin(EEPSIZE);
loadSettingsFromEEPROM(true); loadSettingsFromEEPROM(true);
DEBUG_PRINT("CC: SSID: "); DEBUG_PRINT("CC: SSID: ");
DEBUG_PRINT(clientssid); DEBUG_PRINT(clientssid);

View File

@ -9,19 +9,24 @@ void handleButton()
if (digitalRead(buttonPin) == LOW && !buttonPressedBefore) if (digitalRead(buttonPin) == LOW && !buttonPressedBefore)
{ {
buttonPressedBefore = true; buttonPressedBefore = true;
if (bri == 0) if (buttonMacro == 255)
{ {
bri = bri_last; if (bri == 0)
} else {
{ bri = bri_last;
bri_last = bri; } else
bri = 0; {
bri_last = bri;
bri = 0;
}
colorUpdated(2);
} else {
applyMacro(buttonMacro);
} }
colorUpdated(2);
} }
else if (digitalRead(buttonPin) == HIGH && buttonPressedBefore) else if (digitalRead(buttonPin) == HIGH && buttonPressedBefore)
{ {
delay(15); delay(15); //debounce
if (digitalRead(buttonPin) == HIGH) if (digitalRead(buttonPin) == HIGH)
{ {
buttonPressedBefore = false; buttonPressedBefore = false;

View File

@ -131,17 +131,23 @@ void _overlayAnalogClock()
{ {
int overlaySize = overlayMax - overlayMin +1; int overlaySize = overlayMax - overlayMin +1;
strip.unlockAll(); 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); local = TZ.toLocal(now(), &tcr);
double hourP = ((double)(hour(local)%12))/12; double hourP = ((double)(hour(local)%12))/12;
double minuteP = ((double)minute(local))/60; double minuteP = ((double)minute(local))/60;
hourP = hourP + minuteP/12; hourP = hourP + minuteP/12;
double secondP = ((double)second(local))/60; double secondP = ((double)second(local))/60;
int hourPixel = floor(overlayMin + analogClock12pixel + overlaySize*hourP); int hourPixel = floor(analogClock12pixel + overlaySize*hourP);
if (hourPixel > overlayMax) hourPixel = hourPixel - overlayMax; if (hourPixel > overlayMax) hourPixel = overlayMin -1 + hourPixel - overlayMax;
int minutePixel = floor(overlayMin + analogClock12pixel + overlaySize*minuteP); int minutePixel = floor(analogClock12pixel + overlaySize*minuteP);
if (minutePixel > overlayMax) minutePixel = minutePixel - overlayMax; if (minutePixel > overlayMax) minutePixel = overlayMin -1 + minutePixel - overlayMax;
int secondPixel = floor(overlayMin + analogClock12pixel + overlaySize*secondP); int secondPixel = floor(analogClock12pixel + overlaySize*secondP);
if (secondPixel > overlayMax) secondPixel = secondPixel - overlayMax; if (secondPixel > overlayMax) secondPixel = overlayMin -1 + secondPixel - overlayMax;
if (analogClock5MinuteMarks) if (analogClock5MinuteMarks)
{ {
int pix; int pix;
@ -154,13 +160,13 @@ void _overlayAnalogClock()
} }
if (analogClockSecondsTrail) if (analogClockSecondsTrail)
{ {
strip.setRange(analogClock12pixel, secondPixel, 0x0000FF); strip.setRange(analogClock12pixel, secondPixel, 0x00FF00);
} else } else
{ {
strip.setIndividual(secondPixel, 0x0000FF); strip.setIndividual(secondPixel, 0x00FF00);
} }
strip.setIndividual(minutePixel, 0x00FF00); strip.setIndividual(minutePixel, 0xEEEEEE);
strip.setIndividual(hourPixel, 0xFF0000); strip.setIndividual(hourPixel, 0x0000FF);
overlayRefreshMs = 998; overlayRefreshMs = 998;
} }

View File

@ -1,5 +1,6 @@
void alexaOn(); void alexaOn();
void alexaOff(); void alexaOff();
void alexaDim();
void alexaInit() void alexaInit()
{ {
@ -22,23 +23,30 @@ void handleAlexa()
void alexaOn() void alexaOn()
{ {
if (alexaNotify) if (alexaOnMacro == 255)
{ {
handleSet("win&T=1&IN"); handleSet((alexaNotify)?"win&T=1&IN":"win&T=1&NN&IN");
} else } else
{ {
handleSet("win&T=1&NN&IN"); applyMacro(alexaOnMacro);
} }
} }
void alexaOff() void alexaOff()
{ {
if (alexaNotify) if (alexaOffMacro == 255)
{ {
handleSet("win&T=0&IN"); handleSet((alexaNotify)?"win&T=0&IN":"win&T=0&NN&IN");
} else } 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);
}

View File

@ -145,6 +145,16 @@ void handleCronixie()
{ {
cronixieRefreshedTime = millis(); cronixieRefreshedTime = millis();
local = TZ.toLocal(now(), &tcr); 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 h = hour(local);
uint8_t h0 = h; uint8_t h0 = h;
uint8_t m = minute(local); uint8_t m = minute(local);
@ -152,9 +162,8 @@ void handleCronixie()
uint8_t d = day(local); uint8_t d = day(local);
uint8_t mi = month(local); uint8_t mi = month(local);
int y = year(local); int y = year(local);
uint8_t woy =
//this has to be changed in time for 22nd century //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) if (cronixieUseAMPM)
{ {