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"
//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;

View File

@ -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();
}

View File

@ -262,6 +262,25 @@ boolean handleSet(String req)
return false;
}
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
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)

View File

@ -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);

View File

@ -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;

View File

@ -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;
}

View File

@ -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);
}

View File

@ -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)
{