106 lines
3.2 KiB
C
106 lines
3.2 KiB
C
|
#include "Scheduler.h"
|
||
|
#include "LEDDefinition.h"
|
||
|
#include "NeoPixel.h"
|
||
|
#include "mgos_timers.h"
|
||
|
|
||
|
enum ScheduleItemMode {
|
||
|
ScheduleItemMode_OnOff,
|
||
|
ScheduleItemMode_NeonOn,
|
||
|
ScheduleItemMode_tv_bw,
|
||
|
ScheduleItemMode_tv_color
|
||
|
};
|
||
|
|
||
|
static enum ScheduleItemMode modeFromName(char *name) {
|
||
|
if (strcmp(name, "OnOff") == 0) return ScheduleItemMode_OnOff;
|
||
|
if (strcmp(name, "NeonOn") == 0) return ScheduleItemMode_NeonOn;
|
||
|
if (strcmp(name, "TV_BW") == 0) return ScheduleItemMode_tv_bw;
|
||
|
if (strcmp(name, "TV_Color") == 0) return ScheduleItemMode_tv_color;
|
||
|
LOG(LL_ERROR, ("Invalid mode name: %s", name));
|
||
|
return ScheduleItemMode_OnOff;
|
||
|
}
|
||
|
|
||
|
typedef struct Schedule_t {
|
||
|
uint8_t h;
|
||
|
uint8_t m;
|
||
|
uint8_t led;
|
||
|
enum ScheduleItemMode mode;
|
||
|
LEDColor *color;
|
||
|
} Schedule;
|
||
|
static Schedule *schedule = NULL;
|
||
|
static int numScheduleItems = 0;
|
||
|
static int loadedScheduleItems = 0;
|
||
|
static int numberOfLeds = 0;
|
||
|
static int currentHour = 0;
|
||
|
static int currentMinute = 0;
|
||
|
static int clockSpeed = 1; // # seconds for every real time minute
|
||
|
static bool clockRunning = false;
|
||
|
static mgos_timer_id clockTimer = 0;
|
||
|
|
||
|
static void executeScheduleItem(Schedule *s) {
|
||
|
LOG(LL_INFO, ("%d:%d LED #%d / mode=%d / color=%s", s->h, s->m, s->led, s->mode, s->color->name));
|
||
|
if (s->mode == ScheduleItemMode_OnOff) {
|
||
|
NeoPixel_set(s->led, s->color->red, s->color->green, s->color->blue);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static void LEDScheduler_timerTick() {
|
||
|
bool ledsNeedUpdate = false;
|
||
|
|
||
|
if (clockRunning) {
|
||
|
currentMinute++;
|
||
|
if (currentMinute >= 60) {
|
||
|
currentMinute = 0;
|
||
|
currentHour++;
|
||
|
if (currentHour >= 24) {
|
||
|
currentHour = 0;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
for (int i=0; i<loadedScheduleItems; ++i) {
|
||
|
if (schedule[i].h == currentHour && schedule[i].m == currentMinute) {
|
||
|
// ACTION!
|
||
|
executeScheduleItem(&schedule[i]);
|
||
|
ledsNeedUpdate = true;
|
||
|
}
|
||
|
}
|
||
|
if (ledsNeedUpdate) {
|
||
|
NeoPixel_show();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void LEDScheduler_init(int setNumScheduleItems, int setNumberOfLeds, int ledPin) {
|
||
|
if (schedule != NULL) free(schedule);
|
||
|
numScheduleItems = setNumScheduleItems;
|
||
|
loadedScheduleItems = 0;
|
||
|
numberOfLeds = setNumberOfLeds;
|
||
|
schedule = malloc(numScheduleItems * sizeof(Schedule));
|
||
|
NeoPixel_release();
|
||
|
NeoPixel_create(ledPin, numberOfLeds, NeoPixel_colorOrder_GRB);
|
||
|
clockRunning = false;
|
||
|
clockTimer = mgos_set_timer(1000, true, LEDScheduler_timerTick, NULL);
|
||
|
}
|
||
|
|
||
|
void LEDScheduler_addItem(int h, int m, int led, char *mode, char *colorName) {
|
||
|
if (loadedScheduleItems >= numScheduleItems) {
|
||
|
LOG(LL_ERROR, ("Cannot load schedule item as storage is already full, %d:%d LED #%d", h, m, led));
|
||
|
return;
|
||
|
}
|
||
|
schedule[loadedScheduleItems].h = h;
|
||
|
schedule[loadedScheduleItems].m = m;
|
||
|
schedule[loadedScheduleItems].led = led;
|
||
|
schedule[loadedScheduleItems].mode = modeFromName(mode);
|
||
|
schedule[loadedScheduleItems].color = LEDColor_get(colorName);;
|
||
|
schedule[loadedScheduleItems].h = h;
|
||
|
++loadedScheduleItems;
|
||
|
}
|
||
|
|
||
|
void LEDScheduler_run() { clockRunning = true; }
|
||
|
void LEDScheduler_pause() { clockRunning = false; }
|
||
|
|
||
|
void LEDScheduler_setWatch(int h, int m, int speed) {
|
||
|
currentHour = h;
|
||
|
currentMinute = m;
|
||
|
clockSpeed = speed;
|
||
|
LOG(LL_INFO, ("set time %d:%d and speed to %d real-time seconds for a model minute", h, m, speed));
|
||
|
}
|