mirror of
https://github.com/node-red/node-red-nodes.git
synced 2023-10-10 13:36:58 +02:00
Improvements to BlinkStick node
* Ability to select BlinkStick by serial number * Look up serial numbers of connected BlinkSticks * Ability to set blink, morph and pulse animations * Ability to control the parameters of those animations like duration, * steps, repeats and delay * Repeat blink and pulse animation until new payload is received * Automatically find BlinkStick if it was removed and then plugged back in * Connectivity status when "Node Status" is enabled in the menu * Override parameters with payload object * Improved text in the info pane
This commit is contained in:
parent
71a02ebbce
commit
61ac8fefae
2
hardware/blinkstick/.gitignore
vendored
Normal file
2
hardware/blinkstick/.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
.DS_Store
|
||||||
|
node_modules/
|
@ -1,5 +1,6 @@
|
|||||||
<!--
|
<!--
|
||||||
Copyright 2013 IBM Corp.
|
Copyright 2013-2014 Agile Innovative Ltd.
|
||||||
|
Based on code written by Dave Conway-Jones, IBM Corp.
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
@ -16,25 +17,115 @@
|
|||||||
|
|
||||||
<script type="text/x-red" data-template-name="blinkstick">
|
<script type="text/x-red" data-template-name="blinkstick">
|
||||||
<div class="form-row">
|
<div class="form-row">
|
||||||
|
<div class="form-row" id="node-input-row-payload">
|
||||||
|
<label for="node-input-serial">Serial</label>
|
||||||
|
<input type="text" id="node-input-serial" placeholder="defaults to first found" style="width:60%">
|
||||||
|
<a id="node-lookup-serial" class="btn"><i id="node-lookup-serial-icon" class="fa fa-search"></i></a>
|
||||||
|
</div>
|
||||||
|
<div class="form-row">
|
||||||
|
<label for="node-input-task"><i class="fa fa-empire"></i> Task</label>
|
||||||
|
<select id="node-input-task" style="width:125px !important">
|
||||||
|
<option value="set_color">Set Color</option>
|
||||||
|
<option value="blink">Blink</option>
|
||||||
|
<option value="morph">Morph</option>
|
||||||
|
<option value="pulse">Pulse</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="delay-details" class="form-row">
|
||||||
|
<label for="node-input-delay"><i class="fa fa-clock-o"></i> Delay</label>
|
||||||
|
<input type="text" id="node-input-delay" placeholder="Delay" style="direction:rtl; width:50px !important">
|
||||||
|
milliseconds
|
||||||
|
</div>
|
||||||
|
<div id="repeats-details" class="form-row">
|
||||||
|
<label for="node-input-repeats"><i class="fa fa-history"></i> Repeats</label>
|
||||||
|
<input type="text" id="node-input-repeats" placeholder="Times" style="direction:rtl; width:50px !important">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="duration-details" class="form-row">
|
||||||
|
<label for="node-input-duration"><i class="fa fa-clock-o"></i> Duration</label>
|
||||||
|
<input type="text" id="node-input-duration" placeholder="Duration" style="direction:rtl; width:50px !important">
|
||||||
|
milliseconds
|
||||||
|
</div>
|
||||||
|
<div id="steps-details" class="form-row">
|
||||||
|
<label for="node-input-steps"><i class="fa fa-history"></i> Steps</label>
|
||||||
|
<input type="text" id="node-input-steps" placeholder="Steps" style="direction:rtl; width:50px !important">
|
||||||
|
</div>
|
||||||
|
<div id="repeat-details" class="form-row">
|
||||||
|
<label> </label>
|
||||||
|
<input type="checkbox" id="node-input-repeat" style="display: inline-block; width: auto; vertical-align: top;">
|
||||||
|
<label for="node-input-repeat" style="width: 70%;">Repeat ∞ until next payload received?</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
<label for="node-input-name"><i class="fa fa-tag"></i> Name</label>
|
<label for="node-input-name"><i class="fa fa-tag"></i> Name</label>
|
||||||
<input type="text" id="node-input-name" placeholder="Name">
|
<input type="text" id="node-input-name" placeholder="Name">
|
||||||
</div>
|
</div>
|
||||||
<div class="form-tips">Expects a msg.payload with either hex #rrggbb or decimal red,green,blue.</div>
|
<div class="form-tips">Expects a msg.payload with either hex "#rrggbb" or decimal "red,green,blue" string.</div>
|
||||||
|
|
||||||
|
</script>
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<script type="text/x-red" data-help-name="blinkstick">
|
<script type="text/x-red" data-help-name="blinkstick">
|
||||||
<p>BlinkStick output node. Expects a <b>msg.payload</b> with either a hex string #rrggbb triple or red,green,blue as three 0-255 values.
|
<p><i><a href="http://www.blinkstick.com" target="_new">BlinkStick</a></i> output node. Expects a <b>msg.payload</b> with one of:</p>
|
||||||
It can also accept <i><a href="http://www.w3schools.com/html/html_colornames.asp" target="_new">standard HTML colour</a></i> names</p>
|
<ul>
|
||||||
<p><b>NOTE:</b> currently only works with a single BlinkStick. (As it uses the findFirst() function to attach).</p>
|
<li>A hex string <b>"#rrggbb"</b> triple</li>
|
||||||
<p>For more info see the <i><a href="http://blinkstick.com/" target="_new">BlinkStick website</a></i> or the <i><a href="https://github.com/arvydas/blinkstick-node" target="_new">node module</a></i> documentation.</p>
|
<li><b>"red,green,blue"</b> three 0-255 values as a string</li>
|
||||||
|
<li><b>"random"</b> will generate a random color</li>
|
||||||
|
<li><i><a href="http://www.w3schools.com/html/html_colornames.asp" target="_new">Standard HTML color</a></i> name</li>
|
||||||
|
<li><b>object</b> can override any of the parameters</li>
|
||||||
|
</ul>
|
||||||
|
<p>An object payload can override any of the settings on the node. Omitted parameters are left intact. For example:</p>
|
||||||
|
<pre>
|
||||||
|
{ 'color': 'blue' }
|
||||||
|
{ 'task': 'blink', 'color': 'red' }
|
||||||
|
{ 'task': 'pulse', 'color': 'gree', 'duration': 500 }
|
||||||
|
{ 'task': 'morph', 'color': 'orange', 'duration': 500, 'steps': 20 }
|
||||||
|
</pre>
|
||||||
|
<p>For more info see <i><a href="http://www.blinkstick.com/help/tutorials" target="_new">BlinkStick tutorials</a></i>
|
||||||
|
or the <i><a href="https://github.com/arvydas/blinkstick-node" target="_new">node module</a></i> documentation.</p>
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
|
function updateView(task) {
|
||||||
|
if (task == "set_color") {
|
||||||
|
$("#delay-details").hide();
|
||||||
|
$("#repeats-details").hide();
|
||||||
|
$("#duration-details").hide();
|
||||||
|
$("#steps-details").hide();
|
||||||
|
$("#repeat-details").hide();
|
||||||
|
} else if (task == "blink") {
|
||||||
|
$("#delay-details").show();
|
||||||
|
$("#repeats-details").show();
|
||||||
|
$("#duration-details").hide();
|
||||||
|
$("#steps-details").hide();
|
||||||
|
$("#repeat-details").show();
|
||||||
|
} else if (task == "morph") {
|
||||||
|
$("#delay-details").hide();
|
||||||
|
$("#repeats-details").hide();
|
||||||
|
$("#duration-details").show();
|
||||||
|
$("#steps-details").show();
|
||||||
|
$("#repeat-details").hide();
|
||||||
|
} else if (task == "pulse") {
|
||||||
|
$("#delay-details").hide();
|
||||||
|
$("#repeats-details").hide();
|
||||||
|
$("#duration-details").show();
|
||||||
|
$("#steps-details").show();
|
||||||
|
$("#repeat-details").show();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
RED.nodes.registerType('blinkstick',{
|
RED.nodes.registerType('blinkstick',{
|
||||||
category: 'output',
|
category: 'output',
|
||||||
color:"GoldenRod",
|
color:"GoldenRod",
|
||||||
defaults: {
|
defaults: { // defines the default editable properties of the node
|
||||||
name: {value:""}
|
name: {value:""}, // along with default values.
|
||||||
|
serial: {value:""},
|
||||||
|
task: {value:"set_color", validate:function(v) {return ((v === undefined)||v=="set_color"||v=="blink"||v=="morph"||v=="pulse"); }},
|
||||||
|
delay: {value:"500", validate:function(v) {return ((v === undefined)||(/^\d+$/).test(v)); }},
|
||||||
|
repeats: {value:"1", validate:function(v) {return ((v === undefined)||(/^\d+$/).test(v)); }},
|
||||||
|
duration: {value:"1000", validate:function(v) {return ((v === undefined)||(/^\d+$/).test(v)); }},
|
||||||
|
steps: {value:"50", validate:function(v) {return ((v === undefined)||(/^\d+$/).test(v)); }},
|
||||||
|
repeat: {value:false}
|
||||||
},
|
},
|
||||||
inputs:1,
|
inputs:1,
|
||||||
outputs:0,
|
outputs:0,
|
||||||
@ -45,6 +136,56 @@
|
|||||||
},
|
},
|
||||||
labelStyle: function() {
|
labelStyle: function() {
|
||||||
return this.name?"node_label_italic":"";
|
return this.name?"node_label_italic":"";
|
||||||
|
},
|
||||||
|
oneditprepare: function() {
|
||||||
|
if (!$("#node-input-task").val()) {
|
||||||
|
$("#node-input-task").val("set_color");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$("#node-input-delay").val()) {
|
||||||
|
$("#node-input-delay").val(500);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$("#node-input-repeats").val()) {
|
||||||
|
$("#node-input-repeats").val(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$("#node-input-duration").val()) {
|
||||||
|
$("#node-input-duration").val(1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$("#node-input-steps").val()) {
|
||||||
|
$("#node-input-steps").val(50);
|
||||||
|
}
|
||||||
|
|
||||||
|
$( "#node-input-repeats" ).spinner({min:1,max:100});
|
||||||
|
$( "#node-input-delay" ).spinner({min:10,max:5000});
|
||||||
|
$( "#node-input-duration" ).spinner({min:10,max:5000});
|
||||||
|
$( "#node-input-steps" ).spinner({min:10,max:255});
|
||||||
|
|
||||||
|
$("#node-input-task").on("change",function() {
|
||||||
|
updateView(this.value);
|
||||||
|
});
|
||||||
|
|
||||||
|
updateView(this.task);
|
||||||
|
|
||||||
|
$("#node-lookup-serial").click(function() {
|
||||||
|
$("#node-lookup-serial").addClass('disabled');
|
||||||
|
$.getJSON('blinksticklist',function(data) {
|
||||||
|
$("#node-lookup-serial").removeClass('disabled');
|
||||||
|
var sticks = [];
|
||||||
|
$.each(data, function(i, stick){
|
||||||
|
sticks.push(stick);
|
||||||
|
});
|
||||||
|
$("#node-input-serial").autocomplete({
|
||||||
|
source:sticks,
|
||||||
|
minLength:0,
|
||||||
|
close: function( event, ui ) {
|
||||||
|
$("#node-input-serial").autocomplete( "destroy" );
|
||||||
|
}
|
||||||
|
}).autocomplete("search","");
|
||||||
|
});
|
||||||
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
/**
|
/**
|
||||||
* Copyright 2013 IBM Corp.
|
* Copyright 2013-2014 Agile Innovative Ltd.
|
||||||
|
* Based on code written by Dave Conway-Jones, IBM Corp.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@ -18,45 +19,232 @@ module.exports = function(RED) {
|
|||||||
"use strict";
|
"use strict";
|
||||||
var blinkstick = require("blinkstick");
|
var blinkstick = require("blinkstick");
|
||||||
|
|
||||||
|
var availableTasks = ["set_color", "blink", "pulse", "morph"];
|
||||||
|
|
||||||
Object.size = function(obj) {
|
Object.size = function(obj) {
|
||||||
var size = 0;
|
var size = 0;
|
||||||
for (var key in obj) { if (obj.hasOwnProperty(key)) { size++; } }
|
for (var key in obj) { if (obj.hasOwnProperty(key)) { size++; } }
|
||||||
return size;
|
return size;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
//Helper function to convert decimal number to hex with padding
|
||||||
|
function decimalToHex(d, padding) {
|
||||||
|
var hex = Number(d).toString(16);
|
||||||
|
padding = typeof (padding) === "undefined" || padding === null ? padding = 2 : padding;
|
||||||
|
|
||||||
|
while (hex.length < padding) {
|
||||||
|
hex = "0" + hex;
|
||||||
|
}
|
||||||
|
|
||||||
|
return hex;
|
||||||
|
}
|
||||||
|
|
||||||
|
function validateInt(value, defaultValue) {
|
||||||
|
return typeof (value) === "undefined" || value === null ? value = defaultValue : parseInt(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
function validate(value, defaultValue) {
|
||||||
|
return typeof (value) === "undefined" || value === null ? value = defaultValue : value;
|
||||||
|
}
|
||||||
|
|
||||||
|
function validatePayloadObject (obj) {
|
||||||
|
var
|
||||||
|
task = validate(obj.task),
|
||||||
|
delay = validateInt(obj.delay),
|
||||||
|
repeats = validateInt(obj.repeats),
|
||||||
|
duration = validateInt(obj.duration),
|
||||||
|
steps = validateInt(obj.steps),
|
||||||
|
repeat = validate(obj.repeat),
|
||||||
|
color = validate(obj.color);
|
||||||
|
|
||||||
|
if (typeof(task) !== 'undefined' && availableTasks.indexOf(task) === -1) {
|
||||||
|
return "Task is invalid";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof(color) === 'undefined') {
|
||||||
|
return "Color parameter is not set";
|
||||||
|
}
|
||||||
|
|
||||||
|
return { 'task': task, 'delay': delay, 'repeats': repeats, 'duration': duration, 'steps': steps,
|
||||||
|
'repeat': repeat, 'color': color };
|
||||||
|
}
|
||||||
|
|
||||||
function BlinkStick(n) {
|
function BlinkStick(n) {
|
||||||
RED.nodes.createNode(this,n);
|
RED.nodes.createNode(this,n);
|
||||||
var p1 = /^\#[A-Fa-f0-9]{6}$/
|
|
||||||
var p2 = /[0-9]+,[0-9]+,[0-9]+/
|
|
||||||
this.led = blinkstick.findFirst(); // maybe try findAll() (one day)
|
|
||||||
var node = this;
|
|
||||||
|
|
||||||
this.on("input", function(msg) {
|
this.name = n.name;
|
||||||
if (Object.size(node.led) !== 0) {
|
this.serial = n.serial;
|
||||||
try {
|
this.task = n.task || "set_color";
|
||||||
if (p2.test(msg.payload)) {
|
this.delay = n.delay || 500;
|
||||||
var rgb = msg.payload.split(",");
|
this.repeats = n.repeats || 1;
|
||||||
node.led.setColor(parseInt(rgb[0])&255, parseInt(rgb[1])&255, parseInt(rgb[2])&255);
|
this.duration = n.duration || 1000;
|
||||||
}
|
this.steps = n.steps || 50;
|
||||||
else {
|
this.repeat = n.repeat;
|
||||||
node.led.setColor(msg.payload.toLowerCase().replace(/\s+/g,''));
|
this.closing = false;
|
||||||
}
|
this.color = '';
|
||||||
}
|
this.previousColor = '';
|
||||||
catch (err) {
|
|
||||||
node.warn("BlinkStick missing ?");
|
var p1 = /[0-9]+,[0-9]+,[0-9]+/;
|
||||||
node.led = blinkstick.findFirst();
|
var node = this;
|
||||||
}
|
//Keeps track for active animations
|
||||||
}
|
var animationComplete = true;
|
||||||
else {
|
|
||||||
//node.warn("No BlinkStick found");
|
//Find BlinkStick based on serial number if supplied, otherwise look for first
|
||||||
node.led = blinkstick.findFirst();
|
//Blinkstick in the USB device list
|
||||||
|
var findBlinkStick = function (callback) {
|
||||||
|
if (typeof(node.serial) == 'string' && node.serial.replace(/\s+/g,'') !== '') {
|
||||||
|
blinkstick.findBySerial(node.serial, function (device) {
|
||||||
|
node.led = device;
|
||||||
|
|
||||||
|
if (Object.size(node.led) === 0) {
|
||||||
|
node.status({fill:"red",shape:"ring",text:"disconnected"});
|
||||||
|
node.error("BlinkStick with serial number " + node.serial + " not found");
|
||||||
|
} else {
|
||||||
|
node.status({fill:"green",shape:"dot",text:"connected"});
|
||||||
|
if (callback) callback();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
} else {
|
||||||
|
node.led = blinkstick.findFirst();
|
||||||
|
|
||||||
if (Object.size(node.led) === 0) {
|
if (Object.size(node.led) === 0) {
|
||||||
|
node.status({fill:"red",shape:"ring",text:"disconnected"});
|
||||||
node.error("No BlinkStick found");
|
node.error("No BlinkStick found");
|
||||||
|
} else {
|
||||||
|
node.status({fill:"green",shape:"dot",text:"connected"});
|
||||||
|
if (callback) callback();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
//Check if repeat is enabled. Works only for pulse and blink tasks
|
||||||
|
var canRepeat = function () {
|
||||||
|
return node.task == "pulse" || node.task == "blink";
|
||||||
|
};
|
||||||
|
|
||||||
|
//Event handler for all animation complete events
|
||||||
|
var blinkstickAnimationComplete = function (err) {
|
||||||
|
if (typeof(err) !== 'undefined') {
|
||||||
|
node.warn(err);
|
||||||
|
|
||||||
|
if (typeof(err.name) === 'undefined' || err.name !== 'ReferenceError') {
|
||||||
|
//USB error occurred when BlinkStick was animating
|
||||||
|
node.led.close(function (err) {
|
||||||
|
node.led = undefined;
|
||||||
|
findBlinkStick();
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
animationComplete = true;
|
||||||
|
|
||||||
|
//Apply queued color animation
|
||||||
|
if (!node.closing && node.color !== '') {
|
||||||
|
//Apply new color only if there was no error or queued color is different from the previous color
|
||||||
|
if (typeof(err) === 'undefined' || typeof(err) !== 'undefined' && node.color != node.previousColor) {
|
||||||
|
applyColor();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
var applyColor = function () {
|
||||||
|
animationComplete = false;
|
||||||
|
|
||||||
|
//Store the value of color to check if it has changed
|
||||||
|
node.previousColor = node.color;
|
||||||
|
|
||||||
|
try {
|
||||||
|
//Select animation to perform
|
||||||
|
if (node.task == "pulse") {
|
||||||
|
node.led.pulse(node.color, {'duration': node.duration, 'steps': node.steps }, blinkstickAnimationComplete);
|
||||||
|
} else if (node.task == "morph") {
|
||||||
|
node.led.morph(node.color, {'duration': node.duration, 'steps': node.steps }, blinkstickAnimationComplete);
|
||||||
|
} else if (node.task == "blink") {
|
||||||
|
node.led.blink(node.color,{'repeats': node.repeats, 'delay': node.delay }, blinkstickAnimationComplete);
|
||||||
|
} else {
|
||||||
|
node.led.setColor(node.color, blinkstickAnimationComplete);
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
node.warn("BlinkStick missing ? " + err);
|
||||||
|
//Reset animation
|
||||||
|
animationComplete = true;
|
||||||
|
//Clear color
|
||||||
|
node.color = '';
|
||||||
|
//Look for a BlinkStick
|
||||||
|
findBlinkStick();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Clear color value until next one is received, unless repeat option is set to true
|
||||||
|
if (!node.repeat || !canRepeat()) {
|
||||||
|
node.color = '';
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
findBlinkStick();
|
||||||
|
|
||||||
|
this.on("input", function(msg) {
|
||||||
|
if (typeof(msg.payload) === 'object' ) {
|
||||||
|
var data = validatePayloadObject(msg.payload);
|
||||||
|
|
||||||
|
if (typeof(data) === 'object') {
|
||||||
|
node.task = data.task ? data.task : node.task;
|
||||||
|
node.delay = data.delay ? data.delay : node.delay;
|
||||||
|
node.repeats = data.repeats ? data.repeats : node.repeats;
|
||||||
|
node.duration = data.duration ? data.duration : node.duration;
|
||||||
|
node.steps = data.steps ? data.steps : node.steps;
|
||||||
|
node.repeat = data.repeat ? data.repeat : node.repeat;
|
||||||
|
node.color = data.color ? data.color : node.color;
|
||||||
|
} else {
|
||||||
|
node.error(data);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
} else if (p1.test(msg.payload)) {
|
||||||
|
//Color value is represented as "red,green,blue" string of bytes
|
||||||
|
var rgb = msg.payload.split(",");
|
||||||
|
|
||||||
|
//Convert color value back to HEX string for easier implementation
|
||||||
|
node.color = "#" + decimalToHex(parseInt(rgb[0])&255) +
|
||||||
|
decimalToHex(parseInt(rgb[1])&255) + decimalToHex(parseInt(rgb[2])&255);
|
||||||
|
} else {
|
||||||
|
//Sanitize color value
|
||||||
|
node.color = msg.payload.toLowerCase().replace(/\s+/g,'');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Object.size(node.led) !== 0) {
|
||||||
|
//Start color animation, otherwise the color is queued until current animation completes
|
||||||
|
if (animationComplete) {
|
||||||
|
applyColor();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
//Attempt to find BlinkStick and start animation if it's found
|
||||||
|
findBlinkStick(function() {
|
||||||
|
if (animationComplete) {
|
||||||
|
applyColor();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
this.on("close", function() {
|
||||||
|
//Set the flag to finish all animations
|
||||||
|
this.closing = true;
|
||||||
|
|
||||||
|
if (Object.size(node.led) !== 0) {
|
||||||
|
//Close device and stop animations
|
||||||
|
this.led.close();
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
RED.nodes.registerType("blinkstick",BlinkStick);
|
RED.nodes.registerType("blinkstick",BlinkStick);
|
||||||
}
|
|
||||||
|
RED.httpAdmin.get("/blinksticklist",function(req,res) {
|
||||||
|
blinkstick.findAllSerials(function(serials) {
|
||||||
|
res.writeHead(200, {'Content-Type': 'application/json'});
|
||||||
|
res.write(JSON.stringify(serials));
|
||||||
|
res.end();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
@ -1,11 +1,12 @@
|
|||||||
node-red-node-blinkstick
|
node-red-node-blinkstick
|
||||||
========================
|
========================
|
||||||
A <a href="http://nodered.org" target="_new">Node-RED</a> node to control a <a href="http://blinkstick.com/" target="_new">Blinkstick</a>.
|
|
||||||
|
A <a href="http://nodered.org" target="_new">Node-RED</a> node to control a <a href="http://www.blinkstick.com/" target="_new">BlinkStick</a>.
|
||||||
|
|
||||||
Install
|
Install
|
||||||
-------
|
-------
|
||||||
|
|
||||||
Run the following command in the root directory of your Node-RED install
|
Run the following command in the root directory of your Node-RED install:
|
||||||
|
|
||||||
npm install node-red-node-blinkstick
|
npm install node-red-node-blinkstick
|
||||||
|
|
||||||
@ -13,11 +14,19 @@ Run the following command in the root directory of your Node-RED install
|
|||||||
Usage
|
Usage
|
||||||
-----
|
-----
|
||||||
|
|
||||||
The BlinkStick output node expects a <b>msg.payload</b> with either a hex string #rrggbb triple or red,green,blue as three 0-255 values.
|
<i><a href="http://www.blinkstick.com" target="_new">BlinkStick</a></i> output node. Expects a <b>msg.payload</b> with one of:
|
||||||
|
|
||||||
|
* A hex string <b>"#rrggbb"</b> triple
|
||||||
|
* <b>"red,green,blue"</b> three 0-255 values as a string
|
||||||
|
* <b>"random"</b> will generate a random color
|
||||||
|
* <i><a href="http://www.w3schools.com/html/html_colornames.asp" target="_new">Standard HTML color</a></i> name
|
||||||
|
* <b>object</b> can override any of the parameters
|
||||||
|
|
||||||
It can also accept <i><a href="http://www.w3schools.com/html/html_colornames.asp" target="_new">standard HTML colour</a></i> names.
|
An object payload can override any of the settings on the node. Omitted parameters are left intact. For example:
|
||||||
|
|
||||||
<b>NOTE:</b> currently only works with a single BlinkStick. (As it uses the findFirst() function to attach).
|
{ 'color': 'blue' }
|
||||||
|
{ 'task': 'blink', 'color': 'red' }
|
||||||
|
{ 'task': 'pulse', 'color': 'gree', 'duration': 500 }
|
||||||
|
{ 'task': 'morph', 'color': 'orange', 'duration': 500, 'steps': 20 }
|
||||||
|
|
||||||
For more info see the <i><a href="http://blinkstick.com/" target="_new">BlinkStick website</a></i> or the <i><a href="https://github.com/arvydas/blinkstick-node" target="_new">blinkstick npm</a></i> documentation.
|
For more information see <i><a href="http://www.blinkstick.com/help/tutorials" target="_new">BlinkStick tutorials</a></i> or the <i><a href="https://github.com/arvydas/blinkstick-node" target="_new">node module</a></i> documentation.
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
{
|
{
|
||||||
"name" : "node-red-node-blinkstick",
|
"name" : "node-red-node-blinkstick",
|
||||||
"version" : "0.0.3",
|
"version" : "0.1.0",
|
||||||
"description" : "A Node-RED node to control a Blinkstick",
|
"description" : "A Node-RED node to control a Blinkstick",
|
||||||
"dependencies" : {
|
"dependencies" : {
|
||||||
"blinkstick" : "0.1.*"
|
"blinkstick" : "1.1.*"
|
||||||
},
|
},
|
||||||
"repository" : {
|
"repository" : {
|
||||||
"type":"git",
|
"type":"git",
|
||||||
@ -17,8 +17,15 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"author": {
|
"author": {
|
||||||
|
"name": "Arvydas Juskevicius",
|
||||||
|
"email": "arvydas@agileinnovative.co.uk",
|
||||||
|
"url": "http://www.blinkstick.com"
|
||||||
|
},
|
||||||
|
"contributors": [
|
||||||
|
{
|
||||||
"name": "Dave Conway-Jones",
|
"name": "Dave Conway-Jones",
|
||||||
"email": "ceejay@vnet.ibm.com",
|
"email": "ceejay@vnet.ibm.com",
|
||||||
"url": "http://nodered.org"
|
"url": "http://nodered.org"
|
||||||
}
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user