Compare commits
1 commit
af4c156055
...
901f23feae
Author | SHA1 | Date | |
---|---|---|---|
901f23feae |
1 changed files with 139 additions and 68 deletions
207
lights.js
207
lights.js
|
@ -1,16 +1,20 @@
|
||||||
import ws281x from 'rpi-ws281x';
|
import ws281x from "rpi-ws281x";
|
||||||
import * as fs from 'fs';
|
import * as fs from "fs";
|
||||||
import Logger, { levels } from './logger.js';
|
import Logger, { levels } from "./logger.js";
|
||||||
|
|
||||||
const cfg = JSON.parse(fs.readFileSync('./config.json'));
|
const cfg = JSON.parse(fs.readFileSync("./config.json"));
|
||||||
const log = new Logger("lights", cfg.log_level ? levels[cfg.log_level] : levels.INFO);
|
const log = new Logger(
|
||||||
|
"lights",
|
||||||
|
cfg.log_level ? levels[cfg.log_level] : levels.INFO
|
||||||
|
);
|
||||||
|
|
||||||
const fade_ticks = cfg.fade_ticks || 20;
|
const fade_ticks = cfg.fade_ticks || 20;
|
||||||
|
var num_ticks = 0;
|
||||||
var pixels = new Uint32Array(cfg.leds);
|
var pixels = new Uint32Array(cfg.leds);
|
||||||
var pixel_cache = new Uint32Array(cfg.leds);
|
var pixel_cache = new Uint32Array(cfg.leds);
|
||||||
var next_pattern = new Uint32Array(cfg.leds);
|
var next_pattern = new Uint32Array(cfg.leds);
|
||||||
const targets = {}
|
const targets = {};
|
||||||
var pattern = {}
|
var pattern = {};
|
||||||
|
|
||||||
function rgb_to_int(r, g, b) {
|
function rgb_to_int(r, g, b) {
|
||||||
let rgb = r;
|
let rgb = r;
|
||||||
|
@ -19,9 +23,9 @@ function rgb_to_int(r, g, b) {
|
||||||
return rgb;
|
return rgb;
|
||||||
}
|
}
|
||||||
function int_to_rgb(int) {
|
function int_to_rgb(int) {
|
||||||
var r = (int >> 16) & 0xFF;
|
var r = (int >> 16) & 0xff;
|
||||||
var g = (int >> 8) & 0xFF;
|
var g = (int >> 8) & 0xff;
|
||||||
var b = (int) & 0xFF;
|
var b = int & 0xff;
|
||||||
return { r: r, g: g, b: b };
|
return { r: r, g: g, b: b };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -29,11 +33,11 @@ ws281x.configure({
|
||||||
leds: cfg.leds || 300,
|
leds: cfg.leds || 300,
|
||||||
brightness: cfg.brightness || 200,
|
brightness: cfg.brightness || 200,
|
||||||
gpio: cfg.gpio || 18,
|
gpio: cfg.gpio || 18,
|
||||||
stripType: cfg.type || 'grb'
|
stripType: cfg.type || "grb",
|
||||||
});
|
});
|
||||||
|
|
||||||
export function set_pattern(pat) {
|
export function set_pattern(pat) {
|
||||||
pattern = pat
|
pattern = pat;
|
||||||
log.debug("pattern set");
|
log.debug("pattern set");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -49,53 +53,92 @@ export class Function {
|
||||||
|
|
||||||
export const functions = {
|
export const functions = {
|
||||||
random: new Function(
|
random: new Function(
|
||||||
(index, arg1, arg2) => { return Math.floor(Math.random() * 256) },
|
(index, arg1, arg2) => {
|
||||||
|
return Math.floor(Math.random() * 256);
|
||||||
|
},
|
||||||
{
|
{
|
||||||
requires_arg1: true,
|
requires_arg1: true,
|
||||||
requires_arg2: false,
|
requires_arg2: false,
|
||||||
convert_args: false
|
convert_args: false,
|
||||||
}
|
}
|
||||||
),
|
),
|
||||||
move: new Function(
|
move: new Function(
|
||||||
(index, arg1, arg2) => { return arg2; },
|
(index, arg1, arg2) => {
|
||||||
|
return arg2;
|
||||||
|
},
|
||||||
{
|
{
|
||||||
requires_arg1: true,
|
requires_arg1: true,
|
||||||
requires_arg2: true,
|
requires_arg2: true,
|
||||||
convert_args: true
|
convert_args: true,
|
||||||
}),
|
}
|
||||||
|
),
|
||||||
modulo: new Function(
|
modulo: new Function(
|
||||||
(index, arg1, arg2) => { return arg1 % arg2; },
|
(index, arg1, arg2) => {
|
||||||
|
return arg1 % arg2;
|
||||||
|
},
|
||||||
{
|
{
|
||||||
requires_arg1: true,
|
requires_arg1: true,
|
||||||
requires_arg2: true,
|
requires_arg2: true,
|
||||||
convert_args: true
|
convert_args: true,
|
||||||
}),
|
}
|
||||||
|
),
|
||||||
swap: new Function(
|
swap: new Function(
|
||||||
(index, arg1, arg2) => { let temp = targets[arg2]; targets[arg2] = targets[arg1]; return temp; },
|
(index, arg1, arg2) => {
|
||||||
|
let temp = targets[arg2];
|
||||||
|
targets[arg2] = targets[arg1];
|
||||||
|
return temp;
|
||||||
|
},
|
||||||
{
|
{
|
||||||
requires_arg1: true,
|
requires_arg1: true,
|
||||||
requires_arg2: true,
|
requires_arg2: true,
|
||||||
convert_args: false
|
convert_args: false,
|
||||||
}),
|
}
|
||||||
|
),
|
||||||
add: new Function(
|
add: new Function(
|
||||||
(index, arg1, arg2) => { return arg1 + arg2; },
|
(index, arg1, arg2) => {
|
||||||
|
return arg1 + arg2;
|
||||||
|
},
|
||||||
{
|
{
|
||||||
requires_arg1: true,
|
requires_arg1: true,
|
||||||
requires_arg2: true,
|
requires_arg2: true,
|
||||||
convert_args: true
|
convert_args: true,
|
||||||
}),
|
}
|
||||||
|
),
|
||||||
subtract: new Function(
|
subtract: new Function(
|
||||||
(index, arg1, arg2) => { return arg1 - arg2; },
|
(index, arg1, arg2) => {
|
||||||
|
return arg1 - arg2;
|
||||||
|
},
|
||||||
{
|
{
|
||||||
requires_arg1: true,
|
requires_arg1: true,
|
||||||
requires_arg2: true,
|
requires_arg2: true,
|
||||||
convert_args: true
|
convert_args: true,
|
||||||
})
|
}
|
||||||
}
|
),
|
||||||
|
stagger: new Function(
|
||||||
|
(index, arg1, arg2) => {
|
||||||
|
return (index + arg2) % 255;
|
||||||
|
},
|
||||||
|
{
|
||||||
|
requires_arg1: true,
|
||||||
|
requires_arg2: true,
|
||||||
|
convert_args: true,
|
||||||
|
},
|
||||||
|
slide: new Function(
|
||||||
|
(index, arg1, arg2) => {
|
||||||
|
return (num_ticks + arg2) % 255;
|
||||||
|
},
|
||||||
|
{
|
||||||
|
requires_arg1: true,
|
||||||
|
requires_arg2: true,
|
||||||
|
convert_args: true
|
||||||
|
}
|
||||||
|
)
|
||||||
|
),
|
||||||
|
};
|
||||||
|
|
||||||
function tick_pattern() {
|
function tick_pattern() {
|
||||||
// do the parsing stuff here
|
// do the parsing stuff here
|
||||||
log.debug("TICKING PATTERN")
|
log.debug("TICKING PATTERN");
|
||||||
|
|
||||||
let parsed = pattern.parsed;
|
let parsed = pattern.parsed;
|
||||||
log.debug(`${JSON.stringify(pattern)} ${JSON.stringify(parsed)}`);
|
log.debug(`${JSON.stringify(pattern)} ${JSON.stringify(parsed)}`);
|
||||||
|
@ -108,14 +151,18 @@ function tick_pattern() {
|
||||||
let name = command["command"];
|
let name = command["command"];
|
||||||
log.debug(`${name} matches: ${functions[name]}`);
|
log.debug(`${name} matches: ${functions[name]}`);
|
||||||
if (functions[name] != undefined) {
|
if (functions[name] != undefined) {
|
||||||
if (functions[name].options && functions[name].options["convert_args"]) {
|
if (
|
||||||
|
functions[name].options &&
|
||||||
|
functions[name].options["convert_args"]
|
||||||
|
) {
|
||||||
let param_arg1 = parseInt(command.arg1) || targets[command.arg1];
|
let param_arg1 = parseInt(command.arg1) || targets[command.arg1];
|
||||||
let param_arg2 = parseInt(command.arg2) || targets[command.arg2];
|
let param_arg2 = parseInt(command.arg2) || targets[command.arg2];
|
||||||
let result = functions[name].func(i, param_arg1, param_arg2);
|
let result = functions[name].func(i, param_arg1, param_arg2);
|
||||||
log.debug(`convert ${command.arg1} ${param_arg1} ${command.arg2} ${param_arg2} ${result}`);
|
log.debug(
|
||||||
|
`convert ${command.arg1} ${param_arg1} ${command.arg2} ${param_arg2} ${result}`
|
||||||
|
);
|
||||||
targets[command.arg1] = result;
|
targets[command.arg1] = result;
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
let result = functions[name].func(i, command.arg1, command.arg2);
|
let result = functions[name].func(i, command.arg1, command.arg2);
|
||||||
log.debug(`no convert ${command.arg1} = ${result}`);
|
log.debug(`no convert ${command.arg1} = ${result}`);
|
||||||
targets[command.arg1] = result;
|
targets[command.arg1] = result;
|
||||||
|
@ -123,18 +170,24 @@ function tick_pattern() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
log.debug(`next: ${targets["r"]}, ${targets["g"]}, ${targets["b"]}`);
|
log.debug(`next: ${targets["r"]}, ${targets["g"]}, ${targets["b"]}`);
|
||||||
next_pattern[i] = rgb_to_int(targets["r"] || 0, targets["g"] || 0, targets["b"] || 0);
|
next_pattern[i] = rgb_to_int(
|
||||||
targets["r"] = 0; targets["g"] = 0; targets["b"] = 0;
|
targets["r"] || 0,
|
||||||
|
targets["g"] || 0,
|
||||||
|
targets["b"] || 0
|
||||||
|
);
|
||||||
|
targets["r"] = 0;
|
||||||
|
targets["g"] = 0;
|
||||||
|
targets["b"] = 0;
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
getRandom();
|
||||||
}
|
}
|
||||||
else {
|
num_ticks++;
|
||||||
getRandom()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function getRandom() {
|
function getRandom() {
|
||||||
for (let i = 0; i < cfg.leds; i++) {
|
for (let i = 0; i < cfg.leds; i++) {
|
||||||
var r = Math.floor(Math.random() * 256)
|
var r = Math.floor(Math.random() * 256);
|
||||||
var g = Math.floor(Math.random() * 256);
|
var g = Math.floor(Math.random() * 256);
|
||||||
var b = Math.floor(Math.random() * 256);
|
var b = Math.floor(Math.random() * 256);
|
||||||
next_pattern[i] = rgb_to_int(r, g, b);
|
next_pattern[i] = rgb_to_int(r, g, b);
|
||||||
|
@ -148,21 +201,18 @@ export function tick() {
|
||||||
if (next_pattern[i] == pixel_cache[i]) {
|
if (next_pattern[i] == pixel_cache[i]) {
|
||||||
log.debug("INCONGRUENCE WITH " + i);
|
log.debug("INCONGRUENCE WITH " + i);
|
||||||
pixels[i] = next_pattern[i];
|
pixels[i] = next_pattern[i];
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
changed = true;
|
changed = true;
|
||||||
fade(i);
|
fade(i);
|
||||||
}
|
}
|
||||||
}
|
} else if (pixel_cache[i] != pixels[i]) {
|
||||||
else if (pixel_cache[i] != pixels[i]) {
|
|
||||||
log.debug("PATTERN NOT STORED " + i);
|
log.debug("PATTERN NOT STORED " + i);
|
||||||
pixel_cache[i] = pixels[i];
|
pixel_cache[i] = pixels[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!changed) {
|
if (!changed) {
|
||||||
tick_pattern();
|
tick_pattern();
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
ws281x.render(pixels);
|
ws281x.render(pixels);
|
||||||
}
|
}
|
||||||
//ws281x.sleep(cfg.sleep_time || 500);
|
//ws281x.sleep(cfg.sleep_time || 500);
|
||||||
|
@ -185,53 +235,74 @@ function fade(index) {
|
||||||
var interval_r = sign_r * Math.ceil(Math.abs(diff_r) / fade_ticks);
|
var interval_r = sign_r * Math.ceil(Math.abs(diff_r) / fade_ticks);
|
||||||
var interval_g = sign_g * Math.ceil(Math.abs(diff_g) / fade_ticks);
|
var interval_g = sign_g * Math.ceil(Math.abs(diff_g) / fade_ticks);
|
||||||
var interval_b = sign_b * Math.ceil(Math.abs(diff_b) / fade_ticks);
|
var interval_b = sign_b * Math.ceil(Math.abs(diff_b) / fade_ticks);
|
||||||
log.debug(`r${Math.abs(diff_r) / fade_ticks} ${Math.ceil(Math.abs(diff_r) / fade_ticks)}` +
|
log.debug(
|
||||||
`g${Math.abs(diff_g) / fade_ticks} ${Math.ceil(Math.abs(diff_g) / fade_ticks)}` +
|
`r${Math.abs(diff_r) / fade_ticks} ${Math.ceil(
|
||||||
`b${Math.abs(diff_b) / fade_ticks} ${Math.ceil(Math.abs(diff_b) / fade_ticks)}`);
|
Math.abs(diff_r) / fade_ticks
|
||||||
|
)}` +
|
||||||
|
`g${Math.abs(diff_g) / fade_ticks} ${Math.ceil(
|
||||||
|
Math.abs(diff_g) / fade_ticks
|
||||||
|
)}` +
|
||||||
|
`b${Math.abs(diff_b) / fade_ticks} ${Math.ceil(
|
||||||
|
Math.abs(diff_b) / fade_ticks
|
||||||
|
)}`
|
||||||
|
);
|
||||||
|
|
||||||
var current_tick_r = Math.floor(Math.abs(diff_cr / diff_r) * fade_ticks);
|
var current_tick_r = Math.floor(Math.abs(diff_cr / diff_r) * fade_ticks);
|
||||||
var current_tick_g = Math.floor(Math.abs(diff_cg / diff_g) * fade_ticks);
|
var current_tick_g = Math.floor(Math.abs(diff_cg / diff_g) * fade_ticks);
|
||||||
var current_tick_b = Math.floor(Math.abs(diff_cb / diff_b) * fade_ticks);
|
var current_tick_b = Math.floor(Math.abs(diff_cb / diff_b) * fade_ticks);
|
||||||
if (diff_r == 0 ||
|
if (
|
||||||
|
diff_r == 0 ||
|
||||||
(sign_r == 1 && current.r + interval_r >= final.r) ||
|
(sign_r == 1 && current.r + interval_r >= final.r) ||
|
||||||
(sign_r == -1 && current.r + interval_r <= final.r) ||
|
(sign_r == -1 && current.r + interval_r <= final.r) ||
|
||||||
current_tick_r + 1 >= fade_ticks) {
|
current_tick_r + 1 >= fade_ticks
|
||||||
|
) {
|
||||||
current.r = final.r;
|
current.r = final.r;
|
||||||
interval_r = 0;
|
interval_r = 0;
|
||||||
current_tick_r = fade_ticks;
|
current_tick_r = fade_ticks;
|
||||||
}
|
}
|
||||||
if (diff_g == 0 ||
|
if (
|
||||||
|
diff_g == 0 ||
|
||||||
(sign_g == 1 && current.g + interval_g >= final.g) ||
|
(sign_g == 1 && current.g + interval_g >= final.g) ||
|
||||||
(sign_g == -1 && current.g + interval_g <= final.g) ||
|
(sign_g == -1 && current.g + interval_g <= final.g) ||
|
||||||
current_tick_g + 1 >= fade_ticks) {
|
current_tick_g + 1 >= fade_ticks
|
||||||
|
) {
|
||||||
current.g = final.g;
|
current.g = final.g;
|
||||||
interval_g = 0;
|
interval_g = 0;
|
||||||
current_tick_g = fade_ticks;
|
current_tick_g = fade_ticks;
|
||||||
}
|
}
|
||||||
if (diff_b == 0 ||
|
if (
|
||||||
|
diff_b == 0 ||
|
||||||
(sign_b == 1 && current.b + interval_b >= final.b) ||
|
(sign_b == 1 && current.b + interval_b >= final.b) ||
|
||||||
(sign_b == -1 && current.b + interval_b <= final.b) ||
|
(sign_b == -1 && current.b + interval_b <= final.b) ||
|
||||||
current_tick_b + 1 >= fade_ticks) {
|
current_tick_b + 1 >= fade_ticks
|
||||||
|
) {
|
||||||
current.b = final.b;
|
current.b = final.b;
|
||||||
interval_b = 0;
|
interval_b = 0;
|
||||||
current_tick_b = fade_ticks;
|
current_tick_b = fade_ticks;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (current_tick_r + 1 >= fade_ticks &&
|
if (
|
||||||
|
current_tick_r + 1 >= fade_ticks &&
|
||||||
current_tick_g + 1 >= fade_ticks &&
|
current_tick_g + 1 >= fade_ticks &&
|
||||||
current_tick_b + 1 >= fade_ticks) {
|
current_tick_b + 1 >= fade_ticks
|
||||||
|
) {
|
||||||
log.debug("FINISHED");
|
log.debug("FINISHED");
|
||||||
pixel_cache[index] = next_pattern[index];
|
pixel_cache[index] = next_pattern[index];
|
||||||
}
|
} else {
|
||||||
else {
|
pixels[index] = rgb_to_int(
|
||||||
pixels[index] = rgb_to_int(current.r + interval_r,
|
current.r + interval_r,
|
||||||
current.g + interval_g,
|
current.g + interval_g,
|
||||||
current.b + interval_b);
|
current.b + interval_b
|
||||||
|
);
|
||||||
let prev = int_to_rgb(pixel_cache[index]);
|
let prev = int_to_rgb(pixel_cache[index]);
|
||||||
log.debug(`${current_tick_r} ${current_tick_g} ${current_tick_b}: `
|
log.debug(
|
||||||
+ `CURRENT COLOR: ${current.r} ${current.g} ${current.b} NEW COLOR: ${current.r + interval_r} ${current.g + interval_g} ${current.b + interval_b} ` +
|
`${current_tick_r} ${current_tick_g} ${current_tick_b}: ` +
|
||||||
`FINAL: ${final.r} ${final.g} ${final.b} ` +
|
`CURRENT COLOR: ${current.r} ${current.g} ${current.b} NEW COLOR: ${
|
||||||
`\nINTERVAL: ${interval_r} ${interval_g} ${interval_b} ` +
|
current.r + interval_r
|
||||||
`PREVIOUS: ${prev.r} ${prev.g} ${prev.b}`);
|
} ${current.g + interval_g} ${current.b + interval_b} ` +
|
||||||
|
`FINAL: ${final.r} ${final.g} ${final.b} ` +
|
||||||
|
`\nINTERVAL: ${interval_r} ${interval_g} ${interval_b} ` +
|
||||||
|
`PREVIOUS: ${prev.r} ${prev.g} ${prev.b}`
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue