Skip to content

Commit bd0b620

Browse files
committed
Add scheduleing (kinda replaceing macros?)
1 parent b7bfd6f commit bd0b620

File tree

5 files changed

+135
-0
lines changed

5 files changed

+135
-0
lines changed

wled00/data/settings_time.htm

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,11 @@ <h3>Clock</h3>
178178
Countdown Goal:<br>
179179
Date:&nbsp;<nowrap>20<input name="CY" class="xs" type="number" min="0" max="99" required>-<input name="CI" class="xs" type="number" min="1" max="12" required>-<input name="CD" class="xs" type="number" min="1" max="31" required></nowrap><br>
180180
Time:&nbsp;<nowrap><input name="CH" class="xs" type="number" min="0" max="23" required>:<input name="CM" class="xs" type="number" min="0" max="59" required>:<input name="CS" class="xs" type="number" min="0" max="59" required></nowrap><br>
181+
<h3>Upload Schedule JSON</h3>
182+
<input type="file" name="scheduleFile" id="scheduleFile" accept=".json">
183+
<input type="button" value="Upload" onclick="uploadFile(d.Sf.scheduleFile, '/schedule.json');">
184+
<br>
185+
<a class="btn lnk" id="bckschedule" href="/schedule.json" download="schedule">Backup schedule</a><br>
181186
<h3>Macro presets</h3>
182187
<b>Macros have moved!</b><br>
183188
<i>Presets now also can be used as macros to save both JSON and HTTP API commands.<br>

wled00/schedule.cpp

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
// schedule.cpp
2+
3+
//TODO: make schedule.json trigger loadshedule(); on upload istead of just once a min (line 50)
4+
5+
#include "schedule.h"
6+
#include <WLED.h>
7+
#include <time.h>
8+
9+
#define SCHEDULE_FILE "/schedule.json"
10+
11+
ScheduleEvent scheduleEvents[MAX_SCHEDULE_EVENTS];
12+
uint8_t numScheduleEvents = 0;
13+
14+
bool isTodayInRange(uint8_t sm, uint8_t sd, uint8_t em, uint8_t ed, uint8_t cm, uint8_t cd)
15+
{
16+
if (sm < em || (sm == em && sd <= ed))
17+
{
18+
return (cm > sm || (cm == sm && cd >= sd)) &&
19+
(cm < em || (cm == em && cd <= ed));
20+
}
21+
else
22+
{
23+
return (cm > sm || (cm == sm && cd >= sd)) ||
24+
(cm < em || (cm == em && cd <= ed));
25+
}
26+
}
27+
28+
29+
// Checks the schedule and applies any events that match the current time and date.
30+
31+
void checkSchedule() {
32+
static int lastMinute = -1;
33+
34+
time_t now = localTime;
35+
if (now < 100000) return;
36+
37+
struct tm* timeinfo = localtime(&now);
38+
int thisMinute = timeinfo->tm_min + timeinfo->tm_hour * 60;
39+
40+
if (thisMinute == lastMinute) return;
41+
lastMinute = thisMinute;
42+
43+
44+
uint8_t cm = timeinfo->tm_mon + 1; // months since Jan (0-11)
45+
uint8_t cd = timeinfo->tm_mday;
46+
uint8_t wday = timeinfo->tm_wday; // days since Sunday (0-6)
47+
uint8_t hr = timeinfo->tm_hour;
48+
uint8_t min = timeinfo->tm_min;
49+
50+
loadSchedule();
51+
DEBUG_PRINTF_P(PSTR("[Schedule] Checking schedule at %02u:%02u\n"), hr, min);
52+
53+
for (uint8_t i = 0; i < numScheduleEvents; i++)
54+
{
55+
const ScheduleEvent &e = scheduleEvents[i];
56+
if (e.hour != hr || e.minute != min)
57+
continue;
58+
59+
bool match = false;
60+
if (e.repeatMask && ((e.repeatMask >> wday) & 0x01))
61+
match = true;
62+
if (e.startMonth)
63+
{
64+
if (isTodayInRange(e.startMonth, e.startDay, e.endMonth, e.endDay, cm, cd))
65+
match = true;
66+
}
67+
68+
if (match)
69+
applyPreset(e.presetId);
70+
DEBUG_PRINTF_P(PSTR("[Schedule] Applying preset %u at %02u:%02u\n"), e.presetId, hr, min);
71+
DEBUG_PRINTF_P(PSTR("[Schedule] Checked event %u: match=%d\n"), i, match);
72+
}
73+
}
74+
75+
void loadSchedule()
76+
{
77+
if (!WLED_FS.exists(SCHEDULE_FILE))
78+
return;
79+
File file = WLED_FS.open(SCHEDULE_FILE, "r");
80+
if (!file)
81+
return;
82+
83+
DynamicJsonDocument doc(4096);
84+
if (deserializeJson(doc, file))
85+
{
86+
file.close();
87+
return;
88+
}
89+
file.close();
90+
91+
numScheduleEvents = 0;
92+
for (JsonObject e : doc.as<JsonArray>())
93+
{
94+
if (numScheduleEvents >= MAX_SCHEDULE_EVENTS)
95+
break;
96+
scheduleEvents[numScheduleEvents++] = {
97+
(uint8_t)e["sm"], (uint8_t)e["sd"], // start month, day
98+
(uint8_t)e["em"], (uint8_t)e["ed"], // end month, day
99+
(uint8_t)e["r"], (uint8_t)e["h"], // repeat mask, hour
100+
(uint8_t)e["m"], (uint8_t)e["p"]}; // minute, preset
101+
}
102+
DEBUG_PRINTF_P(PSTR("[Schedule] Loaded %u schedule entries from schedule.json\n"), numScheduleEvents);
103+
104+
}
105+

wled00/schedule.h

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
// schedule.h
2+
#pragma once
3+
4+
#include <stdint.h>
5+
6+
#define MAX_SCHEDULE_EVENTS 32
7+
8+
struct ScheduleEvent {
9+
uint8_t startMonth;
10+
uint8_t startDay;
11+
uint8_t endMonth;
12+
uint8_t endDay;
13+
uint8_t repeatMask;
14+
uint8_t hour;
15+
uint8_t minute;
16+
uint8_t presetId;
17+
};
18+
19+
void loadSchedule();
20+
void checkSchedule();

wled00/wled.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ void WLED::loop()
5454
#endif
5555

5656
handleTime();
57+
checkSchedule();
5758
#ifndef WLED_DISABLE_INFRARED
5859
handleIR(); // 2nd call to function needed for ESP32 to return valid results -- should be good for ESP8266, too
5960
#endif
@@ -526,6 +527,8 @@ void WLED::setup()
526527
#if defined(ARDUINO_ARCH_ESP32) && defined(WLED_DISABLE_BROWNOUT_DET)
527528
WRITE_PERI_REG(RTC_CNTL_BROWN_OUT_REG, 1); //enable brownout detector
528529
#endif
530+
531+
loadSchedule();
529532
}
530533

531534
void WLED::beginStrip()

wled00/wled.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,8 @@
6666

6767
#include <cstddef>
6868
#include <vector>
69+
#include "schedule.h"
70+
6971

7072
// Library inclusions.
7173
#include <Arduino.h>

0 commit comments

Comments
 (0)