Added new mode: Scheduler -- clock based switching of lights
This commit is contained in:
parent
626fe42a90
commit
4aeebe1b33
|
@ -1,28 +1,39 @@
|
|||
let addColor = ffi('void addColor(char *,int,int,int)');
|
||||
let LEDDefinition_addByName = ffi('void LEDDefinition_addByName(char *, char *, char *, char *)');
|
||||
let addAnimationStep = ffi('void addAnimationStep(int, char *, int)');
|
||||
let LEDMode_on=1, LEDMode_off=2, LEDMode_blink=3, LEDMode_tv=4, LEDMode_fire=5;
|
||||
|
||||
let LEDStateEngine_init = ffi('void LEDStateEngine_init(int, int)');
|
||||
let LEDStateEngine_start = ffi('void startLEDStateEngine(void)');
|
||||
let LEDStateEngine_pause = ffi('void pauseLEDStateEngine(void)');
|
||||
let LEDStateEngine_getMinTickTime = ffi('double LEDStateEngine_getMinTickTime(void)');
|
||||
let LEDStateEngine_getMaxTickTime = ffi('double LEDStateEngine_getMaxTickTime(void)');
|
||||
|
||||
let LEDState_getRed = ffi('int LEDState_getLedRed(int)');
|
||||
let LEDState_getGreen = ffi('int LEDState_getLedGreen(int)');
|
||||
let LEDState_getBlue = ffi('int LEDState_getLedBlue(int)');
|
||||
let LEDState_getColorName = ffi('char * LEDState_getLedColorName(int)');
|
||||
let LEDState_getNextTick = ffi('int LEDState_getNextTick(int)');
|
||||
let LEDState_getCurrentTick = ffi('int LEDState_getCurrentTick(int)');
|
||||
|
||||
let LEDDefinition_addByName = ffi('void LEDDefinition_addByName(char *, char *, char *, char *)');
|
||||
let LEDDefinition_getLevel = ffi('char *LEDDefinition_getLevel(int)');
|
||||
let LEDDefinition_getRoom = ffi('char *LEDDefinition_getRoom(int)');
|
||||
let LEDDefinition_getId = ffi('char *LEDDefinition_getId(int)');
|
||||
let LEDDefinition_getOnColorRed = ffi('int LEDDefinition_getOnColorRed(int)');
|
||||
let LEDDefinition_getOnColorGreen = ffi('int LEDDefinition_getOnColorGreen(int)');
|
||||
let LEDDefinition_getOnColorBlue = ffi('int LEDDefinition_getOnColorBlue(int)');
|
||||
|
||||
let getTicks = ffi('int getTicks(void)');
|
||||
let printColor = ffi('void printColor(char *)');
|
||||
|
||||
let NeoPixel_show = ffi('void NeoPixel_show(void)');
|
||||
let NeoPixel_clear = ffi('void NeoPixel_clear(void)');
|
||||
let NeoPixel_set = ffi('void NeoPixel_set(int,int,int,int)');
|
||||
let LEDStateEngine_getMinTickTime = ffi('double LEDStateEngine_getMinTickTime(void)');
|
||||
let LEDStateEngine_getMaxTickTime = ffi('double LEDStateEngine_getMaxTickTime(void)');
|
||||
let LEDStateEngine_getBrightness = ffi('int LEDStateEngine_getBrightness(void)');
|
||||
let LEDStateEngine_setBrightness = ffi('void LEDStateEngine_setBrightness(int)');
|
||||
let NeoPixel_getBrightness = ffi('int NeoPixel_getBrightness(void)');
|
||||
let NeoPixel_setBrightness = ffi('void NeoPixel_setBrightness(int)');
|
||||
|
||||
let LEDScheduler_init = ffi('void LEDScheduler_init(int, int, int)');
|
||||
let LEDScheduler_run = ffi('void LEDScheduler_run(void)');
|
||||
let LEDScheduler_pause = ffi('void LEDScheduler_pause(void)');
|
||||
let LEDScheduler_addItem = ffi('void LEDScheduler_addItem(int, int, int, char *, char *)');
|
||||
let LEDScheduler_setWatch = ffi('void LEDScheduler_setWatch(int, int, int)');
|
||||
|
|
|
@ -1,6 +1,12 @@
|
|||
[
|
||||
{"name": "off", "red": 0, "green": 0, "blue": 0},
|
||||
{"name": "candle", "red": 30, "green": 15, "blue": 4},
|
||||
{"name": "25w", "red": 35, "green": 15, "blue": 6},
|
||||
{"name": "40w", "red": 50, "green": 25, "blue": 10},
|
||||
{"name": "60w", "red": 70, "green": 45, "blue": 20},
|
||||
{"name": "75w", "red": 80, "green": 70, "blue": 30},
|
||||
{"name": "100w", "red": 100, "green": 85, "blue": 50},
|
||||
{"name": "neon", "red": 100, "green": 95, "blue": 70},
|
||||
{"name": "red", "red": 50, "green": 5, "blue": 5},
|
||||
{"name": "green", "red": 5, "green": 50, "blue": 5},
|
||||
{"name": "blue", "red": 5, "green": 5, "blue": 80},
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
{
|
||||
"comment": "7-LED development board",
|
||||
"lampmapping": [
|
||||
"lamp-1", "lamp-2", "lamp-3", "lamp-4", "lamp-5", "lamp-6", "lamp-7"
|
||||
],
|
||||
"mrclock": "N-RE",
|
||||
"clock_starttime": {"h": 2, "m": 0},
|
||||
"clock_speed": 1,
|
||||
"schedule": [
|
||||
{"time": {"h": 2, "m": 30}, "lamp": "lamp-1", "color": "25w", "mode": "OnOff"},
|
||||
{"time": {"h": 2, "m": 31}, "lamp": "lamp-2", "color": "25w", "mode": "OnOff"},
|
||||
{"time": {"h": 2, "m": 32}, "lamp": "lamp-3", "color": "25w", "mode": "OnOff"},
|
||||
{"time": {"h": 2, "m": 45}, "lamp": "lamp-3", "color": "off", "mode": "OnOff"},
|
||||
{"time": {"h": 2, "m": 46}, "lamp": "lamp-2", "color": "off", "mode": "OnOff"},
|
||||
{"time": {"h": 2, "m": 47}, "lamp": "lamp-1", "color": "off", "mode": "OnOff"},
|
||||
{"time": {"h": 4, "m": 2}, "lamp": "lamp-1", "color": "25w", "mode": "OnOff"},
|
||||
{"time": {"h": 4, "m": 4}, "lamp": "lamp-2", "color": "25w", "mode": "OnOff"},
|
||||
{"time": {"h": 4, "m": 4}, "lamp": "lamp-3", "color": "25w", "mode": "OnOff"},
|
||||
{"time": {"h": 4, "m": 18}, "lamp": "lamp-3", "color": "off", "mode": "OnOff"},
|
||||
{"time": {"h": 4, "m": 28}, "lamp": "lamp-1", "color": "off", "mode": "OnOff"},
|
||||
{"time": {"h": 4, "m": 29}, "lamp": "lamp-4", "color": "40w", "mode": "OnOff"},
|
||||
{"time": {"h": 4, "m": 30}, "lamp": "lamp-5", "color": "40w", "mode": "OnOff"},
|
||||
{"time": {"h": 4, "m": 31}, "lamp": "lamp-6", "color": "40w", "mode": "OnOff"},
|
||||
{"time": {"h": 4, "m": 32}, "lamp": "lamp-7", "color": "60w", "mode": "OnOff"}
|
||||
]
|
||||
}
|
72
fs/init.js
72
fs/init.js
|
@ -61,6 +61,8 @@ let configNumLeds = Cfg.get('led.count');
|
|||
let colorFile = Cfg.get('led.colorFile');
|
||||
let animationFile = Cfg.get('led.animationFile');
|
||||
let lampsFile = Cfg.get('led.lampsFile');
|
||||
let scheduleFile = Cfg.get('led.scheduleFile');
|
||||
let dynamicMode = Cfg.get('led.mode');
|
||||
let useDefaults = Cfg.get('led.useDefaults');
|
||||
let tickDuration = Cfg.get('led.tickDuration');
|
||||
let numberOfLeds = configNumLeds, numberOfLedDefs = 0; // from config files, count led definition entries
|
||||
|
@ -155,6 +157,41 @@ function loadAnimDefs() {
|
|||
json = null;
|
||||
}
|
||||
|
||||
function loadScheduleDefs() {
|
||||
// Load Animation Definitions
|
||||
let json = File.read(scheduleFile);
|
||||
let scheduleDef = [];
|
||||
print('scheduleFile =', json);
|
||||
if (json === '') {
|
||||
print('ERROR: Schedule definition file does not exist!');
|
||||
} else {
|
||||
scheduleDef = JSON.parse(json);
|
||||
}
|
||||
LEDScheduler_init(scheduleDef.schedule.length, numberOfLeds, pin);
|
||||
LEDScheduler_setWatch(2, 0, 1); // time 02:00, clock speed = 1 real time second per model minute
|
||||
let ledMapping = scheduleDef.lampmapping;
|
||||
let mapLed = function (name) {
|
||||
for (let i=0; i<ledMapping.length; ++i) {
|
||||
if (ledMapping[i] === name) return i;
|
||||
}
|
||||
print("**** ERROR in schedule definition file: no lamp mapping found for lamp", name);
|
||||
return 0;
|
||||
};
|
||||
|
||||
for (i=0; i<scheduleDef.schedule.length; ++i) {
|
||||
print('- addScheduleItem', scheduleDef.schedule[i].time.h, ":", scheduleDef.schedule[i].time.m, "/",
|
||||
scheduleDef.schedule[i].lamp, "=", mapLed(scheduleDef.schedule[i].lamp), "/",
|
||||
scheduleDef.schedule[i].mode, "/",
|
||||
scheduleDef.schedule[i].color);
|
||||
LEDScheduler_addItem(scheduleDef.schedule[i].time.h, scheduleDef.schedule[i].time.m,
|
||||
mapLed(scheduleDef.schedule[i].lamp),
|
||||
scheduleDef.schedule[i].mode,
|
||||
scheduleDef.schedule[i].color);
|
||||
}
|
||||
json = null;
|
||||
}
|
||||
|
||||
|
||||
function initialize() {
|
||||
print('***** Start initialization', getInfo());
|
||||
let i;
|
||||
|
@ -165,19 +202,11 @@ function initialize() {
|
|||
startLEDStateEngine();
|
||||
} else {
|
||||
loadColorDefs();
|
||||
if (dynamicMode === "animation") {
|
||||
loadLedDefs();
|
||||
loadAnimDefs();
|
||||
// Initialize LED State Engine
|
||||
LEDStateEngine_init(pin, numberOfLeds);
|
||||
}
|
||||
allLedOff();
|
||||
print('***** End of initialization', getInfo());
|
||||
print('_______________________________________________________');
|
||||
print('LedPin:', pin);
|
||||
print('NumLEDs:', numberOfLeds);
|
||||
print('Ticks:', getTicks());
|
||||
print('Tick duration:', tickDuration, 'ms');
|
||||
print('Brightness:', LEDStateEngine_getBrightness(), '%');
|
||||
print('LED', 'Color', 'R', 'G', 'B', 'Tick', 'Level', 'Room', 'Id');
|
||||
print('---', '-----', '---', '---', '-----', '---', '-----', '----', '--');
|
||||
for (i=0; i<numberOfLeds; ++i) {
|
||||
|
@ -191,6 +220,21 @@ function initialize() {
|
|||
LEDDefinition_getRoom(i),
|
||||
LEDDefinition_getId(i));
|
||||
}
|
||||
} else if (dynamicMode === "schedule") {
|
||||
loadScheduleDefs();
|
||||
} else {
|
||||
print("**** ERROR: Unknown dynamic mode", dynamicMode);
|
||||
return;
|
||||
}
|
||||
}
|
||||
allLedOff();
|
||||
print('***** End of initialization', getInfo());
|
||||
print('_______________________________________________________');
|
||||
print('LedPin:', pin);
|
||||
print('NumLEDs:', numberOfLeds);
|
||||
print('Ticks:', getTicks());
|
||||
print('Tick duration:', tickDuration, 'ms');
|
||||
print('Brightness:', NeoPixel_getBrightness(), '%');
|
||||
}
|
||||
|
||||
Timer.set(300, false, function() {
|
||||
|
@ -200,8 +244,14 @@ Timer.set(300, false, function() {
|
|||
allLedOff();
|
||||
print('***** LED test pattern', getInfo());
|
||||
showLedTestPattern();
|
||||
if (dynamicMode === "animation") {
|
||||
print('***** Start LED state engine and LED-update timer', getInfo());
|
||||
LEDStateEngine_start();
|
||||
} else if (dynamicMode === "schedule") {
|
||||
print('***** Start schedule based animation', getInfo());
|
||||
NeoPixel_clear();
|
||||
LEDScheduler_run();
|
||||
}
|
||||
Timer.set(30000, true, function() {
|
||||
print("Timer: minTickTime =", LEDStateEngine_getMinTickTime(),
|
||||
"ms, maxTickTime =", LEDStateEngine_getMaxTickTime(), "ms");
|
||||
|
@ -215,7 +265,7 @@ RPC.addHandler('led.setBrightness', function(args) {
|
|||
// print(args);
|
||||
if (args !== undefined && args.level !== undefined) {
|
||||
if (args.level > 0 && args.level <= 100) {
|
||||
LEDStateEngine_setBrightness(args.level);
|
||||
NeoPixel_setBrightness(args.level);
|
||||
return { result: 'ok' };
|
||||
} else {
|
||||
return { error: 'Brightness level must be in the range 1..100' };
|
||||
|
@ -226,7 +276,7 @@ RPC.addHandler('led.setBrightness', function(args) {
|
|||
}, "{level: %d}");
|
||||
print(' led.getBrightness');
|
||||
RPC.addHandler('led.getBrightness', function(args) {
|
||||
let brightness = LEDStateEngine_getBrightness();
|
||||
let brightness = NeoPixel_getBrightness();
|
||||
return { result: 'ok', brightness: brightness };
|
||||
}, null);
|
||||
print(' led.pause');
|
||||
|
|
|
@ -0,0 +1,30 @@
|
|||
{
|
||||
"comment": "Company office building with facility manager appartement",
|
||||
"lampmapping": [
|
||||
"eg-1.1", "eg-1.2", "eg-3.1", "eg-4", "eg-5", "eg-8", "eg-7, "eg-6", "eg-3.2", "eg-2.2", "eg-2.1",
|
||||
"og-1.1", "og-1.2", "og-3.1", "og-4", "og-5", "og-8", "og-7, "og-6", "og-3.2", "og-2.2", "og-2.1",
|
||||
"dg-1", "dg-2", "dg-3", "dg-4", "dg-5", "dg-6", "dg-7", "dg-8"
|
||||
],
|
||||
"mrclock": "N-RE",
|
||||
"clock_starttime": {"h": 2, "m": 0},
|
||||
"clock_speed": 1,
|
||||
"schedule": [
|
||||
{"time": {"h": 2, "m": 30}, "lamp": "dg-5", "color": "25w", "mode": "OnOff"},
|
||||
{"time": {"h": 2, "m": 31}, "lamp": "dg-8", "color": "25w", "mode": "OnOff"},
|
||||
{"time": {"h": 2, "m": 32}, "lamp": "dg-7", "color": "25w", "mode": "OnOff"},
|
||||
{"time": {"h": 2, "m": 45}, "lamp": "dg-7", "color": "off", "mode": "OnOff"},
|
||||
{"time": {"h": 2, "m": 46}, "lamp": "dg-8", "color": "off", "mode": "OnOff"},
|
||||
{"time": {"h": 2, "m": 47}, "lamp": "dg-5", "color": "off", "mode": "OnOff"},
|
||||
{"time": {"h": 4, "m": 2}, "lamp": "dg-5", "color": "25w", "mode": "OnOff"},
|
||||
{"time": {"h": 4, "m": 4}, "lamp": "dg-8", "color": "25w", "mode": "OnOff"},
|
||||
{"time": {"h": 4, "m": 4}, "lamp": "dg-7", "color": "25w", "mode": "OnOff"},
|
||||
{"time": {"h": 4, "m": 18}, "lamp": "dg-7", "color": "off", "mode": "OnOff"},
|
||||
{"time": {"h": 4, "m": 28}, "lamp": "dg-5", "color": "off", "mode": "OnOff"},
|
||||
{"time": {"h": 4, "m": 29}, "lamp": "dg-3", "color": "40w", "mode": "OnOff"},
|
||||
{"time": {"h": 4, "m": 30}, "lamp": "og-3.2", "color": "40w", "mode": "OnOff"},
|
||||
{"time": {"h": 4, "m": 30}, "lamp": "eg-3.2", "color": "40w", "mode": "OnOff"},
|
||||
{"time": {"h": 4, "m": 30}, "lamp": "eg-4", "color": "60w", "mode": "OnOff"},
|
||||
{"time": {"h": 4, "m": 45}, "lamp": "eg-3.1", "color": "40w", "mode": "OnOff"},
|
||||
{"time": {"h": 4, "m": 47}, "lamp": "eg-1.1", "color": "60w", "mode": "OnOff"}
|
||||
]
|
||||
}
|
2
mos.yml
2
mos.yml
|
@ -39,6 +39,8 @@ config_schema:
|
|||
- ["led.colorFile", "s", "colors.cfg", {title: "File name containing color definitions"}]
|
||||
- ["led.lampsFile", "s", "lamps.cfg", {title: "File name containing lamp definitions"}]
|
||||
- ["led.animationFile", "s", "animations.cfg", {title: "File name containing animation definitions"}]
|
||||
- ["led.mode", "s", "schedule", {title: "Mode = animation (use lampsFile + animationFile) | schedule (use scheduleFile)"}]
|
||||
- ["led.scheduleFile", "s", "demoschedule.cfg", {title: "File name containing schedule definitions"}]
|
||||
build_vars:
|
||||
MGOS_ENABLE_ONEWIRE: 1
|
||||
cflags: []
|
||||
|
|
|
@ -9,7 +9,6 @@
|
|||
|
||||
static LEDStateEngine theLEDStateEngine;
|
||||
static int ticks = 0;
|
||||
static int brightness = 50;
|
||||
|
||||
int getTicks(void) { return ticks; }
|
||||
|
||||
|
@ -27,7 +26,6 @@ void LEDStateEngine_setNumberOfLeds(int numberOfLeds) {
|
|||
void LEDStateEngine_init(int ledPin, int numberOfLeds) {
|
||||
theLEDStateEngine.comment = "";
|
||||
theLEDStateEngine.pin = ledPin;
|
||||
brightness = mgos_sys_config_get_led_brightness();
|
||||
LEDStateEngine_setNumberOfLeds(numberOfLeds);
|
||||
for (int i=0; i<numberOfLeds; ++i) {
|
||||
LEDState_init(i, LEDDefinition_get(i));
|
||||
|
@ -61,24 +59,11 @@ void LEDStateEngine_tick() {
|
|||
double LEDStateEngine_getMinTickTime() { return 1000 * minTickTime; }
|
||||
double LEDStateEngine_getMaxTickTime() { return 1000 * maxTickTime; }
|
||||
|
||||
static uint8_t adjustBrightness(uint8_t value) {
|
||||
return (value * brightness)/100;
|
||||
}
|
||||
|
||||
int LEDStateEngine_getBrightness() { return brightness; }
|
||||
void LEDStateEngine_setBrightness(int newBrightness) {
|
||||
if (newBrightness > 0 && newBrightness <= 100) {
|
||||
brightness = newBrightness;
|
||||
} else {
|
||||
LOG(LL_ERROR, ("invalid brightness value %d", newBrightness));
|
||||
}
|
||||
}
|
||||
|
||||
static void updateLedDisplay(LEDState *state) {
|
||||
NeoPixel_set(state->index,
|
||||
adjustBrightness(state->currentColor.red),
|
||||
adjustBrightness(state->currentColor.green),
|
||||
adjustBrightness(state->currentColor.blue));
|
||||
state->currentColor.red,
|
||||
state->currentColor.green,
|
||||
state->currentColor.blue);
|
||||
}
|
||||
|
||||
void LEDState_tick(int ledNum) {
|
||||
|
|
|
@ -3,12 +3,28 @@
|
|||
#include "mgos_bitbang.h"
|
||||
#include "mgos_gpio.h"
|
||||
#include "mgos_system.h"
|
||||
#include "mgos_sys_config.h"
|
||||
#include "NeoPixel.h"
|
||||
|
||||
static int NeoPixel_pin = 0;
|
||||
static int NeoPixel_numPixels = 0;
|
||||
static uint8_t *NeoPixel_leds = NULL; // pointer to allocated memory
|
||||
static enum NeoPixel_ColorOrder NeoPixel_colorOrder = NeoPixel_colorOrder_RGB;
|
||||
static enum NeoPixel_ColorOrder NeoPixel_colorOrder = NeoPixel_colorOrder_GRB;
|
||||
static int brightness = 50;
|
||||
|
||||
static uint8_t adjustBrightness(uint8_t value) {
|
||||
return (value * brightness)/100;
|
||||
}
|
||||
|
||||
int NeoPixel_getBrightness() { return brightness; }
|
||||
void NeoPixel_setBrightness(int newBrightness) {
|
||||
if (newBrightness > 0 && newBrightness <= 100) {
|
||||
brightness = newBrightness;
|
||||
} else {
|
||||
LOG(LL_ERROR, ("invalid brightness value %d", newBrightness));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ## **`NeoPixel_clear()`**
|
||||
// Clear in-memory values of the pixels.
|
||||
|
@ -44,7 +60,8 @@ void NeoPixel_create(uint8_t pin, uint8_t numPixels, enum NeoPixel_ColorOrder or
|
|||
mgos_gpio_set_mode(pin, MGOS_GPIO_MODE_OUTPUT);
|
||||
// GPIO.write(pin, 0); // Keep in reset.
|
||||
mgos_gpio_write(pin, false);
|
||||
LOG(LL_INFO, ("pin=%d, numPixels=%d, colorOrder=%d", pin, numPixels, order));
|
||||
brightness = mgos_sys_config_get_led_brightness();
|
||||
LOG(LL_INFO, ("pin=%d, numPixels=%d, colorOrder=%d, brightness=%d", pin, numPixels, order, brightness));
|
||||
NeoPixel_clear();
|
||||
}
|
||||
|
||||
|
@ -78,9 +95,9 @@ void NeoPixel_set(int pixel, int red, int green, int blue) {
|
|||
} else if (NeoPixel_colorOrder == NeoPixel_colorOrder_BGR) {
|
||||
v0 = blue; v1 = green; v2 = red;
|
||||
} else return;
|
||||
NeoPixel_leds[3*pixel] = v0;
|
||||
NeoPixel_leds[3*pixel+1] = v1;
|
||||
NeoPixel_leds[3*pixel+2] = v2;
|
||||
NeoPixel_leds[3*pixel] = adjustBrightness(v0);
|
||||
NeoPixel_leds[3*pixel+1] = adjustBrightness(v1);
|
||||
NeoPixel_leds[3*pixel+2] = adjustBrightness(v2);
|
||||
}
|
||||
|
||||
// ## **`NeoPixel_show()`**
|
||||
|
|
|
@ -11,5 +11,7 @@ extern void NeoPixel_release();
|
|||
extern void NeoPixel_create(uint8_t pin, uint8_t numPixels, enum NeoPixel_ColorOrder order);
|
||||
extern void NeoPixel_set(int pixel, int red, int green, int blue);
|
||||
extern void NeoPixel_show();
|
||||
extern int NeoPixel_getBrightness();
|
||||
extern void NeoPixel_setBrightness(int newBrightness);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -0,0 +1,105 @@
|
|||
#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));
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
extern void LEDScheduler_init(int, int, int);
|
||||
extern void LEDScheduler_run();
|
||||
extern void LEDScheduler_pause();
|
||||
extern void LEDScheduler_addItem(int h, int m, int led, char *mode, char *colorName);
|
||||
extern void LEDScheduler_setWatch(int h, int m, int speed);
|
|
@ -52,6 +52,7 @@ static void stateEngineTickTimer() {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
static void delayed_boot() {
|
||||
LOG(LL_INFO, ("*** Start timer for LED state engine ticks"));
|
||||
mgos_set_timer(mgos_sys_config_get_led_tickDuration(), true, stateEngineTickTimer, NULL);
|
||||
|
|
Loading…
Reference in New Issue