First version with demo mode
This commit is contained in:
parent
bf5e39efb6
commit
a8206eb465
|
@ -0,0 +1,3 @@
|
||||||
|
build/
|
||||||
|
*.bak
|
||||||
|
*.tmp
|
|
@ -0,0 +1,155 @@
|
||||||
|
load('api_rpc.js');
|
||||||
|
load("api_neopixel.js");
|
||||||
|
load("api_file.js");
|
||||||
|
|
||||||
|
|
||||||
|
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: 3,
|
||||||
|
ledPin: 4,
|
||||||
|
running: false,
|
||||||
|
mode: "demo",
|
||||||
|
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
|
||||||
|
]
|
||||||
|
};
|
||||||
|
|
||||||
|
// Add RPC handlers
|
||||||
|
|
||||||
|
RPC.addHandler('HouseLightning.Start', function(args) {
|
||||||
|
LightAnimation.running = true;
|
||||||
|
return {result: 'ok'};
|
||||||
|
}, null);
|
||||||
|
|
||||||
|
RPC.addHandler('HouseLightning.Stop', function(args) {
|
||||||
|
LightAnimation.running = false;
|
||||||
|
return {result: 'ok'};
|
||||||
|
}, null);
|
||||||
|
|
||||||
|
RPC.addHandler('HouseLightning.DemoMode', function(args) {
|
||||||
|
LightAnimation.mode = "demo";
|
||||||
|
LightAnimation.running = true;
|
||||||
|
return {result: 'ok'};
|
||||||
|
}, null);
|
||||||
|
|
||||||
|
RPC.addHandler('HouseLightning.CycleMode', function(args) {
|
||||||
|
LightAnimation.mode = "cycle";
|
||||||
|
LightAnimation.running = true;
|
||||||
|
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) {
|
||||||
|
LightAnimation.animationConfig = JSON.parse(args.config);
|
||||||
|
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 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'};
|
||||||
|
} else {
|
||||||
|
return {error: 'parameter config is required'};
|
||||||
|
}
|
||||||
|
}, null);
|
||||||
|
|
||||||
|
function runNeopixel(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, color.r, color.g, 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);
|
||||||
|
|
||||||
|
|
||||||
|
// initialize neoPixel
|
||||||
|
let colorOrder = NeoPixel.GRB;
|
||||||
|
let strip = NeoPixel.create(LightAnimation.ledPin, LightAnimation.numberOfBulbs, colorOrder);
|
||||||
|
strip.clear();
|
||||||
|
strip.show();
|
||||||
|
// initialize test pattern
|
||||||
|
let i = 0;
|
||||||
|
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();
|
||||||
|
|
||||||
|
let shiftAnimation = 1;
|
||||||
|
|
||||||
|
Timer.set(1990 /* msec */, true /* repeat */, function() {
|
||||||
|
if (LightAnimation.running) {
|
||||||
|
if (LightAnimation.mode === "demo") {
|
||||||
|
runNeopixel(strip, shiftAnimation);
|
||||||
|
shiftAnimation++;
|
||||||
|
print("*** demo-mode, next shift=", shiftAnimation);
|
||||||
|
} else print("*** no-ack, mode =", LightAnimation.mode);
|
||||||
|
} else print("*** stopped");
|
||||||
|
}, null);
|
30
fs/init.js
30
fs/init.js
|
@ -2,23 +2,17 @@ load('api_config.js');
|
||||||
load('api_gpio.js');
|
load('api_gpio.js');
|
||||||
load('api_mqtt.js');
|
load('api_mqtt.js');
|
||||||
load('api_sys.js');
|
load('api_sys.js');
|
||||||
|
load('api_rpc.js');
|
||||||
load('api_timer.js');
|
load('api_timer.js');
|
||||||
load("api_neopixel.js");
|
load("animateLights.js");
|
||||||
|
|
||||||
// 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 led = ffi('int get_led_gpio_pin()')();
|
let onBoardLed = ffi('int get_led_gpio_pin()')();
|
||||||
|
|
||||||
let getInfo = function() {
|
let getInfo = function() {
|
||||||
return JSON.stringify({total_ram: Sys.total_ram(), free_ram: Sys.free_ram()});
|
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(1000 /* 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
|
// Publish to MQTT topic on a button press. Button is wired to GPIO pin 0
|
||||||
GPIO.set_button_handler(0, GPIO.PULL_UP, GPIO.INT_EDGE_NEG, 200, function() {
|
GPIO.set_button_handler(0, GPIO.PULL_UP, GPIO.INT_EDGE_NEG, 200, function() {
|
||||||
let topic = '/devices/' + Cfg.get('device.id') + '/events';
|
let topic = '/devices/' + Cfg.get('device.id') + '/events';
|
||||||
|
@ -27,16 +21,12 @@ GPIO.set_button_handler(0, GPIO.PULL_UP, GPIO.INT_EDGE_NEG, 200, function() {
|
||||||
print('Published:', ok ? 'yes' : 'no', 'topic:', topic, 'message:', message);
|
print('Published:', ok ? 'yes' : 'no', 'topic:', topic, 'message:', message);
|
||||||
}, null);
|
}, null);
|
||||||
|
|
||||||
function initNeopixel() {
|
|
||||||
let pin = 2, numPixels = 20, colorOrder = NeoPixel.GRB;
|
|
||||||
let strip = NeoPixel.create(pin, numPixels, colorOrder);
|
|
||||||
strip.setPixel(0 / pixel /, 12, 34, 56);
|
|
||||||
strip.show();
|
|
||||||
|
|
||||||
strip.clear();
|
// Blink built-in LED every second
|
||||||
strip.setPixel(1 / pixel /, 12, 34, 56);
|
GPIO.set_mode(onBoardLed, GPIO.MODE_OUTPUT);
|
||||||
strip.show();
|
|
||||||
}
|
|
||||||
|
|
||||||
initNeopixel();
|
|
||||||
|
|
||||||
|
// Tick-Tock generation
|
||||||
|
Timer.set(1000 /* 1 sec */, true /* repeat */, function() {
|
||||||
|
let value = GPIO.toggle(onBoardLed);
|
||||||
|
print(value ? 'Tick' : 'Tock', 'uptime:', Sys.uptime(), getInfo());
|
||||||
|
}, null);
|
||||||
|
|
|
@ -0,0 +1,18 @@
|
||||||
|
{
|
||||||
|
"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" }
|
||||||
|
]
|
||||||
|
}
|
Loading…
Reference in New Issue