Merge remote-tracking branch 'upstream/master'

This commit is contained in:
Ben Hardill
2013-11-24 13:10:26 +00:00
50 changed files with 2677 additions and 296 deletions

View File

@@ -52,10 +52,10 @@
</script>
<script type="text/x-red" data-help-name="rpi-piface in">
<p>Raspberry Pi PiFace input node. Generates a <b>msg.payload</b> with either a 0 or 1 depending on the state of the input pin. Requires the gpio command to work.</p>
<p>You may also enable the input pullup resitor if required.</p>
<p>The <b>msg.topic</b> is set to <i>pi/{the pin number}</i></p>
<p><b>Note:</b> This node currently polls the pin every 250mS. This is not ideal as it loads the cpu, and will be rewritten shortly to try to use interrupts.</p>
<p>Raspberry Pi PiFace input node. Generates a <b>msg.payload</b> with either a 0 or 1 depending on the state of the input pin. Requires the gpio command to work.</p>
<p>You may also enable the input pullup resitor if required.</p>
<p>The <b>msg.topic</b> is set to <i>pi/{the pin number}</i></p>
<p><b>Note:</b> This node currently polls the pin every 250mS. This is not ideal as it loads the cpu, and will be rewritten shortly to try to use interrupts.</p>
</script>
<script type="text/javascript">
@@ -103,9 +103,9 @@
</script>
<script type="text/x-red" data-help-name="rpi-piface out">
<p>Raspberry Pi PiFace output node. The PiFace board must be fitted. Requires the gpio command to work.</p>
<p>Expects a <b>msg.payload</b> with either a 0 or 1 (or true or false).</p>
<p>Will set the selected relay, LED, or pin on or off depending on the value passed in.</p>
<p>Raspberry Pi PiFace output node. The PiFace board must be fitted. Requires the gpio command to work.</p>
<p>Expects a <b>msg.payload</b> with either a 0 or 1 (or true or false).</p>
<p>Will set the selected relay, LED, or pin on or off depending on the value passed in.</p>
</script>
<script type="text/javascript">

View File

@@ -14,121 +14,121 @@
* limitations under the License.
**/
var RED = require("../../red/red");
var RED = require(process.env.NODE_RED_HOME+"/red/red");
var util = require("util");
var exec = require('child_process').exec;
var fs = require('fs');
if (!fs.existsSync("/usr/local/bin/gpio")) {
exec("cat /proc/cpuinfo | grep BCM27",function(err,stdout,stderr) {
if (stdout.indexOf('BCM27') > -1) {
util.log('[37-rpi-piface.js] Error: Cannot find Wiring-Pi "gpio" command');
}
// else not on a Pi so don't worry anyone with needless messages.
});
return;
exec("cat /proc/cpuinfo | grep BCM27",function(err,stdout,stderr) {
if (stdout.indexOf('BCM27') > -1) {
util.log('[37-rpi-piface.js] Error: Cannot find Wiring-Pi "gpio" command');
}
// else not on a Pi so don't worry anyone with needless messages.
});
return;
}
// Map names of pins to Gordon's gpio PiFace pin numbers
var pintable = {
// Physical : WiringPi
"Button S1":"200",
"Button S2":"201",
"Button S3":"202",
"Button S4":"203",
"Input 5":"204",
"Input 6":"205",
"Input 7":"206",
"Input 8":"207",
"Output0":"208",
"Output1":"209",
"Output2":"210",
"Output3":"211",
"Output4":"212",
"Output5":"213",
"Output6":"214",
"Output7":"215",
"LED 0 / Relay 0":"200",
"LED 1 / Relay 1":"201",
"LED 2":"202",
"LED 3":"203",
"LED 4":"204",
"LED 5":"205",
"LED 6":"206",
"LED 7":"207"
"Button S1":"200",
"Button S2":"201",
"Button S3":"202",
"Button S4":"203",
"Input 5":"204",
"Input 6":"205",
"Input 7":"206",
"Input 8":"207",
"Output0":"208",
"Output1":"209",
"Output2":"210",
"Output3":"211",
"Output4":"212",
"Output5":"213",
"Output6":"214",
"Output7":"215",
"LED 0 / Relay 0":"200",
"LED 1 / Relay 1":"201",
"LED 2":"202",
"LED 3":"203",
"LED 4":"204",
"LED 5":"205",
"LED 6":"206",
"LED 7":"207"
}
function PiFACEInNode(n) {
RED.nodes.createNode(this,n);
this.buttonState = -1;
this.pin = pintable[n.pin];
this.intype = n.intype;
var node = this;
if (node.pin) {
exec("gpio -p mode "+node.pin+" "+node.intype, function(err,stdout,stderr) {
if (err) node.error(err);
else {
node._interval = setInterval( function() {
exec("gpio -p read "+node.pin, function(err,stdout,stderr) {
if (err) node.error(err);
else {
if (node.buttonState !== Number(stdout)) {
var previousState = node.buttonState;
node.buttonState = Number(stdout);
if (previousState !== -1) {
var msg = {topic:"pi/"+node.pin, payload:node.buttonState};
node.send(msg);
}
}
}
});
}, 250);
}
});
}
else {
node.error("Invalid PiFACE pin: "+node.pin);
}
RED.nodes.createNode(this,n);
this.buttonState = -1;
this.pin = pintable[n.pin];
this.intype = n.intype;
var node = this;
if (node.pin) {
exec("gpio -p mode "+node.pin+" "+node.intype, function(err,stdout,stderr) {
if (err) node.error(err);
else {
node._interval = setInterval( function() {
exec("gpio -p read "+node.pin, function(err,stdout,stderr) {
if (err) node.error(err);
else {
if (node.buttonState !== Number(stdout)) {
var previousState = node.buttonState;
node.buttonState = Number(stdout);
if (previousState !== -1) {
var msg = {topic:"pi/"+node.pin, payload:node.buttonState};
node.send(msg);
}
}
}
});
}, 250);
}
});
}
else {
node.error("Invalid PiFACE pin: "+node.pin);
}
}
function PiFACEOutNode(n) {
RED.nodes.createNode(this,n);
this.pin = pintable[n.pin];
var node = this;
if (node.pin) {
node.on("input", function(msg) {
if (msg.payload === "true") msg.payload = true;
if (msg.payload === "false") msg.payload = false;
var out = Number(msg.payload);
if ((out == 0)|(out == 1)) {
exec("gpio -p write "+node.pin+" "+out, function(err,stdout,stderr) {
if (err) node.error(err);
});
}
else node.warn("Invalid input - not 0 or 1");
});
}
else {
node.error("Invalid PiFACE pin: "+node.pin);
}
RED.nodes.createNode(this,n);
this.pin = pintable[n.pin];
var node = this;
if (node.pin) {
node.on("input", function(msg) {
if (msg.payload === "true") msg.payload = true;
if (msg.payload === "false") msg.payload = false;
var out = Number(msg.payload);
if ((out == 0)|(out == 1)) {
exec("gpio -p write "+node.pin+" "+out, function(err,stdout,stderr) {
if (err) node.error(err);
});
}
else node.warn("Invalid input - not 0 or 1");
});
}
else {
node.error("Invalid PiFACE pin: "+node.pin);
}
}
exec("gpio load spi",function(err,stdout,stderr) {
if (err) {
util.log('[37-rpi-piface.js] Error: "gpio load spi" command failed for some reason.');
}
exec("gpio -p reset",function(err,stdout,stderr) {
if (err) {
util.log('[37-rpi-piface.js] Error: "gpio -p reset" command failed for some reason.');
}
RED.nodes.registerType("rpi-piface in",PiFACEInNode);
RED.nodes.registerType("rpi-piface out",PiFACEOutNode);
PiFACEInNode.prototype.close = function() {
clearInterval(this._interval);
}
PiFACEOutNode.prototype.close = function() {
}
});
if (err) {
util.log('[37-rpi-piface.js] Error: "gpio load spi" command failed for some reason.');
}
exec("gpio -p reset",function(err,stdout,stderr) {
if (err) {
util.log('[37-rpi-piface.js] Error: "gpio -p reset" command failed for some reason.');
}
RED.nodes.registerType("rpi-piface in",PiFACEInNode);
RED.nodes.registerType("rpi-piface out",PiFACEOutNode);
PiFACEInNode.prototype.close = function() {
clearInterval(this._interval);
}
PiFACEOutNode.prototype.close = function() {
}
});
});

View File

@@ -23,10 +23,10 @@
</script>
<script type="text/x-red" data-help-name="ledborg">
<p>PiBorg LedBorg LED output node. Expects a <b>msg.payload</b> with a three digit rgb triple, from <b>000</b> to <b>222</b>.</p>
<p>See <i><a href="http://www.piborg.com/ledborg/install" target="_new">the PiBorg site</a></i> for more information.</p>
<p>You can also now use a <b>msg.payload</b> in the standard hex format "#rrggbb". The clip levels are :</p>
<p><pre>0x00 - 0x57 = off<br/>0x58 - 0xA7 = 50%<br/>0xA8 - 0xFF = fully on</pre></p>
<p>PiBorg LedBorg LED output node. Expects a <b>msg.payload</b> with a three digit rgb triple, from <b>000</b> to <b>222</b>.</p>
<p>See <i><a href="http://www.piborg.com/ledborg/install" target="_new">the PiBorg site</a></i> for more information.</p>
<p>You can also now use a <b>msg.payload</b> in the standard hex format "#rrggbb". The clip levels are :</p>
<p><pre>0x00 - 0x57 = off<br/>0x58 - 0xA7 = 50%<br/>0xA8 - 0xFF = fully on</pre></p>
</script>
<script type="text/javascript">

View File

@@ -14,40 +14,39 @@
* limitations under the License.
**/
var RED = require("../../red/red");
var RED = require(process.env.NODE_RED_HOME+"/red/red");
var util = require('util');
var fs = require('fs');
// check if /dev/ledborg exists - if not then don't even show the node.
if (!fs.existsSync("/dev/ledborg")) {
util.log("[78-ledborg.js] Error: PiBorg hardware : LedBorg not found");
return;
util.log("[78-ledborg.js] Warning: PiBorg hardware : LedBorg not found");
return;
}
function LedBorgNode(n) {
RED.nodes.createNode(this,n);
var p1 = /[0-2][0-2][0-2]/
var p2 = /^\#[A-Fa-f0-9]{6}$/
var node = this;
RED.nodes.createNode(this,n);
var p1 = /[0-2][0-2][0-2]/
var p2 = /^\#[A-Fa-f0-9]{6}$/
var node = this;
this.on("input", function(msg) {
if (p1.test(msg.payload)) {
fs.writeFile('/dev/ledborg', msg.payload, function (err) {
if (err) node.warn(msg.payload+" : No LedBorg found");
});
}
if (p2.test(msg.payload)) {
var r = Math.floor(parseInt(msg.payload.slice(1,3),16)/88).toString();
var g = Math.floor(parseInt(msg.payload.slice(3,5),16)/88).toString();
var b = Math.floor(parseInt(msg.payload.slice(5),16)/88).toString();
fs.writeFile('/dev/ledborg', r+g+b, function (err) {
if (err) node.warn(r+g+b+" : No LedBorg found");
});
}
else {
node.warn("Invalid LedBorg colour code");
}
});
this.on("input", function(msg) {
if (p1.test(msg.payload)) {
fs.writeFile('/dev/ledborg', msg.payload, function (err) {
if (err) node.warn(msg.payload+" : No LedBorg found");
});
}
if (p2.test(msg.payload)) {
var r = Math.floor(parseInt(msg.payload.slice(1,3),16)/88).toString();
var g = Math.floor(parseInt(msg.payload.slice(3,5),16)/88).toString();
var b = Math.floor(parseInt(msg.payload.slice(5),16)/88).toString();
fs.writeFile('/dev/ledborg', r+g+b, function (err) {
if (err) node.warn(r+g+b+" : No LedBorg found");
});
}
else {
node.warn("Invalid LedBorg colour code");
}
});
}
RED.nodes.registerType("ledborg",LedBorgNode);

View File

@@ -0,0 +1,50 @@
<!--
Copyright 2013 IBM Corp.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<script type="text/x-red" data-template-name="blinkstick">
<div class="form-row">
<label for="node-input-name"><i class="icon-tag"></i> Name</label>
<input type="text" id="node-input-name" placeholder="Name">
</div>
<div class="form-tips">Expects a msg.payload with either hex #rrggbb or decimal red,green,blue.</div>
</script>
<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.
It can also accept <i><a href="http://www.w3schools.com/html/html_colornames.asp" target="_new">standard HTML colour</a></i> names</p>
<p><b>NOTE:</b> currently only works with a single BlinkStick. (As it uses the findFirst() function to attach).</p>
<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>
</script>
<script type="text/javascript">
RED.nodes.registerType('blinkstick',{
category: 'output',
color:"GoldenRod",
defaults: {
name: {value:""}
},
inputs:1,
outputs:0,
icon: "light.png",
align: "right",
label: function() {
return this.name||"blinkstick";
},
labelStyle: function() {
return this.name?"node_label_italic":"";
}
});
</script>

View File

@@ -0,0 +1,62 @@
/**
* Copyright 2013 IBM Corp.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
**/
var RED = require(process.env.NODE_RED_HOME+"/red/red");
var blinkstick = require("blinkstick");
Object.size = function(obj) {
var size = 0, key;
for (key in obj) { if (obj.hasOwnProperty(key)) size++; }
return size;
};
function BlinkStick(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) {
if (msg != null) {
if (Object.size(node.led) !== 0) {
try {
if (p2.test(msg.payload)) {
var rgb = msg.payload.split(",");
node.led.setColor(parseInt(rgb[0])&255, parseInt(rgb[1])&255, parseInt(rgb[2])&255);
}
else {
node.led.setColor(msg.payload.toLowerCase().replace(/\s+/g,''));
}
}
catch (err) {
node.warn("BlinkStick missing ?");
node.led = blinkstick.findFirst();
}
}
else {
//node.warn("No BlinkStick found");
node.led = blinkstick.findFirst();
}
}
});
if (Object.size(node.led) === 0) {
node.error("No BlinkStick found");
}
}
RED.nodes.registerType("blinkstick",BlinkStick);

View File

@@ -0,0 +1,52 @@
<!--
Copyright 2013 IBM Corp.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<script type="text/x-red" data-template-name="blink1">
<div class="form-row">
<label for="node-input-fade"><i class="icon-signal"></i> Fade (mS)</label>
<input type="text" id="node-input-fade" placeholder="0">
</div>
<div class="form-row">
<label for="node-input-name"><i class="icon-tag"></i> Name</label>
<input type="text" id="node-input-name" placeholder="Name">
</div>
<div class="form-tips">Expects a msg.payload with three part csv string of r,g,b.</div>
</script>
<script type="text/x-red" data-help-name="blink1">
<p>ThingM Blink1 output node. Expects a msg.payload with a three part csv string of r,g,b.</p>
</script>
<script type="text/javascript">
RED.nodes.registerType('blink1',{
category: 'output',
color:"GoldenRod",
defaults: {
fade: {value:"0",required:true,validate:RED.validators.number()},
name: {value:""}
},
inputs:1,
outputs:0,
icon: "light.png",
align: "right",
label: function() {
return this.name||"blink1";
},
labelStyle: function() {
return this.name?"node_label_italic":"";
}
});
</script>

View File

@@ -0,0 +1,59 @@
/**
* Copyright 2013 IBM Corp.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
**/
var RED = require(process.env.NODE_RED_HOME+"/red/red");
var Blink1 = require("node-blink1");
function Blink1Node(n) {
RED.nodes.createNode(this,n);
this.fade = n.fade||0;
var node = this;
try {
var p1 = /^\#[A-Fa-f0-9]{6}$/
var p2 = /[0-9]+,[0-9]+,[0-9]+/
this.on("input", function(msg) {
if (blink1) {
if (p1.test(msg.payload)) {
// if it is a hex colour string
var r = parseInt(msg.payload.slice(1,3),16);
var g = parseInt(msg.payload.slice(3,5),16);
var b = parseInt(msg.payload.slice(5),16);
if (node.fade == 0) { blink1.setRGB( r, g, b ); }
else { blink1.fadeToRGB(node.fade, r, g, b ); }
}
else if (p2.test(msg.payload)) {
// if it is a r,g,b triple
var rgb = msg.payload.split(',');
if (node.fade == 0) { blink1.setRGB(parseInt(rgb[0])&255, parseInt(rgb[1])&255, parseInt(rgb[2])&255); }
else { blink1.fadeToRGB(node.fade, parseInt(rgb[0])&255, parseInt(rgb[1])&255, parseInt(rgb[2])&255); }
}
else {
// you can add fancy colours by name here if you want...
node.warn("Blink1 : invalid msg : "+msg.payload);
}
}
else {
node.warn("No Blink1 found");
}
});
var blink1 = new Blink1.Blink1();
}
catch(e) {
node.error("No Blink1 found");
}
}
RED.nodes.registerType("blink1",Blink1Node);

View File

@@ -14,55 +14,34 @@
limitations under the License.
-->
<!-- First, the content of the edit dialog is defined. -->
<script type="text/x-red" data-template-name="digiRGB">
<!-- data-template-name identifies the node type this is for -->
<!-- Each of the following divs creates a field in the edit dialog. -->
<!-- Generally, there should be an input for each property of the node. -->
<!-- The for and id attributes identify the corresponding property -->
<!-- (with the 'node-input-' prefix). -->
<!-- The available icon classes are defined in Twitter Bootstrap -->
<!-- By convention, most nodes have a 'name' property. The following div -->
<!-- provides the necessary field. -->
<div class="form-row">
<label for="node-input-name"><i class="icon-tag"></i> Name</label>
<input type="text" id="node-input-name" placeholder="Name">
<input type="text" id="node-input-name" placeholder="DigiSpark">
</div>
<div class="form-tips">Expects a msg.payload with three part csv string of r,g,b.</div>
</script>
<!-- Next, some simple help text is provided for the node. -->
<script type="text/x-red" data-help-name="digiRGB">
<!-- data-help-name identifies the node type this help is for -->
<!-- This content appears in the Info sidebar when a node is selected -->
<!-- The first <p> is used as the pop-up tool tip when hovering over a -->
<!-- node in the palette. -->
<p>Simple output node to drive digispark RGB</p>
<p>Requires msg.payload to be of the form 'r,g,b'</p>
<p>Simple output node to drive digispark RGB</p>
<p>Requires <b>msg.payload</b> to be of the form 'r,g,b'</p>
</script>
<!-- Finally, the node type is registered along with all of its properties -->
<!-- The example below shows a small subset of the properties that can be set-->
<script type="text/javascript">
RED.nodes.registerType('digiRGB',{
category: 'output', // the palette category
category: 'output',
color:"GoldenRod",
defaults: { // defines the editable properties of the node
name: {value:"digiSparkRGB"} // along with default values.
defaults: {
name: {value:""}
},
inputs:1, // set the number of inputs - only 0 or 1
outputs:0, // set the number of outputs - 0 to n
icon: "light.png", // set the icon (held in public/icons)
inputs:1,
outputs:0,
icon: "light.png",
align: "right",
label: function() { // sets the default label contents
return this.name||this.topic||"sample";
label: function() {
return this.name||"digiSparkRGB";
},
labelStyle: function() { // sets the class to apply to the label
labelStyle: function() {
return this.name?"node_label_italic":"";
}
});

View File

@@ -14,70 +14,56 @@
* limitations under the License.
**/
// Sample Node-RED node file
// Require main module
var RED = require("../../red/red");
var RED = require(process.env.NODE_RED_HOME+"/red/red");
var HID = require('node-hid');
var device;
var node;
// The main node definition - most things happen in here
function DigiRGBNode(n) {
// Create a RED node
RED.nodes.createNode(this,n);
node=this;
var devices = HID.devices(0x16c0,0x05df);
for (var i=0; i< devices.length; i++) {
if (devices[i].product == 'DigiUSB') {
path = devices[i].path;
node.log("found: " + path);
try {
device = new HID.HID(devices[i].path);
break;
} catch (e) {
node.log(e)
}
}
}
var p1 = /^\#[A-Fa-f0-9]{6}$/
var p2 = /[0-9]+,[0-9]+,[0-9]+/
if (device) {
this.on("input", function(msg) {
if (msg != null) {
if (p1.test(msg.payload)) {
var r = parseInt(msg.payload.slice(1,3),16);
var g = parseInt(msg.payload.slice(3,5),16);
var b = parseInt(msg.payload.slice(5),16);
device.sendFeatureReport([115,r,g,b]);
} else if (p2.test(msg.payload)) {
var args = msg.payload.split(',');
if (args.length == 3) {
device.sendFeatureReport([115,parseInt(args[0]),parseInt(args[1]),parseInt(args[2])]);
if (devices[i].product == 'DigiUSB') {
path = devices[i].path;
node.log("found: " + path);
try {
device = new HID.HID(devices[i].path);
break;
} catch (e) {
node.log(e)
}
} else {
node.warn("incompatable input - " + msg.payload);
}
}
});
} else {
node.warn("no digispark RGB found");
}
}
// Register the node by name. This must be called before overriding any of the
// Node functions.
RED.nodes.registerType("digiRGB",DigiRGBNode);
DigiRGBNode.prototype.close = function() {
// Called when the node is shutdown - eg on redeploy.
// Allows ports to be closed, connections dropped etc.
// eg: this.client.disconnect();
if (device) {
device.close();
}
var p1 = /^\#[A-Fa-f0-9]{6}$/
var p2 = /[0-9]+,[0-9]+,[0-9]+/
if (device) {
this.on("input", function(msg) {
if (msg != null) {
if (p1.test(msg.payload)) {
var r = parseInt(msg.payload.slice(1,3),16);
var g = parseInt(msg.payload.slice(3,5),16);
var b = parseInt(msg.payload.slice(5),16);
device.sendFeatureReport([115,r,g,b]);
} else if (p2.test(msg.payload)) {
var args = msg.payload.split(',');
if (args.length == 3) {
device.sendFeatureReport([115,parseInt(args[0]),parseInt(args[1]),parseInt(args[2])]);
}
} else {
node.warn("incompatable input - " + msg.payload);
}
}
});
} else {
node.warn("no digispark RGB found");
}
this.on('close', function() {
if (device) { device.close(); }
});
}
RED.nodes.registerType("digiRGB",DigiRGBNode);

View File

@@ -19,52 +19,52 @@
**/
//might need to modify accordingly
var RED = require("../../red/red");
var RED = require(process.env.NODE_RED_HOME+"/red/red");
//import noble
var noble = require('noble');
// The main node definition - most things happen in here
function BleScan(n) {
// Create a RED node
RED.nodes.createNode(this,n);
// Create a RED node
RED.nodes.createNode(this,n);
var msg = {};
var ble_name;
var node = this;
var ble_name;
var node = this;
//get name and uuid from user
this.ble_name = n.ble_name;
this.ble_uuid = n.ble_uuid;
this.on("input", function(msg){
noble.startScanning();
noble.startScanning();
});
noble.on('scanStart', function(msg) {
var msg = {};
msg.topic = node.topic;
msg.payload = "Scanning initiated..." //debugging
//console.log('scanning initiated...');
node.send(msg);
var msg = {};
msg.topic = node.topic;
msg.payload = "Scanning initiated..." //debugging
//console.log('scanning initiated...');
node.send(msg);
});
noble.on('discover', function(peripheral) {
var msg = {};
msg.topic = node.topic;
msg.payload = "not found";
//check for the device name and the UUID (first one from the UUID list)
if(peripheral.advertisement.localName==node.ble_name && peripheral.advertisement.serviceUuids[0]==node.ble_uuid) {
msg.payload=peripheral.advertisement.localName;
noble.stopScanning(); }
node.send(msg);
var msg = {};
msg.topic = node.topic;
msg.payload = "not found";
//check for the device name and the UUID (first one from the UUID list)
if(peripheral.advertisement.localName==node.ble_name && peripheral.advertisement.serviceUuids[0]==node.ble_uuid) {
msg.payload=peripheral.advertisement.localName;
noble.stopScanning(); }
node.send(msg);
});
this.on("close", function() {
try { noble.stopScanning(); }
catch (err) { console.log(err); }
});
this.on("close", function() {
try { noble.stopScanning(); }
catch (err) { console.log(err); }
});
}
// Register the node by name. This must be called before overriding any of the

View File

@@ -0,0 +1,90 @@
<!--
Copyright 2013 IBM Corp.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<script type="text/x-red" data-template-name="wemo out">
<div class="form-row">
<label for="node-input-ipaddr"><i class="icon-globe"></i> IP Address</label>
<input type="text" id="node-input-ipaddr" placeholder="192.168.1.100">
</div>
<div class="form-row">
<label for="node-input-name"><i class="icon-tag"></i> Name</label>
<input type="text" id="node-input-name" placeholder="Name">
</div>
<div class="form-tips">Expects a msg.payload with either 1/0, on/off, or true/false</div>
</script>
<script type="text/x-red" data-help-name="wemo out">
<p>Wemo output node. Expects a <b>msg.payload</b> with either 1/0, on/off or true/false.</p>
<p>It doesn't yet do any ip address discovery of the wemo devices.</p>
</script>
<script type="text/javascript">
RED.nodes.registerType('wemo out',{
category: 'advanced-output',
color:"GoldenRod",
defaults: {
ipaddr: {value:"",required:true},
name: {value:""}
},
inputs:1,
outputs:0,
icon: "light.png",
align: "right",
label: function() {
return this.name||"wemo";
},
labelStyle: function() {
return this.name?"node_label_italic":"";
}
});
</script>
<script type="text/x-red" data-template-name="wemo in">
<div class="form-row">
<label for="node-input-ipaddr"><i class="icon-globe"></i> IP Address</label>
<input type="text" id="node-input-ipaddr" placeholder="192.168.1.100">
</div>
<div class="form-row">
<label for="node-input-name"><i class="icon-tag"></i> Name</label>
<input type="text" id="node-input-name" placeholder="Name">
</div>
<div class="form-tips">Creates a msg.payload with either 1, 0, nc or na.</div>
</script>
<script type="text/x-red" data-help-name="wemo in">
<p>Wemo input node. Creates a <b>msg.payload</b> with either 1, 0, nc (no change), or na (not available).</p>
<p>It doesn't yet do any ip address discovery of the wemo devices.</p>
</script>
<script type="text/javascript">
RED.nodes.registerType('wemo in',{
category: 'advanced-input',
color:"GoldenRod",
defaults: {
ipaddr: {value:"",required:true},
name: {value:""}
},
inputs:0,
outputs:1,
icon: "light.png",
label: function() {
return this.name||"wemo";
},
labelStyle: function() {
return this.name?"node_label_italic":"";
}
});
</script>

60
hardware/wemo/60-wemo.js Normal file
View File

@@ -0,0 +1,60 @@
/**
* Copyright 2013 IBM Corp.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
**/
var RED = require(process.env.NODE_RED_HOME+"/red/red");
var WeMo = new require('wemo');
function WeMoOut(n) {
RED.nodes.createNode(this,n);
this.ipaddr = n.ipaddr;
this.wemoSwitch = new WeMo(n.ipaddr);
var node = this;
this.on("input", function(msg) {
if (msg != null) {
var state = 0;
if ( msg.payload == 1 || msg.payload == true || msg.payload == "on" ) { var state = 1; }
node.wemoSwitch.setBinaryState(state, function(err, result) {
if (err) node.warn(err);
//else { node.log(result); }
});
}
});
}
RED.nodes.registerType("wemo out",WeMoOut);
function WeMoIn(n) {
RED.nodes.createNode(this,n);
this.ipaddr = n.ipaddr;
this.wemoSwitch = new WeMo(n.ipaddr);
this.wemoSwitch.state = 0;
var node = this;
var tick = setInterval(function() {
wemoSwitch.getBinaryState(function(err, result) {
if (err) node.warn(err);
if (parseInt(result) != wemoSwitch.state) {
wemoSwitch.state = parseInt(result);
node.send({payload:wemoSwitch.state,topic:"wemo/"+node.ipaddr});
}
});
}, 2000);
this.on("close", function() {
clearInterval(tick);
});
}
RED.nodes.registerType("wemo in",WeMoOut);