Skip to content

Instantly share code, notes, and snippets.

@jamesbulpin
Created December 10, 2018 16:24
Show Gist options
  • Save jamesbulpin/c050bde1d8841a705536818fb27936c5 to your computer and use it in GitHub Desktop.
Save jamesbulpin/c050bde1d8841a705536818fb27936c5 to your computer and use it in GitHub Desktop.
#IoTree MQTT version
var ws281x = require('rpi-ws281x-native');
var tinycolor = require("tinycolor2");
var mqtt = require('mqtt');
var font5x7 = require('./font.js');
var fs = require('fs');
try {
var xy = require('./xy.json');
}
catch (ex) {
var xy = null;
}
var config_mqtt = require("../config/config_mqtt.js");
restartTimer = setTimeout(function() {
console.log("[" + new Date() + "] " + "Exiting after pre-set delay.");
var state = {};
state.mode = mode;
state.color = color;
state.dmmessage = dmmessage;
fs.writeFile("/tmp/ws2811.json", JSON.stringify(state), function(err) {
process.exit(0);
});
}, 3600000);
var NUM_LEDS = 100,
pixelData = new Uint32Array(NUM_LEDS),
modulation = new Uint32Array(NUM_LEDS);
var mode = "";
var color = 0xffffff;
var dmmessage = " XMAS";
try {
var state = require('/tmp/ws2811.json');
mode = state.mode;
color = state.color;
dmmessage = state.dmmessage;
}
catch (ex) {
}
var dmarray = new Uint32Array(dmmessage.length * 7 + 5);
var dmcolor = new Uint32Array(dmmessage.length * 7 + 5);
var colorcycle = 255;
function renderMessage() {
dmarray = new Uint32Array(dmmessage.length * 7 + 5);
dmcolor = new Uint32Array(dmmessage.length * 7 + 5);
for (var i = 0; i < dmmessage.length; i++) {
var fonttablebase = (dmmessage.charCodeAt(i) - 0x20) * 5;
for (var j = 0; j < 5; j++) {
dmarray[i*7+j] = font5x7[fonttablebase + j];
dmcolor[i*7+j] = colorcycle;
}
if (colorcycle == 0xff0000) {
colorcycle = 255;
} else {
colorcycle = colorcycle << 8;
}
}
}
renderMessage();
// Rainbow colours
rbcolor = [];
["red", "orange", "yellow", "green", "blue", "indigo", "violet"].forEach(function (c) {
var rgb = tinycolor(c).toRgb();
rbcolor.push(rgb2Int(rgb.r, rgb.g, rgb.b));
});
ws281x.init(NUM_LEDS);
last_vals = []
for (var i =0; i < 50; i++) {
last_vals.push(-33.0);
}
last_val_index = 0;
// ---- trap the SIGINT and reset before exit
process.on('SIGINT', function () {
ws281x.reset();
process.nextTick(function () { process.exit(0); });
});
// ---- animation-loop
var offset = 0;
setInterval(function () {
for (var i = 0; i < NUM_LEDS; i++) {
if ((offset % 40) == (i % 40)) {
modulation[i] = Math.round(Math.random());
}
switch (mode) {
case "colorwheel":
pixelData[i] = colorwheel((offset + i) % 256);
break;
case "bars":
case "yoyo":
case "yo-yo":
pixelData[i] = bars(i, offset % (NUM_LEDS*2));
break;
case "solid":
pixelData[i] = color;
break;
case "octoblu":
pixelData[i] = octoblu(i);
break;
case "concentric":
pixelData[i] = concentric(i, Math.floor(offset/10)%10);
break;
case "snowfall":
pixelData[i] = snowfall(i, (offset/2) % 100);
break;
case "twinkle":
case "twinklewhite":
pixelData[i] = twinklewhite(i);
break;
case "flashing":
case "twinklecolor":
pixelData[i] = twinklecolor(i);
break;
case "nothing":
pixelData[i] = 0;
break;
case "dotmatrix":
pixelData[i] = dotmatrix(i);
break;
case "xytest":
pixelData[i] = xytest(i);
break;
case "rainbow":
pixelData[i] = rainbow(i);
break;
}
}
offset = (offset + 1);
ws281x.render(pixelData);
}, 1000 / 120);
console.log('Press <ctrl>+C to exit.');
function bars(pos, step) {
if (step > (NUM_LEDS-1)) {
step = (NUM_LEDS*2) - 1 - step;
}
if (step >= pos) {
return colorwheel((offset + pos) % 256);
}
return 0;
}
var snowfall_rg = {}
function snowfall(pos, step) {
if (xy) {
pos = xy.xy[pos][1];
}
else {
pos = 99 - pos;
}
if (Math.abs(pos-step) < 5) {
var rg = 0;
if (snowfall_rg[pos]) {
rg = snowfall_rg[pos];
}
else {
rg = 127 + Math.random() * 128;
snowfall_rg[pos] = rg;
}
return rgb2Int(rg, rg, 255);
}
snowfall_rg[pos] = null;
return rgb2Int(0, 0, 0);
}
function twinklewhite(pos) {
return modulation[pos] * rgb2Int(255, 255, 255);
}
function twinklecolor(pos) {
return modulation[pos] * colorwheel((offset + pos)%256);
}
// rainbow-colors, taken from http://goo.gl/Cs3H0v
function colorwheel(pos) {
pos = 255 - pos;
if (pos < 85) { return rgb2Int(255 - pos * 3, 0, pos * 3); }
else if (pos < 170) { pos -= 85; return rgb2Int(0, pos * 3, 255 - pos * 3); }
else { pos -= 170; return rgb2Int(pos * 3, 255 - pos * 3, 0); }
}
function octoblu(pos) {
var segment = (pos % 50)/6.25;
if (segment < 7) {
return rgb2Int(0, 0, 255);
}
return rgb2Int(0, 255, 0);
}
function concentric(pos, step) {
if (step >= 5) step = 9 - step;
var ppos = Math.floor(pos/50);
if (ppos == step) return colorwheel((offset + pos) % 256);
return 0;
}
function xytest(pos) {
var phase = Math.floor(offset/200)%4;
switch (phase) {
case 0:
if (Math.abs((offset%200)/2 - xy.xy[pos][0]) < 5.0) {
return color;
} else {
return 0;
}
break;
case 1:
if (Math.abs((offset%200)/2 - xy.xy[pos][1]) < 5.0) {
return color;
} else {
return 0;
}
break;
case 2:
if (Math.abs(xy.xy[pos][0] + xy.xy[pos][1] - (offset%200)) < 10.0) {
return color;
} else {
return 0;
}
break;
case 3:
if (Math.abs(100 + xy.xy[pos][0] - xy.xy[pos][1] - (offset%200)) < 10.0) {
return color;
} else {
return 0;
}
break;
}
}
function rainbow(pos) {
var z = xy.xy[pos][0] + xy.xy[pos][1] - ((offset/3)%200);
if (z < 0) z += 200;
if (z < 28) {
return rbcolor[0];
}
if (z < 57) {
return rbcolor[1];
}
if (z < 86) {
return rbcolor[2];
}
if (z < 114) {
return rbcolor[3];
}
if (z < 143) {
return rbcolor[4];
}
if (z < 171) {
return rbcolor[5];
}
return rbcolor[6];
}
function dotmatrix_x(x) {
if (x < 30.0) return 0;
if (x < 43.0) return 1;
if (x < 57.0) return 2;
if (x < 70.0) return 3;
return 4;
}
function dotmatrix_y(y) {
if (y < 25.0) return 8;
if (y < 40.0) return 0;
if (y < 50.0) return 1;
if (y < 60.0) return 2;
if (y < 70.0) return 3;
if (y < 80.0) return 4;
if (y < 90.0) return 5;
return 6;
}
function dotmatrix(pos) {
//var xdot = dotmatrix_x(xy.xy[pos][0]);
var x = xy.xy[pos][0];
var ydot = dotmatrix_y(xy.xy[pos][1]);
//var column = dmarray[(offset/20 + xdot)%dmarray.length];
var idx = Math.floor(((offset + x)/10)%dmarray.length);
var column = dmarray[idx];
if ((1<<ydot)&column) {
return dmcolor[idx];
}
return 0;
}
function rgb2Int(r, g, b) {
return ((g & 0xff) << 16) + ((r & 0xff) << 8) + (b & 0xff);
}
function handle_message(newmode, newcolor) {
if (newmode == "solid") {
if (newcolor) {
var c = parseInt(newcolor);
if (isNaN(c)) {
var rgb = tinycolor(newcolor).toRgb();
c = rgb2Int(rgb.r, rgb.g, rgb.b);
}
color = c;
console.log("Setting colour " + c);
}
}
mode = newmode;
}
var client = mqtt.connect(config_mqtt.URL, config_mqtt.PROTOCOL);
client.on('connect', function () {
console.log("Connected to MQTT");
client.subscribe('IoTree/#');
});
client.on('message', function (topic, message) {
console.log("MQTT RX t=" + topic + " m=" + message.toString());
switch (topic) {
case "IoTree/mode":
handle_message(message.toString(), null);
break;
case "IoTree/color":
handle_message("solid", message.toString());
break;
case "IoTree/message":
dmmessage = message.toString();
renderMessage();
handle_message("dotmatrix", null);
break;
}
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment