From 065d47d1736a628a4f81f40d3a9d6ae808eea015 Mon Sep 17 00:00:00 2001 From: Dave C-J Date: Sun, 8 Sep 2013 11:21:26 +0100 Subject: [PATCH 1/7] handle more errors for sockets. one step forward. --- nodes/io/30-socketin.js | 34 ++++++++++++++++++++++++---------- 1 file changed, 24 insertions(+), 10 deletions(-) diff --git a/nodes/io/30-socketin.js b/nodes/io/30-socketin.js index 848256c4c..7358ad730 100644 --- a/nodes/io/30-socketin.js +++ b/nodes/io/30-socketin.js @@ -24,17 +24,24 @@ function SocketIn(n) { var node = this; if (this.trans == "http") { var http = require('http'); - var serv = http.createServer(function (req, res) { + var server = http.createServer(function (req, res) { //node.log("http "+req.url); var msg = {topic:node.topic,payload:req.url.slice(1)}; node.send(msg); res.writeHead(304, {'Content-Type': 'text/plain'}); res.end('\n'); }).listen(node.port); + server.on('error', function (e) { + if (e.code == 'EADDRINUSE') { + setTimeout(node.error('TCP port is already in use - please reconfigure socket.'),250); + } + else { console.log(e); } + server = null; + }); node.log('http listener at http://127.0.0.1:'+node.port+'/'); this._close = function() { - serv.close(); + if (server) server.close(); node.log('http listener stopped'); } } @@ -44,11 +51,11 @@ function SocketIn(n) { var server = net.createServer(function (socket) { var buffer = null; socket.on('data', function (chunk) { - if (buffer == null) { - buffer = chunk; - } else { - buffer = Buffer.concat([buffer,chunk]); - } + if (buffer == null) { + buffer = chunk; + } else { + buffer = Buffer.concat([buffer,chunk]); + } }); socket.on('end', function() { var msg = {topic:node.topic, payload:buffer, fromip:socket.remoteAddress+':'+socket.remotePort}; @@ -59,12 +66,14 @@ function SocketIn(n) { if (e.code == 'EADDRINUSE') { setTimeout(node.error('TCP port is already in use - please reconfigure socket.'),250); } + else { console.log(e); } + server = null; }); server.listen(node.port); node.log('tcp listener on port :'+node.port); this._close = function() { - server.close(); + if (server) server.close(); node.log('tcp listener stopped'); } } @@ -95,13 +104,14 @@ function SocketIn(n) { client.on('error', function() { node.log('tcpc socket error'); + client = null; to = setTimeout(setupTcpClient, 10000); //Try to reconnect }); } setupTcpClient(); this._close = function() { - client.end(); + if (client) client.end(); //client.destroy(); clearTimeout(to); node.log('tcpc stopped client'); @@ -120,10 +130,14 @@ function SocketIn(n) { var msg = {topic:node.topic,payload:message,fromip:remote.address+':'+remote.port}; node.send(msg); }); + server.on('error', function (e) { + console.log(e); + server = null; + }); server.bind(node.port); this._close = function() { - server.close(); + if (server) server.close(); node.log('udp listener stopped'); } } From 06930cb65cad7bf37a5daa1ab9222622a21eed16 Mon Sep 17 00:00:00 2001 From: Dave C-J Date: Sun, 8 Sep 2013 11:21:52 +0100 Subject: [PATCH 2/7] added (some) query capability to MongoDB node. --- nodes/storage/66-mongodb.html | 79 ++++++++++++++++++++++++++++------- nodes/storage/66-mongodb.js | 68 ++++++++++++++++++++++++------ 2 files changed, 118 insertions(+), 29 deletions(-) diff --git a/nodes/storage/66-mongodb.html b/nodes/storage/66-mongodb.html index 343a05a5f..6aa261814 100644 --- a/nodes/storage/66-mongodb.html +++ b/nodes/storage/66-mongodb.html @@ -27,10 +27,6 @@ - - - - - - + + + + + + + - diff --git a/nodes/storage/66-mongodb.js b/nodes/storage/66-mongodb.js index 83c08a2c1..93dc615f4 100644 --- a/nodes/storage/66-mongodb.js +++ b/nodes/storage/66-mongodb.js @@ -30,25 +30,26 @@ function MongoOutNode(n) { RED.nodes.createNode(this,n); this.collection = n.collection; this.mongodb = n.mongodb; + this.payonly = n.payonly || false; this.mongoConfig = RED.nodes.getNode(this.mongodb); if (this.mongoConfig) { var node = this; - this.clientDb = new mongo.Db(node.mongoConfig.db, new mongo.Server(node.mongoConfig.hostname, node.mongoConfig.port, {}), {w: 1}); this.clientDb.open(function(err,cli) { - if (err) { node.error(err); } - else { - node.clientDb.collection(node.collection,function(err,coll) { - if (err) { node.error(err); } - else { - node.on("input",function(msg) { - delete msg._topic; - coll.save(msg,function(err,item){if (err){node.error(err);}}); - }); - } - }); - } + if (err) { node.error(err); } + else { + node.clientDb.collection(node.collection,function(err,coll) { + if (err) { node.error(err); } + else { + node.on("input",function(msg) { + delete msg._topic; + if (node.payonly) coll.save(msg.payload,function(err,item){if (err){node.error(err);}}); + else coll.save(msg,function(err,item){if (err){node.error(err);}}); + }); + } + }); + } }); } else { this.error("missing mongodb configuration"); @@ -63,4 +64,45 @@ MongoOutNode.prototype.close = function() { } } +function MongoInNode(n) { + RED.nodes.createNode(this,n); + this.collection = n.collection; + this.mongodb = n.mongodb; + this.mongoConfig = RED.nodes.getNode(this.mongodb); + if (this.mongoConfig) { + var node = this; + this.clientDb = new mongo.Db(node.mongoConfig.db, new mongo.Server(node.mongoConfig.hostname, node.mongoConfig.port, {}), {w: 1}); + this.clientDb.open(function(err,cli) { + if (err) { node.error(err); } + else { + node.clientDb.collection(node.collection,function(err,coll) { + if (err) { node.error(err); } + else { + node.on("input",function(msg) { + msg.projection = msg.projection || {}; + coll.find(msg.payload,msg.projection).sort(msg.sort).limit(msg.limit).toArray(function(err, items) { + if (err) { node.error(err); } + msg.payload = items; + delete msg.projection; + delete msg.sort; + delete msg.limit; + node.send(msg); + }); + }); + } + }); + } + }); + } else { + this.error("missing mongodb configuration"); + } +} + +RED.nodes.registerType("mongodb in",MongoInNode); + +MongoInNode.prototype.close = function() { + if (this.clientDb) { + this.clientDb.close(); + } +} From 163d0c624a55803a9db664db6fb578c9a308721f Mon Sep 17 00:00:00 2001 From: Dave C-J Date: Sun, 8 Sep 2013 13:05:41 +0100 Subject: [PATCH 3/7] added prototype BlinkStick node... --- nodes/hardware/76-blinkstick.html | 49 +++++++++++++++++++++++++++++++ nodes/hardware/76-blinkstick.js | 47 +++++++++++++++++++++++++++++ 2 files changed, 96 insertions(+) create mode 100644 nodes/hardware/76-blinkstick.html create mode 100644 nodes/hardware/76-blinkstick.js diff --git a/nodes/hardware/76-blinkstick.html b/nodes/hardware/76-blinkstick.html new file mode 100644 index 000000000..fd21490b2 --- /dev/null +++ b/nodes/hardware/76-blinkstick.html @@ -0,0 +1,49 @@ + + + + + + + diff --git a/nodes/hardware/76-blinkstick.js b/nodes/hardware/76-blinkstick.js new file mode 100644 index 000000000..dadfe05a1 --- /dev/null +++ b/nodes/hardware/76-blinkstick.js @@ -0,0 +1,47 @@ +/** + * 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("../../red/red"); +var blinkstick = require("blinkstick"); + +function BlinkStick(n) { + RED.nodes.createNode(this,n); + var node = this; + var p1 = /^#.*/ + var p2 = /[0-9]+,[0-9]+,[0-9]+/ + + var led = new blinkstick.findFirst(); + + node.log("started"); + this.on("input", function(msg) { + if (msg != null) { + if (led.length > 0) { + if ((p1.test(msg.payload))|(p2.test(msg.payload))) { + led.setColor(msg.payload); + } + else { + node.error("Incorrect format: "+msg.payload); + } + } + else { + node.error("No BlinkStick found"); + } + } + }); + +} + +RED.nodes.registerType("blinkstick",BlinkStick); From 9a26916d29137505a206d559bafc830da950b238 Mon Sep 17 00:00:00 2001 From: Dave C-J Date: Sun, 8 Sep 2013 16:45:51 +0100 Subject: [PATCH 4/7] over zealous error checking for device... - now under zealous - tricky to debug without actual hardware in hand :-) 4/10 must try harder --- nodes/hardware/76-blinkstick.js | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/nodes/hardware/76-blinkstick.js b/nodes/hardware/76-blinkstick.js index dadfe05a1..3cb02d15f 100644 --- a/nodes/hardware/76-blinkstick.js +++ b/nodes/hardware/76-blinkstick.js @@ -19,26 +19,21 @@ var blinkstick = require("blinkstick"); function BlinkStick(n) { RED.nodes.createNode(this,n); - var node = this; var p1 = /^#.*/ var p2 = /[0-9]+,[0-9]+,[0-9]+/ - var led = new blinkstick.findFirst(); + this.led = new blinkstick.findFirst(); + var node = this; node.log("started"); this.on("input", function(msg) { if (msg != null) { - if (led.length > 0) { if ((p1.test(msg.payload))|(p2.test(msg.payload))) { - led.setColor(msg.payload); + node.led.setColor(msg.payload); } else { node.error("Incorrect format: "+msg.payload); } - } - else { - node.error("No BlinkStick found"); - } } }); From 77a6b0a71dfff69062055a7f2e511ebceb327d65 Mon Sep 17 00:00:00 2001 From: Nicholas O'Leary Date: Mon, 9 Sep 2013 09:55:50 +0100 Subject: [PATCH 5/7] Import fails on nodes with config labels --- nodes/io/25-serial.html | 6 ++++-- nodes/social/91-irc.html | 3 ++- nodes/storage/66-mongodb.html | 6 ++++-- 3 files changed, 10 insertions(+), 5 deletions(-) diff --git a/nodes/io/25-serial.html b/nodes/io/25-serial.html index 6e5adb1e2..2b0b37a40 100644 --- a/nodes/io/25-serial.html +++ b/nodes/io/25-serial.html @@ -42,7 +42,8 @@ outputs:1, icon: "serial.png", label: function() { - return this.name||(this.serial)?RED.nodes.node(this.serial).label():"serial"; + var serialNode = RED.nodes.node(this.serial); + return this.name||(serialNode?serialNode.label():"serial"); }, labelStyle: function() { return this.name?"node_label_italic":""; @@ -80,7 +81,8 @@ icon: "serial.png", align: "right", label: function() { - return this.name||((this.serial)?RED.nodes.node(this.serial).label():"serial"); + var serialNode = RED.nodes.node(this.serial); + return this.name||(serialNode?serialNode.label():"serial"); }, labelStyle: function() { return this.name?"node_label_italic":""; diff --git a/nodes/social/91-irc.html b/nodes/social/91-irc.html index f2c5b4f0d..5c78784d4 100644 --- a/nodes/social/91-irc.html +++ b/nodes/social/91-irc.html @@ -42,7 +42,8 @@ outputs:1, icon: "hash.png", label: function() { - return this.name||(this.ircserver)?RED.nodes.node(this.ircserver).label():"irc"; + var ircNode = RED.nodes.node(this.ircserver); + return this.name||((ircNode?ircNode.label():"irc"); }, labelStyle: function() { return this.name?"node_label_italic":""; diff --git a/nodes/storage/66-mongodb.html b/nodes/storage/66-mongodb.html index 6aa261814..4737d2e7e 100644 --- a/nodes/storage/66-mongodb.html +++ b/nodes/storage/66-mongodb.html @@ -86,7 +86,8 @@ icon: "mongodb.png", align: "right", label: function() { - return this.name||((this.mongodb)?RED.nodes.node(this.mongodb).label()+"//"+this.collection:"mongodb"); + var mongoNode = RED.nodes.node(this.mongodb); + return this.name||this.collection||(mongoNode?mongoNode.label():"mongodb"); }, labelStyle: function() { return this.name?"node_label_italic":""; @@ -129,7 +130,8 @@ outputs:1, icon: "mongodb.png", label: function() { - return this.name||((this.mongodb)?RED.nodes.node(this.mongodb).label()+"//"+this.collection:"mongodb"); + var mongoNode = RED.nodes.node(this.mongodb); + return this.name||(mongoNode?mongoNode.label()+"//"+this.collection:"mongodb"); }, labelStyle: function() { return this.name?"node_label_italic":""; From 95675bc6bcd70dbe3a28a317080bb2eea81a2c79 Mon Sep 17 00:00:00 2001 From: Nicholas O'Leary Date: Mon, 9 Sep 2013 20:03:22 +0100 Subject: [PATCH 6/7] Start to add server-side events --- red/events.js | 19 +++++++++++++++++++ red/nodes.js | 17 +++++++++++++---- red/red.js | 13 ++++++++++--- 3 files changed, 42 insertions(+), 7 deletions(-) create mode 100644 red/events.js diff --git a/red/events.js b/red/events.js new file mode 100644 index 000000000..89590494e --- /dev/null +++ b/red/events.js @@ -0,0 +1,19 @@ +/** + * 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 events = require("events"); + +module.exports = new events.EventEmitter(); diff --git a/red/nodes.js b/red/nodes.js index 7401db39e..5648df481 100644 --- a/red/nodes.js +++ b/red/nodes.js @@ -14,9 +14,9 @@ * limitations under the License. **/ var util = require("util"); -var events = require("events"); +var EventEmitter = require("events").EventEmitter; var fs = require("fs"); - +var events = require("./events"); function getCallerFilename(type) { //if (type == "summary") { @@ -59,9 +59,11 @@ var registry = (function() { return nodes[i]; }, clear: function() { + events.emit("nodes-stopping"); for (var n in nodes) { nodes[n].close(); } + events.emit("nodes-stopped"); nodes = {}; }, @@ -72,7 +74,7 @@ var registry = (function() { return obj; })(); -var ConsoleLogHandler = new events.EventEmitter(); +var ConsoleLogHandler = new EventEmitter(); ConsoleLogHandler.on("log",function(msg) { util.log("["+msg.level+"] ["+msg.type+":"+(msg.name||msg.id)+"] "+msg.msg); }); @@ -128,7 +130,7 @@ function Node(n) { } this.wires = n.wires||[]; } -util.inherits(Node,events.EventEmitter); +util.inherits(Node,EventEmitter); Node.prototype.close = function() { // called when a node is removed @@ -253,6 +255,8 @@ module.exports.load = function() { } loadNodes("nodes"); + + events.emit("nodes-loaded"); } @@ -261,7 +265,10 @@ module.exports.getNode = function(nid) { return registry.get(nid); } module.exports.parseConfig = function(conf) { + registry.clear(); + + events.emit("nodes-starting"); for (var i in conf) { var nn = null; var nt = node_type_registry.get(conf[i].type); @@ -286,5 +293,7 @@ module.exports.parseConfig = function(conf) { if (deletedCredentials) { saveCredentialsFile(); } + events.emit("nodes-started"); + } diff --git a/red/red.js b/red/red.js index f35be52e4..7ff626b52 100644 --- a/red/red.js +++ b/red/red.js @@ -14,15 +14,22 @@ * limitations under the License. **/ +var events = require("./events"); var server = require("./server"); var nodes = require("./nodes"); var library = require("./library"); var settings = require("../settings"); -module.exports = { + +var events = require("events"); + +var RED = { nodes: nodes, app: server.app, server: server.server, settings: settings, - library: library -} + library: library, + events: events +}; + +module.exports = RED; From f7bdece08180e803aeb0c1660da6e8c1c1e7497c Mon Sep 17 00:00:00 2001 From: Nicholas O'Leary Date: Mon, 9 Sep 2013 21:42:12 +0100 Subject: [PATCH 7/7] Fix the irc label breakage --- nodes/social/91-irc.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nodes/social/91-irc.html b/nodes/social/91-irc.html index 5c78784d4..10f062ec9 100644 --- a/nodes/social/91-irc.html +++ b/nodes/social/91-irc.html @@ -43,7 +43,7 @@ icon: "hash.png", label: function() { var ircNode = RED.nodes.node(this.ircserver); - return this.name||((ircNode?ircNode.label():"irc"); + return this.name||(ircNode?ircNode.label():"irc"); }, labelStyle: function() { return this.name?"node_label_italic":"";