node-blink1-server
Version:
HTTP REST API server in Node for blink(1) devices
310 lines (279 loc) • 9.59 kB
JavaScript
/**
* node-blink1-server
*
*
* @author Tod E. Kurt, http://todbot.com/blog
*
*/
;
var debug = require('debug')('http');
var Blink1 = require('node-blink1');
var parsecolor = require('parse-color');
var express = require('express');
var app = express();
app.set('json spaces', 4);
var port = 8080; // default, can be set as an argument
var devices = Blink1.devices(); // returns array of serial numbers
var blink1 = null;
if( devices.length ) {
blink1 = new Blink1(); // gets first device found
}
var lastColor = '#000000';
var lastTime = 0;
var lastLedn = 0;
var lastRepeats = 0;
// rescan if we know we have no blink1
var blink1TryConnect = function() {
if( blink1 ) { return false; }
devices = Blink1.devices();
if( devices.length ) {
blink1 = new Blink1();
}
return true;
};
// Call blink1.setRGB while dealing with disconnect / reconnect of blink1
var blink1Set = function( r, g, b ){
blink1TryConnect();
if( !blink1 ) { return "no blink1"; }
try {
blink1.setRGB( r, g, b );
} catch(err) {
blink1 = null;
return ""+err;
}
return "success";
};
// Call blink1.fadeToRGB while dealing with disconnect / reconnect of blink1
var blink1Fade = function( millis, r, g, b, ledn ){
blink1TryConnect();
if( !blink1 ) { return "no blink1"; }
try {
blink1.fadeToRGB( millis, r, g, b, ledn );
} catch(err) {
blink1 = null;
return ""+err;
}
return "success";
};
var blink1Blink = function( onoff, repeats, millis, r, g, b, ledn ) {
// console.log("blink1Blink:", onoff, repeats, millis, r, g, b, ledn );
if( onoff ) {
blink1Fade( millis/2, r, g, b, ledn );
} else {
blink1Fade( millis/2, 0, 0, 0, ledn );
repeats--;
}
onoff = !onoff;
if( repeats ) {
setTimeout( function() {
blink1Blink(onoff, repeats, millis, r, g, b, ledn);
}, millis );
}
};
var blink1Pattern = function(time, rgb, position) {
blink1.writePatternLine(time * 1000, rgb[0], rgb[1], rgb[2], position);
};
// parse the standard args into a data struct
var parseQueryArgs = function(query) {
var args = {};
args.color = parsecolor(query.rgb);
args.time = Number(query.time) || 0.1;
args.ledn = Number(query.ledn) || 0;
args.repeats = Number(query.repeats) || 3;
args.blink1_id = query.blink1_id;
return args;
};
app.get('/blink1', function(req, res) {
blink1TryConnect();
var response = {
blink1Connected: blink1 !== null,
blink1Serials: devices,
currentColor: '#000000',
lastColor: lastColor,
lastTime: lastTime,
lastLedn: lastLedn,
lastRepeats: lastRepeats,
cmd: "info",
status: "success"
};
if( blink1 == null ) { // in case no blink1 plugged in
res.json(response);
return;
}
try {
blink1.rgb(function(r, g, b) {
var color = parsecolor("rgb("+r+","+g+","+b+")");
response.blink1Connected = true;
response.currentColor = color.hex;
res.json( response );
});
} catch(err) {
blink1 = null;
res.json( response );
}
});
app.get('/blink1/:type(fadeToRGB|on|off|red|green|blue|yellow|cyan|magenta)', function(req, res) {
if( req.params.type == 'on' ) { req.query.rgb = '#FFFFFF'; }
else if( req.params.type == 'off' ) { req.query.rgb = '#000000'; }
else if( req.params.type == 'red' ) { req.query.rgb = '#FF0000'; }
else if( req.params.type == 'green' ) { req.query.rgb = '#00FF00'; }
else if( req.params.type == 'blue' ) { req.query.rgb = '#0000FF'; }
else if( req.params.type == 'yellow' ) { req.query.rgb = '#FFFF00'; }
else if( req.params.type == 'cyan' ) { req.query.rgb = '#00FFFF'; }
else if( req.params.type == 'magenta') { req.query.rgb = '#FF00FF'; }
var args = parseQueryArgs(req.query);
var status = req.params.type;
if( typeof(args.color.rgb) != 'undefined' ) {
lastColor = args.color.hex;
lastTime = args.time;
lastLedn = args.ledn;
var rgb = args.color.rgb;
status = blink1Fade( args.time*1000, rgb[0], rgb[1], rgb[2], args.ledn );
}
else {
status = "bad hex color specified '" + req.query.rgb + "'";
}
var response = {
blink1Connected: blink1 !== null,
blink1Serials: devices,
currentColor: lastColor,
lastColor: lastColor,
lastTime: lastTime,
lastLedn: lastLedn,
lastRepeats: lastRepeats,
cmd: "fadeToRGB",
status: status
};
res.json( response );
});
app.get('/blink1/setRGB', function(req, res) {
var color = parsecolor(req.query.rgb);
var time = Number(req.query.time) || 0.1;
var ledn = Number(req.query.ledn) || 0;
var status = "success";
var rgb = color.rgb;
if( rgb ) {
lastColor = color.hex;
lastTime = time;
lastLedn = ledn;
status = blink1Set( rgb[0], rgb[1], rgb[2] );
}
else {
status = "bad hex color specified " + req.query.rgb;
}
var response = {
blink1Connected: blink1 !== null,
blink1Serials: devices,
currentColor: lastColor,
lastColor: lastColor,
lastTime: lastTime,
lastLedn: lastLedn,
lastRepeats: lastRepeats,
cmd: "setRGB",
status: status
};
res.json( response );
});
app.get('/blink1/blink', function(req, res) {
var color = parsecolor(req.query.rgb);
var time = Number(req.query.time) || 0.1;
var ledn = Number(req.query.ledn) || 0;
var repeats = Number(req.query.repeats) || Number(req.query.count) || 3;
var status = "success";
var rgb = color.rgb;
if( rgb ) {
lastColor = color.hex;
lastTime = time;
lastLedn = ledn;
lastRepeats = repeats;
blink1Blink( true, repeats, time*1000, rgb[0], rgb[1], rgb[2], ledn );
}
else {
status = "bad hex color specified " + req.query.rgb;
}
var response = {
blink1Connected: blink1 !== null,
blink1Serials: devices,
currentColor: lastColor,
lastColor: lastColor,
lastTime: lastTime,
lastLedn: lastLedn,
lastRepeats: lastRepeats,
cmd: "blink1",
status: status
};
res.json( response );
});
app.get('/blink1/pattern', function(req, res) {
var colors = req.query.rgb.split(',');
var time = Number(req.query.time) || 0.1;
// var repeats = Number(req.query.repeats) || Number(req.query.count) || 3;
var repeats = parseInt( req.query.repeats || req.query.count );
repeats = (repeats == NaN ) ? 3 : repeats;
var status = "success";
blink1TryConnect();
if( blink1 ) {
for (var i=0, len=colors.length; i < len; i++) {
var rgb = parsecolor(colors[i]).rgb;
blink1Pattern(time, rgb, i);
}
blink1.playLoop(0, colors.length, repeats);
if (colors.length > 16) {
status = "can only display first 16 colors. " + colors.length + " colors specified"
}
}
else {
status = "no blink1 connected";
}
var response = {
blink1Connected: blink1 !== null,
blink1Serials: devices,
time: time,
colors: colors,
repeats: repeats,
cmd: "pattern",
status: status
};
res.json( response );
});
// respond with "Hello World!" on the homepage
app.get('/', function(req, res) {
res.send("<html>" +
"<h2> Welcome to blink1-server</h2> \n" +
"<p>" +
"Supported URIs: <ul>\n" +
"<li> <code> /blink1 </code> " +
" -- status info\n" +
"<li> <code> /blink1/on </code> -- #FFFFFF full white" +
"<li> <code> /blink1/off </code> -- #000000 full dark" +
"<li> <code> /blink1/red </code> -- #FF0000 red " +
"<li> <code> /blink1/green </code> -- #00FF00 green " +
"<li> <code> /blink1/blue </code> -- #0000FF blue " +
"<li> <code> /blink1/yellow </code> -- #FFFF00 yellow " +
"<li> <code> /blink1/cyan </code> -- #00FF00 cyan " +
"<li> <code> /blink1/magenta </code> -- #FF00FF magenta " +
"<li> <code> /blink1/fadeToRGB?rgb=%23FF00FF&time=1.5&ledn=2 </code> " +
"-- fade to a RGB color over time for led\n" +
"<li> <code> /blink1/setRGB?rgb=%23FF00FF&ledn=2 </code> " +
"-- set a RGB color immediately for led\n" +
"<li> <code> /blink1/blink?rgb=%23FF00FF&time=0.5&repeats=5 </code> " +
"-- blink an RGB color over time for number of repeats\n" +
"<li> <code> /blink1/pattern?rgb=%23ff0000,%23ffffff,%230000ff&time=.2&repeats=8 </code> " +
"-- blink a sequence of colors\n" +
"</ul></p>\n" +
"When starting server, argument specified is port to run on, e.g.:" +
"<code> blink1-server 8080 </code>\n" +
"</html>");
});
// if we have args
if( process.argv.length > 2 ) {
var p = Number(process.argv[2]);
port = (p) ? p : port;
}
var server = app.listen(port, function() {
var host = server.address().address;
var port = server.address().port;
host = (host === '::' ) ? "localhost" : host;
console.log('blink1-server listening at http://%s:%s/', host, port);
});