Animation works with default animation

This commit is contained in:
Dirk Jahnke 2017-11-27 06:47:27 +01:00
parent e2209504da
commit 54a6ee1cd1
14 changed files with 216 additions and 918 deletions

View File

@ -1,352 +0,0 @@
/* animateLights.js
* LED animation for house lightning
*/
load('api_rpc.js');
load("api_neopixel.js");
load("api_file.js");
let floor = ffi('double floor(double)');
let colors = {
black: {r:0, g:0, b:0},
red: {r:255, g:0, b:0},
green: {r:0, g:255, b:0},
blue: {r:0, g:0, b:255},
yellow: {r:255, g:255, b:0},
orange: {r:255, g:127, b:0},
purple: {r:255, g:0, b:255},
white: {r:255, g:255, b:255},
dimmedWhite: {r:50, g:50, b:50}
};
let LightAnimation = {
numberOfBulbs: 22,
ledPin: 2,
that: this,
running: false,
mode: "demo", // "demo", "stop", "animate"
generalBrightness: 30, // percentage, value 0..100
description: "Default house lightning",
defaultColor: colors.dimmedWhite,
defaultMode: "demo",
tickResolution: 100, // number of milliseconds between ticks
currentTick: 0,
animationConfig: {}, // overwritten when loading animationConfig.js
colorSequence: [
colors.dimmedWhite,
colors.red,
colors.green,
colors.blue,
colors.yellow,
colors.orange,
colors.purple,
colors.red,
colors.red,
colors.green,
colors.green,
colors.white,
colors.white
],
adjustBrightness: function (value) { return floor(value / LightAnimation.generalBrightness); },
changeMode: function (newMode) {
if (newMode === "animate") {
LightAnimation.running = true;
LightAnimation.mode = "start-animate"; // through transient mode start-animate to animate
} else
if (newMode === "stop") {
LightAnimation.running = true; // first we want to turn off LEDs, thus needs stop-mode but running
LightAnimation.mode = "stop";
} else
if (newMode === "demo") {
LightAnimation.mode = "demo";
LightAnimation.running = true;
} else
if (newMode === "cycle") {
LightAnimation.mode = "cycle";
LightAnimation.running = true;
} else
{
print("IGNORED: changeMode called with invalid mode = ", newMode);
}
},
updateAnimationConfig: function (config) {
LightAnimation.animationConfig = JSON.parse(config);
return LightAnimation.verifyAnimationConfig();
},
verifyAnimationConfig: function() {
if (LightAnimation.animationConfig.comment === undefined) {
return {error: 'config is incomplete or invalid / comment not found'};
}
if (LightAnimation.animationConfig.lights === undefined) {
return {error: 'config is incomplete or invalid / lights definition not found'};
}
if (LightAnimation.animationConfig.lights[0] === undefined) {
return {error: 'config is incomplete or invalid / lights is not an array?'};
}
let i;
for (i=0; i<LightAnimation.animationConfig.lights.length; ++i) {
if (LightAnimation.animationConfig.lights[i].level === undefined) {
return {error: 'config is incomplete or invalid / level missing in lights definition'};
}
if (LightAnimation.animationConfig.lights[i].room === undefined) {
return {error: 'config is incomplete or invalid / room missing in lights definition'};
}
if (LightAnimation.animationConfig.lights[i].on === undefined) {
return {error: 'config is incomplete or invalid / on missing in lights definition'};
}
if (LightAnimation.animationConfig.lights[i].on[0] === undefined) {
return {error: 'config is incomplete or invalid / on not an array in lights definition?'};
}
if (LightAnimation.animationConfig.lights[i].on.length !== 3) {
return {error: 'config is incomplete or invalid / on must have 3 elements for R/G/B in lights definition?'};
}
if (LightAnimation.animationConfig.lights[i].id === undefined) {
return {error: 'config is incomplete or invalid / id missing in lights definition'};
}
}
return {result: 'ok'};
},
findNextAnimationStep: function (lightIndex, afterStep) {
let i = afterStep + 1;
for (i=afterStep + 1; i<LightAnimation.animationConfig.animation.length; ++i) {
if (LightAnimation.animationConfig.animation[i].lightsIndex === lightIndex)
return i;
}
// nothing found, thus start from the beginning
for (i=0; i<=afterStep; ++i) {
if (LightAnimation.animationConfig.animation[i].lightsIndex === lightIndex)
return i;
}
// nothing found again, thus it seems, there is no config for this lightIndex
return -1;
}
};
// load("animationConfig.js", LightAnimation);
load("animationConfig.js");
print(LightAnimation.verifyAnimationConfig());
print("Initialize neoPixel");
let colorOrder = NeoPixel.GRB;
let strip = NeoPixel.create(LightAnimation.ledPin, LightAnimation.numberOfBulbs, colorOrder);
let i = 0;
strip.clear();
strip.show();
// initialize test pattern
for (i=0; i<LightAnimation.numberOfBulbs; ++i) {
if (i % 2) {
strip.setPixel(i, 80, 20, 20);
} else {
strip.setPixel(i, 20, 80, 20);
}
}
strip.show();
return; // @TODO
// Add RPC handlers
RPC.addHandler('HouseLightning.Start', function(args) {
LightAnimation.changeMOde("animate");
return {result: 'ok'};
}, null);
RPC.addHandler('HouseLightning.Stop', function(args) {
LightAnimation.changeMode("stop");
return {result: 'ok'};
}, null);
RPC.addHandler('HouseLightning.DemoMode', function(args) {
LightAnimation.changeMode("demo");
return {result: 'ok'};
}, null);
RPC.addHandler('HouseLightning.CycleMode', function(args) {
LightAnimation.changeMOde("cycle");
return {result: 'ok'};
}, null);
RPC.addHandler('HouseLightning.GetAnimationConfig', function(args) {
return LightAnimation.animationConfig;
}, null);
RPC.addHandler('HouseLightning.SetAnimationConfig', function(args) {
if (args !== undefined && args.config !== undefined) {
return LightAnimation.updateAnimationConfig(args.config);
} else {
return {error: 'parameter config is required'};
}
}, null);
function demoAnimation(strip, shiftBy) {
let i=0, colorIndex=0, color;
for (i=0; i<LightAnimation.numberOfBulbs; ++i) {
colorIndex = shiftBy % LightAnimation.colorSequence.length;
color = LightAnimation.colorSequence[colorIndex];
strip.setPixel(i, LightAnimation.adjustBrightness(color.r), LightAnimation.adjustBrightness(color.g), LightAnimation.adjustBrightness(color.b));
// print("runNeo shift =", shiftBy, ", colorIndex =", colorIndex, ", r =", color.r, ", g =", color.g, ", b =", color.b);
shiftBy++;
}
strip.show();
}
// initialize module
let configString = "";
/*configString = File.read("lights.cfg");
if (configString === "" || configString === null) configString = "***default***";
// print("configString = ", configString);
LightAnimation.animationConfig = JSON.parse(configString);
configString = null;*/
// LightAnimation.animationConfig = animationConfig;
// print("LightAnimation.animationConfig = ", JSON.stringify(LightAnimation.animationConfig));
print("Animation length: ", LightAnimation.animationConfig.animation.length);
// initialize internal data structure
let LEDstate = [{"index":0}]; //LightAnimation.numberOfBulbs];
let defaultLEDstate = {
index: 0, // LED #
nextTick: 0, // next action necessary on tick #
rampTickDelta: 0, // to be added on nextTick for Ramp-Animation
mode: "off", // "on", "off", "blink", "tv", "fire", "welding"
currentLEDCtrl: 0, // index on LEDCtrl[LEDnum][...]
numLEDCtrl: 0, // number of LEDCtrl entries for this bulb
modeStep: 0, // dependent on mode to ctrl animation details
clockEndHours: 23, // time, this animation should end
clockEndMinutes: 59,
currentRed: colors.dimmedWhite.r, currentGreen: colors.dimmedWhite.g, currentBlue: colors.dimmedWhite.b,
onRed: colors.dimmedWhite.r, onGreen: colors.dimmedWhite.g, onBlue: colors.dimmedWhite.b,
targetRed: 0, targetGreen: 0, targetBlue: 0,
currentAnimationStep:0 // animation step in LightAnimation.animationConfig.animation[step]
};
for (i=0; i<LightAnimation.numberOfBulbs; ++i) {
print("Init LEDstate", i);
LEDstate[i].index = i;
LEDstate[i].nextTick = defaultLEDstate.nextTick;
LEDstate[i].rampTickDelta = defaultLEDstate.rampTickDelta;
LEDstate[i].mode = defaultLEDstate.mode;
LEDstate[i].currentLEDCtrl = defaultLEDstate.currentLEDCtrl;
LEDstate[i].numLEDCtrl = defaultLEDstate.numLEDCtrl;
LEDstate[i].modeStep = defaultLEDstate.modeStep;
LEDstate[i].clockEndHours = defaultLEDstate.clockEndHours;
LEDstate[i].clockEndMinutes = defaultLEDstate.clockEndMinutes;
LEDstate[i].currentRed = defaultLEDstate.currentRed;
LEDstate[i].currentGreen = defaultLEDstate.currentGreen;
LEDstate[i].currentBlue = defaultLEDstate.currentBlue;
LEDstate[i].targetRed = defaultLEDstate.targetRed;
LEDstate[i].targetGreen = defaultLEDstate.targetGreen;
LEDstate[i].targetBlue = defaultLEDstate.targetBlue;
LEDstate[i].onRed = defaultLEDstate.onRed; //LightAnimation.animationConfig.lights.on[0];
LEDstate[i].onGreen = defaultLEDstate.onGreen; //LightAnimation.animationConfig.lights.on[1];
LEDstate[i].onBlue = defaultLEDstate.onBlue; //LightAnimation.animationConfig.lights.on[2];
LEDstate[i].currentAnimationStep = LightAnimation.findNextAnimationStep(i, -1);
}
// print("LEDstate=", JSON.stringify(LEDstate));
function animateBulb(bulb, currentTick) {
if (LEDstate[bulb].mode === "on") {
strip.setPixel(bulb, LightAnimation.adjustBrightness(LEDstate[bulb].currentRed), LightAnimation.adjustBrightness(LEDstate[bulb].currentGreen), LightAnimation.adjustBrightness(LEDstate[bulb].currentBlue));
} else
if (LEDstate[bulb].mode === "off") {
strip.setPixel(bulb, 0, 0, 0);
} else print ("animateBulb: mode not yet implemented - ", LEDstate[bulb].mode);
}
let shiftAnimation = 1; // needed for demo mode
function animateTick() {
// started for every single ticks; does all changes necessary according to animation configuration
if (LightAnimation.running) {
if (LightAnimation.mode === "demo") {
demoAnimation(strip, shiftAnimation);
shiftAnimation++;
// print("*** demo-mode, next shift=", shiftAnimation);
} else if (LightAnimation.mode === "stop") {
strip.clear();
strip.show();
LightAnimation.running = false;
print("*** stopped");
} else if (LightAnimation.mode === "start-animate") {
strip.clear();
strip.show();
LightAnimation.running = true;
LightAnimation.mode = "animate";
print("*** started");
} else if (LightAnimation.mode === "animate") {
LightAnimation.currentTick++;
// do animation step changes
for (i=0; i<LightAnimation.animationConfig.animation.length; ++i) {
if (LightAnimation.animationConfig.animation[i].time === animateTick) {
// activate new state
let bulbIndex = LightAnimation.animationConfig.animation[i].lightsIndex;
let nextAnimationStep = LightAnimation.findNextAnimationStep(bulbIndex, LEDstate[bulbIndex].currentAnimationStep);
LEDstate[bulbIndex].currentAnimationStep = nextAnimationStep;
LEDstate[bulbIndex].nextTick = LightAnimation.animationConfig.animation[nextAnimationStep].time;
LEDstate[bulbIndex].mode = LightAnimation.animationConfig.animation[nextAnimationStep].stepType;
LEDstate[bulbIndex].modeStep = 0; // reset to start
if (LEDstate[bulbIndex].mode === "off") {
LEDstate[bulbIndex].targetRed = 0;
LEDstate[bulbIndex].targetGreen = 0;
LEDstate[bulbIndex].targetBlue = 0;
LEDstate[bulbIndex].currentRed = LEDstate[bulbIndex].targetRed;
LEDstate[bulbIndex].currentGreen = LEDstate[bulbIndex].targetGreen;
LEDstate[bulbIndex].currentBlue = LEDstate[bulbIndex].targetBlue;
} else
if (LEDstate[bulbIndex].mode === "on") {
LEDstate[bulbIndex].targetRed = LEDstate[bulbIndex].onRed;
LEDstate[bulbIndex].targetGreen = LEDstate[bulbIndex].onGreen;
LEDstate[bulbIndex].targetBlue = LEDstate[bulbIndex].onBlue;
LEDstate[bulbIndex].currentRed = LEDstate[bulbIndex].targetRed;
LEDstate[bulbIndex].currentGreen = LEDstate[bulbIndex].targetGreen;
LEDstate[bulbIndex].currentBlue = LEDstate[bulbIndex].targetBlue;
} else
print("ERROR: Unsupported mode in LEDstate[", bulbIndex, "].mode=", LEDstate[bulbIndex].mode);
// updateBulbAnimation(bulbIndex, animateTick, LightAnimation.animationConfig.animation[i]);
/*
if (LightAnimation.animationConfig.animation[i].stepType === "on") {
LEDstate[bulbIndex].mode = "on";
strip.setPixel(bulbIndex, LEDstate[bulbIndex].defaultColor.r, LEDstate[bulbIndex].defaultColor.g, LEDstate[bulbIndex].defaultColor.b);
} else
if (LightAnimation.animationConfig.animation[i].stepType === "off") {
LEDstate[LightAnimation.lightsIndex].mode = "off";
strip.setPixel(LightAnimation.lightsIndex, 0, 0, 0);
} else print("*** animation stepType not implemented: ", LightAnimation.animationConfig[i].stepType);
*/
}
}
// do microanimation
for (i=0; i<LightAnimation.numberOfBulbs; ++i) {
animateBulb(i, LightAnimation.currentTick);
if (LightAnimation.currentTick >= LEDstate[i].nextTick) {
// update this animated bulb
}
// strip.setPixel called in animateBulb
// strip.setPixel(i, LightAnimation.adjustBrightness(LEDstate[i].currentRed), LightAnimation.adjustBrightness(LEDstate[i].currentGreen), LightAnimation.adjustBrightness(LEDstate[i].currentBlue));
}
strip.show();
} else print("*** Unknown LightAnimation.mode =", LightAnimation.mode);
}
}
return; // @TODO
// Show start pattern for 3 seconds, then switch to default colors
Timer.set(3000 /* msec */, true /* repeat */, function() {
for (i=0; i<LightAnimation.numberOfBulbs; ++i) {
strip.setPixel(i, LightAnimation.defaultColor.r, LightAnimation.defaultColor.g, LightAnimation.defaultColor.b);
}
strip.show();
print("START animation");
Timer.set(LightAnimation.tickResolution, true /* repeat */, animateTick, null);
}, null);

View File

@ -1,371 +0,0 @@
/* animateLights.js
* LED animation for house lightning
*/
load('api_rpc.js');
load("api_neopixel.js");
load("api_file.js");
let floor = ffi('double floor(double)');
let colors = {
black: {r:0, g:0, b:0},
red: {r:255, g:0, b:0},
green: {r:0, g:255, b:0},
blue: {r:0, g:0, b:255},
yellow: {r:255, g:255, b:0},
orange: {r:255, g:127, b:0},
purple: {r:255, g:0, b:255},
white: {r:255, g:255, b:255},
dimmedWhite: {r:50, g:50, b:50}
};
let LightAnimation = {
numberOfBulbs: 22,
ledPin: 2,
that: this,
running: false,
mode: "demo", // "demo", "stop", "animate"
generalBrightness: 30, // percentage, value 0..100
description: "Default house lightning",
defaultColor: colors.dimmedWhite,
defaultMode: "demo",
tickResolution: 1000, // number of milliseconds between ticks
currentTick: 0,
animationConfig: {}, // overwritten when loading animationConfig.js
colorSequence: [
colors.dimmedWhite,
colors.red,
colors.green,
colors.blue,
colors.yellow,
colors.orange,
colors.purple,
colors.red,
colors.red,
colors.green,
colors.green,
colors.white,
colors.white
],
adjustBrightness: function (value) { return floor(value / LightAnimation.generalBrightness); },
changeMode: function (newMode) {
if (newMode === "animate") {
LightAnimation.running = true;
LightAnimation.mode = "start-animate"; // through transient mode start-animate to animate
} else
if (newMode === "stop") {
LightAnimation.running = true; // first we want to turn off LEDs, thus needs stop-mode but running
LightAnimation.mode = "stop";
} else
if (newMode === "demo") {
LightAnimation.mode = "demo";
LightAnimation.running = true;
} else
if (newMode === "cycle") {
LightAnimation.mode = "cycle";
LightAnimation.running = true;
} else
{
print("IGNORED: changeMode called with invalid mode = ", newMode);
}
},
updateAnimationConfig: function (config) {
LightAnimation.animationConfig = JSON.parse(config);
return LightAnimation.verifyAnimationConfig();
},
verifyAnimationConfig: function() {
if (LightAnimation.animationConfig.comment === undefined) {
return {error: 'config is incomplete or invalid / comment not found'};
}
if (LightAnimation.animationConfig.lights === undefined) {
return {error: 'config is incomplete or invalid / lights definition not found'};
}
if (LightAnimation.animationConfig.lights[0] === undefined) {
return {error: 'config is incomplete or invalid / lights is not an array?'};
}
let i;
for (i=0; i<LightAnimation.animationConfig.lights.length; ++i) {
if (LightAnimation.animationConfig.lights[i].level === undefined) {
return {error: 'config is incomplete or invalid / level missing in lights definition'};
}
if (LightAnimation.animationConfig.lights[i].room === undefined) {
return {error: 'config is incomplete or invalid / room missing in lights definition'};
}
if (LightAnimation.animationConfig.lights[i].on === undefined) {
return {error: 'config is incomplete or invalid / on missing in lights definition'};
}
if (LightAnimation.animationConfig.lights[i].on[0] === undefined) {
return {error: 'config is incomplete or invalid / on not an array in lights definition?'};
}
if (LightAnimation.animationConfig.lights[i].on.length !== 3) {
return {error: 'config is incomplete or invalid / on must have 3 elements for R/G/B in lights definition?'};
}
if (LightAnimation.animationConfig.lights[i].id === undefined) {
return {error: 'config is incomplete or invalid / id missing in lights definition'};
}
}
return {result: 'ok'};
},
findNextAnimationStep: function (lightIndex, afterStep) {
let i = afterStep + 1;
for (i=afterStep + 1; i<LightAnimation.animationConfig.animation.length; ++i) {
if (LightAnimation.animationConfig.animation[i].lightsIndex === lightIndex)
return i;
}
// nothing found, thus start from the beginning
for (i=0; i<=afterStep; ++i) {
if (LightAnimation.animationConfig.animation[i].lightsIndex === lightIndex)
return i;
}
// nothing found again, thus it seems, there is no config for this lightIndex
return -1;
}
};
gc(true);
// load("animationConfig.js", LightAnimation);
load("animationConfig.js");
/*
LightAnimation.animationConfig = {
"comment": "lights.cfg / JSON",
"lights": [
{ "level":"EG", "room":"Wohnzimmer", "on":[200,200,200], "id":"EG-WoZi" }
],
"animation": [
{ "lightsIndex": 2, "stepType": "on", "time": 1, "comment": "Fr. S. wacht auf" }
]
};
*/
// print(LightAnimation.verifyAnimationConfig());
gc(true);
print("Initialize neoPixel");
let colorOrder = NeoPixel.GRB;
let strip = NeoPixel.create(LightAnimation.ledPin, LightAnimation.numberOfBulbs, colorOrder);
let i = 0;
strip.clear();
strip.show();
// initialize test pattern
for (i=0; i<LightAnimation.numberOfBulbs; ++i) {
if (i % 2) {
strip.setPixel(i, 80, 20, 20);
} else {
strip.setPixel(i, 20, 80, 20);
}
}
strip.show();
// Add RPC handlers
print("Initialize RPC Handlers");
RPC.addHandler('HouseLightning.Start', function(args) {
LightAnimation.changeMOde("animate");
return {result: 'ok'};
}, null);
RPC.addHandler('HouseLightning.Stop', function(args) {
LightAnimation.changeMode("stop");
return {result: 'ok'};
}, null);
RPC.addHandler('HouseLightning.DemoMode', function(args) {
LightAnimation.changeMode("demo");
return {result: 'ok'};
}, null);
RPC.addHandler('HouseLightning.CycleMode', function(args) {
LightAnimation.changeMOde("cycle");
return {result: 'ok'};
}, null);
RPC.addHandler('HouseLightning.GetAnimationConfig', function(args) {
return LightAnimation.animationConfig;
}, null);
RPC.addHandler('HouseLightning.SetAnimationConfig', function(args) {
if (args !== undefined && args.config !== undefined) {
return LightAnimation.updateAnimationConfig(args.config);
} else {
return {error: 'parameter config is required'};
}
}, null);
function demoAnimation(strip, shiftBy) {
let i=0, colorIndex=0, color;
for (i=0; i<LightAnimation.numberOfBulbs; ++i) {
colorIndex = shiftBy % LightAnimation.colorSequence.length;
color = LightAnimation.colorSequence[colorIndex];
strip.setPixel(i, LightAnimation.adjustBrightness(color.r), LightAnimation.adjustBrightness(color.g), LightAnimation.adjustBrightness(color.b));
// print("runNeo shift =", shiftBy, ", colorIndex =", colorIndex, ", r =", color.r, ", g =", color.g, ", b =", color.b);
shiftBy++;
}
strip.show();
}
// initialize module
let configString = "";
/*configString = File.read("lights.cfg");
if (configString === "" || configString === null) configString = "***default***";
// print("configString = ", configString);
LightAnimation.animationConfig = JSON.parse(configString);
configString = null;*/
// LightAnimation.animationConfig = animationConfig;
// print("LightAnimation.animationConfig = ", JSON.stringify(LightAnimation.animationConfig));
print("Animation length: ", LightAnimation.animationConfig.animation.length);
// initialize internal data structure
let defaultLEDstate = {
index: 0, // LED #
nextTick: 0, // next action necessary on tick #
rampTickDelta: 0, // to be added on nextTick for Ramp-Animation
mode: "off", // "on", "off", "blink", "tv", "fire", "welding"
currentLEDCtrl: 0, // index on LEDCtrl[LEDnum][...]
numLEDCtrl: 0, // number of LEDCtrl entries for this bulb
modeStep: 0, // dependent on mode to ctrl animation details
clockEndHours: 23, // time, this animation should end
clockEndMinutes: 59,
currentRed: colors.dimmedWhite.r, currentGreen: colors.dimmedWhite.g, currentBlue: colors.dimmedWhite.b,
onRed: colors.dimmedWhite.r, onGreen: colors.dimmedWhite.g, onBlue: colors.dimmedWhite.b,
targetRed: 0, targetGreen: 0, targetBlue: 0,
currentAnimationStep:0 // animation step in LightAnimation.animationConfig.animation[step]
};
let LEDstate = [];
for (i=0; i<1/*LightAnimation.numberOfBulbs*/; ++i) {
gc(true);
print("Init LEDstate", i, ", free RAM ", Sys.free_ram());
LEDstate[i] =Object.create(defaultLEDstate);
LEDstate[i].index = i;
LEDstate[i].nextTick = defaultLEDstate.nextTick;
LEDstate[i].rampTickDelta = defaultLEDstate.rampTickDelta;
LEDstate[i].mode = defaultLEDstate.mode;
LEDstate[i].currentLEDCtrl = defaultLEDstate.currentLEDCtrl;
LEDstate[i].numLEDCtrl = defaultLEDstate.numLEDCtrl;
LEDstate[i].modeStep = defaultLEDstate.modeStep;
LEDstate[i].clockEndHours = defaultLEDstate.clockEndHours;
LEDstate[i].clockEndMinutes = defaultLEDstate.clockEndMinutes;
LEDstate[i].currentRed = defaultLEDstate.currentRed;
LEDstate[i].currentGreen = defaultLEDstate.currentGreen;
LEDstate[i].currentBlue = defaultLEDstate.currentBlue;
LEDstate[i].targetRed = defaultLEDstate.targetRed;
LEDstate[i].targetGreen = defaultLEDstate.targetGreen;
LEDstate[i].targetBlue = defaultLEDstate.targetBlue;
LEDstate[i].onRed = defaultLEDstate.onRed; //LightAnimation.animationConfig.lights.on[0];
LEDstate[i].onGreen = defaultLEDstate.onGreen; //LightAnimation.animationConfig.lights.on[1];
LEDstate[i].onBlue = defaultLEDstate.onBlue; //LightAnimation.animationConfig.lights.on[2];
// LEDstate[i].currentAnimationStep = LightAnimation.findNextAnimationStep(i, -1);
}
print("LEDstate index0=", LEDstate[0].index, ", index1=", LEDstate[1].index);
print("LEDstate=", JSON.stringify(LEDstate));
function animateBulb(bulb, currentTick) {
if (LEDstate[bulb].mode === "on") {
strip.setPixel(bulb, LightAnimation.adjustBrightness(LEDstate[bulb].currentRed), LightAnimation.adjustBrightness(LEDstate[bulb].currentGreen), LightAnimation.adjustBrightness(LEDstate[bulb].currentBlue));
} else
if (LEDstate[bulb].mode === "off") {
strip.setPixel(bulb, 0, 0, 0);
} else print ("animateBulb: mode not yet implemented - ", LEDstate[bulb].mode);
}
let shiftAnimation = 1; // needed for demo mode
function animateTick() {
// started for every single ticks; does all changes necessary according to animation configuration
print("***animate***");
return;
if (LightAnimation.running) {
if (LightAnimation.mode === "demo") {
demoAnimation(strip, shiftAnimation);
shiftAnimation++;
// print("*** demo-mode, next shift=", shiftAnimation);
} else if (LightAnimation.mode === "stop") {
strip.clear();
strip.show();
LightAnimation.running = false;
print("*** stopped");
} else if (LightAnimation.mode === "start-animate") {
strip.clear();
strip.show();
LightAnimation.running = true;
LightAnimation.mode = "animate";
print("*** started");
} else if (LightAnimation.mode === "animate") {
LightAnimation.currentTick++;
// do animation step changes
for (i=0; i<LightAnimation.animationConfig.animation.length; ++i) {
if (LightAnimation.animationConfig.animation[i].time === animateTick) {
// activate new state
let bulbIndex = LightAnimation.animationConfig.animation[i].lightsIndex;
let nextAnimationStep = LightAnimation.findNextAnimationStep(bulbIndex, LEDstate[bulbIndex].currentAnimationStep);
LEDstate[bulbIndex].currentAnimationStep = nextAnimationStep;
LEDstate[bulbIndex].nextTick = LightAnimation.animationConfig.animation[nextAnimationStep].time;
LEDstate[bulbIndex].mode = LightAnimation.animationConfig.animation[nextAnimationStep].stepType;
LEDstate[bulbIndex].modeStep = 0; // reset to start
if (LEDstate[bulbIndex].mode === "off") {
LEDstate[bulbIndex].targetRed = 0;
LEDstate[bulbIndex].targetGreen = 0;
LEDstate[bulbIndex].targetBlue = 0;
LEDstate[bulbIndex].currentRed = LEDstate[bulbIndex].targetRed;
LEDstate[bulbIndex].currentGreen = LEDstate[bulbIndex].targetGreen;
LEDstate[bulbIndex].currentBlue = LEDstate[bulbIndex].targetBlue;
} else
if (LEDstate[bulbIndex].mode === "on") {
LEDstate[bulbIndex].targetRed = LEDstate[bulbIndex].onRed;
LEDstate[bulbIndex].targetGreen = LEDstate[bulbIndex].onGreen;
LEDstate[bulbIndex].targetBlue = LEDstate[bulbIndex].onBlue;
LEDstate[bulbIndex].currentRed = LEDstate[bulbIndex].targetRed;
LEDstate[bulbIndex].currentGreen = LEDstate[bulbIndex].targetGreen;
LEDstate[bulbIndex].currentBlue = LEDstate[bulbIndex].targetBlue;
} else
print("ERROR: Unsupported mode in LEDstate[", bulbIndex, "].mode=", LEDstate[bulbIndex].mode);
// updateBulbAnimation(bulbIndex, animateTick, LightAnimation.animationConfig.animation[i]);
/*
if (LightAnimation.animationConfig.animation[i].stepType === "on") {
LEDstate[bulbIndex].mode = "on";
strip.setPixel(bulbIndex, LEDstate[bulbIndex].defaultColor.r, LEDstate[bulbIndex].defaultColor.g, LEDstate[bulbIndex].defaultColor.b);
} else
if (LightAnimation.animationConfig.animation[i].stepType === "off") {
LEDstate[LightAnimation.lightsIndex].mode = "off";
strip.setPixel(LightAnimation.lightsIndex, 0, 0, 0);
} else print("*** animation stepType not implemented: ", LightAnimation.animationConfig[i].stepType);
*/
}
}
// do microanimation
for (i=0; i<LightAnimation.numberOfBulbs; ++i) {
animateBulb(i, LightAnimation.currentTick);
if (LightAnimation.currentTick >= LEDstate[i].nextTick) {
// update this animated bulb
}
// strip.setPixel called in animateBulb
// strip.setPixel(i, LightAnimation.adjustBrightness(LEDstate[i].currentRed), LightAnimation.adjustBrightness(LEDstate[i].currentGreen), LightAnimation.adjustBrightness(LEDstate[i].currentBlue));
}
strip.show();
} else print("*** Unknown LightAnimation.mode =", LightAnimation.mode);
}
}
// Garbage collection before startup, full=true --> reclaim RAM to OS
gc(true);
print("Initialize timer, start in 5 seconds");
// Show start pattern for 5 seconds, then switch to default colors
Timer.set(5000 /* msec */, false /* repeat */, function() {
print("START animation");
for (i=0; i<LightAnimation.numberOfBulbs; ++i) {
strip.setPixel(i, LightAnimation.defaultColor.r, LightAnimation.defaultColor.g, LightAnimation.defaultColor.b);
}
strip.show();
Timer.set(LightAnimation.tickResolution, true /* repeat */, animateTick, null);
}, null);

View File

@ -1,30 +0,0 @@
LightAnimation.animationConfig = {
"comment": "lights.cfg / JSON",
"lights": [
{ "level":"EG", "room":"Wohnzimmer", "on":[200,200,200], "id":"EG-WoZi" },
{ "level":"EG", "room":"Bad", "on":[150,150,150], "id":"EG-Bad" },
{ "level":"EG", "room":"Schlafzimmer", "on":[130,130,130], "id":"EG-Schlafen" },
{ "level":"EG", "room":"Buero 0.1", "on":[150,150,130], "id":"EG-Buero-1" },
{ "level":"EG", "room":"Buero 0.2", "on":[150,150,130], "id":"EG-Buero-2" },
{ "level":"OG1", "room":"Buero 1.1", "on":[150,150,130], "id":"OG1-Buero-1" },
{ "level":"OG1", "room":"Buero 1.2", "on":[150,150,130], "id":"OG1-Buero-2" },
{ "level":"OG1", "room":"Buero 1.3", "on":[150,150,130], "id":"OG1-Buero-3" },
{ "level":"OG1", "room":"Buero 1.4", "on":[150,150,130], "id":"OG1-Buero-4" },
{ "level":"OG2", "room":"Buero 2.1", "on":[150,150,130], "id":"OG2-Buero-1" },
{ "level":"OG2", "room":"Buero 2.2", "on":[150,150,130], "id":"OG2-Buero-2" },
{ "level":"OG2", "room":"Buero 2.3", "on":[150,150,130], "id":"OG2-Buero-3" },
{ "level":"OG2", "room":"Buero 2.4", "on":[150,150,130], "id":"OG2-Buero-4" }
],
"animation": [
{ "lightsIndex": 2, "stepType": "on", "time": 1, "comment": "Fr. S. wacht auf" },
{ "lightsIndex": 2, "stepType": "off", "time": 55, "comment": "Fr. S. geht ins Bad" },
{ "lightsIndex": 1, "stepType": "on", "time": 56, "comment": "Fr. S. duscht" },
{ "lightsIndex": 2, "stepType": "on", "time": 250, "comment": "Fr. S. zieht sich an" },
{ "lightsIndex": 0, "stepType": "on", "time": 350, "comment": "Fr. S. setzt einen Kaffee auf und raeumt auf" },
{ "lightsIndex": 1, "stepType": "off", "time": 355, "comment": "Fr. S. ist fertig im Bad" },
{ "lightsIndex": 2, "stepType": "off", "time": 400, "comment": "Fr. S. ist fertig im Schlafzimmer" },
{ "lightsIndex": 0, "stepType": "off", "time": 500, "comment": "Fr. S. hat gefruehstueckt und verlaesst die Wohnung" },
{ "lightsIndex": 3, "stepType": "on", "time": 520, "comment": "Fr. S. ist im Buero" },
{ "lightsIndex": 4, "stepType": "on", "time": 700, "comment": "Fr. S. ist im Buero" }
]
};

View File

@ -1,10 +0,0 @@
/* api_ledlights.js */
/*
let LED = {
Red: ffi('int get_led_red(int)'),
Green: ffi('int get_led_red(int)'),
Blue: ffi('int get_led_red(int)'),
Tick: ffi('void led_evaluate_tick(void)')
};
*/

View File

@ -1,57 +0,0 @@
load('api_config.js');
load('api_gpio.js');
load('api_mqtt.js');
load('api_net.js');
load('api_sys.js');
load('api_rpc.js');
load('api_timer.js');
/* load("animateLights.js"); */
load('api_ledlights.js');
let led = Cfg.get('pins.led');
// Helper C function get_led_gpio_pin() in src/main.c returns built-in LED GPIO
// let onBoardLed = ffi('int get_led_gpio_pin()')();
let button = Cfg.get('pins.button');
let topic = '/devices/' + Cfg.get('device.id') + '/events';
print('LED GPIO:', led, 'button GPIO:', button);
let getInfo = function() {
return JSON.stringify({
total_ram: Sys.total_ram(),
free_ram: Sys.free_ram()
});
};
// Blink built-in LED every second
GPIO.set_mode(led, GPIO.MODE_OUTPUT);
Timer.set(5000 /* 1 sec */, true /* repeat */, function() {
let value = GPIO.toggle(led);
print(value ? 'Tick' : 'Tock', 'uptime:', Sys.uptime(), getInfo());
}, null);
// Publish to MQTT topic on a button press. Button is wired to GPIO pin 0
/*
GPIO.set_button_handler(button, GPIO.PULL_UP, GPIO.INT_EDGE_NEG, 200, function() {
let message = getInfo();
let ok = MQTT.pub(topic, message, 1);
print('Published:', ok, topic, '->', message);
}, null);
*/
// Monitor network connectivity.
Net.setStatusEventHandler(function(ev, arg) {
let evs = '???';
if (ev === Net.STATUS_DISCONNECTED) {
evs = 'DISCONNECTED';
} else if (ev === Net.STATUS_CONNECTING) {
evs = 'CONNECTING';
} else if (ev === Net.STATUS_CONNECTED) {
evs = 'CONNECTED';
} else if (ev === Net.STATUS_GOT_IP) {
evs = 'GOT_IP';
}
print('== Net event:', ev, evs);
}, null);

View File

@ -1,29 +0,0 @@
{ "comment": "lights.cfg / JSON",
"lights": [
{ "level":"EG", "room":"Wohnzimmer", "on":[200,200,200], "id":"EG-WoZi" },
{ "level":"EG", "room":"Bad", "on":[150,150,150], "id":"EG-Bad" },
{ "level":"EG", "room":"Schlafzimmer", "on":[130,130,130], "id":"EG-Schlafen" },
{ "level":"EG", "room":"Buero 0.1", "on":[150,150,130], "id":"EG-Buero-1" },
{ "level":"EG", "room":"Buero 0.2", "on":[150,150,130], "id":"EG-Buero-2" },
{ "level":"OG1", "room":"Buero 1.1", "on":[150,150,130], "id":"OG1-Buero-1" },
{ "level":"OG1", "room":"Buero 1.2", "on":[150,150,130], "id":"OG1-Buero-2" },
{ "level":"OG1", "room":"Buero 1.3", "on":[150,150,130], "id":"OG1-Buero-3" },
{ "level":"OG1", "room":"Buero 1.4", "on":[150,150,130], "id":"OG1-Buero-4" },
{ "level":"OG2", "room":"Buero 2.1", "on":[150,150,130], "id":"OG2-Buero-1" },
{ "level":"OG2", "room":"Buero 2.2", "on":[150,150,130], "id":"OG2-Buero-2" },
{ "level":"OG2", "room":"Buero 2.3", "on":[150,150,130], "id":"OG2-Buero-3" },
{ "level":"OG2", "room":"Buero 2.4", "on":[150,150,130], "id":"OG2-Buero-4" }
],
"animation": [
{ "lightsIndex": 2, "stepType": "on", "time": 1, "comment": "Fr. S. wacht auf" },
{ "lightsIndex": 2, "stepType": "off", "time": 55, "comment": "Fr. S. geht ins Bad" },
{ "lightsIndex": 1, "stepType": "on", "time": 56, "comment": "Fr. S. duscht" },
{ "lightsIndex": 2, "stepType": "on", "time": 250, "comment": "Fr. S. zieht sich an" },
{ "lightsIndex": 0, "stepType": "on", "time": 350, "comment": "Fr. S. setzt einen Kaffee auf und raeumt auf" },
{ "lightsIndex": 1, "stepType": "off", "time": 355, "comment": "Fr. S. ist fertig im Bad" },
{ "lightsIndex": 2, "stepType": "off", "time": 400, "comment": "Fr. S. ist fertig im Schlafzimmer" },
{ "lightsIndex": 0, "stepType": "off", "time": 500, "comment": "Fr. S. hat gefruehstueckt und verlaesst die Wohnung" },
{ "lightsIndex": 3, "stepType": "on", "time": 520, "comment": "Fr. S. ist im Buero" },
{ "lightsIndex": 4, "stepType": "on", "time": 700, "comment": "Fr. S. ist im Buero" }
]
}

View File

@ -1,33 +0,0 @@
let x = {
"animation":
[
{"comment":"Frau Schlemmer wacht auf","time":1,"stepType":"on","lightsIndex":2},
{"comment":"Frau Schlemmer geht ins Bad","time":55,"stepType":"off","lightsIndex":2},
{"comment":"Frau Schlemmer duscht","time":56,"stepType":"on","lightsIndex":1},
{"comment":"Frau Schlemmer zieht sich an","time":250,"stepType":"on","lightsIndex":2},
{"comment":"Frau Schlemmer setzt einen Kaffee auf und r\xc3\x83\xc2\x83\xc3\x82\xc2\xa4umt auf","time":350,"stepType":"on","lightsIndex":0},
{"comment":"Frau Schlemmer ist fertig im Bad","time":355,"stepType":"off","lightsIndex":1},
{"comment":"Frau Schlemmer ist fertig im Schlafzimmer","time":400,"stepType":"off","lightsIndex":2},
{"comment":"Frau Schlemmer hat gefr\xc3\x83\xc2\x83\xc3\x82\xc2\xbchst\xc3\x83\xc2\x83\xc3\x82\xc2\xbcckt und verl\xc3\x83\xc2\x83\xc3\x82\xc2\xa4sst die Wohnung","time":500,"stepType":"off","lightsIndex":0},
{"comment":"Frau Schlemmer ist im B\xc3\x83\xc2\x83\xc3\x82\xc2\xbcro","time":520,"stepType":"on","lightsIndex":3},{"comment":"Frau Schlemmer ist im B\xc3\x83\xc2\x83\xc3\x82\xc2\xbcro","time":700,"stepType":"on","lightsIndex":4}
],
"lights":
[
{"id":"EG-WoZi","on":[200,200,200],"room":"Wohnzimmer","level":"EG"},
{"id":"EG-Bad","on":[150,150,150],"room":"Bad","level":"EG"},
{"id":"EG-Schlafen","on":[130,130,130],"room":"Schlafzimmer","level":"EG"},
{"id":"EG-Buero-1","on":[150,150,130],"room":"Buero 0.1","level":"EG"},
{"id":"EG-Buero-2","on":[150,150,130],"room":"Buero 0.2","level":"EG"},
{"id":"OG1-Buero-1","on":[150,150,130],"room":"Buero 1.1","level":"OG1"},
{"id":"OG1-Buero-2","on":[150,150,130],"room":"Buero 1.2","level":"OG1"},
{"id":"OG1-Buero-3","on":[150,150,130],"room":"Buero 1.3","level":"OG1"},
{"id":"OG1-Buero-4","on":[150,150,130],"room":"Buero 1.4","level":"OG1"},
{"id":"OG2-Buero-1","on":[150,150,130],"room":"Buero 2.1","level":"OG2"},
{"id":"OG2-Buero-2","on":[150,150,130],"room":"Buero 2.2","level":"OG2"},
{"id":"OG2-Buero-3","on":[150,150,130],"room":"Buero 2.3","level":"OG2"},
{"id":"OG2-Buero-4","on":[150,150,130],"room":"Buero 2.4","level":"OG2"}
],
"comment":"lights.cfg / JSON"
};
let LEDstate= [{"targetBlue":0,"targetGreen":0,"targetRed":0,"currentBlue":0,"currentGreen":0,"currentRed":0,"clockEndMinutes":59,"clockEndHours":23,"modeStep":0,"numLEDCtrl":0,"currentLEDCtrl":0,"mode":"onoff","rampTickDelta":0,"nextTick":0,"index":0},{"targetBlue":0,"targetGreen":0,"targetRed":0,"currentBlue":0,"currentGreen":0,"currentRed":0,"clockEndMinutes":59,"clockEndHours":23,"modeStep":0,"numLEDCtrl":0,"currentLEDCtrl":0,"mode":"onoff","rampTickDelta":0,"nextTick":0,"index":0},{"targetBlue":0,"targetGreen":0,"targetRed":0,"currentBlue":0,"currentGreen":0,"currentRed":0,"clockEndMinutes":59,"clockEndHours":23,"modeStep":0,"numLEDCtrl":0,"currentLEDCtrl":0,"mode":"onoff","rampTickDelta":0,"nextTick":0,"index":0},{"targetBlue":0,"targetGreen":0,"targetRed":0,"currentBlue":0,"currentGreen":0,"currentRed":0,"clockEndMinutes":59,"clockEndHours":23,"modeStep":0,"numLEDCtrl":0,"currentLEDCtrl":0,"mode":"onoff","rampTickDelta":0,"nextTick":0,"index":0},{"targetBlue":0,"targetGreen":0,"targetRed":0,"currentBlue":0,"currentGreen":0,"currentRed":0,"clockEndMinutes":59,"clockEndHours":23,"modeStep":0,"numLEDCtrl":0,"currentLEDCtrl":0,"mode":"onoff","rampTickDelta":0,"nextTick":0,"index":0},{"targetBlue":0,"targetGreen":0,"targetRed":0,"currentBlue":0,"currentGreen":0,"currentRed":0,"clockEndMinutes":59,"clockEndHours":23,"modeStep":0,"numLEDCtrl":0,"currentLEDCtrl":0,"mode":"onoff","rampTickDelta":0,"nextTick":0,"index":0},{"targetBlue":0,"targetGreen":0,"targetRed":0,"currentBlue":0,"currentGreen":0,"currentRed":0,"clockEndMinutes":59,"clockEndHours":23,"modeStep":0,"numLEDCtrl":0,"currentLEDCtrl":0,"mode":"onoff","rampTickDelta":0,"nextTick":0,"index":0},{"targetBlue":0,"targetGreen":0,"targetRed":0,"currentBlue":0,"currentGreen":0,"currentRed":0,"clockEndMinutes":59,"clockEndHours":23,"modeStep":0,"numLEDCtrl":0,"currentLEDCtrl":0,"mode":"onoff","rampTickDelta":0,"nextTick":0,"index":0},{"targetBlue":0,"targetGreen":0,"targetRed":0,"currentBlue":0,"currentGreen":0,"currentRed":0,"clockEndMinutes":59,"clockEndHours":23,"modeStep":0,"numLEDCtrl":0,"currentLEDCtrl":0,"mode":"onoff","rampTickDelta":0,"nextTick":0,"index":0},{"targetBlue":0,"targetGreen":0,"targetRed":0,"currentBlue":0,"currentGreen":0,"currentRed":0,"clockEndMinutes":59,"clockEndHours":23,"modeStep":0,"numLEDCtrl":0,"currentLEDCtrl":0,"mode":"onoff","rampTickDelta":0,"nextTick":0,"index":0},{"targetBlue":0,"targetGreen":0,"targetRed":0,"currentBlue":0,"currentGreen":0,"currentRed":0,"clockEndMinutes":59,"clockEndHours":23,"modeStep":0,"numLEDCtrl":0,"currentLEDCtrl":0,"mode":"onoff","rampTickDelta":0,"nextTick":0,"index":0}] ;

View File

@ -5,16 +5,16 @@ load('api_net.js');
load('api_sys.js'); load('api_sys.js');
load('api_rpc.js'); load('api_rpc.js');
load('api_timer.js'); load('api_timer.js');
load("api_math.js");
load("api_neopixel.js");
let led = Cfg.get('pins.led');
// Helper C function get_led_gpio_pin() in src/main.c returns built-in LED GPIO // Helper C function get_led_gpio_pin() in src/main.c returns built-in LED GPIO
// let onBoardLed = ffi('int get_led_gpio_pin()')(); let onBoardLed = ffi('int get_led_gpio_pin(void)')();
let button = Cfg.get('pins.button'); let button = Cfg.get('pins.button');
let topic = '/devices/' + Cfg.get('device.id') + '/events'; let topic = '/devices/' + Cfg.get('device.id') + '/events';
print('LED GPIO:', led, 'button GPIO:', button); print('LED GPIO:', onBoardLed, 'button GPIO:', button);
let getInfo = function() { let getInfo = function() {
return JSON.stringify({ return JSON.stringify({
@ -24,11 +24,13 @@ let getInfo = function() {
}; };
// Blink built-in LED every second // Blink built-in LED every second
GPIO.set_mode(led, GPIO.MODE_OUTPUT); /*
Timer.set(5000 /* 1 sec */, true /* repeat */, function() { GPIO.set_mode(onBoardLed, GPIO.MODE_OUTPUT);
let value = GPIO.toggle(led); Timer.set(5000, true, function() {
let value = GPIO.toggle(onBoardLed);
print(value ? 'Tick' : 'Tock', 'uptime:', Sys.uptime(), getInfo()); print(value ? 'Tick' : 'Tock', 'uptime:', Sys.uptime(), getInfo());
}, null); }, null);
*/
// Publish to MQTT topic on a button press. Button is wired to GPIO pin 0 // Publish to MQTT topic on a button press. Button is wired to GPIO pin 0
/* /*
@ -61,5 +63,114 @@ let addAnimationStep = ffi('void addAnimationStep(int, int, int)');
let LEDMode_on=1, LEDMode_off=2, LEDMode_blink=3, LEDMode_tv=4, LEDMode_fire=5; let LEDMode_on=1, LEDMode_off=2, LEDMode_blink=3, LEDMode_tv=4, LEDMode_fire=5;
let LEDStateEngine_start = ffi('void startLEDStateEngine(void)'); let LEDStateEngine_start = ffi('void startLEDStateEngine(void)');
let LEDStateEngine_pause = ffi('void pauseLEDStateEngine(void)'); let LEDStateEngine_pause = ffi('void pauseLEDStateEngine(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_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 pin = Cfg.get('led.pin'), numPixels = Cfg.get('led.count'), colorOrder = NeoPixel.GRB;
let strip = NeoPixel.create(pin, numPixels, colorOrder);
/* Create test pattern */
function createLedTestPattern() {
let i;
let switchMod;
for (i=0; i<numPixels; ++i) {
switchMod = i - 6 * Math.floor(i/6);
if (switchMod === 0) strip.setPixel(i, 100, 100, 100);
if (switchMod === 1) strip.setPixel(i, 100, 100, 100);
if (switchMod === 2) strip.setPixel(i, 100, 100, 0);
if (switchMod === 3) strip.setPixel(i, 0, 100, 0);
if (switchMod === 4) strip.setPixel(i, 0, 100, 100);
if (switchMod === 5) strip.setPixel(i, 0, 0, 100);
if (switchMod < 0 || switchMod > 5) print("WRONG -- should never reach this in switch statement!");
/*
switch (switchMod) {
case 0:
strip.setPixel(i, 100, 100, 100);
break;
case 1:
strip.setPixel(i, 100, 0, 0);
break;
case 2:
strip.setPixel(i, 100, 100, 0);
break;
case 3:
strip.setPixel(i, 0, 100, 0);
break;
case 4:
strip.setPixel(i, 0, 100, 100);
break;
case 5:
strip.setPixel(i, 0, 0, 100);
break;
default:
print("WRONG -- should never reach this in switch statement!");
}
*/
// strip.setPixel(i, 100, 100, 100);
}
strip.show();
}
function allLedOn() {
let i;
for (i=0; i<numPixels; ++i) {
strip.setPixel(i, 100, 100, 100);
}
strip.show();
}
function allLedOff() {
strip.clear();
strip.show();
}
// initialize LEDs
allLedOff();
print('End of initialization:');
print('LedPin:', pin);
print('NumLEDs:', numPixels);
print('Ticks:', getTicks());
let i;
print('LED', 'Color', 'R', 'G', 'B', 'Tick', 'Level', 'Room', 'Id');
print('---', '-----', '---', '---', '-----', '---', '-----', '----', '--');
for (i=0; i<numPixels; ++i) {
// print(i, LEDState_getRed(i), LEDState_getGreen(i), LEDState_getBlue(i), LEDState_getCurrentTick(i), LEDDefinition_getLevel(i), LEDDefinition_getRoom(i), LEDDefinition_getId(i))
print(i, LEDState_getColorName(i), LEDDefinition_getOnColorRed(i), LEDDefinition_getOnColorGreen(i), LEDDefinition_getOnColorBlue(i), LEDState_getCurrentTick(i), LEDDefinition_getLevel(i), LEDDefinition_getRoom(i), LEDDefinition_getId(i))
}
Timer.set(500 /* 0,5 sec */, false /* repeat */, function() {
createLedTestPattern();
print('Created LED test pattern, uptime:', Sys.uptime(), getInfo());
LEDStateEngine_start();
Timer.set(100, true, function () {
let i;
for (i=0; i<numPixels; ++i) {
strip.setPixel(i, LEDState_getRed(i), LEDState_getGreen(i), LEDState_getBlue(i));
}
strip.show();
}, null);
}, null);
/*
Timer.set(30000, true, function () {
let i;
print('Ticks:', getTicks());
print('LED', 'Tick', 'Next');
print('---', '-----', '----');
for (i=0; i<numPixels; ++i) {
print(i, LEDState_getCurrentTick(i), LEDState_getNextTick(i));
}
}, null);
*/

View File

@ -29,10 +29,11 @@ libs:
- origin: https://github.com/mongoose-os-libs/aws - origin: https://github.com/mongoose-os-libs/aws
- origin: https://github.com/mongoose-os-libs/mjs - origin: https://github.com/mongoose-os-libs/mjs
config_schema: config_schema:
- ["i2c.enable", false] - ["i2c.enable", true]
- ["led", "o", {"title": "LED control settings"}]
- ["led.pin", "i", 2, {title: "Pin for data to WS2812 based LED chain"}] - ["led.pin", "i", 2, {title: "Pin for data to WS2812 based LED chain"}]
- ["led.useDefaults", "b", true, {title: "Use default values for colors, led-definitions, animations"}] - ["led.useDefaults", "b", true, {title: "Use default values for colors, led-definitions, animations"}]
- ["led.count", "i", 5, {title: "Number of LEDs connected in the chain"}] - ["led.count", "i", 32, {title: "Number of LEDs connected in the chain"}]
build_vars: build_vars:
MGOS_ENABLE_ONEWIRE: 1 MGOS_ENABLE_ONEWIRE: 1
cflags: [] cflags: []

View File

@ -64,6 +64,7 @@ void LEDDefinition_add(char *level, char *room, char *id, uint8_t red, uint8_t g
ledDefinition[numberOfLEDDefinitions].level = level; ledDefinition[numberOfLEDDefinitions].level = level;
ledDefinition[numberOfLEDDefinitions].room = room; ledDefinition[numberOfLEDDefinitions].room = room;
ledDefinition[numberOfLEDDefinitions].id = id; ledDefinition[numberOfLEDDefinitions].id = id;
ledDefinition[numberOfLEDDefinitions].onColor.name = "autoColor";
ledDefinition[numberOfLEDDefinitions].onColor.red = red; ledDefinition[numberOfLEDDefinitions].onColor.red = red;
ledDefinition[numberOfLEDDefinitions].onColor.green = green; ledDefinition[numberOfLEDDefinitions].onColor.green = green;
ledDefinition[numberOfLEDDefinitions].onColor.blue = blue; ledDefinition[numberOfLEDDefinitions].onColor.blue = blue;
@ -72,6 +73,7 @@ void LEDDefinition_add(char *level, char *room, char *id, uint8_t red, uint8_t g
LOG(LL_ERROR, ("Error: Too many LED Definitions to load, ignoring level=%s, room=%s, id=%s", level, room, id)); LOG(LL_ERROR, ("Error: Too many LED Definitions to load, ignoring level=%s, room=%s, id=%s", level, room, id));
} }
} }
void LEDDefinition_init(int numberOfLeds, bool loadDefaultData) { void LEDDefinition_init(int numberOfLeds, bool loadDefaultData) {
// initialize // initialize
numberOfLEDDefinitions = 0; numberOfLEDDefinitions = 0;
@ -95,3 +97,27 @@ void LEDDefinition_init(int numberOfLeds, bool loadDefaultData) {
} }
} }
char *LEDDefinition_getLevel(int ledNum) {
ledNum = verifyLedDefinitionNum(ledNum);
return ledDefinition[ledNum].level;
}
char *LEDDefinition_getRoom(int ledNum) {
ledNum = verifyLedDefinitionNum(ledNum);
return ledDefinition[ledNum].room;
}
char *LEDDefinition_getId(int ledNum) {
ledNum = verifyLedDefinitionNum(ledNum);
return ledDefinition[ledNum].id;
}
int LEDDefinition_getOnColorRed(int ledNum) {
ledNum = verifyLedDefinitionNum(ledNum);
return ledDefinition[ledNum].onColor.red;
}
int LEDDefinition_getOnColorGreen(int ledNum) {
ledNum = verifyLedDefinitionNum(ledNum);
return ledDefinition[ledNum].onColor.green;
}
int LEDDefinition_getOnColorBlue(int ledNum) {
ledNum = verifyLedDefinitionNum(ledNum);
return ledDefinition[ledNum].onColor.blue;
}

View File

@ -36,6 +36,12 @@ extern LEDDefinition ledDefinition[MAX_LEDS];
extern LEDDefinition *LEDDefinition_get(int ledNum); extern LEDDefinition *LEDDefinition_get(int ledNum);
extern void LEDDefinition_init(int numberOfLeds, bool loadDefaultData); extern void LEDDefinition_init(int numberOfLeds, bool loadDefaultData);
void LEDDefinition_add(char *level, char *room, char *id, uint8_t red, uint8_t green, uint8_t blue); extern void LEDDefinition_add(char *level, char *room, char *id, uint8_t red, uint8_t green, uint8_t blue);
extern char *LEDDefinition_getLevel(int ledNum);
extern char *LEDDefinition_getRoom(int ledNum);
extern char *LEDDefinition_getId(int ledNum);
extern int LEDDefinition_getOnColorRed(int ledNum);
extern int LEDDefinition_getOnColorGreen(int ledNum);
extern int LEDDefinition_getOnColorBlue(int ledNum);
#endif #endif

View File

@ -6,6 +6,9 @@
static LEDStateEngine theLEDStateEngine; static LEDStateEngine theLEDStateEngine;
static int ticks = 0;
int getTicks(void) { return ticks; }
void LEDStateEngine_setNumberOfLeds(int numberOfLeds) { void LEDStateEngine_setNumberOfLeds(int numberOfLeds) {
if (numberOfLeds < 1 || numberOfLeds > MAX_LEDS) { if (numberOfLeds < 1 || numberOfLeds > MAX_LEDS) {
@ -13,13 +16,14 @@ void LEDStateEngine_setNumberOfLeds(int numberOfLeds) {
numberOfLeds = MAX_LEDS; numberOfLeds = MAX_LEDS;
} }
theLEDStateEngine.numberOfLeds = numberOfLeds; theLEDStateEngine.numberOfLeds = numberOfLeds;
LOG(LL_INFO, ("LEDStateEngine initialized: numLEDs=%d, MAX_LEDS=%d", numberOfLeds, MAX_LEDS));
} }
void LEDStateEngine_init(int numberOfLeds) { void LEDStateEngine_init(int numberOfLeds) {
LEDStateEngine_setNumberOfLeds(numberOfLeds); LEDStateEngine_setNumberOfLeds(numberOfLeds);
theLEDStateEngine.comment = ""; theLEDStateEngine.comment = "";
for (int i=0; i<numberOfLeds; ++i) { for (int i=0; i<numberOfLeds; ++i) {
LEDstate_init(i, LEDDefinition_get(i)); LEDState_init(i, LEDDefinition_get(i));
} }
} }
@ -33,24 +37,26 @@ uint16_t LEDStateEngine_getNumberOfLeds() {
void LEDStateEngine_tick() { void LEDStateEngine_tick() {
++ticks;
// LOG(LL_INFO, ("# %d/%d", theLEDStateEngine.numberOfLeds, ticks));
for (int i=0; i<theLEDStateEngine.numberOfLeds; ++i) { for (int i=0; i<theLEDStateEngine.numberOfLeds; ++i) {
LEDState_tick(i); LEDState_tick(i);
} }
} }
void LEDState_tick(int ledNum) { void LEDState_tick(int ledNum) {
LEDState *state = &theLEDStateEngine.ledState[ledNum]; LEDState *state = LEDStateEngine_getLedState(ledNum);
if (/*state->index < 0 ||*/ state->index >= theLEDStateEngine.numberOfLeds) state->currentTick = state->currentTick + 1;
return; // ignore LED entries, that are not setup correctly // LOG(LL_INFO,("LEDState_tick(%d) %d", ledNum, state->currentTick));
state->currentTick++;
if (state->currentTick == state->nextTick) { if (state->currentTick == state->nextTick) {
// perform/initiate next state change // perform/initiate next state change
//LOG(LL_INFO, ("State change for led %d", ledNum));
state->currentAnimationStep = AnimationConfig_getNextAnimationStepForLED(ledNum, state->currentAnimationStep); state->currentAnimationStep = AnimationConfig_getNextAnimationStepForLED(ledNum, state->currentAnimationStep);
state->nextTick = state->currentTick + theAnimationConfig.animationStep[state->currentAnimationStep].durationTicks; state->nextTick = state->currentTick + theAnimationConfig.animationStep[state->currentAnimationStep].durationTicks;
state->mode = theAnimationConfig.animationStep[state->currentAnimationStep].ledMode; state->mode = theAnimationConfig.animationStep[state->currentAnimationStep].ledMode;
switch (state->mode) { switch (state->mode) {
case LEDMode_on: case LEDMode_on:
state->currentColor = state->onColor; state->currentColor = state->ledDefinition->onColor; // state->onColor;
break; break;
case LEDMode_off: case LEDMode_off:
state->currentColor = offColor; state->currentColor = offColor;
@ -79,35 +85,57 @@ static int verifyLedNumber(int n) {
return n; return n;
} }
void LEDstate_initDefault(int n, LEDMode defaultMode) { void LEDState_initDefault(int n, LEDMode defaultMode) {
n = verifyLedNumber(n); n = verifyLedNumber(n);
LEDState *state = &theLEDStateEngine.ledState[n];
state->index = n;
state->mode = defaultMode;
state->nextTick = 0;
state->ledDefinition = LEDDefinition_get(n);
}
void LEDstate_init(int n, LEDDefinition *ledDefinition) {
n = verifyLedNumber(n);
LEDstate_initDefault(n, LEDMode_off);
LEDState *state = LEDStateEngine_getLedState(n); LEDState *state = LEDStateEngine_getLedState(n);
state->index = n; state->index = n;
state->mode = defaultMode;
state->currentTick = -10;
state->nextTick = 0;
state->ledDefinition = LEDDefinition_get(n);
state->currentAnimationStep = AnimationConfig_getNextAnimationStepForLED(n, 0);
}
void LEDState_init(int n, LEDDefinition *ledDefinition) {
n = verifyLedNumber(n);
LEDState_initDefault(n, LEDMode_off);
LEDState *state = LEDStateEngine_getLedState(n);
state->ledDefinition = ledDefinition; state->ledDefinition = ledDefinition;
state->onColor = ledDefinition->onColor; // state->onColor = ledDefinition->onColor;
state->onColor.name = ledDefinition->onColor.name;
state->onColor.red = ledDefinition->onColor.red;
state->onColor.green = ledDefinition->onColor.green;
state->onColor.blue = ledDefinition->onColor.blue;
} }
int LEDState_getLedRed(int ledNum) { int LEDState_getLedRed(int ledNum) {
ledNum = verifyLedNumber(ledNum);
LEDState *state = LEDStateEngine_getLedState(ledNum); LEDState *state = LEDStateEngine_getLedState(ledNum);
return state->currentColor.red; return state->currentColor.red;
} }
int LEDState_getLedGreen(int ledNum) { int LEDState_getLedGreen(int ledNum) {
ledNum = verifyLedNumber(ledNum);
LEDState *state = LEDStateEngine_getLedState(ledNum); LEDState *state = LEDStateEngine_getLedState(ledNum);
return state->currentColor.green; return state->currentColor.green;
} }
int LEDState_getLedBlue(int ledNum) { int LEDState_getLedBlue(int ledNum) {
ledNum = verifyLedNumber(ledNum);
LEDState *state = LEDStateEngine_getLedState(ledNum); LEDState *state = LEDStateEngine_getLedState(ledNum);
return state->currentColor.blue; return state->currentColor.blue;
} }
char * LEDState_getLedColorName(int ledNum) {
ledNum = verifyLedNumber(ledNum);
LEDState *state = LEDStateEngine_getLedState(ledNum);
return state->currentColor.name;
}
int LEDState_getCurrentTick(int ledNum) {
ledNum = verifyLedNumber(ledNum);
LEDState *state = LEDStateEngine_getLedState(ledNum);
return state->currentTick;
}
int LEDState_getNextTick(int ledNum) {
ledNum = verifyLedNumber(ledNum);
LEDState *state = LEDStateEngine_getLedState(ledNum);
return state->nextTick;
}

View File

@ -28,6 +28,8 @@ typedef struct LEDStateEngine_t {
char *comment; char *comment;
} LEDStateEngine; } LEDStateEngine;
extern int getTicks(void);
/* LEDStateEngine */ /* LEDStateEngine */
extern void LEDStateEngine_init(int numberOfLeds); extern void LEDStateEngine_init(int numberOfLeds);
extern void LEDStateEngine_addComment(char *comment); extern void LEDStateEngine_addComment(char *comment);
@ -37,11 +39,14 @@ extern void LEDStateEngine_tick();
extern uint16_t LEDStateEngine_getNumberOfLeds(); extern uint16_t LEDStateEngine_getNumberOfLeds();
/* LEDState */ /* LEDState */
extern void LEDstate_init(int n, LEDDefinition *ledDefinition); extern void LEDState_init(int n, LEDDefinition *ledDefinition);
extern void LEDstate_initDefault(int n, LEDMode defaultMode); extern void LEDState_initDefault(int n, LEDMode defaultMode);
extern void LEDState_tick(int ledNum); extern void LEDState_tick(int ledNum);
extern int LEDState_getLedRed(int ledNum); extern int LEDState_getLedRed(int ledNum);
extern int LEDState_getLedGreen(int ledNum); extern int LEDState_getLedGreen(int ledNum);
extern int LEDState_getLedBlue(int ledNum); extern int LEDState_getLedBlue(int ledNum);
extern char * LEDState_getLedColorName(int ledNum);
extern int LEDState_getCurrentTick(int ledNum);
extern int LEDState_getNextTick(int ledNum);
#endif #endif

View File

@ -37,9 +37,9 @@ int get_led_gpio_pin(void) {
LEDStateEngine ledStateEngine; LEDStateEngine ledStateEngine;
static bool stateEngineRunning = false; static bool stateEngineRunning = false;
static void timer_cb() { static void stateEngineTickTimer() {
if (stateEngineRunning) { if (stateEngineRunning) {
LOG(LL_INFO, ("tick")); // LOG(LL_INFO, ("digg"));
LEDStateEngine_tick(); LEDStateEngine_tick();
} else { } else {
LOG(LL_INFO, ("--paused--")); LOG(LL_INFO, ("--paused--"));
@ -47,12 +47,13 @@ static void timer_cb() {
} }
static void delayed_boot() { static void delayed_boot() {
mgos_set_timer(100, true, timer_cb, NULL); // every 0.1 second call timer_cb LOG(LL_INFO, ("*** Start timer for LED state engine ticks"));
mgos_set_timer(100, true, stateEngineTickTimer, NULL); // every 0.1 second call timer_cb
} }
enum mgos_app_init_result mgos_app_init(void) { enum mgos_app_init_result mgos_app_init(void) {
int numberOfLeds = 20; /*mgos_sys_config_get_led_count()*/ int numberOfLeds = mgos_sys_config_get_led_count();
bool loadDefaultData = true; /*mgos_sys_config_get_led_useDefaults()*/ bool loadDefaultData = mgos_sys_config_get_led_useDefaults();
LEDColor_init(loadDefaultData); LEDColor_init(loadDefaultData);
LEDDefinition_init(numberOfLeds, loadDefaultData); LEDDefinition_init(numberOfLeds, loadDefaultData);
@ -88,7 +89,9 @@ void addAnimationStep(int ledIndex, int ledMode, int duration) {
void startLEDStateEngine(void) { void startLEDStateEngine(void) {
stateEngineRunning = true; stateEngineRunning = true;
LOG(LL_INFO, ("LEDStateEngine started"));
} }
void pauseLEDStateEngine(void) { void pauseLEDStateEngine(void) {
stateEngineRunning = false; stateEngineRunning = false;
LOG(LL_INFO, ("LEDStateEngine stopped"));
} }