Added sunrise/sunset triggered presets.
This commit is contained in:
parent
f74a45a33e
commit
b5abc6c724
@ -335,7 +335,8 @@ void deserializeConfig() {
|
||||
JsonArray timers = tm[F("ins")];
|
||||
uint8_t it = 0;
|
||||
for (JsonObject timer : timers) {
|
||||
if (it > 7) break;
|
||||
if (it > 9) break;
|
||||
if (it<8 && timer[F("hour")]==255) it=8;
|
||||
CJSON(timerHours[it], timer[F("hour")]);
|
||||
CJSON(timerMinutes[it], timer[F("min")]);
|
||||
CJSON(timerMacro[it], timer[F("macro")]);
|
||||
@ -645,8 +646,8 @@ void serializeConfig() {
|
||||
|
||||
JsonArray timers_ins = timers.createNestedArray("ins");
|
||||
|
||||
for (byte i = 0; i < 8; i++) {
|
||||
if (timerMacro[i] == 0 && timerHours[i] == 0 && timerMinutes[i] == 0) continue;
|
||||
for (byte i = 0; i < 10; i++) {
|
||||
if (timerMacro[i] == 0 && (timerHours[i] == 0 || timerHours[i] == 255) && timerMinutes[i] == 0) continue;
|
||||
JsonObject timers_ins0 = timers_ins.createNestedObject();
|
||||
timers_ins0[F("en")] = (timerWeekday[i] & 0x01);
|
||||
timers_ins0[F("hour")] = timerHours[i];
|
||||
|
@ -49,19 +49,23 @@
|
||||
ih+="<tr><td><input name=\"W"+i+"\" id=\"W"+i+"\" type=\"number\" style=\"display:none\"><input id=\"W"+i+"0\" type=\"checkbox\"></td><td><input name=\"H"+i+"\" type=\"number\" min=\"0\" max=\"24\"></td><td><input name=\"N"+i+"\" type=\"number\" min=\"0\" max=\"59\"></td><td><input name=\"T"+i+"\" type=\"number\" min=\"0\" max=\"250\"></td>";
|
||||
for (j=1;j<8;j++) ih+="<td><input id=\"W"+i+j+"\" type=\"checkbox\"></td>";
|
||||
}
|
||||
ih+="<tr><td><input name=\"W8\" id=\"W8\" type=\"number\" style=\"display:none\"><input id=\"W80\" type=\"checkbox\"></td><td>Sunrise<input name=\"H8\" value=\"255\" type=\"hidden\"></td><td><input name=\"N8\" type=\"number\" min=\"-59\" max=\"59\"></td><td><input name=\"T8\" type=\"number\" min=\"0\" max=\"250\"></td>";
|
||||
for (j=1;j<8;j++) ih+="<td><input id=\"W8"+j+"\" type=\"checkbox\"></td>";
|
||||
ih+="<tr><td><input name=\"W9\" id=\"W9\" type=\"number\" style=\"display:none\"><input id=\"W90\" type=\"checkbox\"></td><td>Sunset<input name=\"H9\" value=\"255\" type=\"hidden\"></td><td><input name=\"N9\" type=\"number\" min=\"-59\" max=\"59\"><td><input name=\"T9\" type=\"number\" min=\"0\" max=\"250\"></td>";
|
||||
for (j=1;j<8;j++) ih+="<td><input id=\"W9"+j+"\" type=\"checkbox\"></td>";
|
||||
gId("TMT").innerHTML=ih;
|
||||
}
|
||||
function FC()
|
||||
{
|
||||
for(j=0;j<8;j++)
|
||||
{
|
||||
for(i=0;i<8;i++) gId("W"+i+j).checked=gId("W"+i).value>>j&1;
|
||||
for(i=0;i<10;i++) gId("W"+i+j).checked=gId("W"+i).value>>j&1;
|
||||
}
|
||||
}
|
||||
function Wd()
|
||||
{
|
||||
a=[0,0,0,0,0,0,0,0];
|
||||
for(i=0;i<8;i++)
|
||||
a=[0,0,0,0,0,0,0,0,0,0];
|
||||
for(i=0;i<10;i++)
|
||||
{
|
||||
m=1;
|
||||
for(j=0;j<8;j++)
|
||||
|
@ -297,7 +297,7 @@ type="submit">Save</button></form></body></html>)=====";
|
||||
// Autogenerated from wled00/data/settings_time.htm, do not edit!!
|
||||
const char PAGE_settings_time[] PROGMEM = R"=====(<!DOCTYPE html><html lang="en"><head><meta name="viewport" content="width=500">
|
||||
<meta charset="utf-8"><title>Time Settings</title><script>
|
||||
var d=document;function H(){window.open("https://github.com/Aircoookie/WLED/wiki/Settings#time-settings")}function B(){window.open("/settings","_self")}function S(){BTa(),GetV(),Cs(),FC()}function gId(t){return d.getElementById(t)}function Cs(){gId("cac").style.display="none",gId("coc").style.display="block",gId("ccc").style.display="none",gId("ca").selected&&(gId("cac").style.display="block"),gId("cc").selected&&(gId("coc").style.display="none",gId("ccc").style.display="block"),gId("cn").selected&&(gId("coc").style.display="none")}function BTa(){var t="<tr><th>Active</th><th>Hour</th><th>Minute</th><th>Preset</th><th>M</th><th>T</th><th>W</th><th>T</th><th>F</th><th>S</th><th>S</th></tr>";for(i=0;i<8;i++)for(t+='<tr><td><input name="W'+i+'" id="W'+i+'" type="number" style="display:none"><input id="W'+i+'0" type="checkbox"></td><td><input name="H'+i+'" type="number" min="0" max="24"></td><td><input name="N'+i+'" type="number" min="0" max="59"></td><td><input name="T'+i+'" type="number" min="0" max="250"></td>',j=1;j<8;j++)t+='<td><input id="W'+i+j+'" type="checkbox"></td>';gId("TMT").innerHTML=t}function FC(){for(j=0;j<8;j++)for(i=0;i<8;i++)gId("W"+i+j).checked=gId("W"+i).value>>j&1}function Wd(){for(a=[0,0,0,0,0,0,0,0],i=0;i<8;i++){for(m=1,j=0;j<8;j++)a[i]+=gId("W"+i+j).checked*m,m*=2;gId("W"+i).value=a[i]}}function GetV() {
|
||||
var d=document;function H(){window.open("https://github.com/Aircoookie/WLED/wiki/Settings#time-settings")}function B(){window.open("/settings","_self")}function S(){BTa(),GetV(),Cs(),FC()}function gId(t){return d.getElementById(t)}function Cs(){gId("cac").style.display="none",gId("coc").style.display="block",gId("ccc").style.display="none",gId("ca").selected&&(gId("cac").style.display="block"),gId("cc").selected&&(gId("coc").style.display="none",gId("ccc").style.display="block"),gId("cn").selected&&(gId("coc").style.display="none")}function BTa(){var t="<tr><th>Active</th><th>Hour</th><th>Minute</th><th>Preset</th><th>M</th><th>T</th><th>W</th><th>T</th><th>F</th><th>S</th><th>S</th></tr>";for(i=0;i<8;i++)for(t+='<tr><td><input name="W'+i+'" id="W'+i+'" type="number" style="display:none"><input id="W'+i+'0" type="checkbox"></td><td><input name="H'+i+'" type="number" min="0" max="24"></td><td><input name="N'+i+'" type="number" min="0" max="59"></td><td><input name="T'+i+'" type="number" min="0" max="250"></td>',j=1;j<8;j++)t+='<td><input id="W'+i+j+'" type="checkbox"></td>';for(t+='<tr><td><input name="W8" id="W8" type="number" style="display:none"><input id="W80" type="checkbox"></td><td>Sunrise<input name="H8" value="255" type="hidden"></td><td><input name="N8" type="number" min="-59" max="59"></td><td><input name="T8" type="number" min="0" max="250"></td>',j=1;j<8;j++)t+='<td><input id="W8'+j+'" type="checkbox"></td>';for(t+='<tr><td><input name="W9" id="W9" type="number" style="display:none"><input id="W90" type="checkbox"></td><td>Sunset<input name="H9" value="255" type="hidden"></td><td><input name="N9" type="number" min="-59" max="59"><td><input name="T9" type="number" min="0" max="250"></td>',j=1;j<8;j++)t+='<td><input id="W9'+j+'" type="checkbox"></td>';gId("TMT").innerHTML=t}function FC(){for(j=0;j<8;j++)for(i=0;i<10;i++)gId("W"+i+j).checked=gId("W"+i).value>>j&1}function Wd(){for(a=[0,0,0,0,0,0,0,0,0,0],i=0;i<10;i++){for(m=1,j=0;j<8;j++)a[i]+=gId("W"+i+j).checked*m,m*=2;gId("W"+i).value=a[i]}}function GetV() {
|
||||
%CSS%%SCSS%</head><body onload="S()"><form
|
||||
id="form_s" name="Sf" method="post" onsubmit="Wd()"><div class="toprow"><div
|
||||
class="helpB"><button type="button" onclick="H()">?</button></div><button
|
||||
|
@ -509,7 +509,15 @@ void serializeInfo(JsonObject root)
|
||||
|
||||
root[F("freeheap")] = ESP.getFreeHeap();
|
||||
root[F("uptime")] = millis()/1000 + rolloverMillis*4294967;
|
||||
|
||||
root[F("isday")] = daytime;
|
||||
#ifdef WLED_DEBUG
|
||||
char tmp[30];
|
||||
sprintf(tmp,"%02d:%02d",hour(sunrise),minute(sunrise));
|
||||
root[F("sunrise")] = String(tmp);
|
||||
sprintf(tmp,"%02d:%02d",hour(sunset),minute(sunset));
|
||||
root[F("sunset")] = String(tmp);
|
||||
#endif
|
||||
|
||||
usermods.addToJsonInfo(root);
|
||||
|
||||
|
146
wled00/ntp.cpp
146
wled00/ntp.cpp
@ -219,9 +219,7 @@ void getTimeString(char* out)
|
||||
if (hr > 11) hr -= 12;
|
||||
if (hr == 0) hr = 12;
|
||||
}
|
||||
sprintf(out,"%i-%i-%i, %i:%s%i:%s%i",year(localTime), month(localTime), day(localTime),
|
||||
hr,(minute(localTime)<10)?"0":"",minute(localTime),
|
||||
(second(localTime)<10)?"0":"",second(localTime));
|
||||
sprintf(out,"%i-%i-%i, %02d:%02d:%02d",year(localTime), month(localTime), day(localTime), hr, minute(localTime), second(localTime));
|
||||
if (useAMPM)
|
||||
{
|
||||
strcat(out,(hour(localTime) > 11)? " PM":" AM");
|
||||
@ -259,16 +257,37 @@ byte weekdayMondayFirst()
|
||||
return wd;
|
||||
}
|
||||
|
||||
int getSunriseUTC(int year, int month, int day, float lat, float lon, bool sunset=false);
|
||||
|
||||
void checkTimers()
|
||||
{
|
||||
if (lastTimerMinute != minute(localTime)) //only check once a new minute begins
|
||||
{
|
||||
daytime = isDayTime();
|
||||
if (prevDaytime != daytime) {
|
||||
// sunrise or sunset
|
||||
DEBUG_PRINTLN(daytime?F("Sunrise"):F("Sunset"));
|
||||
}
|
||||
lastTimerMinute = minute(localTime);
|
||||
|
||||
// calculate sunrise and sunset at midnight (if longitude and latitude are set)
|
||||
if (((int)longitude || (int)latitude) && ((!hour(localTime) && !minute(localTime)) || !sunrise)) {
|
||||
struct tm tim_0;
|
||||
tim_0.tm_year = year(localTime)-1900;
|
||||
tim_0.tm_mon = month(localTime)-1;
|
||||
tim_0.tm_mday = day(localTime);
|
||||
tim_0.tm_sec = 0;
|
||||
tim_0.tm_isdst = 0;
|
||||
|
||||
int minUTC = getSunriseUTC(year(localTime), month(localTime), day(localTime), latitude, longitude);
|
||||
tim_0.tm_hour = minUTC / 60;
|
||||
tim_0.tm_min = minUTC % 60;
|
||||
sunrise = tz->toLocal(mktime(&tim_0) - utcOffsetSecs);
|
||||
DEBUG_PRINTF("Sunrise: %02d:%02d\n", hour(sunrise),minute(sunrise));
|
||||
|
||||
minUTC = getSunriseUTC(year(localTime), month(localTime), day(localTime), latitude, longitude, true);
|
||||
tim_0.tm_hour = minUTC / 60;
|
||||
tim_0.tm_min = minUTC % 60;
|
||||
sunset = tz->toLocal(mktime(&tim_0) - utcOffsetSecs);
|
||||
DEBUG_PRINTF("Sunset: %02d:%02d\n", hour(sunset),minute(sunset));
|
||||
}
|
||||
if (sunrise && sunset) daytime = difftime(localTime, sunrise) > 0 && difftime(localTime, sunset) < 0;
|
||||
|
||||
for (uint8_t i = 0; i < 8; i++)
|
||||
{
|
||||
if (timerMacro[i] != 0
|
||||
@ -280,54 +299,77 @@ void checkTimers()
|
||||
applyPreset(timerMacro[i]);
|
||||
}
|
||||
}
|
||||
// sunrise macro
|
||||
if (sunrise && timerMacro[8] != 0
|
||||
&& (hour(sunrise) == hour(localTime))
|
||||
&& (minute(sunrise) + timerMinutes[8]) == minute(localTime)
|
||||
&& (timerWeekday[8] & 0x01) //timer is enabled
|
||||
&& timerWeekday[8] >> weekdayMondayFirst() & 0x01) //timer should activate at current day of week
|
||||
{
|
||||
applyPreset(timerMacro[8]);
|
||||
}
|
||||
// sunset macro
|
||||
if (sunset && timerMacro[9] != 0
|
||||
&& (hour(sunrise) == hour(localTime))
|
||||
&& (minute(sunrise) + timerMinutes[9]) == minute(localTime)
|
||||
&& (timerWeekday[9] & 0x01) //timer is enabled
|
||||
&& timerWeekday[9] >> weekdayMondayFirst() & 0x01) //timer should activate at current day of week
|
||||
{
|
||||
applyPreset(timerMacro[9]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#define ZENITH -.83
|
||||
int getSunriseUTC(int year, int month, int day, float lat, float lon, bool sunset) {
|
||||
//1. first calculate the day of the year
|
||||
float N1 = floor(275 * month / 9);
|
||||
float N2 = floor((month + 9) / 12);
|
||||
float N3 = (1 + floor((year - 4 * floor(year / 4) + 2) / 3));
|
||||
float N = N1 - (N2 * N3) + day - 30;
|
||||
|
||||
//2. convert the longitude to hour value and calculate an approximate time
|
||||
float lngHour = lon / 15.0;
|
||||
float t = N + (((sunset ? 18 : 6) - lngHour) / 24);
|
||||
|
||||
//3. calculate the Sun's mean anomaly
|
||||
float M = (0.9856 * t) - 3.289;
|
||||
|
||||
//4. calculate the Sun's true longitude
|
||||
float L = fmod(M + (1.916 * sin((PI/180)*M)) + (0.020 * sin(2 *(PI/180) * M)) + 282.634,360.0);
|
||||
|
||||
//5a. calculate the Sun's right ascension
|
||||
float RA = fmod(180/PI*atan(0.91764 * tan((PI/180)*L)),360.0);
|
||||
|
||||
//5b. right ascension value needs to be in the same quadrant as L
|
||||
float Lquadrant = floor( L/90) * 90;
|
||||
float RAquadrant = floor(RA/90) * 90;
|
||||
RA = RA + (Lquadrant - RAquadrant);
|
||||
|
||||
//5c. right ascension value needs to be converted into hours
|
||||
RA = RA / 15;
|
||||
|
||||
//6. calculate the Sun's declination
|
||||
float sinDec = 0.39782 * sin((PI/180)*L);
|
||||
float cosDec = cos(asin(sinDec));
|
||||
|
||||
//7a. calculate the Sun's local hour angle
|
||||
float cosH = (sin((PI/180)*ZENITH) - (sinDec * sin((PI/180)*lat))) / (cosDec * cos((PI/180)*lat));
|
||||
/*
|
||||
* This program calculates solar positions as a function of location, date, and time.
|
||||
* The equations are from Jean Meeus, Astronomical Algorithms, Willmann-Bell, Inc., Richmond, VA
|
||||
* (C) 2015, David Brooks, Institute for Earth Science Research and Education.
|
||||
* http://www.instesre.org/ArduinoUnoSolarCalculations.pdf
|
||||
if (cosH > 1) the sun never rises on this location (on the specified date)
|
||||
if (cosH < -1) the sun never sets on this location (on the specified date)
|
||||
*/
|
||||
//#define DEG_TO_RAD 0.01745329
|
||||
//#define PI 3.141592654
|
||||
#define TWOPI 6.28318531
|
||||
|
||||
long JulianDate(int year, int month, int day) {
|
||||
if (month<=2) {
|
||||
year--; month+=12;
|
||||
}
|
||||
int A=year/100;
|
||||
int B=2-A+A/4;
|
||||
return (long)(365.25*(year + 4716)) + (int)(30.6001*(month + 1)) + day + B - 1524;
|
||||
}
|
||||
|
||||
bool isDayTime() {
|
||||
float JD_frac,T,L0,M,C,L_true,GrHrAngle,Obl,RA,Decl,HrAngle,elev;
|
||||
long JD_whole,JDx;
|
||||
|
||||
float Lon = longitude*DEG_TO_RAD;
|
||||
float Lat = latitude*DEG_TO_RAD;
|
||||
|
||||
// calculate elevation of the sun (>0 daytime, <0 nighttime)
|
||||
JD_whole = JulianDate(year(localTime), month(localTime), day(localTime));
|
||||
JD_frac = (hour(localTime) + minute(localTime)/60. + second(localTime)/3600.)/24. - .5;
|
||||
JDx = JD_whole - 2451545;
|
||||
T = (JDx + JD_frac)/36525.;
|
||||
L0 = DEG_TO_RAD*fmod(280.46645 + 36000.76983*T, 360);
|
||||
M = DEG_TO_RAD*fmod(357.5291 + 35999.0503*T, 360);
|
||||
C = DEG_TO_RAD*((1.9146-0.004847*T)*sin(M) + (0.019993-0.000101*T)*sin(2*M) + 0.00029*sin(3*M));
|
||||
Obl = DEG_TO_RAD*(23 + 26/60. + 21.448/3600. - 46.815/3600*T);
|
||||
GrHrAngle = 280.46061837 + (360*JDx)%360 + .98564736629*JDx + 360.98564736629*JD_frac;
|
||||
GrHrAngle = fmod(GrHrAngle, 360.);
|
||||
L_true = fmod(C + L0, TWOPI);
|
||||
RA = atan2(sin(L_true)*cos(Obl), cos(L_true));
|
||||
Decl = asin(sin(Obl)*sin(L_true));
|
||||
HrAngle = DEG_TO_RAD*GrHrAngle + Lon - RA;
|
||||
|
||||
elev = asin(sin(Lat)*sin(Decl) + cos(Lat)*(cos(Decl)*cos(HrAngle)));
|
||||
// Azimuth measured eastward from north.
|
||||
// azimuth = PI+atan2(sin(HrAngle),cos(HrAngle)*sin(Lat)-tan(Decl)*cos(Lat));
|
||||
|
||||
return elev > 0.; // if elevation is gt 0 then it is a day
|
||||
//7b. finish calculating H and convert into hours
|
||||
float H = sunset ? (180/PI)*acos(cosH) : 360 - (180/PI)*acos(cosH);
|
||||
H = H / 15;
|
||||
|
||||
//8. calculate local mean time of rising/setting
|
||||
float T = H + RA - (0.06571 * t) - 6.622;
|
||||
|
||||
//9. adjust back to UTC
|
||||
float UT = fmod(T - lngHour,24.0);
|
||||
|
||||
// return in minutes from midnight
|
||||
return UT*60;
|
||||
}
|
||||
|
@ -328,7 +328,7 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage)
|
||||
macroDoublePress = request->arg(F("MD")).toInt();
|
||||
|
||||
char k[3]; k[2] = 0;
|
||||
for (int i = 0; i<8; i++)
|
||||
for (int i = 0; i<10; i++)
|
||||
{
|
||||
k[1] = i+48;//ascii 0,1,2,3
|
||||
|
||||
|
@ -8,7 +8,7 @@
|
||||
*/
|
||||
|
||||
// version code in format yymmddb (b = daily build)
|
||||
#define VERSION 2103051
|
||||
#define VERSION 2103070
|
||||
|
||||
//uncomment this if you have a "my_config.h" file you'd like to use
|
||||
//#define WLED_USE_MY_CONFIG
|
||||
@ -451,10 +451,10 @@ WLED_GLOBAL bool countdownOverTriggered _INIT(true);
|
||||
|
||||
// timer
|
||||
WLED_GLOBAL byte lastTimerMinute _INIT(0);
|
||||
WLED_GLOBAL byte timerHours[] _INIT_N(({ 0, 0, 0, 0, 0, 0, 0, 0 }));
|
||||
WLED_GLOBAL byte timerMinutes[] _INIT_N(({ 0, 0, 0, 0, 0, 0, 0, 0 }));
|
||||
WLED_GLOBAL byte timerMacro[] _INIT_N(({ 0, 0, 0, 0, 0, 0, 0, 0 }));
|
||||
WLED_GLOBAL byte timerWeekday[] _INIT_N(({ 255, 255, 255, 255, 255, 255, 255, 255 })); // weekdays to activate on
|
||||
WLED_GLOBAL byte timerHours[] _INIT_N(({ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }));
|
||||
WLED_GLOBAL int8_t timerMinutes[] _INIT_N(({ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }));
|
||||
WLED_GLOBAL byte timerMacro[] _INIT_N(({ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }));
|
||||
WLED_GLOBAL byte timerWeekday[] _INIT_N(({ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 })); // weekdays to activate on
|
||||
// bit pattern of arr elem: 0b11111111: sun,sat,fri,thu,wed,tue,mon,validity
|
||||
|
||||
// blynk
|
||||
@ -516,9 +516,10 @@ WLED_GLOBAL IPAddress ntpServerIP;
|
||||
WLED_GLOBAL uint16_t ntpLocalPort _INIT(2390);
|
||||
WLED_GLOBAL uint16_t rolloverMillis _INIT(0);
|
||||
WLED_GLOBAL bool daytime _INIT(false);
|
||||
WLED_GLOBAL bool prevDaytime _INIT(false);
|
||||
WLED_GLOBAL float longitude _INIT(0.0);
|
||||
WLED_GLOBAL float latitude _INIT(0.0);
|
||||
WLED_GLOBAL time_t sunrise _INIT(0);
|
||||
WLED_GLOBAL time_t sunset _INIT(0);
|
||||
|
||||
// Temp buffer
|
||||
WLED_GLOBAL char* obuf;
|
||||
|
@ -480,10 +480,10 @@ void getSettingsJS(byte subPage, char* dest)
|
||||
|
||||
char k[4];
|
||||
k[2] = 0; //Time macros
|
||||
for (int i = 0; i<8; i++)
|
||||
for (int i = 0; i<10; i++)
|
||||
{
|
||||
k[1] = 48+i; //ascii 0,1,2,3
|
||||
k[0] = 'H'; sappend('v',k,timerHours[i]);
|
||||
if (i<8) { k[0] = 'H'; sappend('v',k,timerHours[i]); }
|
||||
k[0] = 'N'; sappend('v',k,timerMinutes[i]);
|
||||
k[0] = 'T'; sappend('v',k,timerMacro[i]);
|
||||
k[0] = 'W'; sappend('v',k,timerWeekday[i]);
|
||||
|
Loading…
Reference in New Issue
Block a user