diff --git a/99-sample.html.demo b/99-sample.html.demo new file mode 100644 index 00000000..e26197aa --- /dev/null +++ b/99-sample.html.demo @@ -0,0 +1,77 @@ + + + + + + + + + + + + + + + + + + diff --git a/99-sample.js.demo b/99-sample.js.demo new file mode 100644 index 00000000..c591185a --- /dev/null +++ b/99-sample.js.demo @@ -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. + **/ + +// If you use this as a template, replace IBM Corp. with your own name. + +// Sample Node-RED node file + +// Require main module +var RED = require(process.env.NODE_RED_HOME+"/red/red"); + +// The main node definition - most things happen in here +function SampleNode(n) { + // Create a RED node + RED.nodes.createNode(this,n); + + // Store local copies of the node configuration (as defined in the .html) + this.topic = n.topic; + + // Do whatever you need to do in here - declare callbacks etc + // Note: this sample doesn't do anything much - it will only send + // this message once at startup... + // Look at other real nodes for some better ideas of what to do.... + var msg = {}; + msg.topic = this.topic; + msg.payload = "Hello world !" + + // send out the message to the rest of the workspace. + this.send(msg); + + this.on("close", function() { + // Called when the node is shutdown - eg on redeploy. + // Allows ports to be closed, connections dropped etc. + // eg: this.client.disconnect(); + }); +} + +// Register the node by name. This must be called before overriding any of the +// Node functions. +RED.nodes.registerType("sample",SampleNode); 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 new file mode 100644 index 00000000..34379f9b --- /dev/null +++ b/analysis/swearfilter/74-swearfilter.html @@ -0,0 +1,46 @@ + + + + + + + diff --git a/analysis/swearfilter/74-swearfilter.js b/analysis/swearfilter/74-swearfilter.js new file mode 100644 index 00000000..135c9455 --- /dev/null +++ b/analysis/swearfilter/74-swearfilter.js @@ -0,0 +1,29 @@ +/** + * 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 badwordsRegExp = require('badwords/regexp'); + +function BadwordsNode(n) { + RED.nodes.createNode(this,n); + var node = this; + this.on("input", function(msg) { + if (typeof msg.payload === "string") { + if ( !badwordsRegExp.test(msg.payload) ) { node.send(msg); } + } + }); +} +RED.nodes.registerType("badwords",BadwordsNode); diff --git a/analysis/wordpos/72-wordpos.html b/analysis/wordpos/72-wordpos.html new file mode 100644 index 00000000..6b098990 --- /dev/null +++ b/analysis/wordpos/72-wordpos.html @@ -0,0 +1,56 @@ + + + + + + + diff --git a/analysis/wordpos/72-wordpos.js b/analysis/wordpos/72-wordpos.js new file mode 100644 index 00000000..6f472781 --- /dev/null +++ b/analysis/wordpos/72-wordpos.js @@ -0,0 +1,31 @@ +/** + * 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 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); + }); + }); +} +RED.nodes.registerType("wordpos",WordPOSNode); diff --git a/hardware/Pi/37-rpi-piface.html b/hardware/Pi/37-rpi-piface.html index 3e3ac043..36e91117 100644 --- a/hardware/Pi/37-rpi-piface.html +++ b/hardware/Pi/37-rpi-piface.html @@ -52,10 +52,10 @@ + + + + diff --git a/hardware/blink/76-blinkstick.js b/hardware/blink/76-blinkstick.js new file mode 100644 index 00000000..ebbdacc7 --- /dev/null +++ b/hardware/blink/76-blinkstick.js @@ -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); diff --git a/hardware/blink/77-blink1.html b/hardware/blink/77-blink1.html new file mode 100644 index 00000000..25ebf6b9 --- /dev/null +++ b/hardware/blink/77-blink1.html @@ -0,0 +1,52 @@ + + + + + + + diff --git a/hardware/blink/77-blink1.js b/hardware/blink/77-blink1.js new file mode 100644 index 00000000..580e1060 --- /dev/null +++ b/hardware/blink/77-blink1.js @@ -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); 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 be6740a6..301aea4c 100644 --- a/io/ping/88-ping.js +++ b/io/ping/88-ping.js @@ -13,45 +13,43 @@ * See the License for the specific language governing permissions and * limitations under the License. **/ -var RED = require("../../red/red"); + +var RED = require(process.env.NODE_RED_HOME+"/red/red"); var spawn = require('child_process').spawn; var plat = require('os').platform(); function PingNode(n) { - RED.nodes.createNode(this,n); - this.host = n.host; - this.timer = n.timer * 1000; - var node = this; + RED.nodes.createNode(this,n); + this.host = n.host; + this.timer = n.timer * 1000; + var node = this; - node.tout = setInterval(function() { - var ex; - if (plat == "linux") ex = spawn('ping', ['-n', '-w 5', '-c 1', node.host]); - else if (plat.match(/^win/)) ex = spawn('ping', ['-n 1', '-w 5000', node.host]); - else if (plat == "darwin") ex = spawn('ping', ['-n', '-t 5', '-c 1', node.host]); - else node.error("Sorry - your platform - "+plat+" - is not recognised."); - var res=""; + node.tout = setInterval(function() { + var ex; + if (plat == "linux") ex = spawn('ping', ['-n', '-w 5', '-c 1', node.host]); + else if (plat.match(/^win/)) ex = spawn('ping', ['-n 1', '-w 5000', node.host]); + else if (plat == "darwin") ex = spawn('ping', ['-n', '-t 5', '-c 1', node.host]); + else node.error("Sorry - your platform - "+plat+" - is not recognised."); + var res=""; + ex.stdout.on('data', function (data) { + //console.log('[ping] stdout: ' + data.toString()); + var regex = /time=(.*)ms/; + var m = regex.exec(data.toString())||[""]; + res = Number(m[1]); + }); + ex.stderr.on('data', function (data) { + //console.log('[ping] stderr: ' + data); + }); + ex.on('close', function (code) { + //console.log('[ping] result: ' + code); + var msg = { payload: false, topic:node.host }; + if (code == 0) msg = { payload: res, topic:node.host }; + node.send(msg); + }); + }, node.timer); - ex.stdout.on('data', function (data) { - //console.log('[ping] stdout: ' + data.toString()); - var regex = /time=(.*)ms/; - var m = regex.exec(data.toString())||[""]; - res = Number(m[1]); - }); - ex.stderr.on('data', function (data) { - //console.log('[ping] stderr: ' + data); - }); - ex.on('close', function (code) { - //console.log('[ping] result: ' + code); - var msg = { payload: false, topic:node.host }; - if (code == 0) msg = { payload: res, topic:node.host }; - node.send(msg); - }); - - }, node.timer); + this.on("close", function() { + clearInterval(this.tout); + }); } - RED.nodes.registerType("ping",PingNode); - -PingNode.prototype.close = function() { - clearInterval(this.tout); -} diff --git a/io/rawserial/26-rawserial.html b/io/rawserial/26-rawserial.html new file mode 100644 index 00000000..c7b7c362 --- /dev/null +++ b/io/rawserial/26-rawserial.html @@ -0,0 +1,102 @@ + + + + + + + + + + + + + diff --git a/io/rawserial/26-rawserial.js b/io/rawserial/26-rawserial.js new file mode 100644 index 00000000..6fcefc2d --- /dev/null +++ b/io/rawserial/26-rawserial.js @@ -0,0 +1,112 @@ +/** + * 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 settings = RED.settings; +var util = require("util"); +var fs = require('fs'); +var plat = require('os').platform(); +var pre = "\\\\.\\"; + +if (! plat.match(/^win/)) { + util.log("[26-rawserial.js] Advise: Only really needed for Windows boxes without serialport npm module installed."); + pre = ""; +} + +function RawSerialInNode(n) { + RED.nodes.createNode(this,n); + this.port = n.port; + this.split = n.split||null; + if (this.split == '\\n') this.split = "\n"; + if (this.split == '\\r') this.split = "\r"; + var node = this; + + var setupSerial = function() { + node.inp = fs.createReadStream(pre+node.port); + node.inp.setEncoding('utf8'); + var line = ""; + node.inp.on('data', function (data) { + if (node.split != null) { + if (data == node.split) { + node.send({payload:line}); + line = ""; + } + else { line += data; } + } + else { node.send({payload:data}); } + }); + //node.inp.on('end', function (error) {console.log("End", error);}); + node.inp.on('close', function (error) { + util.log("[rawserial] "+node.port+" closed"); + node.tout = setTimeout(function() { + setupSerial(); + },settings.serialReconnectTime); + }); + node.inp.on('error', function(error) { + if (error.code == "ENOENT") { util.log("[rawserial] port "+node.port+" not found"); } + else { util.log("[rawserial] "+node.port+" error "+error); } + node.tout = setTimeout(function() { + setupSerial(); + },settings.serialReconnectTime); + }); + } + setupSerial(); + + node.on('close', function() { + if (node.tout) { clearTimeout(node.tout); } + if (node.inp) { node.inp.pause(); } + }); + +} +RED.nodes.registerType("rawserial in",RawSerialInNode); + + +function RawSerialOutNode(n) { + RED.nodes.createNode(this,n); + this.port = n.port; + var node = this; + + var setupSerial = function() { + node.oup = fs.createWriteStream(pre+node.port,{ flags:'w', encoding:'utf8', mode:0666 }); + node.on("input", function(msg) { + if (msg.payload != null) { + node.oup.write(msg.payload); + } + }); + node.oup.on('open', function (error) { util.log("[rawserial] opened "+node.port); }); + node.oup.on('end', function (error) { console.log("End",error); }); + node.oup.on('close', function (error) { + util.log("[rawserial] "+node.port+" closed"); + node.tout = setTimeout(function() { + setupSerial(); + },settings.serialReconnectTime); + }); + node.oup.on('error', function(error) { + if (error.code == "EACCES") { util.log("[rawserial] can't access port "+node.port); } + else if (error.code == "EIO") { util.log("[rawserial] can't write to port "+node.port); } + else { util.log("[rawserial] "+node.port+" error "+error); } + node.tout = setTimeout(function() { + setupSerial(); + },settings.serialReconnectTime); + }); + } + setupSerial(); + + node.on('close', function() { + if (node.tout) { clearTimeout(node.tout); } + }); +} +RED.nodes.registerType("rawserial out",RawSerialOutNode); diff --git a/io/wol/39-wol.html b/io/wol/39-wol.html new file mode 100644 index 00000000..c2d051d9 --- /dev/null +++ b/io/wol/39-wol.html @@ -0,0 +1,54 @@ + + + + + + + diff --git a/io/wol/39-wol.js b/io/wol/39-wol.js new file mode 100644 index 00000000..497474fc --- /dev/null +++ b/io/wol/39-wol.js @@ -0,0 +1,41 @@ +/** + * 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 wol = require('wake_on_lan'); +var chk = /^([0-9A-F]{2}[:-]){5}([0-9A-F]{2})$/; + +function WOLnode(n) { + RED.nodes.createNode(this,n); + this.mac = n.mac + var node = this; + + this.on("input", function(msg) { + if (msg != null) { + var mac = this.mac || msg.mac || null; + if (mac != null) { + if (chk.test(mac)) { + wol.wake(mac, function(error) { + if (error) { node.warn(error); } + }); + } + else { node.warn("WOL: bad mac address "+mac); } + } + else { node.warn("WOL: no mac address specified"); } + } + }); +} +RED.nodes.registerType("wake on lan",WOLnode); diff --git a/io/wol/icons/onoff.png b/io/wol/icons/onoff.png new file mode 100644 index 00000000..ba3d9cb9 Binary files /dev/null and b/io/wol/icons/onoff.png differ diff --git a/social/music/69-mpd.html b/social/music/69-mpd.html new file mode 100644 index 00000000..acfc07be --- /dev/null +++ b/social/music/69-mpd.html @@ -0,0 +1,80 @@ + + + + + + + + + + + + + diff --git a/social/music/69-mpd.js b/social/music/69-mpd.js new file mode 100644 index 00000000..298d4cf4 --- /dev/null +++ b/social/music/69-mpd.js @@ -0,0 +1,84 @@ +/** + * 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 komponist = require('komponist'); + +var mpc = ""; +komponist.createConnection(6600, 'localhost', function(err, client) { + if (err) node.error("MPD: Failed to connect to MPD server"); + mpc = client; +}); + +function MPDOut(n) { + RED.nodes.createNode(this,n); + var node = this; + node.mpc = mpc; + + this.on("input", function(msg) { + if (msg != null) { + console.log(msg); + try { + //node.mpc.command(msg.payload); + node.mpc.command(msg.payload, msg.param, function(err, results) { + if (err) { console.log("MPD: Error:",err); } + //else { console.log(results); } + }); + } catch (err) { console.log("MPD: Error:",err); } + } + }); + + node.mpc.on('error', function(err) { + console.log("MPD: Error:",err); + }); +} +RED.nodes.registerType("mpd out",MPDOut); + +function MPDIn(n) { + RED.nodes.createNode(this,n); + var node = this; + node.mpc = mpc; + var oldMsg = ""; + + getSong(); + + function getSong() { + node.mpc.currentsong(function(err, info) { + if (err) console.log(err); + else { + var msg = {payload:{},topic:"music"}; + msg.payload.Artist = info.Artist; + msg.payload.Album = info.Album; + msg.payload.Title = info.Title; + msg.payload.Genre = info.Genre; + msg.payload.Date = info.Date; + if (JSON.stringify(msg) != oldMsg) { + node.send(msg); + oldMsg = JSON.stringify(msg); + } + } + }); + } + + node.mpc.on('changed', function(system) { + getSong(); + }); + + this.on("close", function() { + // node.mpc.command("stop"); + }); +} +RED.nodes.registerType("mpd in",MPDIn); diff --git a/social/music/icons/music.png b/social/music/icons/music.png new file mode 100644 index 00000000..4e99a1bf Binary files /dev/null and b/social/music/icons/music.png differ diff --git a/social/notify/57-notify.html b/social/notify/57-notify.html new file mode 100644 index 00000000..67c04cbf --- /dev/null +++ b/social/notify/57-notify.html @@ -0,0 +1,55 @@ + + + + + + + diff --git a/social/notify/57-notify.js b/social/notify/57-notify.js new file mode 100644 index 00000000..db4b2e20 --- /dev/null +++ b/social/notify/57-notify.js @@ -0,0 +1,39 @@ +/** + * 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 growl = require('growl'); +var imagefile = process.env.NODE_RED_HOME+"/public/mqtt-node-red.png"; + +function NotifyNode(n) { + RED.nodes.createNode(this,n); + this.title = n.title; + var node = this; + this.on("input",function(msg) { + var titl = this.title||msg.topic; + if (typeof(msg.payload) == 'object') { + msg.payload = JSON.stringify(msg.payload); + } + if (typeof(titl) != 'undefined') { + growl(msg.payload, { title: titl, image: imagefile }); + } + else { + growl(msg.payload, { image: imagefile }); + } + }); +} + +RED.nodes.registerType("notify",NotifyNode); diff --git a/social/prowl/57-prowl.html b/social/prowl/57-prowl.html new file mode 100644 index 00000000..6a897f79 --- /dev/null +++ b/social/prowl/57-prowl.html @@ -0,0 +1,63 @@ + + + + + + + diff --git a/social/prowl/57-prowl.js b/social/prowl/57-prowl.js new file mode 100644 index 00000000..df07759e --- /dev/null +++ b/social/prowl/57-prowl.js @@ -0,0 +1,67 @@ +/** + * 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 Prowl = require('node-prowl'); +var util = require('util'); + +// Either add a line like this to settings.js +// prowl: {prowlkey:'My-API-KEY'}, +// or create pushkey.js in dir ABOVE node-red, it just needs to be like +// module.exports = {prowlkey:'My-API-KEY'} + +try { + var pushkey = require(process.env.NODE_RED_HOME+"/settings").prowl || require(process.env.NODE_RED_HOME+"/../pushkey.js"); +} +catch(err) { + util.log("[57-prowl.js] Error: Failed to load Prowl credentials"); +} + +if (pushkey) { + var prowl = new Prowl(pushkey.prowlkey); +} + +function ProwlNode(n) { + RED.nodes.createNode(this,n); + this.title = n.title; + this.priority = parseInt(n.priority); + if (this.priority > 2) this.priority = 2; + if (this.priority < -2) this.priority = -2; + var node = this; + this.on("input",function(msg) { + var titl = this.title||msg.topic||"Node-RED"; + var pri = msg.priority||this.priority; + if (typeof(msg.payload) == 'object') { + msg.payload = JSON.stringify(msg.payload); + } + if (pushkey) { + try { + prowl.push(msg.payload, titl, { priority: pri }, function(err, remaining) { + if (err) node.error(err); + node.log( remaining + ' calls to Prowl api during current hour.' ); + }); + } + catch (err) { + node.error(err); + } + } + else { + node.warn("Prowl credentials not set/found. See node info."); + } + }); +} + +RED.nodes.registerType("prowl",ProwlNode); diff --git a/social/prowl/icons/prowl.png b/social/prowl/icons/prowl.png new file mode 100644 index 00000000..43f32253 Binary files /dev/null and b/social/prowl/icons/prowl.png differ diff --git a/social/pushbullet/57-pushbullet.html b/social/pushbullet/57-pushbullet.html new file mode 100644 index 00000000..32020297 --- /dev/null +++ b/social/pushbullet/57-pushbullet.html @@ -0,0 +1,57 @@ + + + + + + + diff --git a/social/pushbullet/57-pushbullet.js b/social/pushbullet/57-pushbullet.js new file mode 100644 index 00000000..fa39d94b --- /dev/null +++ b/social/pushbullet/57-pushbullet.js @@ -0,0 +1,64 @@ +/** + * 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 PushBullet = require('pushbullet'); +var util = require('util'); + +// Either add a line like this to settings.js +// pushbullet: {pushbullet:'My-API-KEY', deviceid:'12345'}, +// or create pushkey.js in dir ABOVE node-red, it just needs to be like +// module.exports = {pushbullet:'My-API-KEY', deviceid:'12345'} + +try { + var pushkey = RED.settings.pushbullet || require(process.env.NODE_RED_HOME+"/../pushkey.js"); +} +catch(err) { + util.log("[57-pushbullet.js] Error: Failed to load PushBullet credentials"); +} + +if (pushkey) { + var pusher = new PushBullet(pushkey.pushbullet); + var deviceId = pushkey.deviceid; +} + +function PushbulletNode(n) { + RED.nodes.createNode(this,n); + this.title = n.title; + var node = this; + this.on("input",function(msg) { + var titl = this.title||msg.topic||"Node-RED"; + if (typeof(msg.payload) == 'object') { + msg.payload = JSON.stringify(msg.payload); + } + if (pushkey) { + try { + pusher.note(deviceId, titl, msg.payload, function(err, response) { + if (err) node.error(err); + console.log(response); + }); + } + catch (err) { + node.error(err); + } + } + else { + node.warn("Pushbullet credentials not set/found. See node info."); + } + }); +} + +RED.nodes.registerType("pushbullet",PushbulletNode); diff --git a/social/pushbullet/icons/bullet.png b/social/pushbullet/icons/bullet.png new file mode 100644 index 00000000..3cf11b3f Binary files /dev/null and b/social/pushbullet/icons/bullet.png differ diff --git a/social/twilio/56-twilio.html b/social/twilio/56-twilio.html new file mode 100644 index 00000000..21badcb7 --- /dev/null +++ b/social/twilio/56-twilio.html @@ -0,0 +1,58 @@ + + + + + + + diff --git a/social/twilio/56-twilio.js b/social/twilio/56-twilio.js new file mode 100644 index 00000000..6f301f71 --- /dev/null +++ b/social/twilio/56-twilio.js @@ -0,0 +1,64 @@ +/** + * Copyright 2013 Andrew D Lindsay @AndrewDLindsay + * http://blog.thiseldo.co.uk + * + * 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 util = require('util'); + +// Either add a line like this to settings.js +// twilio: { account:'My-ACCOUNT-SID', authtoken:'TWILIO-TOKEN',from:'FROM-NUMBER' }, +// Or as a twiliokey.js file in the directory ABOVE node-red. +// module.exports = { account:'My-ACCOUNT-SID', authtoken:'TWILIO-TOKEN',from:'FROM-NUMBER' } + +try { + var twiliokey = RED.settings.twilio || require(process.env.NODE_RED_HOME+"/../twiliokey.js"); +} +catch(err) { + util.log("[56-twilio.js] Error: Failed to load Twilio credentials"); +} + +if (twiliokey) { + var twilioClient = require('twilio')(twiliokey.account, twiliokey.authtoken); + var fromNumber = twiliokey.from; +} + +function TwilioOutNode(n) { + RED.nodes.createNode(this,n); + this.title = n.title; + var node = this; + this.on("input",function(msg) { + if (typeof(msg.payload) == 'object') { + msg.payload = JSON.stringify(msg.payload); + } + if (twiliokey) { + try { + // Send SMS + twilioClient.sendMessage( {to: msg.topic, from: fromNumber, body: msg.payload}, function(err, response) { + if (err) node.error(err); + //console.log(response); + }); + } + catch (err) { + node.error(err); + } + } + else { + node.warn("Twilio credentials not set/found. See node info."); + } + }); +} + +RED.nodes.registerType("twilio out",TwilioOutNode); diff --git a/social/twilio/icons/twilio.png b/social/twilio/icons/twilio.png new file mode 100644 index 00000000..7404be1d Binary files /dev/null and b/social/twilio/icons/twilio.png differ diff --git a/social/xmpp/92-xmpp.html b/social/xmpp/92-xmpp.html new file mode 100644 index 00000000..b16f4c5a --- /dev/null +++ b/social/xmpp/92-xmpp.html @@ -0,0 +1,86 @@ + + + + + + + diff --git a/social/xmpp/92-xmpp.js b/social/xmpp/92-xmpp.js new file mode 100644 index 00000000..5c250b41 --- /dev/null +++ b/social/xmpp/92-xmpp.js @@ -0,0 +1,122 @@ +/** + * 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 orig=console.warn; +console.warn=(function() { // suppress warning from stringprep when not needed) + var orig=console.warn; + return function() { + //orig.apply(console, arguments); + }; +})(); + +var RED = require(process.env.NODE_RED_HOME+"/red/red"); +var xmpp = require('simple-xmpp'); +console.warn = orig; + +try { + var xmppkey = require(process.env.NODE_RED_HOME+"/settings").xmpp || require(process.env.NODE_RED_HOME+"/../xmppkeys.js"); +} catch(err) { + throw new Error("Failed to load XMPP credentials"); +} + +function XmppNode(n) { + RED.nodes.createNode(this,n); + this.server = n.server; + this.port = n.port; + this.join = n.join || false; + this.nick = n.nick || "Node-RED"; + this.sendAll = n.sendObject; + this.to = n.to || ""; + var node = this; + + setTimeout(function() { + xmpp.connect({ + jid : xmppkey.jid, + password : xmppkey.password, + host : this.server, + port : this.port, + skipPresence : true, + reconnect : false + }); + }, 5000); + + xmpp.on('online', function() { + node.log('connected to '+node.server); + xmpp.setPresence('online', node.nick+' online'); + if (node.join) { + xmpp.join(node.to+'/'+node.nick); + } + }); + + xmpp.on('chat', function(from, message) { + var msg = { topic:from, payload:message }; + node.send([msg,null]); + }); + + xmpp.on('groupchat', function(conference, from, message, stamp) { + var msg = { topic:from, payload:message, room:conference }; + if (from != node.nick) { node.send([msg,null]); } + }); + + //xmpp.on('chatstate', function(from, state) { + //console.log('%s is currently %s', from, state); + //var msg = { topic:from, payload:state }; + //node.send([null,msg]); + //}); + + xmpp.on('buddy', function(jid, state, statusText) { + node.log(jid+" is "+state+" : "+statusText); + var msg = { topic:jid, payload: { presence:state, status:statusText} }; + node.send([null,msg]); + }); + + xmpp.on('error', function(err) { + console.error(err); + }); + + xmpp.on('close', function(err) { + node.log('connection closed'); + }); + + xmpp.on('subscribe', function(from) { + xmpp.acceptSubscription(from); + }); + + this.on("input", function(msg) { + var to = msg.topic; + if (node.to != "") { to = node.to; } + if (node.sendAll) { + xmpp.send(to, JSON.stringify(msg), node.join); + } + else { + xmpp.send(to, msg.payload, node.join); + } + }); + + this.on("close", function() { + xmpp.setPresence('offline'); + try { + xmpp.disconnect(); + // TODO - DCJ NOTE... this is not good. It leaves the connection up over a restart - which will end up with bad things happening... + // (but requires the underlying xmpp lib to be fixed, which does have an open bug request on fixing the close method - and a work around. + // see - https://github.com/simple-xmpp/node-simple-xmpp/issues/12 for the fix + } catch(e) { + this.warn("Due to an underlying bug in the xmpp library this does not disconnect old sessions. This is bad... A restart would be better."); + } + }); +} + +RED.nodes.registerType("xmpp",XmppNode); diff --git a/social/xmpp/icons/xmpp.png b/social/xmpp/icons/xmpp.png new file mode 100644 index 00000000..57e43fc4 Binary files /dev/null and b/social/xmpp/icons/xmpp.png differ diff --git a/storage/leveldb/67-leveldb.html b/storage/leveldb/67-leveldb.html new file mode 100644 index 00000000..72ead707 --- /dev/null +++ b/storage/leveldb/67-leveldb.html @@ -0,0 +1,122 @@ + + + + + + + + + + + + + + + + + + + diff --git a/storage/leveldb/67-leveldb.js b/storage/leveldb/67-leveldb.js new file mode 100644 index 00000000..f4a91db6 --- /dev/null +++ b/storage/leveldb/67-leveldb.js @@ -0,0 +1,94 @@ +/** + * 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 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; + }); + this.on('close', function() { + if (node.db) { node.db.close(); } + }); +} +RED.nodes.registerType("leveldbase",LevelNode); + + +function LevelDBNodeIn(n) { + 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"); + } +} +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); + + 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 new file mode 100644 index 00000000..a68e642b --- /dev/null +++ b/storage/mysql/68-mysql.html @@ -0,0 +1,134 @@ + + + + + + + + + + + + diff --git a/storage/mysql/68-mysql.js b/storage/mysql/68-mysql.js new file mode 100644 index 00000000..d01d6f92 --- /dev/null +++ b/storage/mysql/68-mysql.js @@ -0,0 +1,195 @@ +/** + * 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 reconnect = RED.settings.mysqlReconnectTime || 30000; +var mysqldb = require('mysql'); +var querystring = require('querystring'); + +RED.app.get('/MySQLdatabase/:id',function(req,res) { + var credentials = RED.nodes.getCredentials(req.params.id); + if (credentials) { + res.send(JSON.stringify({user:credentials.user,hasPassword:(credentials.password&&credentials.password!="")})); + } else { + res.send(JSON.stringify({})); + } +}); + +RED.app.delete('/MySQLdatabase/:id',function(req,res) { + RED.nodes.deleteCredentials(req.params.id); + res.send(200); +}); + +RED.app.post('/MySQLdatabase/:id',function(req,res) { + var body = ""; + req.on('data', function(chunk) { + body+=chunk; + }); + req.on('end', function(){ + var newCreds = querystring.parse(body); + var credentials = RED.nodes.getCredentials(req.params.id)||{}; + if (newCreds.user == null || newCreds.user == "") { + delete credentials.user; + } else { + credentials.user = newCreds.user; + } + if (newCreds.password == "") { + delete credentials.password; + } else { + credentials.password = newCreds.password||credentials.password; + } + RED.nodes.addCredentials(req.params.id,credentials); + res.send(200); + }); +}); + + +function MySQLNode(n) { + RED.nodes.createNode(this,n); + this.host = n.host; + this.port = n.port; + + this.connected = false; + this.connecting = false; + + if (n.user) { + var credentials = {}; + credentials.user = n.user; + credentials.password = n.pass; + RED.nodes.addCredentials(n.id,credentials); + this.user = n.user; + this.password = n.pass; + } else { + var credentials = RED.nodes.getCredentials(n.id); + if (credentials) { + this.user = credentials.user; + this.password = credentials.password; + } + } + + this.dbname = n.db; + var node = this; + + function doConnect() { + node.connecting = true; + node.connection = mysqldb.createConnection({ + host : node.host, + port : node.port, + user : node.user, + password : node.password, + database : node.dbname, + insecureAuth: true + }); + + node.connection.connect(function(err) { + node.connecting = false; + if (err) { + node.warn(err); + node.tick = setTimeout(doConnect, reconnect); + } else { + node.connected = true; + } + }); + + node.connection.on('error', function(err) { + node.connected = false; + if (err.code === 'PROTOCOL_CONNECTION_LOST') { + doConnect(); // silently reconnect... + } else { + node.error(err); + doConnect(); + } + }); + } + + this.connect = function() { + if (!this.connected && !this.connecting) { + doConnect(); + } + } + + this.on('close', function () { + if (this.tick) { clearTimeout(this.tick); } + if (this.connection) { + node.connection.end(function(err) { + if (err) node.error(err); + }); + } + }); +} +RED.nodes.registerType("MySQLdatabase",MySQLNode); + + +function MysqlDBNodeIn(n) { + RED.nodes.createNode(this,n); + this.mydb = n.mydb; + this.mydbConfig = RED.nodes.getNode(this.mydb); + + if (this.mydbConfig) { + this.mydbConfig.connect(); + var node = this; + node.on("input", function(msg) { + if (typeof msg.topic === 'string') { + //console.log("query:",msg.topic); + node.mydbConfig.connection.query(msg.topic, function(err, rows) { + if (err) { node.warn(err); } + else { + msg.payload = rows; + node.send(msg); + } + }); + } + else { + if (typeof msg.topic !== 'string') node.error("msg.topic : the query is not defined as a string"); + } + }); + } + else { + this.error("MySQL database not configured"); + } +} +RED.nodes.registerType("mysql",MysqlDBNodeIn); + + +//function MysqlDBNodeOut(n) { + //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("MySQL database not configured"); + //} +//} +//RED.nodes.registerType("mysql out",MysqlDBNodeOut); diff --git a/time/79-suncalc.js b/time/79-suncalc.js index 383824a3..8004633d 100644 --- a/time/79-suncalc.js +++ b/time/79-suncalc.js @@ -13,7 +13,8 @@ * See the License for the specific language governing permissions and * limitations under the License. **/ -var RED = require("../../red/red"); + +var RED = require(process.env.NODE_RED_HOME+"/red/red"); var SunCalc = require('suncalc'); function SunNode(n) { diff --git a/time/icons/sun.png b/time/icons/sun.png new file mode 100644 index 00000000..c4918e56 Binary files /dev/null and b/time/icons/sun.png differ