diff --git a/README.md b/README.md index 28c37f0c..5c150f4c 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Node-RED Nodes -A collection of nodes for [Node-RED](http://nodered.org). +A collection of nodes for [Node-RED](http://nodered.org). See below for a list. ## Installation @@ -27,9 +27,9 @@ The key points are: ### Contributor License Agreement In order for us to accept pull-requests, the contributor must first complete -a Contributor License Agreement (CLA). This clarifies the intellectual -property license granted with any contribution. It is for your protection as a -Contributor as well as the protection of IBM and its customers; it does not +a Contributor License Agreement (CLA). This clarifies the intellectual +property license granted with any contribution. It is for your protection as a +Contributor as well as the protection of IBM and its customers; it does not change your rights to use your own Contributions for any other purpose. Once you have created a pull-request, we'll provide a link to the appropriate @@ -42,3 +42,64 @@ slightly different. ## Copyright and license Copyright 2013 IBM Corp. under [the Apache 2.0 license](LICENSE). + +# Extra Node Information + +### Analysis + +**72-wordpos** - Analyses the payload and classifies the part-of-speech of each word. The resulting message has msg.pos added with the results. A word may appear in multiple categories (eg, 'great' is both a noun and an adjective). + +**74-swearfilter** - Analyses the payload and tries to filter out any messages containing bad swear words. This only operates on payloads of type string. Everything else is blocked. + +### Hardware + +**37-rpi-piface** - Adds support for the PiFace interface module for Raspberry Pi. + +**78-ledborg** - A simple driver for the LEDborg plug on module for Raspberry Pi. + +**60-wemo** - Basic node to drive a WeMo socket and switch. Does not use discovery. + +**76-blinkstick** - Provides support for the BlinkStick USB LED device. + +**77-blink1** - Provides support for the Blink1 USB LED from ThingM. + +**78-digiRGB** - Provides support for the DigiSpark RGB USB LED. + +**79-sensorTag** - Reads data from the Ti BLE SensorTag device. + +**101-scanBLE** - Scans for a particular Bluetooth Low Energy (BLE) device. + +### IO + +**26-rawserial** - Only really needed for Windows boxes without serialport npm module installed. +Uses a simple read of the serial port as a file to input data. You **must** set the baud rate etc externally *before* starting Node-RED. This node does not implement pooling of connections so only one instance of each port may be used - so in **or** out but **not** both. + +**39-wol** - Sends a Wake-On-LAN magic packet to the mac address specified. You may instead set msg.mac to dynamically set the target device mac to wake up. + +**88-ping** - Pings a machine and returns the trip time in mS. Returns false if no response received within 3 seconds, or if the host is unresolveable. Default ping is every 20 seconds but can be configured. + +### Social + +**69-mpd** - MPD music control nodes. Output node expects payload to be a valid mpc command. Currently only simple commands that expect no reply are supported. Input node creates a payload object with Artist, Album, Title, Genre and Date. + +**57-notify** - Uses Growl to provide a desktop popup containing the payload. Only useful on the local machine. + +**57-prowl** - Uses Prowl to push the payload to an Apple device that has the Prowl app installed. + +**57-pushbullet** - Uses PushBullet to push the payload to an Android device that has the PushBullet app installed. + +**92-xmpp** - Connects to an XMPP server to send and receive messages. + +### Storage + +**67-leveldb** - Uses LevelDB for a simple key value pair database. + +**68-mysql** - Allows basic access to a MySQL database. This node uses the **query** operation against the configured database. This does allow both INSERTS and DELETES. By it's very nature it allows SQL injection... *so be careful out there...* + +### Time + +**79-suncalc** - Uses the suncalc module to generate an output at sunrise and sunset based on a specified location. Several choices of definition of sunrise and sunset are available, + +### Misc + +**99-sample** - A sample node with more comments than most to try to help you get started without any other docs... diff --git a/analysis/swearfilter/74-swearfilter.html b/analysis/swearfilter/74-swearfilter.html index fd0abeb5..34379f9b 100644 --- a/analysis/swearfilter/74-swearfilter.html +++ b/analysis/swearfilter/74-swearfilter.html @@ -22,7 +22,8 @@ diff --git a/analysis/swearfilter/74-swearfilter.js b/analysis/swearfilter/74-swearfilter.js index f8b445b3..765e497b 100644 --- a/analysis/swearfilter/74-swearfilter.js +++ b/analysis/swearfilter/74-swearfilter.js @@ -21,8 +21,9 @@ function BadwordsNode(n) { RED.nodes.createNode(this,n); var node = this; this.on("input", function(msg) { - if (badwords.ok(msg.payload)) { node.send(msg); } + if (typeof msg.payload == "string") { + if (badwords.ok(msg.payload)) { node.send(msg); } + } }); } - RED.nodes.registerType("badwords",BadwordsNode); diff --git a/analysis/wordpos/72-wordpos.html b/analysis/wordpos/72-wordpos.html index b50156ea..6b098990 100644 --- a/analysis/wordpos/72-wordpos.html +++ b/analysis/wordpos/72-wordpos.html @@ -24,14 +24,14 @@ @@ -53,5 +53,4 @@ return this.name?"node_label_italic":""; } }); - diff --git a/analysis/wordpos/72-wordpos.js b/analysis/wordpos/72-wordpos.js index ca6739b9..6f472781 100644 --- a/analysis/wordpos/72-wordpos.js +++ b/analysis/wordpos/72-wordpos.js @@ -15,20 +15,17 @@ **/ var RED = require(process.env.NODE_RED_HOME+"/red/red"); -var util = require("util"); var WordPos = require('wordpos'); - var wordpos = new WordPos(); function WordPOSNode(n) { RED.nodes.createNode(this,n); this.on("input", function(msg) { - var node = this; - wordpos.getPOS(msg.payload, function (result) { - msg.pos = result; - node.send(msg); - }); + var node = this; + wordpos.getPOS(msg.payload, function (result) { + msg.pos = result; + node.send(msg); + }); }); } - RED.nodes.registerType("wordpos",WordPOSNode); diff --git a/hardware/Pi/78-ledborg.js b/hardware/Pi/78-ledborg.js index 4c153d05..8d47db04 100644 --- a/hardware/Pi/78-ledborg.js +++ b/hardware/Pi/78-ledborg.js @@ -20,7 +20,7 @@ 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"); + util.log("[78-ledborg.js] Warning: PiBorg hardware : LedBorg not found"); return; } @@ -49,5 +49,4 @@ function LedBorgNode(n) { } }); } - RED.nodes.registerType("ledborg",LedBorgNode); diff --git a/hardware/blink/77-blink1.html b/hardware/blink/77-blink1.html index 00579ce8..25ebf6b9 100644 --- a/hardware/blink/77-blink1.html +++ b/hardware/blink/77-blink1.html @@ -27,7 +27,7 @@ diff --git a/hardware/blink/77-blink1.js b/hardware/blink/77-blink1.js index 54e7a3be..580e1060 100644 --- a/hardware/blink/77-blink1.js +++ b/hardware/blink/77-blink1.js @@ -18,43 +18,42 @@ 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; + 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 do 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"); - } + 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); diff --git a/hardware/digiRGB/78-digiRGB.html b/hardware/digiRGB/78-digiRGB.html index a8f0b309..bbb2a128 100644 --- a/hardware/digiRGB/78-digiRGB.html +++ b/hardware/digiRGB/78-digiRGB.html @@ -14,55 +14,34 @@ limitations under the License. --> - - - - - - - + + + + + + + + + + diff --git a/hardware/wemo/60-wemo.js b/hardware/wemo/60-wemo.js new file mode 100644 index 00000000..34391dee --- /dev/null +++ b/hardware/wemo/60-wemo.js @@ -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); diff --git a/io/ping/88-ping.html b/io/ping/88-ping.html index 051a9ab8..f171c2c5 100644 --- a/io/ping/88-ping.html +++ b/io/ping/88-ping.html @@ -15,18 +15,18 @@ --> diff --git a/io/ping/88-ping.js b/io/ping/88-ping.js index 72e875c0..301aea4c 100644 --- a/io/ping/88-ping.js +++ b/io/ping/88-ping.js @@ -51,7 +51,5 @@ function PingNode(n) { this.on("close", function() { clearInterval(this.tout); }); - } - RED.nodes.registerType("ping",PingNode); diff --git a/io/rawserial/26-rawserial.html b/io/rawserial/26-rawserial.html index 55c622f9..c7b7c362 100644 --- a/io/rawserial/26-rawserial.html +++ b/io/rawserial/26-rawserial.html @@ -15,18 +15,18 @@ --> diff --git a/storage/leveldb/67-leveldb.html b/storage/leveldb/67-leveldb.html index bca7afb0..72ead707 100644 --- a/storage/leveldb/67-leveldb.html +++ b/storage/leveldb/67-leveldb.html @@ -15,108 +15,108 @@ --> diff --git a/storage/leveldb/67-leveldb.js b/storage/leveldb/67-leveldb.js index 3289a961..f4a91db6 100644 --- a/storage/leveldb/67-leveldb.js +++ b/storage/leveldb/67-leveldb.js @@ -18,76 +18,77 @@ var RED = require(process.env.NODE_RED_HOME+"/red/red"); var lvldb = require('level'); function LevelNode(n) { - RED.nodes.createNode(this,n); - this.dbname = n.db; - var node = this; - lvldb(this.dbname, function(err, db) { - if (err) node.error(err); - node.db = db; - }); + RED.nodes.createNode(this,n); + this.dbname = n.db; + var node = this; + lvldb(this.dbname, function(err, db) { + if (err) node.error(err); + node.db = db; + }); + this.on('close', function() { + if (node.db) { node.db.close(); } + }); } RED.nodes.registerType("leveldbase",LevelNode); -LevelNode.prototype.close = function() { - this.db.close(); -} + function LevelDBNodeIn(n) { - RED.nodes.createNode(this,n); - this.level = n.level; - this.levelConfig = RED.nodes.getNode(this.level); + RED.nodes.createNode(this,n); + this.level = n.level; + this.levelConfig = RED.nodes.getNode(this.level); - if (this.levelConfig) { - var node = this; - node.on("input", function(msg) { - if (typeof msg.topic === 'string') { - node.levelConfig.db.get(msg.topic, function(err, value) { - if (err) { - //node.warn(err); - // for some reason they treat nothing found as an error... - msg.payload = null; // so we should return null - } - else { msg.payload = value; } - node.send(msg); - }); - } - else { - if (typeof msg.topic !== 'string') node.error("msg.topic (the key is not defined"); - } - }); - } - else { - this.error("LevelDB database name not configured"); - } + if (this.levelConfig) { + var node = this; + node.on("input", function(msg) { + if (typeof msg.topic === 'string') { + node.levelConfig.db.get(msg.topic, function(err, value) { + if (err) { + //node.warn(err); + // for some reason they treat nothing found as an error... + msg.payload = null; // so we should return null + } + else { msg.payload = value; } + node.send(msg); + }); + } + else { + if (typeof msg.topic !== 'string') node.error("msg.topic (the key is not defined"); + } + }); + } + else { + this.error("LevelDB database name not configured"); + } } RED.nodes.registerType("leveldb in",LevelDBNodeIn); function LevelDBNodeOut(n) { - RED.nodes.createNode(this,n); - this.level = n.level; - this.operation = n.operation; - this.levelConfig = RED.nodes.getNode(this.level); + RED.nodes.createNode(this,n); + this.level = n.level; + this.operation = n.operation; + this.levelConfig = RED.nodes.getNode(this.level); - if (this.levelConfig) { - var node = this; - node.on("input", function(msg) { - if (typeof msg.topic === 'string') { - if (node.operation === "delete") { - node.levelConfig.db.del(msg.topic); - } - else { - node.levelConfig.db.put(msg.topic, msg.payload, function(err) { - if (err) node.error(err); - }); - } - } - else { - if (typeof msg.topic !== 'string') node.error("msg.topic (the key is not defined"); - } - }); - } - else { - this.error("LevelDB database name not configured"); - } + if (this.levelConfig) { + var node = this; + node.on("input", function(msg) { + if (typeof msg.topic === 'string') { + if (node.operation === "delete") { + node.levelConfig.db.del(msg.topic); + } + else { + node.levelConfig.db.put(msg.topic, msg.payload, function(err) { + if (err) node.error(err); + }); + } + } + else { + if (typeof msg.topic !== 'string') node.error("msg.topic (the key is not defined"); + } + }); + } + else { + this.error("LevelDB database name not configured"); + } } RED.nodes.registerType("leveldb out",LevelDBNodeOut); diff --git a/storage/mysql/68-mysql.html b/storage/mysql/68-mysql.html index 2b805133..11c6fd80 100644 --- a/storage/mysql/68-mysql.html +++ b/storage/mysql/68-mysql.html @@ -54,7 +54,6 @@ - - -