mirror of
				https://github.com/node-red/node-red.git
				synced 2025-03-01 10:36:34 +00:00 
			
		
		
		
	Migrate to new node function style
This commit is contained in:
		| @@ -17,7 +17,7 @@ | |||||||
| <!-- Sample html file that corresponds to the 99-sample.js file              --> | <!-- Sample html file that corresponds to the 99-sample.js file              --> | ||||||
| <!-- This creates and configures the onscreen elements of the node           --> | <!-- This creates and configures the onscreen elements of the node           --> | ||||||
|  |  | ||||||
| <!-- If you use this as a template, replace IBM Corp. with your own name.    --> | <!-- If you use this as a template, update the copyright with your own name. --> | ||||||
|  |  | ||||||
| <!-- First, the content of the edit dialog is defined.                       --> | <!-- First, the content of the edit dialog is defined.                       --> | ||||||
|  |  | ||||||
|   | |||||||
| @@ -14,39 +14,41 @@ | |||||||
|  * limitations under the License. |  * limitations under the License. | ||||||
|  **/ |  **/ | ||||||
|  |  | ||||||
| // If you use this as a template, replace IBM Corp. with your own name. | // If you use this as a template, update the copyright with your own name. | ||||||
|  |  | ||||||
| // Sample Node-RED node file | // 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 | module.export = function(RED) { | ||||||
| function SampleNode(n) { |      | ||||||
|     // Create a RED node |     // The main node definition - most things happen in here | ||||||
|     RED.nodes.createNode(this,n); |     function SampleNode(n) { | ||||||
|  |         // Create a RED node | ||||||
|     // Store local copies of the node configuration (as defined in the .html) |         RED.nodes.createNode(this,n); | ||||||
|     this.topic = n.topic; |      | ||||||
|  |         // Store local copies of the node configuration (as defined in the .html) | ||||||
|     // Do whatever you need to do in here - declare callbacks etc |         this.topic = n.topic; | ||||||
|     // Note: this sample doesn't do anything much - it will only send |      | ||||||
|     // this message once at startup... |         // Do whatever you need to do in here - declare callbacks etc | ||||||
|     // Look at other real nodes for some better ideas of what to do.... |         // Note: this sample doesn't do anything much - it will only send | ||||||
|     var msg = {}; |         // this message once at startup... | ||||||
|     msg.topic = this.topic; |         // Look at other real nodes for some better ideas of what to do.... | ||||||
|     msg.payload = "Hello world !" |         var msg = {}; | ||||||
|  |         msg.topic = this.topic; | ||||||
|     // send out the message to the rest of the workspace. |         msg.payload = "Hello world !" | ||||||
|     this.send(msg); |      | ||||||
|  |         // send out the message to the rest of the workspace. | ||||||
|     this.on("close", function() { |         this.send(msg); | ||||||
|         // Called when the node is shutdown - eg on redeploy. |      | ||||||
|         // Allows ports to be closed, connections dropped etc. |         this.on("close", function() { | ||||||
|         // eg: this.client.disconnect(); |             // 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); | ||||||
|  |      | ||||||
| } | } | ||||||
|  |  | ||||||
| // Register the node by name. This must be called before overriding any of the |  | ||||||
| // Node functions. |  | ||||||
| RED.nodes.registerType("sample",SampleNode); |  | ||||||
|   | |||||||
| @@ -14,18 +14,19 @@ | |||||||
|  * limitations under the License. |  * limitations under the License. | ||||||
|  **/ |  **/ | ||||||
|  |  | ||||||
| var RED = require(process.env.NODE_RED_HOME+"/red/red"); | module.exports = function(RED) { | ||||||
| var sentiment = require('sentiment'); |     var sentiment = require('sentiment'); | ||||||
|  |      | ||||||
| function SentimentNode(n) { |     function SentimentNode(n) { | ||||||
|     RED.nodes.createNode(this,n); |         RED.nodes.createNode(this,n); | ||||||
|     var node = this; |         var node = this; | ||||||
|  |      | ||||||
|     this.on("input", function(msg) { |         this.on("input", function(msg) { | ||||||
|         sentiment(msg.payload, msg.overrides || null, function (err, result) { |             sentiment(msg.payload, msg.overrides || null, function (err, result) { | ||||||
|             msg.sentiment = result; |                 msg.sentiment = result; | ||||||
|             node.send(msg); |                 node.send(msg); | ||||||
|  |             }); | ||||||
|         }); |         }); | ||||||
|     }); |     } | ||||||
|  |     RED.nodes.registerType("sentiment",SentimentNode); | ||||||
| } | } | ||||||
| RED.nodes.registerType("sentiment",SentimentNode); |  | ||||||
|   | |||||||
| @@ -14,31 +14,32 @@ | |||||||
|  * limitations under the License. |  * limitations under the License. | ||||||
|  **/ |  **/ | ||||||
|  |  | ||||||
| var RED = require(process.env.NODE_RED_HOME+"/red/red"); | module.exports = function(RED) { | ||||||
| var util = require("util"); |     var util = require("util"); | ||||||
| var parseString = require('xml2js').parseString; |     var parseString = require('xml2js').parseString; | ||||||
| var useColors = true; |     var useColors = true; | ||||||
| //util.inspect.styles.boolean = "red"; |     //util.inspect.styles.boolean = "red"; | ||||||
|  |      | ||||||
| function Xml2jsNode(n) { |     function Xml2jsNode(n) { | ||||||
|     RED.nodes.createNode(this,n); |         RED.nodes.createNode(this,n); | ||||||
|     this.useEyes = n.useEyes||false; |         this.useEyes = n.useEyes||false; | ||||||
|     var node = this; |         var node = this; | ||||||
|     this.on("input", function(msg) { |         this.on("input", function(msg) { | ||||||
|         try { |             try { | ||||||
|             parseString(msg.payload, {strict:true,async:true}, function (err, result) { |                 parseString(msg.payload, {strict:true,async:true}, function (err, result) { | ||||||
|             //parseString(msg.payload, {strict:false,async:true}, function (err, result) { |                 //parseString(msg.payload, {strict:false,async:true}, function (err, result) { | ||||||
|                 if (err) { node.error(err); } |                     if (err) { node.error(err); } | ||||||
|                 else { |                     else { | ||||||
|                     msg.payload = result; |                         msg.payload = result; | ||||||
|                     node.send(msg); |                         node.send(msg); | ||||||
|                     if (node.useEyes == true) { |                         if (node.useEyes == true) { | ||||||
|                         node.log("\n"+util.inspect(msg, {colors:useColors, depth:10})); |                             node.log("\n"+util.inspect(msg, {colors:useColors, depth:10})); | ||||||
|  |                         } | ||||||
|                     } |                     } | ||||||
|                 } |                 }); | ||||||
|             }); |             } | ||||||
|         } |             catch(e) { util.log("[73-parsexml.js] "+e); } | ||||||
|         catch(e) { util.log("[73-parsexml.js] "+e); } |         }); | ||||||
|     }); |     } | ||||||
|  |     RED.nodes.registerType("xml2js",Xml2jsNode); | ||||||
| } | } | ||||||
| RED.nodes.registerType("xml2js",Xml2jsNode); |  | ||||||
|   | |||||||
| @@ -14,23 +14,24 @@ | |||||||
|  * limitations under the License. |  * limitations under the License. | ||||||
|  **/ |  **/ | ||||||
|  |  | ||||||
| var RED = require(process.env.NODE_RED_HOME+"/red/red"); | module.exports = function(RED) { | ||||||
| var js2xmlparser = require("js2xmlparser"); |     var js2xmlparser = require("js2xmlparser"); | ||||||
|  |      | ||||||
| function Js2XmlNode(n) { |     function Js2XmlNode(n) { | ||||||
|     RED.nodes.createNode(this,n); |         RED.nodes.createNode(this,n); | ||||||
|     this.root = n.root; |         this.root = n.root; | ||||||
|     var node = this; |         var node = this; | ||||||
|  |      | ||||||
|     this.on("input", function(msg) { |         this.on("input", function(msg) { | ||||||
|         try { |             try { | ||||||
|             var root = node.root || typeof msg.payload; |                 var root = node.root || typeof msg.payload; | ||||||
|             if (typeof msg.payload !== "object") { msg.payload = '"'+msg.payload+'"'; } |                 if (typeof msg.payload !== "object") { msg.payload = '"'+msg.payload+'"'; } | ||||||
|             console.log(root, typeof msg.payload,msg.payload); |                 console.log(root, typeof msg.payload,msg.payload); | ||||||
|             msg.payload = js2xmlparser(root, msg.payload); |                 msg.payload = js2xmlparser(root, msg.payload); | ||||||
|             node.send(msg); |                 node.send(msg); | ||||||
|         } |             } | ||||||
|         catch(e) { console.log(e); } |             catch(e) { console.log(e); } | ||||||
|     }); |         }); | ||||||
|  |     } | ||||||
|  |     RED.nodes.registerType("json2xml",Js2XmlNode); | ||||||
| } | } | ||||||
| RED.nodes.registerType("json2xml",Js2XmlNode); |  | ||||||
|   | |||||||
| @@ -1,5 +1,5 @@ | |||||||
| /** | /** | ||||||
|  * Copyright 2013 IBM Corp. |  * Copyright 2013, 2014 IBM Corp. | ||||||
|  * |  * | ||||||
|  * Licensed under the Apache License, Version 2.0 (the "License"); |  * Licensed under the Apache License, Version 2.0 (the "License"); | ||||||
|  * you may not use this file except in compliance with the License. |  * you may not use this file except in compliance with the License. | ||||||
| @@ -14,87 +14,84 @@ | |||||||
|  * limitations under the License. |  * limitations under the License. | ||||||
|  **/ |  **/ | ||||||
|  |  | ||||||
| var RED = require(process.env.NODE_RED_HOME+"/red/red"); | module.exports = function(RED) { | ||||||
| try { |  | ||||||
|     var cron = require("cron"); |     var cron = require("cron"); | ||||||
| } catch(err) { |      | ||||||
|     require("util").log("[inject] Warning: cannot find module 'cron'"); |     function InjectNode(n) { | ||||||
| } |         RED.nodes.createNode(this,n); | ||||||
|  |         this.topic = n.topic; | ||||||
| function InjectNode(n) { |         this.payload = n.payload; | ||||||
|     RED.nodes.createNode(this,n); |         this.payloadType = n.payloadType; | ||||||
|     this.topic = n.topic; |         this.repeat = n.repeat; | ||||||
|     this.payload = n.payload; |         this.crontab = n.crontab; | ||||||
|     this.payloadType = n.payloadType; |         this.once = n.once; | ||||||
|     this.repeat = n.repeat; |         var node = this; | ||||||
|     this.crontab = n.crontab; |         this.interval_id = null; | ||||||
|     this.once = n.once; |         this.cronjob = null; | ||||||
|     var node = this; |      | ||||||
|     this.interval_id = null; |         if (this.repeat && !isNaN(this.repeat) && this.repeat > 0) { | ||||||
|     this.cronjob = null; |             this.repeat = this.repeat * 1000; | ||||||
|  |             this.log("repeat = "+this.repeat); | ||||||
|     if (this.repeat && !isNaN(this.repeat) && this.repeat > 0) { |             this.interval_id = setInterval( function() { | ||||||
|         this.repeat = this.repeat * 1000; |                 node.emit("input",{}); | ||||||
|         this.log("repeat = "+this.repeat); |             }, this.repeat ); | ||||||
|         this.interval_id = setInterval( function() { |         } else if (this.crontab) { | ||||||
|             node.emit("input",{}); |             if (cron) { | ||||||
|         }, this.repeat ); |                 this.log("crontab = "+this.crontab); | ||||||
|     } else if (this.crontab) { |                 this.cronjob = new cron.CronJob(this.crontab, | ||||||
|         if (cron) { |                     function() { | ||||||
|             this.log("crontab = "+this.crontab); |                         node.emit("input",{}); | ||||||
|             this.cronjob = new cron.CronJob(this.crontab, |                     }, | ||||||
|                 function() { |                     null,true); | ||||||
|                     node.emit("input",{}); |             } else { | ||||||
|                 }, |                 this.error("'cron' module not found"); | ||||||
|                 null,true); |             } | ||||||
|         } else { |         } | ||||||
|             this.error("'cron' module not found"); |      | ||||||
|  |         if (this.once) { | ||||||
|  |             setTimeout( function(){ node.emit("input",{}); }, 100); | ||||||
|  |         } | ||||||
|  |      | ||||||
|  |         this.on("input",function(msg) { | ||||||
|  |             var msg = {topic:this.topic}; | ||||||
|  |             if ( (this.payloadType == null && this.payload == "") || this.payloadType == "date") { | ||||||
|  |                 msg.payload = Date.now(); | ||||||
|  |             } else if (this.payloadType == null || this.payloadType == "string") { | ||||||
|  |                 msg.payload = this.payload; | ||||||
|  |             } else { | ||||||
|  |                 msg.payload = ""; | ||||||
|  |             } | ||||||
|  |             this.send(msg); | ||||||
|  |             msg = null; | ||||||
|  |         }); | ||||||
|  |     } | ||||||
|  |      | ||||||
|  |     RED.nodes.registerType("inject",InjectNode); | ||||||
|  |      | ||||||
|  |     InjectNode.prototype.close = function() { | ||||||
|  |         if (this.interval_id != null) { | ||||||
|  |             clearInterval(this.interval_id); | ||||||
|  |             this.log("inject: repeat stopped"); | ||||||
|  |         } else if (this.cronjob != null) { | ||||||
|  |             this.cronjob.stop(); | ||||||
|  |             this.log("inject: cronjob stopped"); | ||||||
|  |             delete this.cronjob; | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |      | ||||||
|     if (this.once) { |     RED.httpAdmin.post("/inject/:id", function(req,res) { | ||||||
|         setTimeout( function(){ node.emit("input",{}); }, 100); |             var node = RED.nodes.getNode(req.params.id); | ||||||
|     } |             if (node != null) { | ||||||
|  |                 try { | ||||||
|     this.on("input",function(msg) { |                     node.receive(); | ||||||
|         var msg = {topic:this.topic}; |                     res.send(200); | ||||||
|         if ( (this.payloadType == null && this.payload == "") || this.payloadType == "date") { |                 } catch(err) { | ||||||
|             msg.payload = Date.now(); |                     res.send(500); | ||||||
|         } else if (this.payloadType == null || this.payloadType == "string") { |                     node.error("Inject failed:"+err); | ||||||
|             msg.payload = this.payload; |                     console.log(err.stack); | ||||||
|         } else { |                 } | ||||||
|             msg.payload = ""; |             } else { | ||||||
|         } |                 res.send(404); | ||||||
|         this.send(msg); |             } | ||||||
|         msg = null; |  | ||||||
|     }); |     }); | ||||||
| } | } | ||||||
|  |  | ||||||
| RED.nodes.registerType("inject",InjectNode); |  | ||||||
|  |  | ||||||
| InjectNode.prototype.close = function() { |  | ||||||
|     if (this.interval_id != null) { |  | ||||||
|         clearInterval(this.interval_id); |  | ||||||
|         this.log("inject: repeat stopped"); |  | ||||||
|     } else if (this.cronjob != null) { |  | ||||||
|         this.cronjob.stop(); |  | ||||||
|         this.log("inject: cronjob stopped"); |  | ||||||
|         delete this.cronjob; |  | ||||||
|     } |  | ||||||
| } |  | ||||||
|  |  | ||||||
| RED.httpAdmin.post("/inject/:id", function(req,res) { |  | ||||||
|         var node = RED.nodes.getNode(req.params.id); |  | ||||||
|         if (node != null) { |  | ||||||
|             try { |  | ||||||
|                 node.receive(); |  | ||||||
|                 res.send(200); |  | ||||||
|             } catch(err) { |  | ||||||
|                 res.send(500); |  | ||||||
|                 node.error("Inject failed:"+err); |  | ||||||
|                 console.log(err.stack); |  | ||||||
|             } |  | ||||||
|         } else { |  | ||||||
|             res.send(404); |  | ||||||
|         } |  | ||||||
| }); |  | ||||||
|   | |||||||
| @@ -14,157 +14,158 @@ | |||||||
|  * limitations under the License. |  * limitations under the License. | ||||||
|  **/ |  **/ | ||||||
|  |  | ||||||
| var RED = require(process.env.NODE_RED_HOME+"/red/red"); | module.exports = function(RED) { | ||||||
| var util = require("util"); |     var util = require("util"); | ||||||
| var ws = require("ws"); |     var ws = require("ws"); | ||||||
| var events = require("events"); |     var events = require("events"); | ||||||
| var debuglength = RED.settings.debugMaxLength||1000; |     var debuglength = RED.settings.debugMaxLength||1000; | ||||||
| var useColors = false; |     var useColors = false; | ||||||
| // util.inspect.styles.boolean = "red"; |     // util.inspect.styles.boolean = "red"; | ||||||
|  |      | ||||||
| function DebugNode(n) { |     function DebugNode(n) { | ||||||
|     RED.nodes.createNode(this,n); |         RED.nodes.createNode(this,n); | ||||||
|     this.name = n.name; |         this.name = n.name; | ||||||
|     this.complete = n.complete; |         this.complete = n.complete; | ||||||
|     this.console = n.console; |         this.console = n.console; | ||||||
|     this.active = (n.active == null)||n.active; |         this.active = (n.active == null)||n.active; | ||||||
|     var node = this; |         var node = this; | ||||||
|  |      | ||||||
|     this.on("input",function(msg) { |         this.on("input",function(msg) { | ||||||
|         if (this.complete == "true") { // debug complete msg object |             if (this.complete == "true") { // debug complete msg object | ||||||
|             if (this.console == "true") { |                 if (this.console == "true") { | ||||||
|                 node.log("\n"+util.inspect(msg, {colors:useColors, depth:10})); |                     node.log("\n"+util.inspect(msg, {colors:useColors, depth:10})); | ||||||
|             } |                 } | ||||||
|             if (msg.payload instanceof Buffer) { msg.payload = "(Buffer) "+msg.payload.toString('hex'); } |                 if (msg.payload instanceof Buffer) { msg.payload = "(Buffer) "+msg.payload.toString('hex'); } | ||||||
|             if (this.active) { |                 if (this.active) { | ||||||
|                 DebugNode.send({id:this.id,name:this.name,topic:msg.topic,msg:msg,_path:msg._path}); |                     DebugNode.send({id:this.id,name:this.name,topic:msg.topic,msg:msg,_path:msg._path}); | ||||||
|             } |                 } | ||||||
|         } else { // debug just the msg.payload |             } else { // debug just the msg.payload | ||||||
|             if (this.console == "true") { |                 if (this.console == "true") { | ||||||
|                 if (typeof msg.payload === "string") { |                     if (typeof msg.payload === "string") { | ||||||
|                     if (msg.payload.indexOf("\n") != -1) { msg.payload = "\n"+msg.payload; } |                         if (msg.payload.indexOf("\n") != -1) { msg.payload = "\n"+msg.payload; } | ||||||
|                     node.log(msg.payload); |                         node.log(msg.payload); | ||||||
|  |                     } | ||||||
|  |                     else if (typeof msg.payload === "object") { node.log("\n"+util.inspect(msg.payload, {colors:useColors, depth:10})); } | ||||||
|  |                     else { node.log(util.inspect(msg.payload, {colors:useColors})); } | ||||||
|  |                 } | ||||||
|  |                 if (typeof msg.payload == "undefined") { msg.payload = "(undefined)"; } | ||||||
|  |                 if (msg.payload instanceof Buffer) { msg.payload = "(Buffer) "+msg.payload.toString('hex'); } | ||||||
|  |                 if (this.active) { | ||||||
|  |                     DebugNode.send({id:this.id,name:this.name,topic:msg.topic,msg:msg.payload,_path:msg._path}); | ||||||
|                 } |                 } | ||||||
|                 else if (typeof msg.payload === "object") { node.log("\n"+util.inspect(msg.payload, {colors:useColors, depth:10})); } |  | ||||||
|                 else { node.log(util.inspect(msg.payload, {colors:useColors})); } |  | ||||||
|             } |             } | ||||||
|             if (typeof msg.payload == "undefined") { msg.payload = "(undefined)"; } |         }); | ||||||
|             if (msg.payload instanceof Buffer) { msg.payload = "(Buffer) "+msg.payload.toString('hex'); } |     } | ||||||
|             if (this.active) { |      | ||||||
|                 DebugNode.send({id:this.id,name:this.name,topic:msg.topic,msg:msg.payload,_path:msg._path}); |     var lastSentTime = (new Date()).getTime(); | ||||||
|  |      | ||||||
|  |     setInterval(function() { | ||||||
|  |         var now = (new Date()).getTime(); | ||||||
|  |         if (now-lastSentTime > 15000) { | ||||||
|  |             lastSentTime = now; | ||||||
|  |             for (var i in DebugNode.activeConnections) { | ||||||
|  |                 var ws = DebugNode.activeConnections[i]; | ||||||
|  |                 try { | ||||||
|  |                     var p = JSON.stringify({heartbeat:lastSentTime}); | ||||||
|  |                     ws.send(p); | ||||||
|  |                 } catch(err) { | ||||||
|  |                     util.log("[debug] ws heartbeat error : "+err); | ||||||
|  |                 } | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|     }); |     }, 15000); | ||||||
| } |      | ||||||
|  |      | ||||||
| var lastSentTime = (new Date()).getTime(); |      | ||||||
|  |     RED.nodes.registerType("debug",DebugNode); | ||||||
| setInterval(function() { |      | ||||||
|     var now = (new Date()).getTime(); |     DebugNode.send = function(msg) { | ||||||
|     if (now-lastSentTime > 15000) { |         if (msg.msg instanceof Error) { | ||||||
|         lastSentTime = now; |             msg.msg = msg.msg.toString(); | ||||||
|  |         } else if (typeof msg.msg === 'object') { | ||||||
|  |             var seen = []; | ||||||
|  |             var ty = "(Object) "; | ||||||
|  |             if (util.isArray(msg.msg)) { ty = "(Array) "; } | ||||||
|  |             msg.msg = ty + JSON.stringify(msg.msg, function(key, value) { | ||||||
|  |                 if (typeof value === 'object' && value !== null) { | ||||||
|  |                     if (seen.indexOf(value) !== -1) { return "[circular]"; } | ||||||
|  |                     seen.push(value); | ||||||
|  |                 } | ||||||
|  |                 return value; | ||||||
|  |             }," "); | ||||||
|  |             seen = null; | ||||||
|  |         } else if (typeof msg.msg === "boolean") { | ||||||
|  |             msg.msg = "(boolean) "+msg.msg.toString(); | ||||||
|  |         } else if (msg.msg === 0) { | ||||||
|  |             msg.msg = "0"; | ||||||
|  |         } else if (msg.msg == null) { | ||||||
|  |             msg.msg = "[undefined]"; | ||||||
|  |         } | ||||||
|  |      | ||||||
|  |         if (msg.msg.length > debuglength) { | ||||||
|  |             msg.msg = msg.msg.substr(0,debuglength) +" ...."; | ||||||
|  |         } | ||||||
|  |          | ||||||
|         for (var i in DebugNode.activeConnections) { |         for (var i in DebugNode.activeConnections) { | ||||||
|             var ws = DebugNode.activeConnections[i]; |             var ws = DebugNode.activeConnections[i]; | ||||||
|             try { |             try { | ||||||
|                 var p = JSON.stringify({heartbeat:lastSentTime}); |                 var p = JSON.stringify(msg); | ||||||
|                 ws.send(p); |                 ws.send(p); | ||||||
|             } catch(err) { |             } catch(err) { | ||||||
|                 util.log("[debug] ws heartbeat error : "+err); |                 util.log("[debug] ws error : "+err); | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|     } |         lastSentTime = (new Date()).getTime(); | ||||||
| }, 15000); |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
| RED.nodes.registerType("debug",DebugNode); |  | ||||||
|  |  | ||||||
| DebugNode.send = function(msg) { |  | ||||||
|     if (msg.msg instanceof Error) { |  | ||||||
|         msg.msg = msg.msg.toString(); |  | ||||||
|     } else if (typeof msg.msg === 'object') { |  | ||||||
|         var seen = []; |  | ||||||
|         var ty = "(Object) "; |  | ||||||
|         if (util.isArray(msg.msg)) { ty = "(Array) "; } |  | ||||||
|         msg.msg = ty + JSON.stringify(msg.msg, function(key, value) { |  | ||||||
|             if (typeof value === 'object' && value !== null) { |  | ||||||
|                 if (seen.indexOf(value) !== -1) { return "[circular]"; } |  | ||||||
|                 seen.push(value); |  | ||||||
|             } |  | ||||||
|             return value; |  | ||||||
|         }," "); |  | ||||||
|         seen = null; |  | ||||||
|     } else if (typeof msg.msg === "boolean") { |  | ||||||
|         msg.msg = "(boolean) "+msg.msg.toString(); |  | ||||||
|     } else if (msg.msg === 0) { |  | ||||||
|         msg.msg = "0"; |  | ||||||
|     } else if (msg.msg == null) { |  | ||||||
|         msg.msg = "[undefined]"; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     if (msg.msg.length > debuglength) { |  | ||||||
|         msg.msg = msg.msg.substr(0,debuglength) +" ...."; |  | ||||||
|     } |     } | ||||||
|      |      | ||||||
|     for (var i in DebugNode.activeConnections) { |     DebugNode.activeConnections = []; | ||||||
|         var ws = DebugNode.activeConnections[i]; |      | ||||||
|         try { |     var path = RED.settings.httpAdminRoot || "/"; | ||||||
|             var p = JSON.stringify(msg); |     path = path + (path.slice(-1) == "/" ? "":"/") + "debug/ws"; | ||||||
|             ws.send(p); |      | ||||||
|         } catch(err) { |     DebugNode.wsServer = new ws.Server({server:RED.server,path:path}); | ||||||
|             util.log("[debug] ws error : "+err); |     DebugNode.wsServer.on('connection',function(ws) { | ||||||
|         } |         DebugNode.activeConnections.push(ws); | ||||||
|     } |         ws.on('close',function() { | ||||||
|     lastSentTime = (new Date()).getTime(); |             for (var i in DebugNode.activeConnections) { | ||||||
| } |                 if (DebugNode.activeConnections[i] === ws) { | ||||||
|  |                     DebugNode.activeConnections.splice(i,1); | ||||||
| DebugNode.activeConnections = []; |                     break; | ||||||
|  |                 } | ||||||
| var path = RED.settings.httpAdminRoot || "/"; |  | ||||||
| path = path + (path.slice(-1) == "/" ? "":"/") + "debug/ws"; |  | ||||||
|  |  | ||||||
| DebugNode.wsServer = new ws.Server({server:RED.server,path:path}); |  | ||||||
| DebugNode.wsServer.on('connection',function(ws) { |  | ||||||
|     DebugNode.activeConnections.push(ws); |  | ||||||
|     ws.on('close',function() { |  | ||||||
|         for (var i in DebugNode.activeConnections) { |  | ||||||
|             if (DebugNode.activeConnections[i] === ws) { |  | ||||||
|                 DebugNode.activeConnections.splice(i,1); |  | ||||||
|                 break; |  | ||||||
|             } |             } | ||||||
|  |         }); | ||||||
|  |         ws.on('error', function(err) { | ||||||
|  |             util.log("[debug] ws error : "+err); | ||||||
|  |         }); | ||||||
|  |     }); | ||||||
|  |      | ||||||
|  |     DebugNode.wsServer.on('error', function(err) { | ||||||
|  |         util.log("[debug] ws server error : "+err); | ||||||
|  |     }); | ||||||
|  |      | ||||||
|  |     DebugNode.logHandler = new events.EventEmitter(); | ||||||
|  |     DebugNode.logHandler.on("log",function(msg) { | ||||||
|  |         if (msg.level == "warn" || msg.level == "error") { | ||||||
|  |             DebugNode.send(msg); | ||||||
|         } |         } | ||||||
|     }); |     }); | ||||||
|     ws.on('error', function(err) { |     RED.log.addHandler(DebugNode.logHandler); | ||||||
|         util.log("[debug] ws error : "+err); |      | ||||||
|     }); |     RED.httpAdmin.post("/debug/:id/:state", function(req,res) { | ||||||
| }); |         var node = RED.nodes.getNode(req.params.id); | ||||||
|  |         var state = req.params.state; | ||||||
| DebugNode.wsServer.on('error', function(err) { |         if (node != null) { | ||||||
|     util.log("[debug] ws server error : "+err); |             if (state === "enable") { | ||||||
| }); |                 node.active = true; | ||||||
|  |                 res.send(200); | ||||||
| DebugNode.logHandler = new events.EventEmitter(); |             } else if (state === "disable") { | ||||||
| DebugNode.logHandler.on("log",function(msg) { |                 node.active = false; | ||||||
|     if (msg.level == "warn" || msg.level == "error") { |                 res.send(201); | ||||||
|         DebugNode.send(msg); |             } else { | ||||||
|     } |                 res.send(404); | ||||||
| }); |             } | ||||||
| RED.log.addHandler(DebugNode.logHandler); |  | ||||||
|  |  | ||||||
| RED.httpAdmin.post("/debug/:id/:state", function(req,res) { |  | ||||||
|     var node = RED.nodes.getNode(req.params.id); |  | ||||||
|     var state = req.params.state; |  | ||||||
|     if (node != null) { |  | ||||||
|         if (state === "enable") { |  | ||||||
|             node.active = true; |  | ||||||
|             res.send(200); |  | ||||||
|         } else if (state === "disable") { |  | ||||||
|             node.active = false; |  | ||||||
|             res.send(201); |  | ||||||
|         } else { |         } else { | ||||||
|             res.send(404); |             res.send(404); | ||||||
|         } |         } | ||||||
|     } else { |     }); | ||||||
|         res.send(404); | } | ||||||
|     } |  | ||||||
| }); |  | ||||||
|   | |||||||
| @@ -14,68 +14,68 @@ | |||||||
|  * limitations under the License. |  * limitations under the License. | ||||||
|  **/ |  **/ | ||||||
|  |  | ||||||
| var RED = require(process.env.NODE_RED_HOME+"/red/red"); | module.exports = function(RED) { | ||||||
|  |     var spawn = require('child_process').spawn; | ||||||
| var spawn = require('child_process').spawn; |     var exec = require('child_process').exec; | ||||||
| var exec = require('child_process').exec; |      | ||||||
|  |     function ExecNode(n) { | ||||||
| function ExecNode(n) { |         RED.nodes.createNode(this,n); | ||||||
|     RED.nodes.createNode(this,n); |         this.cmd = n.command.trim(); | ||||||
|     this.cmd = n.command.trim(); |         this.append = n.append.trim() || ""; | ||||||
|     this.append = n.append.trim() || ""; |         this.useSpawn = n.useSpawn; | ||||||
|     this.useSpawn = n.useSpawn; |      | ||||||
|  |         var node = this; | ||||||
|     var node = this; |         this.on("input", function(msg) { | ||||||
|     this.on("input", function(msg) { |             if (msg != null) { | ||||||
|         if (msg != null) { |      | ||||||
|  |                 if (this.useSpawn == true) { | ||||||
|             if (this.useSpawn == true) { |                     // make the extra args into an array | ||||||
|                 // make the extra args into an array |                     // then prepend with the msg.payload | ||||||
|                 // then prepend with the msg.payload |                     if (typeof(msg.payload !== "string")) { msg.payload = msg.payload.toString(); } | ||||||
|                 if (typeof(msg.payload !== "string")) { msg.payload = msg.payload.toString(); } |                     var arg = []; | ||||||
|                 var arg = []; |                     if (node.append.length > 0) { arg = node.append.split(","); } | ||||||
|                 if (node.append.length > 0) { arg = node.append.split(","); } |                     if (msg.payload.trim() != "") { arg.unshift(msg.payload); } | ||||||
|                 if (msg.payload.trim() != "") { arg.unshift(msg.payload); } |                     node.log(node.cmd+" ["+arg+"]"); | ||||||
|                 node.log(node.cmd+" ["+arg+"]"); |                     if (node.cmd.indexOf(" ") == -1) { | ||||||
|                 if (node.cmd.indexOf(" ") == -1) { |                         var ex = spawn(node.cmd,arg); | ||||||
|                     var ex = spawn(node.cmd,arg); |                         ex.stdout.on('data', function (data) { | ||||||
|                     ex.stdout.on('data', function (data) { |                             //console.log('[exec] stdout: ' + data); | ||||||
|                         //console.log('[exec] stdout: ' + data); |                             msg.payload = data.toString(); | ||||||
|                         msg.payload = data.toString(); |                             node.send([msg,null,null]); | ||||||
|                         node.send([msg,null,null]); |                         }); | ||||||
|                     }); |                         ex.stderr.on('data', function (data) { | ||||||
|                     ex.stderr.on('data', function (data) { |                             //console.log('[exec] stderr: ' + data); | ||||||
|                         //console.log('[exec] stderr: ' + data); |                             msg.payload = data.toString(); | ||||||
|                         msg.payload = data.toString(); |                             node.send([null,msg,null]); | ||||||
|                         node.send([null,msg,null]); |                         }); | ||||||
|                     }); |                         ex.on('close', function (code) { | ||||||
|                     ex.on('close', function (code) { |                             //console.log('[exec] result: ' + code); | ||||||
|                         //console.log('[exec] result: ' + code); |                             msg.payload = code; | ||||||
|                         msg.payload = code; |                             node.send([null,null,msg]); | ||||||
|                         node.send([null,null,msg]); |                         }); | ||||||
|  |                     } | ||||||
|  |                     else { node.error("Spawn command must be just the command - no spaces or extra parameters"); } | ||||||
|  |                 } | ||||||
|  |      | ||||||
|  |                 else { | ||||||
|  |                     var cl = node.cmd+" "+msg.payload+" "+node.append; | ||||||
|  |                     node.log(cl); | ||||||
|  |                     var child = exec(cl, function (error, stdout, stderr) { | ||||||
|  |                         msg.payload = stdout; | ||||||
|  |                         var msg2 = {payload:stderr}; | ||||||
|  |                         //console.log('[exec] stdout: ' + stdout); | ||||||
|  |                         //console.log('[exec] stderr: ' + stderr); | ||||||
|  |                         if (error !== null) { | ||||||
|  |                             var msg3 = {payload:error}; | ||||||
|  |                             //console.log('[exec] error: ' + error); | ||||||
|  |                         } | ||||||
|  |                         node.send([msg,msg2,msg3]); | ||||||
|                     }); |                     }); | ||||||
|                 } |                 } | ||||||
|                 else { node.error("Spawn command must be just the command - no spaces or extra parameters"); } |  | ||||||
|             } |             } | ||||||
|  |      | ||||||
|             else { |         }); | ||||||
|                 var cl = node.cmd+" "+msg.payload+" "+node.append; |     } | ||||||
|                 node.log(cl); |      | ||||||
|                 var child = exec(cl, function (error, stdout, stderr) { |     RED.nodes.registerType("exec",ExecNode); | ||||||
|                     msg.payload = stdout; |  | ||||||
|                     var msg2 = {payload:stderr}; |  | ||||||
|                     //console.log('[exec] stdout: ' + stdout); |  | ||||||
|                     //console.log('[exec] stderr: ' + stderr); |  | ||||||
|                     if (error !== null) { |  | ||||||
|                         var msg3 = {payload:error}; |  | ||||||
|                         //console.log('[exec] error: ' + error); |  | ||||||
|                     } |  | ||||||
|                     node.send([msg,msg2,msg3]); |  | ||||||
|                 }); |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|     }); |  | ||||||
| } | } | ||||||
|  |  | ||||||
| RED.nodes.registerType("exec",ExecNode); |  | ||||||
|   | |||||||
| @@ -14,58 +14,58 @@ | |||||||
|  * limitations under the License. |  * limitations under the License. | ||||||
|  **/ |  **/ | ||||||
|  |  | ||||||
| var RED = require(process.env.NODE_RED_HOME+"/red/red"); | module.exports = function(RED) { | ||||||
|  |     var util = require("util"); | ||||||
| var util = require("util"); |     var vm = require("vm"); | ||||||
| var vm = require("vm"); |     var fs = require('fs'); | ||||||
| var fs = require('fs'); |     var fspath = require('path'); | ||||||
| var fspath = require('path'); |      | ||||||
|  |     function FunctionNode(n) { | ||||||
| function FunctionNode(n) { |         RED.nodes.createNode(this,n); | ||||||
|     RED.nodes.createNode(this,n); |         this.name = n.name; | ||||||
|     this.name = n.name; |         this.func = n.func; | ||||||
|     this.func = n.func; |         var functionText = "var results = (function(msg){"+this.func+"\n})(msg);"; | ||||||
|     var functionText = "var results = (function(msg){"+this.func+"\n})(msg);"; |         this.topic = n.topic; | ||||||
|     this.topic = n.topic; |         this.context = {global:RED.settings.functionGlobalContext || {}}; | ||||||
|     this.context = {global:RED.settings.functionGlobalContext || {}}; |         try { | ||||||
|     try { |             this.script = vm.createScript(functionText); | ||||||
|         this.script = vm.createScript(functionText); |             this.on("input", function(msg) { | ||||||
|         this.on("input", function(msg) { |                     if (msg != null) { | ||||||
|                 if (msg != null) { |                         var sandbox = {msg:msg,console:console,util:util,Buffer:Buffer,context:this.context}; | ||||||
|                     var sandbox = {msg:msg,console:console,util:util,Buffer:Buffer,context:this.context}; |                         try { | ||||||
|                     try { |                             this.script.runInNewContext(sandbox); | ||||||
|                         this.script.runInNewContext(sandbox); |                             var results = sandbox.results; | ||||||
|                         var results = sandbox.results; |      | ||||||
|  |                             if (results == null) { | ||||||
|                         if (results == null) { |                                 results = []; | ||||||
|                             results = []; |                             } else if (results.length == null) { | ||||||
|                         } else if (results.length == null) { |                                 results = [results]; | ||||||
|                             results = [results]; |                             } | ||||||
|                         } |                             if (msg._topic) { | ||||||
|                         if (msg._topic) { |                                 for (var m in results) { | ||||||
|                             for (var m in results) { |                                     if (results[m]) { | ||||||
|                                 if (results[m]) { |                                         if (util.isArray(results[m])) { | ||||||
|                                     if (util.isArray(results[m])) { |                                             for (var n in results[m]) { | ||||||
|                                         for (var n in results[m]) { |                                                 results[m][n]._topic = msg._topic; | ||||||
|                                             results[m][n]._topic = msg._topic; |                                             } | ||||||
|  |                                         } else { | ||||||
|  |                                             results[m]._topic = msg._topic; | ||||||
|                                         } |                                         } | ||||||
|                                     } else { |  | ||||||
|                                         results[m]._topic = msg._topic; |  | ||||||
|                                     } |                                     } | ||||||
|                                 } |                                 } | ||||||
|                             } |                             } | ||||||
|  |                             this.send(results); | ||||||
|  |      | ||||||
|  |                         } catch(err) { | ||||||
|  |                             this.error(err); | ||||||
|                         } |                         } | ||||||
|                         this.send(results); |  | ||||||
|  |  | ||||||
|                     } catch(err) { |  | ||||||
|                         this.error(err); |  | ||||||
|                     } |                     } | ||||||
|                 } |             }); | ||||||
|         }); |         } catch(err) { | ||||||
|     } catch(err) { |             this.error(err); | ||||||
|         this.error(err); |         } | ||||||
|     } |     } | ||||||
|  |      | ||||||
|  |     RED.nodes.registerType("function",FunctionNode); | ||||||
|  |     RED.library.register("functions"); | ||||||
| } | } | ||||||
|  |  | ||||||
| RED.nodes.registerType("function",FunctionNode); |  | ||||||
| RED.library.register("functions"); |  | ||||||
|   | |||||||
| @@ -14,28 +14,28 @@ | |||||||
|  * limitations under the License. |  * limitations under the License. | ||||||
|  **/ |  **/ | ||||||
|  |  | ||||||
| var RED = require(process.env.NODE_RED_HOME+"/red/red"); | module.exports = function(RED) { | ||||||
|  |     var mustache = require("mustache"); | ||||||
| var mustache = require("mustache"); |     var util = require("util"); | ||||||
| var util = require("util"); |     var fs = require('fs'); | ||||||
| var fs = require('fs'); |      | ||||||
|  |     function TemplateNode(n) { | ||||||
| function TemplateNode(n) { |         RED.nodes.createNode(this,n); | ||||||
|     RED.nodes.createNode(this,n); |         this.name = n.name; | ||||||
|     this.name = n.name; |         this.template = n.template; | ||||||
|     this.template = n.template; |         this.on("input", function(msg) { | ||||||
|     this.on("input", function(msg) { |                 if (msg != null) { | ||||||
|             if (msg != null) { |                     try { | ||||||
|                 try { |                         msg.payload = mustache.render(this.template,msg) | ||||||
|                     msg.payload = mustache.render(this.template,msg) |                         this.send(msg); | ||||||
|                     this.send(msg); |                     } catch(err) { | ||||||
|                 } catch(err) { |                         this.error(err.message); | ||||||
|                     this.error(err.message); |                     } | ||||||
|                 } |                 } | ||||||
|             } |         }); | ||||||
|     }); |     } | ||||||
|  |      | ||||||
|  |     RED.nodes.registerType("template",TemplateNode); | ||||||
|  |      | ||||||
|  |     RED.library.register("templates"); | ||||||
| } | } | ||||||
|  |  | ||||||
| RED.nodes.registerType("template",TemplateNode); |  | ||||||
|  |  | ||||||
| RED.library.register("templates"); |  | ||||||
|   | |||||||
| @@ -15,140 +15,140 @@ | |||||||
|  **/ |  **/ | ||||||
|  |  | ||||||
| //Simple node to introduce a pause into a flow | //Simple node to introduce a pause into a flow | ||||||
| var RED = require(process.env.NODE_RED_HOME+"/red/red"); | module.exports = function(RED) { | ||||||
|  |     function random(n) { | ||||||
| function random(n) { |         var wait = n.randomFirst + (n.diff * Math.random()); | ||||||
|     var wait = n.randomFirst + (n.diff * Math.random()); |         if (n.buffer.length > 0) { | ||||||
|     if (n.buffer.length > 0) { |             n.send(n.buffer.pop()); | ||||||
|         n.send(n.buffer.pop()); |             n.randomID = setTimeout(function() {random(n);},wait); | ||||||
|         n.randomID = setTimeout(function() {random(n);},wait); |         } else { | ||||||
|     } else { |             n.randomID = -1; | ||||||
|         n.randomID = -1; |         } | ||||||
|     } |     } | ||||||
| } |      | ||||||
|  |     function DelayNode(n) { | ||||||
| function DelayNode(n) { |         RED.nodes.createNode(this,n); | ||||||
|     RED.nodes.createNode(this,n); |      | ||||||
|  |         this.pauseType = n.pauseType; | ||||||
|     this.pauseType = n.pauseType; |         this.timeoutUnits = n.timeoutUnits; | ||||||
|     this.timeoutUnits = n.timeoutUnits; |         this.randomUnits = n.randomUnits; | ||||||
|     this.randomUnits = n.randomUnits; |         this.rateUnits = n.rateUnits; | ||||||
|     this.rateUnits = n.rateUnits; |      | ||||||
|  |         if (n.timeoutUnits === "milliseconds") { | ||||||
|     if (n.timeoutUnits === "milliseconds") { |             this.timeout = n.timeout; | ||||||
|         this.timeout = n.timeout; |         } else if (n.timeoutUnits === "seconds") { | ||||||
|     } else if (n.timeoutUnits === "seconds") { |             this.timeout = n.timeout * 1000; | ||||||
|         this.timeout = n.timeout * 1000; |         } else if (n.timeoutUnits === "minutes") { | ||||||
|     } else if (n.timeoutUnits === "minutes") { |             this.timeout = n.timeout * (60 * 1000); | ||||||
|         this.timeout = n.timeout * (60 * 1000); |         } else if (n.timeoutUnits === "hours") { | ||||||
|     } else if (n.timeoutUnits === "hours") { |             this.timeout = n.timeout * (60 * 60 * 1000); | ||||||
|         this.timeout = n.timeout * (60 * 60 * 1000); |         } else if (n.timeoutUnits === "days") { | ||||||
|     } else if (n.timeoutUnits === "days") { |             this.timeout = n.timeout * (24 * 60 * 60 * 1000); | ||||||
|         this.timeout = n.timeout * (24 * 60 * 60 * 1000); |         } | ||||||
|     } |      | ||||||
|  |         if (n.rateUnits === "second") { | ||||||
|     if (n.rateUnits === "second") { |             this.rate = 1000/n.rate; | ||||||
|         this.rate = 1000/n.rate; |         } else if (n.rateUnits === "minute") { | ||||||
|     } else if (n.rateUnits === "minute") { |             this.rate = (60 * 1000)/n.rate; | ||||||
|         this.rate = (60 * 1000)/n.rate; |         } else if (n.rateUnits === "hour") { | ||||||
|     } else if (n.rateUnits === "hour") { |             this.rate = (60 * 60 * 1000)/n.rate; | ||||||
|         this.rate = (60 * 60 * 1000)/n.rate; |         } else if (n.rateUnits === "day") { | ||||||
|     } else if (n.rateUnits === "day") { |             this.rate = (24 * 60 * 60 * 1000)/n.rate; | ||||||
|         this.rate = (24 * 60 * 60 * 1000)/n.rate; |         } | ||||||
|     } |      | ||||||
|  |         if (n.randomUnits === "milliseconds") { | ||||||
|     if (n.randomUnits === "milliseconds") { |             this.randomFirst = n.randomFirst; | ||||||
|         this.randomFirst = n.randomFirst; |             this.randomLast = n.randomLast; | ||||||
|         this.randomLast = n.randomLast; |         } else if (n.randomUnits === "seconds") { | ||||||
|     } else if (n.randomUnits === "seconds") { |             this.randomFirst = n.randomFirst * 1000; | ||||||
|         this.randomFirst = n.randomFirst * 1000; |             this.randomLast = n.randomLast * 1000; | ||||||
|         this.randomLast = n.randomLast * 1000; |         } else if (n.randomUnits === "minutes") { | ||||||
|     } else if (n.randomUnits === "minutes") { |             this.randomFirst = n.randomFirst * (60 * 1000); | ||||||
|         this.randomFirst = n.randomFirst * (60 * 1000); |             this.randomLast = n.randomLast * (60 * 1000); | ||||||
|         this.randomLast = n.randomLast * (60 * 1000); |         } else if (n.randomUnits === "hours") { | ||||||
|     } else if (n.randomUnits === "hours") { |             this.randomFirst = n.randomFirst * (60 * 60 * 1000); | ||||||
|         this.randomFirst = n.randomFirst * (60 * 60 * 1000); |             this.randomLast = n.randomLast * (60 * 60 * 1000); | ||||||
|         this.randomLast = n.randomLast * (60 * 60 * 1000); |         } else if (n.randomUnits === "days") { | ||||||
|     } else if (n.randomUnits === "days") { |             this.randomFirst = n.randomFirst * (24 * 60 * 60 * 1000); | ||||||
|         this.randomFirst = n.randomFirst * (24 * 60 * 60 * 1000); |             this.randomLast = n.randomLast * (24 * 60 * 60 * 1000); | ||||||
|         this.randomLast = n.randomLast * (24 * 60 * 60 * 1000); |         } | ||||||
|     } |      | ||||||
|  |         this.diff = this.randomLast - this.randomFirst; | ||||||
|     this.diff = this.randomLast - this.randomFirst; |         this.name = n.name; | ||||||
|     this.name = n.name; |         this.idList = []; | ||||||
|     this.idList = []; |         this.buffer = []; | ||||||
|     this.buffer = []; |         this.intervalID = -1; | ||||||
|     this.intervalID = -1; |         this.randomID = -1; | ||||||
|     this.randomID = -1; |         this.lastSent = Date.now(); | ||||||
|     this.lastSent = Date.now(); |         var node = this; | ||||||
|     var node = this; |      | ||||||
|  |         if (this.pauseType === "delay") { | ||||||
|     if (this.pauseType === "delay") { |             this.on("input", function(msg) { | ||||||
|         this.on("input", function(msg) { |                 var id; | ||||||
|             var id; |                 id = setTimeout(function(){ | ||||||
|             id = setTimeout(function(){ |                     node.idList.splice(node.idList.indexOf(id),1); | ||||||
|                 node.idList.splice(node.idList.indexOf(id),1); |                     node.send(msg); | ||||||
|                 node.send(msg); |                 }, node.timeout); | ||||||
|             }, node.timeout); |                 this.idList.push(id); | ||||||
|             this.idList.push(id); |             }); | ||||||
|         }); |      | ||||||
|  |             this.on("close", function() { | ||||||
|         this.on("close", function() { |                 for (var i=0; i<this.idList.length; i++ ) { | ||||||
|             for (var i=0; i<this.idList.length; i++ ) { |                     clearTimeout(this.idList[i]); | ||||||
|                 clearTimeout(this.idList[i]); |                 } | ||||||
|             } |                 this.idList = []; | ||||||
|             this.idList = []; |             }); | ||||||
|         }); |      | ||||||
|  |         } else if (this.pauseType === "rate") { | ||||||
|     } else if (this.pauseType === "rate") { |             this.on("input", function(msg) { | ||||||
|         this.on("input", function(msg) { |                 if (node.drop) { | ||||||
|             if (node.drop) { |                     if ( node.intervalID !== -1) { | ||||||
|                 if ( node.intervalID !== -1) { |                         node.buffer.push(msg); | ||||||
|                     node.buffer.push(msg); |                         if (node.buffer.length > 1000) { | ||||||
|                     if (node.buffer.length > 1000) { |                             node.warn(this.name + " buffer exceeded 1000 messages"); | ||||||
|                         node.warn(this.name + " buffer exceeded 1000 messages"); |                         } | ||||||
|  |                     } else { | ||||||
|  |                         node.send(msg); | ||||||
|  |                         node.intervalID = setInterval(function() { | ||||||
|  |                             if (node.buffer.length === 0) { | ||||||
|  |                                 clearInterval(node.intervalID); | ||||||
|  |                                 node.intervalID = -1; | ||||||
|  |                             } | ||||||
|  |          | ||||||
|  |                             if (node.buffer.length > 0) { | ||||||
|  |                                 node.send(node.buffer.shift()); | ||||||
|  |                             } | ||||||
|  |                         },node.rate); | ||||||
|                     } |                     } | ||||||
|                 } else { |                 } else { | ||||||
|                     node.send(msg); |                     var now = Date.now(); | ||||||
|                     node.intervalID = setInterval(function() { |                     if (now-node.lastSent > node.rate) { | ||||||
|                         if (node.buffer.length === 0) { |                         node.lastSent = now; | ||||||
|                             clearInterval(node.intervalID); |                         node.send(msg); | ||||||
|                             node.intervalID = -1; |                     } | ||||||
|                         } |                 } | ||||||
|  |             }); | ||||||
|      |      | ||||||
|                         if (node.buffer.length > 0) { |             this.on("close", function() { | ||||||
|                             node.send(node.buffer.shift()); |                 clearInterval(this.intervalID); | ||||||
|                         } |                 this.buffer = []; | ||||||
|                     },node.rate); |             }); | ||||||
|  |      | ||||||
|  |         } else if (this.pauseType === "random") { | ||||||
|  |             this.on("input",function(msg){ | ||||||
|  |                 node.buffer.push(msg); | ||||||
|  |                 if (node.randomID === -1) { | ||||||
|  |                     var wait = node.randomFirst + (node.diff * Math.random()); | ||||||
|  |                     node.randomID = setTimeout(function() {random(node);},wait); | ||||||
|                 } |                 } | ||||||
|             } else { |             }); | ||||||
|                 var now = Date.now(); |      | ||||||
|                 if (now-node.lastSent > node.rate) { |             this.on("close", function (){ | ||||||
|                     node.lastSent = now; |                 if (this.randomID !== -1) { | ||||||
|                     node.send(msg); |                     clearTimeout(this.randomID); | ||||||
|                 } |                 } | ||||||
|             } |             }); | ||||||
|         }); |         } | ||||||
|  |  | ||||||
|         this.on("close", function() { |  | ||||||
|             clearInterval(this.intervalID); |  | ||||||
|             this.buffer = []; |  | ||||||
|         }); |  | ||||||
|  |  | ||||||
|     } else if (this.pauseType === "random") { |  | ||||||
|         this.on("input",function(msg){ |  | ||||||
|             node.buffer.push(msg); |  | ||||||
|             if (node.randomID === -1) { |  | ||||||
|                 var wait = node.randomFirst + (node.diff * Math.random()); |  | ||||||
|                 node.randomID = setTimeout(function() {random(node);},wait); |  | ||||||
|             } |  | ||||||
|         }); |  | ||||||
|  |  | ||||||
|         this.on("close", function (){ |  | ||||||
|             if (this.randomID !== -1) { |  | ||||||
|                 clearTimeout(this.randomID); |  | ||||||
|             } |  | ||||||
|         }); |  | ||||||
|     } |     } | ||||||
|  |     RED.nodes.registerType("delay",DelayNode); | ||||||
| } | } | ||||||
| RED.nodes.registerType("delay",DelayNode); |  | ||||||
|   | |||||||
| @@ -14,10 +14,10 @@ | |||||||
|  * limitations under the License. |  * limitations under the License. | ||||||
|  **/ |  **/ | ||||||
|  |  | ||||||
| var RED = require(process.env.NODE_RED_HOME+"/red/red"); | module.exports = function(RED) { | ||||||
|  |     function CommentNode(n) { | ||||||
| function CommentNode(n) { |         RED.nodes.createNode(this,n); | ||||||
| 	RED.nodes.createNode(this,n); |     } | ||||||
|  |      | ||||||
|  |     RED.nodes.registerType("comment",CommentNode); | ||||||
| } | } | ||||||
|  |  | ||||||
| RED.nodes.registerType("comment",CommentNode); |  | ||||||
|   | |||||||
| @@ -14,9 +14,9 @@ | |||||||
|  * limitations under the License. |  * limitations under the License. | ||||||
|  **/ |  **/ | ||||||
|  |  | ||||||
| var RED = require(process.env.NODE_RED_HOME+"/red/red"); | module.exports = function(RED) { | ||||||
|  |     function UnknownNode(n) { | ||||||
| function UnknownNode(n) { |         RED.nodes.createNode(this,n); | ||||||
|     RED.nodes.createNode(this,n); |     } | ||||||
|  |     RED.nodes.registerType("unknown",UnknownNode); | ||||||
| } | } | ||||||
| RED.nodes.registerType("unknown",UnknownNode); |  | ||||||
|   | |||||||
| @@ -14,174 +14,176 @@ | |||||||
|  * limitations under the License. |  * limitations under the License. | ||||||
|  **/ |  **/ | ||||||
|  |  | ||||||
| var RED = require(process.env.NODE_RED_HOME+"/red/red"); | module.exports = function(RED) { | ||||||
| var util = require("util"); |      | ||||||
| var firmata = require("firmata"); |     var util = require("util"); | ||||||
| var arduinoReady = false; |     var firmata = require("firmata"); | ||||||
| var thisboard = null; |     var arduinoReady = false; | ||||||
|  |     var thisboard = null; | ||||||
| // The Board Definition - this opens (and closes) the connection |      | ||||||
| function ArduinoNode(n) { |     // The Board Definition - this opens (and closes) the connection | ||||||
|     RED.nodes.createNode(this,n); |     function ArduinoNode(n) { | ||||||
|     this.device = n.device; |         RED.nodes.createNode(this,n); | ||||||
|     this.repeat = n.repeat||25; |         this.device = n.device; | ||||||
|     util.log("[firmata] Opening "+this.device); |         this.repeat = n.repeat||25; | ||||||
|     var node = this; |         util.log("[firmata] Opening "+this.device); | ||||||
|  |  | ||||||
|     node.toun = setInterval(function() { |  | ||||||
|         if (!arduinoReady) { |  | ||||||
|             if (thisboard == null) { |  | ||||||
|                 node.board = new firmata.Board(node.device, function(err) { |  | ||||||
|                     if (err) { |  | ||||||
|                         util.log("[firmata] error: "+err); |  | ||||||
|                         return; |  | ||||||
|                     } |  | ||||||
|                     arduinoReady = true; |  | ||||||
|                     thisboard = node.board; |  | ||||||
|                     clearInterval(node.toun); |  | ||||||
|                     util.log('[firmata] Arduino connected'); |  | ||||||
|                 }); |  | ||||||
|             } |  | ||||||
|             else { |  | ||||||
|                 node.board = thisboard; |  | ||||||
|                 node.board.removeAllListeners(); |  | ||||||
|                 arduinoReady = true; |  | ||||||
|                 clearInterval(node.toun); |  | ||||||
|                 node.toun = false; |  | ||||||
|                 util.log("[firmata] Arduino already connected"); |  | ||||||
|             } |  | ||||||
|         } else { util.log("[firmata] Waiting for Firmata"); } |  | ||||||
|     }, 10000); // wait for firmata to connect to arduino |  | ||||||
|  |  | ||||||
|     this.on('close', function() { |  | ||||||
|         //this.board.sp.close(function() { console.log("[firmata] Serial port closed"); arduinoReady = false; }); |  | ||||||
|         arduinoReady = false; |  | ||||||
|         if (node.toun) { |  | ||||||
|             clearInterval(node.toun); |  | ||||||
|             util.log("[firmata] arduino wait loop stopped"); |  | ||||||
|         } |  | ||||||
|         util.log("[firmata] Stopped"); |  | ||||||
|     }); |  | ||||||
| } |  | ||||||
| RED.nodes.registerType("arduino-board",ArduinoNode); |  | ||||||
|  |  | ||||||
|  |  | ||||||
| // The Input Node |  | ||||||
| function DuinoNodeIn(n) { |  | ||||||
|     RED.nodes.createNode(this,n); |  | ||||||
|     this.buttonState = -1; |  | ||||||
|     this.pin = n.pin; |  | ||||||
|     this.state = n.state; |  | ||||||
|     this.arduino = n.arduino; |  | ||||||
|     this.serverConfig = RED.nodes.getNode(this.arduino); |  | ||||||
|     if (typeof this.serverConfig === "object") { |  | ||||||
|         this.board = this.serverConfig.board; |  | ||||||
|         this.repeat = this.serverConfig.repeat; |  | ||||||
|         var node = this; |         var node = this; | ||||||
|  |      | ||||||
|         node.toui = setInterval(function() { |         node.toun = setInterval(function() { | ||||||
|             if (thisboard != null) { |             if (!arduinoReady) { | ||||||
|                 node.board = thisboard; |                 if (thisboard == null) { | ||||||
|                 clearInterval(node.toui); |                     node.board = new firmata.Board(node.device, function(err) { | ||||||
|                 node.toui = false; |                         if (err) { | ||||||
|                 //console.log("i",node.state,node.pin,node.board.MODES[node.state]); |                             util.log("[firmata] error: "+err); | ||||||
|                 node.board.pinMode(node.pin, node.board.MODES[node.state]); |                             return; | ||||||
|                 node.board.setSamplingInterval(node.repeat); |  | ||||||
|                 var oldrdg = ""; |  | ||||||
|                 if (node.state == "ANALOG") { |  | ||||||
|                     node.board.analogRead(node.pin, function(data) { |  | ||||||
|                         var msg = {payload:data, topic:"A"+node.pin}; |  | ||||||
|                         if (data != oldrdg) { |  | ||||||
|                             node.send(msg); |  | ||||||
|                             oldrdg = data; |  | ||||||
|                         } |                         } | ||||||
|  |                         arduinoReady = true; | ||||||
|  |                         thisboard = node.board; | ||||||
|  |                         clearInterval(node.toun); | ||||||
|  |                         util.log('[firmata] Arduino connected'); | ||||||
|                     }); |                     }); | ||||||
|                 } |                 } | ||||||
|                 else { |                 else { | ||||||
|                     node.board.digitalRead(node.pin, function(data) { |                     node.board = thisboard; | ||||||
|                         var msg = {payload:data, topic:node.pin}; |                     node.board.removeAllListeners(); | ||||||
|                         node.send(msg); |                     arduinoReady = true; | ||||||
|                     }); |                     clearInterval(node.toun); | ||||||
|  |                     node.toun = false; | ||||||
|  |                     util.log("[firmata] Arduino already connected"); | ||||||
|                 } |                 } | ||||||
|             } |             } else { util.log("[firmata] Waiting for Firmata"); } | ||||||
|             else { node.log("Waiting for Arduino"); } |         }, 10000); // wait for firmata to connect to arduino | ||||||
|         }, 5000); // loop to wait for firmata to connect to arduino |      | ||||||
|  |  | ||||||
|         this.on('close', function() { |         this.on('close', function() { | ||||||
|             if (node.toui) { |             //this.board.sp.close(function() { console.log("[firmata] Serial port closed"); arduinoReady = false; }); | ||||||
|                 clearInterval(node.toui); |             arduinoReady = false; | ||||||
|                 util.log("[firmata] input wait loop stopped"); |             if (node.toun) { | ||||||
|  |                 clearInterval(node.toun); | ||||||
|  |                 util.log("[firmata] arduino wait loop stopped"); | ||||||
|             } |             } | ||||||
|  |             util.log("[firmata] Stopped"); | ||||||
|         }); |         }); | ||||||
|     } |     } | ||||||
|     else { |     RED.nodes.registerType("arduino-board",ArduinoNode); | ||||||
|         util.log("[firmata] Serial Port not Configured"); |      | ||||||
|  |      | ||||||
|  |     // The Input Node | ||||||
|  |     function DuinoNodeIn(n) { | ||||||
|  |         RED.nodes.createNode(this,n); | ||||||
|  |         this.buttonState = -1; | ||||||
|  |         this.pin = n.pin; | ||||||
|  |         this.state = n.state; | ||||||
|  |         this.arduino = n.arduino; | ||||||
|  |         this.serverConfig = RED.nodes.getNode(this.arduino); | ||||||
|  |         if (typeof this.serverConfig === "object") { | ||||||
|  |             this.board = this.serverConfig.board; | ||||||
|  |             this.repeat = this.serverConfig.repeat; | ||||||
|  |             var node = this; | ||||||
|  |      | ||||||
|  |             node.toui = setInterval(function() { | ||||||
|  |                 if (thisboard != null) { | ||||||
|  |                     node.board = thisboard; | ||||||
|  |                     clearInterval(node.toui); | ||||||
|  |                     node.toui = false; | ||||||
|  |                     //console.log("i",node.state,node.pin,node.board.MODES[node.state]); | ||||||
|  |                     node.board.pinMode(node.pin, node.board.MODES[node.state]); | ||||||
|  |                     node.board.setSamplingInterval(node.repeat); | ||||||
|  |                     var oldrdg = ""; | ||||||
|  |                     if (node.state == "ANALOG") { | ||||||
|  |                         node.board.analogRead(node.pin, function(data) { | ||||||
|  |                             var msg = {payload:data, topic:"A"+node.pin}; | ||||||
|  |                             if (data != oldrdg) { | ||||||
|  |                                 node.send(msg); | ||||||
|  |                                 oldrdg = data; | ||||||
|  |                             } | ||||||
|  |                         }); | ||||||
|  |                     } | ||||||
|  |                     else { | ||||||
|  |                         node.board.digitalRead(node.pin, function(data) { | ||||||
|  |                             var msg = {payload:data, topic:node.pin}; | ||||||
|  |                             node.send(msg); | ||||||
|  |                         }); | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  |                 else { node.log("Waiting for Arduino"); } | ||||||
|  |             }, 5000); // loop to wait for firmata to connect to arduino | ||||||
|  |      | ||||||
|  |             this.on('close', function() { | ||||||
|  |                 if (node.toui) { | ||||||
|  |                     clearInterval(node.toui); | ||||||
|  |                     util.log("[firmata] input wait loop stopped"); | ||||||
|  |                 } | ||||||
|  |             }); | ||||||
|  |         } | ||||||
|  |         else { | ||||||
|  |             util.log("[firmata] Serial Port not Configured"); | ||||||
|  |         } | ||||||
|     } |     } | ||||||
|  |     RED.nodes.registerType("arduino in",DuinoNodeIn); | ||||||
|  |      | ||||||
|  |      | ||||||
|  |     // The Output Node | ||||||
|  |     function DuinoNodeOut(n) { | ||||||
|  |         RED.nodes.createNode(this,n); | ||||||
|  |         this.buttonState = -1; | ||||||
|  |         this.pin = n.pin; | ||||||
|  |         this.state = n.state; | ||||||
|  |         this.arduino = n.arduino; | ||||||
|  |         this.serverConfig = RED.nodes.getNode(this.arduino); | ||||||
|  |         if (typeof this.serverConfig === "object") { | ||||||
|  |             this.board = this.serverConfig.board; | ||||||
|  |             var node = this; | ||||||
|  |      | ||||||
|  |             this.on("input", function(msg) { | ||||||
|  |                 //console.log(msg); | ||||||
|  |                 if (node.board != null) { | ||||||
|  |                     if (node.state == "OUTPUT") { | ||||||
|  |                         if ((msg.payload == true)||(msg.payload == 1)||(msg.payload.toString().toLowerCase() == "on")) { | ||||||
|  |                             node.board.digitalWrite(node.pin, node.board.HIGH); | ||||||
|  |                         } | ||||||
|  |                         if ((msg.payload == false)||(msg.payload == 0)||(msg.payload.toString().toLowerCase() == "off")) { | ||||||
|  |                             node.board.digitalWrite(node.pin, node.board.LOW); | ||||||
|  |                         } | ||||||
|  |                     } | ||||||
|  |                     if (node.state == "PWM") { | ||||||
|  |                         msg.payload = msg.payload * 1; | ||||||
|  |                         if ((msg.payload >= 0) && (msg.payload <= 255)) { | ||||||
|  |                             //console.log(msg.payload, node.pin); | ||||||
|  |                             node.board.servoWrite(node.pin, msg.payload); | ||||||
|  |                         } | ||||||
|  |                     } | ||||||
|  |                     if (node.state == "SERVO") { | ||||||
|  |                         msg.payload = msg.payload * 1; | ||||||
|  |                         if ((msg.payload >= 0) && (msg.payload <= 180)) { | ||||||
|  |                             //console.log(msg.payload, node.pin); | ||||||
|  |                             node.board.servoWrite(node.pin, msg.payload); | ||||||
|  |                         } | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  |                 //else { console.log("Arduino not ready"); } | ||||||
|  |             }); | ||||||
|  |      | ||||||
|  |             node.touo = setInterval(function() { | ||||||
|  |                 if (thisboard != null) { | ||||||
|  |                     clearInterval(node.touo); | ||||||
|  |                     node.touo = false; | ||||||
|  |                     node.board = thisboard; | ||||||
|  |                     //console.log("o",node.state,node.pin,node.board.MODES[node.state]); | ||||||
|  |                     node.board.pinMode(node.pin, node.board.MODES[node.state]); | ||||||
|  |                 } | ||||||
|  |                 else { util.log("[firmata] waiting for arduino to connect"); } | ||||||
|  |             }, 5000); // loop to wait for firmata to connect to arduino | ||||||
|  |      | ||||||
|  |             this.on('close', function() { | ||||||
|  |                 if (node.touo) { | ||||||
|  |                     clearInterval(node.touo); | ||||||
|  |                     util.log("[firmata] output wait loop stopped"); | ||||||
|  |                 } | ||||||
|  |             }); | ||||||
|  |         } | ||||||
|  |         else { | ||||||
|  |             util.log("[firmata] Serial Port not Configured"); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |     RED.nodes.registerType("arduino out",DuinoNodeOut); | ||||||
| } | } | ||||||
| RED.nodes.registerType("arduino in",DuinoNodeIn); |  | ||||||
|  |  | ||||||
|  |  | ||||||
| // The Output Node |  | ||||||
| function DuinoNodeOut(n) { |  | ||||||
|     RED.nodes.createNode(this,n); |  | ||||||
|     this.buttonState = -1; |  | ||||||
|     this.pin = n.pin; |  | ||||||
|     this.state = n.state; |  | ||||||
|     this.arduino = n.arduino; |  | ||||||
|     this.serverConfig = RED.nodes.getNode(this.arduino); |  | ||||||
|     if (typeof this.serverConfig === "object") { |  | ||||||
|         this.board = this.serverConfig.board; |  | ||||||
|         var node = this; |  | ||||||
|  |  | ||||||
|         this.on("input", function(msg) { |  | ||||||
|             //console.log(msg); |  | ||||||
|             if (node.board != null) { |  | ||||||
|                 if (node.state == "OUTPUT") { |  | ||||||
|                     if ((msg.payload == true)||(msg.payload == 1)||(msg.payload.toString().toLowerCase() == "on")) { |  | ||||||
|                         node.board.digitalWrite(node.pin, node.board.HIGH); |  | ||||||
|                     } |  | ||||||
|                     if ((msg.payload == false)||(msg.payload == 0)||(msg.payload.toString().toLowerCase() == "off")) { |  | ||||||
|                         node.board.digitalWrite(node.pin, node.board.LOW); |  | ||||||
|                     } |  | ||||||
|                 } |  | ||||||
|                 if (node.state == "PWM") { |  | ||||||
|                     msg.payload = msg.payload * 1; |  | ||||||
|                     if ((msg.payload >= 0) && (msg.payload <= 255)) { |  | ||||||
|                         //console.log(msg.payload, node.pin); |  | ||||||
|                         node.board.servoWrite(node.pin, msg.payload); |  | ||||||
|                     } |  | ||||||
|                 } |  | ||||||
|                 if (node.state == "SERVO") { |  | ||||||
|                     msg.payload = msg.payload * 1; |  | ||||||
|                     if ((msg.payload >= 0) && (msg.payload <= 180)) { |  | ||||||
|                         //console.log(msg.payload, node.pin); |  | ||||||
|                         node.board.servoWrite(node.pin, msg.payload); |  | ||||||
|                     } |  | ||||||
|                 } |  | ||||||
|             } |  | ||||||
|             //else { console.log("Arduino not ready"); } |  | ||||||
|         }); |  | ||||||
|  |  | ||||||
|         node.touo = setInterval(function() { |  | ||||||
|             if (thisboard != null) { |  | ||||||
|                 clearInterval(node.touo); |  | ||||||
|                 node.touo = false; |  | ||||||
|                 node.board = thisboard; |  | ||||||
|                 //console.log("o",node.state,node.pin,node.board.MODES[node.state]); |  | ||||||
|                 node.board.pinMode(node.pin, node.board.MODES[node.state]); |  | ||||||
|             } |  | ||||||
|             else { util.log("[firmata] waiting for arduino to connect"); } |  | ||||||
|         }, 5000); // loop to wait for firmata to connect to arduino |  | ||||||
|  |  | ||||||
|         this.on('close', function() { |  | ||||||
|             if (node.touo) { |  | ||||||
|                 clearInterval(node.touo); |  | ||||||
|                 util.log("[firmata] output wait loop stopped"); |  | ||||||
|             } |  | ||||||
|         }); |  | ||||||
|     } |  | ||||||
|     else { |  | ||||||
|         util.log("[firmata] Serial Port not Configured"); |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| RED.nodes.registerType("arduino out",DuinoNodeOut); |  | ||||||
|   | |||||||
| @@ -14,145 +14,146 @@ | |||||||
|  * limitations under the License. |  * limitations under the License. | ||||||
|  **/ |  **/ | ||||||
|  |  | ||||||
| var RED = require(process.env.NODE_RED_HOME+"/red/red"); | module.exports = function(RED) { | ||||||
| var util = require("util"); |     var util = require("util"); | ||||||
| var exec = require('child_process').exec; |     var exec = require('child_process').exec; | ||||||
| var fs =  require('fs'); |     var fs =  require('fs'); | ||||||
|  |      | ||||||
| if (!fs.existsSync("/dev/ttyAMA0")) { // unlikely if not on a Pi |     if (!fs.existsSync("/dev/ttyAMA0")) { // unlikely if not on a Pi | ||||||
|     throw "Info : Ignoring Raspberry Pi specific node."; |         throw "Info : Ignoring Raspberry Pi specific node."; | ||||||
| } |  | ||||||
|  |  | ||||||
| if (!fs.existsSync("/usr/local/bin/gpio")) { // gpio command not installed |  | ||||||
|     throw "Info : Can't find Raspberry Pi wiringPi gpio command."; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| // Map physical P1 pins to Gordon's Wiring-Pi Pins (as they should be V1/V2 tolerant) |  | ||||||
| var pintable = { |  | ||||||
| // Physical : WiringPi |  | ||||||
|         "11":"0", |  | ||||||
|         "12":"1", |  | ||||||
|         "13":"2", |  | ||||||
|         "15":"3", |  | ||||||
|         "16":"4", |  | ||||||
|         "18":"5", |  | ||||||
|         "22":"6", |  | ||||||
|          "7":"7", |  | ||||||
|          "3":"8", |  | ||||||
|          "5":"9", |  | ||||||
|         "24":"10", |  | ||||||
|         "26":"11", |  | ||||||
|         "19":"12", |  | ||||||
|         "21":"13", |  | ||||||
|         "23":"14", |  | ||||||
|          "8":"15", |  | ||||||
|         "10":"16" |  | ||||||
| } |  | ||||||
| var tablepin = { |  | ||||||
| // WiringPi : Physical |  | ||||||
|         "0":"11", |  | ||||||
|         "1":"12", |  | ||||||
|         "2":"13", |  | ||||||
|         "3":"15", |  | ||||||
|         "4":"16", |  | ||||||
|         "5":"18", |  | ||||||
|         "6":"22", |  | ||||||
|         "7":"7", |  | ||||||
|         "8":"3", |  | ||||||
|         "9":"5", |  | ||||||
|        "10":"24", |  | ||||||
|        "11":"26", |  | ||||||
|        "12":"19", |  | ||||||
|        "13":"21", |  | ||||||
|        "14":"23", |  | ||||||
|        "15":"8", |  | ||||||
|        "16":"10" |  | ||||||
| } |  | ||||||
|  |  | ||||||
| function GPIOInNode(n) { |  | ||||||
|     RED.nodes.createNode(this,n); |  | ||||||
|     this.buttonState = -1; |  | ||||||
|     this.pin = pintable[n.pin]; |  | ||||||
|     this.intype = n.intype; |  | ||||||
|     var node = this; |  | ||||||
|  |  | ||||||
|     if (this.pin) { |  | ||||||
|         exec("gpio mode "+node.pin+" "+node.intype, function(err,stdout,stderr) { |  | ||||||
|             if (err) node.error(err); |  | ||||||
|             else { |  | ||||||
|                 node._interval = setInterval( function() { |  | ||||||
|                     exec("gpio 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/"+tablepin[node.pin], payload:node.buttonState}; |  | ||||||
|                                     node.send(msg); |  | ||||||
|                                 } |  | ||||||
|                             } |  | ||||||
|                         } |  | ||||||
|                     }); |  | ||||||
|                 }, 250); |  | ||||||
|             } |  | ||||||
|         }); |  | ||||||
|     } |     } | ||||||
|     else { |      | ||||||
|         this.error("Invalid GPIO pin: "+this.pin); |     if (!fs.existsSync("/usr/local/bin/gpio")) { // gpio command not installed | ||||||
|  |         throw "Info : Can't find Raspberry Pi wiringPi gpio command."; | ||||||
|     } |     } | ||||||
|  |      | ||||||
|     this.on("close", function() { |     // Map physical P1 pins to Gordon's Wiring-Pi Pins (as they should be V1/V2 tolerant) | ||||||
|         clearInterval(this._interval); |     var pintable = { | ||||||
|     }); |     // Physical : WiringPi | ||||||
| } |             "11":"0", | ||||||
|  |             "12":"1", | ||||||
| function GPIOOutNode(n) { |             "13":"2", | ||||||
|     RED.nodes.createNode(this,n); |             "15":"3", | ||||||
|     this.pin = pintable[n.pin]; |             "16":"4", | ||||||
|     var node = this; |             "18":"5", | ||||||
|  |             "22":"6", | ||||||
|     if (this.pin) { |              "7":"7", | ||||||
|         process.nextTick(function() { |              "3":"8", | ||||||
|             exec("gpio mode "+node.pin+" out", function(err,stdout,stderr) { |              "5":"9", | ||||||
|  |             "24":"10", | ||||||
|  |             "26":"11", | ||||||
|  |             "19":"12", | ||||||
|  |             "21":"13", | ||||||
|  |             "23":"14", | ||||||
|  |              "8":"15", | ||||||
|  |             "10":"16" | ||||||
|  |     } | ||||||
|  |     var tablepin = { | ||||||
|  |     // WiringPi : Physical | ||||||
|  |             "0":"11", | ||||||
|  |             "1":"12", | ||||||
|  |             "2":"13", | ||||||
|  |             "3":"15", | ||||||
|  |             "4":"16", | ||||||
|  |             "5":"18", | ||||||
|  |             "6":"22", | ||||||
|  |             "7":"7", | ||||||
|  |             "8":"3", | ||||||
|  |             "9":"5", | ||||||
|  |            "10":"24", | ||||||
|  |            "11":"26", | ||||||
|  |            "12":"19", | ||||||
|  |            "13":"21", | ||||||
|  |            "14":"23", | ||||||
|  |            "15":"8", | ||||||
|  |            "16":"10" | ||||||
|  |     } | ||||||
|  |      | ||||||
|  |     function GPIOInNode(n) { | ||||||
|  |         RED.nodes.createNode(this,n); | ||||||
|  |         this.buttonState = -1; | ||||||
|  |         this.pin = pintable[n.pin]; | ||||||
|  |         this.intype = n.intype; | ||||||
|  |         var node = this; | ||||||
|  |      | ||||||
|  |         if (this.pin) { | ||||||
|  |             exec("gpio mode "+node.pin+" "+node.intype, function(err,stdout,stderr) { | ||||||
|                 if (err) node.error(err); |                 if (err) node.error(err); | ||||||
|                 else { |                 else { | ||||||
|                     node.on("input", function(msg) { |                     node._interval = setInterval( function() { | ||||||
|                         if (msg.payload === "true") msg.payload = true; |                         exec("gpio read "+node.pin, function(err,stdout,stderr) { | ||||||
|                         if (msg.payload === "false") msg.payload = false; |                             if (err) node.error(err); | ||||||
|                         var out = Number(msg.payload); |                             else { | ||||||
|                         if ((out == 0)|(out == 1)) { |                                 if (node.buttonState !== Number(stdout)) { | ||||||
|                             exec("gpio write "+node.pin+" "+out, function(err,stdout,stderr) { |                                     var previousState = node.buttonState; | ||||||
|                                 if (err) node.error(err); |                                     node.buttonState = Number(stdout); | ||||||
|                             }); |                                     if (previousState !== -1) { | ||||||
|                         } |                                         var msg = {topic:"pi/"+tablepin[node.pin], payload:node.buttonState}; | ||||||
|                         else node.warn("Invalid input - not 0 or 1"); |                                         node.send(msg); | ||||||
|                     }); |                                     } | ||||||
|  |                                 } | ||||||
|  |                             } | ||||||
|  |                         }); | ||||||
|  |                     }, 250); | ||||||
|                 } |                 } | ||||||
|             }); |             }); | ||||||
|  |         } | ||||||
|  |         else { | ||||||
|  |             this.error("Invalid GPIO pin: "+this.pin); | ||||||
|  |         } | ||||||
|  |      | ||||||
|  |         this.on("close", function() { | ||||||
|  |             clearInterval(this._interval); | ||||||
|         }); |         }); | ||||||
|     } |     } | ||||||
|     else { |      | ||||||
|         this.error("Invalid GPIO pin: "+this.pin); |     function GPIOOutNode(n) { | ||||||
|  |         RED.nodes.createNode(this,n); | ||||||
|  |         this.pin = pintable[n.pin]; | ||||||
|  |         var node = this; | ||||||
|  |      | ||||||
|  |         if (this.pin) { | ||||||
|  |             process.nextTick(function() { | ||||||
|  |                 exec("gpio mode "+node.pin+" out", function(err,stdout,stderr) { | ||||||
|  |                     if (err) node.error(err); | ||||||
|  |                     else { | ||||||
|  |                         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 write "+node.pin+" "+out, function(err,stdout,stderr) { | ||||||
|  |                                     if (err) node.error(err); | ||||||
|  |                                 }); | ||||||
|  |                             } | ||||||
|  |                             else node.warn("Invalid input - not 0 or 1"); | ||||||
|  |                         }); | ||||||
|  |                     } | ||||||
|  |                 }); | ||||||
|  |             }); | ||||||
|  |         } | ||||||
|  |         else { | ||||||
|  |             this.error("Invalid GPIO pin: "+this.pin); | ||||||
|  |         } | ||||||
|  |      | ||||||
|  |         this.on("close", function() { | ||||||
|  |             exec("gpio mode "+this.pin+" in"); | ||||||
|  |         }); | ||||||
|     } |     } | ||||||
|  |      | ||||||
|     this.on("close", function() { |     exec("gpio mode 0 in",function(err,stdout,stderr) { | ||||||
|         exec("gpio mode "+this.pin+" in"); |         if (err) { | ||||||
|  |             util.log('[36-rpi-gpio.js] Error: "gpio" command failed for some reason.'); | ||||||
|  |         } | ||||||
|  |         exec("gpio mode 1 in"); | ||||||
|  |         exec("gpio mode 2 in"); | ||||||
|  |         exec("gpio mode 3 in"); | ||||||
|  |         exec("gpio mode 4 in"); | ||||||
|  |         exec("gpio mode 5 in"); | ||||||
|  |         exec("gpio mode 6 in"); | ||||||
|  |         exec("gpio mode 7 in"); | ||||||
|     }); |     }); | ||||||
|  |      | ||||||
|  |     RED.nodes.registerType("rpi-gpio in",GPIOInNode); | ||||||
|  |     RED.nodes.registerType("rpi-gpio out",GPIOOutNode); | ||||||
| } | } | ||||||
|  |  | ||||||
| exec("gpio mode 0 in",function(err,stdout,stderr) { |  | ||||||
|     if (err) { |  | ||||||
|         util.log('[36-rpi-gpio.js] Error: "gpio" command failed for some reason.'); |  | ||||||
|     } |  | ||||||
|     exec("gpio mode 1 in"); |  | ||||||
|     exec("gpio mode 2 in"); |  | ||||||
|     exec("gpio mode 3 in"); |  | ||||||
|     exec("gpio mode 4 in"); |  | ||||||
|     exec("gpio mode 5 in"); |  | ||||||
|     exec("gpio mode 6 in"); |  | ||||||
|     exec("gpio mode 7 in"); |  | ||||||
| }); |  | ||||||
|  |  | ||||||
| RED.nodes.registerType("rpi-gpio in",GPIOInNode); |  | ||||||
| RED.nodes.registerType("rpi-gpio out",GPIOOutNode); |  | ||||||
|   | |||||||
| @@ -14,122 +14,124 @@ | |||||||
|  * limitations under the License. |  * limitations under the License. | ||||||
|  **/ |  **/ | ||||||
|  |  | ||||||
| var RED = require(process.env.NODE_RED_HOME+"/red/red"); | module.exports = function(RED) { | ||||||
| var connectionPool = require("./lib/mqttConnectionPool"); |      | ||||||
| var util = require("util"); |     var connectionPool = require("./lib/mqttConnectionPool"); | ||||||
|  |     var util = require("util"); | ||||||
| function MQTTBrokerNode(n) { |      | ||||||
|     RED.nodes.createNode(this,n); |     function MQTTBrokerNode(n) { | ||||||
|     this.broker = n.broker; |         RED.nodes.createNode(this,n); | ||||||
|     this.port = n.port; |         this.broker = n.broker; | ||||||
|     this.clientid = n.clientid; |         this.port = n.port; | ||||||
|     var credentials = RED.nodes.getCredentials(n.id); |         this.clientid = n.clientid; | ||||||
|     if (credentials) { |         var credentials = RED.nodes.getCredentials(n.id); | ||||||
|         this.username = credentials.user; |         if (credentials) { | ||||||
|         this.password = credentials.password; |             this.username = credentials.user; | ||||||
|     }   |             this.password = credentials.password; | ||||||
| } |         }   | ||||||
| RED.nodes.registerType("mqtt-broker",MQTTBrokerNode); |  | ||||||
|  |  | ||||||
| var querystring = require('querystring'); |  | ||||||
|  |  | ||||||
| RED.httpAdmin.get('/mqtt-broker/: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.nodes.registerType("mqtt-broker",MQTTBrokerNode); | ||||||
|  |      | ||||||
| RED.httpAdmin.delete('/mqtt-broker/:id',function(req,res) { |     var querystring = require('querystring'); | ||||||
|     RED.nodes.deleteCredentials(req.params.id); |      | ||||||
|     res.send(200); |     RED.httpAdmin.get('/mqtt-broker/:id',function(req,res) { | ||||||
| }); |         var credentials = RED.nodes.getCredentials(req.params.id); | ||||||
|  |         if (credentials) { | ||||||
| RED.httpAdmin.post('/mqtt-broker/:id',function(req,res) { |             res.send(JSON.stringify({user:credentials.user,hasPassword:(credentials.password&&credentials.password!="")})); | ||||||
|     var body = ""; |         } else { | ||||||
|     req.on('data', function(chunk) { |             res.send(JSON.stringify({})); | ||||||
|         body+=chunk; |         } | ||||||
|     }); |     }); | ||||||
|     req.on('end', function(){ |      | ||||||
|         var newCreds = querystring.parse(body); |     RED.httpAdmin.delete('/mqtt-broker/:id',function(req,res) { | ||||||
|         var credentials = RED.nodes.getCredentials(req.params.id)||{}; |         RED.nodes.deleteCredentials(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); |         res.send(200); | ||||||
|     }); |     }); | ||||||
| }); |      | ||||||
|  |     RED.httpAdmin.post('/mqtt-broker/:id',function(req,res) { | ||||||
|  |         var body = ""; | ||||||
| function MQTTInNode(n) { |         req.on('data', function(chunk) { | ||||||
|     RED.nodes.createNode(this,n); |             body+=chunk; | ||||||
|     this.topic = n.topic; |  | ||||||
|     this.broker = n.broker; |  | ||||||
|     this.brokerConfig = RED.nodes.getNode(this.broker); |  | ||||||
|     if (this.brokerConfig) { |  | ||||||
|         this.client = connectionPool.get(this.brokerConfig.broker,this.brokerConfig.port,this.brokerConfig.clientid,this.brokerConfig.username,this.brokerConfig.password); |  | ||||||
|         var node = this; |  | ||||||
|         this.client.subscribe(this.topic,2,function(topic,payload,qos,retain) { |  | ||||||
|                 var msg = {topic:topic,payload:payload,qos:qos,retain:retain}; |  | ||||||
|                 if ((node.brokerConfig.broker == "localhost")||(node.brokerConfig.broker == "127.0.0.1")) { |  | ||||||
|                     msg._topic = topic; |  | ||||||
|                 } |  | ||||||
|                 node.send(msg); |  | ||||||
|         }); |         }); | ||||||
|         this.client.connect(); |         req.on('end', function(){ | ||||||
|     } else { |             var newCreds = querystring.parse(body); | ||||||
|         this.error("missing broker configuration"); |             var credentials = RED.nodes.getCredentials(req.params.id)||{}; | ||||||
|     } |             if (newCreds.user == null || newCreds.user == "") { | ||||||
| } |                 delete credentials.user; | ||||||
|  |             } else { | ||||||
| RED.nodes.registerType("mqtt in",MQTTInNode); |                 credentials.user = newCreds.user; | ||||||
|  |  | ||||||
| MQTTInNode.prototype.close = function() { |  | ||||||
|     if (this.client) { |  | ||||||
|         this.client.disconnect(); |  | ||||||
|     } |  | ||||||
| } |  | ||||||
|  |  | ||||||
|  |  | ||||||
| function MQTTOutNode(n) { |  | ||||||
|     RED.nodes.createNode(this,n); |  | ||||||
|  |  | ||||||
|     this.topic = n.topic; |  | ||||||
|     this.broker = n.broker; |  | ||||||
|  |  | ||||||
|     this.brokerConfig = RED.nodes.getNode(this.broker); |  | ||||||
|  |  | ||||||
|     if (this.brokerConfig) { |  | ||||||
|         this.client = connectionPool.get(this.brokerConfig.broker,this.brokerConfig.port,this.brokerConfig.clientid,this.brokerConfig.username,this.brokerConfig.password); |  | ||||||
|         this.on("input",function(msg) { |  | ||||||
|             if (msg != null) { |  | ||||||
|                 if (this.topic) { |  | ||||||
|                     msg.topic = this.topic; |  | ||||||
|                 } |  | ||||||
|                 this.client.publish(msg); |  | ||||||
|             } |             } | ||||||
|  |             if (newCreds.password == "") { | ||||||
|  |                 delete credentials.password; | ||||||
|  |             } else { | ||||||
|  |                 credentials.password = newCreds.password||credentials.password; | ||||||
|  |             } | ||||||
|  |             RED.nodes.addCredentials(req.params.id,credentials); | ||||||
|  |             res.send(200); | ||||||
|         }); |         }); | ||||||
|         this.client.connect(); |     }); | ||||||
|     } else { |      | ||||||
|         this.error("missing broker configuration"); |      | ||||||
|     } |     function MQTTInNode(n) { | ||||||
| } |         RED.nodes.createNode(this,n); | ||||||
|  |         this.topic = n.topic; | ||||||
| RED.nodes.registerType("mqtt out",MQTTOutNode); |         this.broker = n.broker; | ||||||
|  |         this.brokerConfig = RED.nodes.getNode(this.broker); | ||||||
| MQTTOutNode.prototype.close = function() { |         if (this.brokerConfig) { | ||||||
|     if (this.client) { |             this.client = connectionPool.get(this.brokerConfig.broker,this.brokerConfig.port,this.brokerConfig.clientid,this.brokerConfig.username,this.brokerConfig.password); | ||||||
|         this.client.disconnect(); |             var node = this; | ||||||
|  |             this.client.subscribe(this.topic,2,function(topic,payload,qos,retain) { | ||||||
|  |                     var msg = {topic:topic,payload:payload,qos:qos,retain:retain}; | ||||||
|  |                     if ((node.brokerConfig.broker == "localhost")||(node.brokerConfig.broker == "127.0.0.1")) { | ||||||
|  |                         msg._topic = topic; | ||||||
|  |                     } | ||||||
|  |                     node.send(msg); | ||||||
|  |             }); | ||||||
|  |             this.client.connect(); | ||||||
|  |         } else { | ||||||
|  |             this.error("missing broker configuration"); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |      | ||||||
|  |     RED.nodes.registerType("mqtt in",MQTTInNode); | ||||||
|  |      | ||||||
|  |     MQTTInNode.prototype.close = function() { | ||||||
|  |         if (this.client) { | ||||||
|  |             this.client.disconnect(); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |      | ||||||
|  |      | ||||||
|  |     function MQTTOutNode(n) { | ||||||
|  |         RED.nodes.createNode(this,n); | ||||||
|  |      | ||||||
|  |         this.topic = n.topic; | ||||||
|  |         this.broker = n.broker; | ||||||
|  |      | ||||||
|  |         this.brokerConfig = RED.nodes.getNode(this.broker); | ||||||
|  |      | ||||||
|  |         if (this.brokerConfig) { | ||||||
|  |             this.client = connectionPool.get(this.brokerConfig.broker,this.brokerConfig.port,this.brokerConfig.clientid,this.brokerConfig.username,this.brokerConfig.password); | ||||||
|  |             this.on("input",function(msg) { | ||||||
|  |                 if (msg != null) { | ||||||
|  |                     if (this.topic) { | ||||||
|  |                         msg.topic = this.topic; | ||||||
|  |                     } | ||||||
|  |                     this.client.publish(msg); | ||||||
|  |                 } | ||||||
|  |             }); | ||||||
|  |             this.client.connect(); | ||||||
|  |         } else { | ||||||
|  |             this.error("missing broker configuration"); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |      | ||||||
|  |     RED.nodes.registerType("mqtt out",MQTTOutNode); | ||||||
|  |      | ||||||
|  |     MQTTOutNode.prototype.close = function() { | ||||||
|  |         if (this.client) { | ||||||
|  |             this.client.disconnect(); | ||||||
|  |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -14,232 +14,234 @@ | |||||||
|  * limitations under the License. |  * limitations under the License. | ||||||
|  **/ |  **/ | ||||||
|  |  | ||||||
| var RED = require(process.env.NODE_RED_HOME+"/red/red"); | module.exports = function(RED) { | ||||||
| var util = require("util"); |      | ||||||
| var http = require("follow-redirects").http; |     var util = require("util"); | ||||||
| var https = require("follow-redirects").https; |     var http = require("follow-redirects").http; | ||||||
| var urllib = require("url"); |     var https = require("follow-redirects").https; | ||||||
| var express = require("express"); |     var urllib = require("url"); | ||||||
| var getBody = require('raw-body'); |     var express = require("express"); | ||||||
| var mustache = require("mustache"); |     var getBody = require('raw-body'); | ||||||
| var querystring = require("querystring"); |     var mustache = require("mustache"); | ||||||
|  |     var querystring = require("querystring"); | ||||||
| var cors = require('cors'); |      | ||||||
| var jsonParser = express.json(); |     var cors = require('cors'); | ||||||
| var urlencParser = express.urlencoded(); |     var jsonParser = express.json(); | ||||||
|  |     var urlencParser = express.urlencoded(); | ||||||
| function rawBodyParser(req, res, next) { |      | ||||||
|     if (req._body) return next(); |     function rawBodyParser(req, res, next) { | ||||||
|     req.body = ""; |         if (req._body) return next(); | ||||||
|     req._body = true; |         req.body = ""; | ||||||
|     getBody(req, { |         req._body = true; | ||||||
|         limit: '1mb', |         getBody(req, { | ||||||
|         length: req.headers['content-length'], |             limit: '1mb', | ||||||
|         encoding: 'utf8' |             length: req.headers['content-length'], | ||||||
|     }, function (err, buf) { |             encoding: 'utf8' | ||||||
|         if (err) return next(err); |         }, function (err, buf) { | ||||||
|         req.body = buf; |             if (err) return next(err); | ||||||
|         next(); |             req.body = buf; | ||||||
|     }); |             next(); | ||||||
| } |         }); | ||||||
|  |     } | ||||||
|  |      | ||||||
| function HTTPIn(n) { |      | ||||||
|     RED.nodes.createNode(this,n); |     function HTTPIn(n) { | ||||||
|     if (RED.settings.httpNodeRoot !== false) { |         RED.nodes.createNode(this,n); | ||||||
|  |         if (RED.settings.httpNodeRoot !== false) { | ||||||
|         this.url = n.url; |      | ||||||
|         this.method = n.method; |             this.url = n.url; | ||||||
|  |             this.method = n.method; | ||||||
|         var node = this; |      | ||||||
|  |             var node = this; | ||||||
|         this.errorHandler = function(err,req,res,next) { |      | ||||||
|             node.warn(err); |             this.errorHandler = function(err,req,res,next) { | ||||||
|             res.send(500); |                 node.warn(err); | ||||||
|         }; |                 res.send(500); | ||||||
|  |             }; | ||||||
|         this.callback = function(req,res) { |      | ||||||
|             if (node.method == "post") { |             this.callback = function(req,res) { | ||||||
|                 node.send({req:req,res:res,payload:req.body}); |                 if (node.method == "post") { | ||||||
|             } else if (node.method == "get") { |                     node.send({req:req,res:res,payload:req.body}); | ||||||
|                 node.send({req:req,res:res,payload:req.query}); |                 } else if (node.method == "get") { | ||||||
|             } else { |                     node.send({req:req,res:res,payload:req.query}); | ||||||
|                 node.send({req:req,res:res}); |                 } else { | ||||||
|             } |                     node.send({req:req,res:res}); | ||||||
|         } |  | ||||||
|  |  | ||||||
|         var corsHandler = function(req,res,next) { next(); } |  | ||||||
|  |  | ||||||
|         if (RED.settings.httpNodeCors) { |  | ||||||
|             corsHandler = cors(RED.settings.httpNodeCors); |  | ||||||
|             RED.httpNode.options(this.url,corsHandler); |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         if (this.method == "get") { |  | ||||||
|             RED.httpNode.get(this.url,corsHandler,this.callback,this.errorHandler); |  | ||||||
|         } else if (this.method == "post") { |  | ||||||
|             RED.httpNode.post(this.url,corsHandler,jsonParser,urlencParser,rawBodyParser,this.callback,this.errorHandler); |  | ||||||
|         } else if (this.method == "put") { |  | ||||||
|             RED.httpNode.put(this.url,corsHandler,jsonParser,urlencParser,rawBodyParser,this.callback,this.errorHandler); |  | ||||||
|         } else if (this.method == "delete") { |  | ||||||
|             RED.httpNode.delete(this.url,corsHandler,this.callback,errorHandler); |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         this.on("close",function() { |  | ||||||
|             var routes = RED.httpNode.routes[this.method]; |  | ||||||
|             for (var i = 0; i<routes.length; i++) { |  | ||||||
|                 if (routes[i].path == this.url) { |  | ||||||
|                     routes.splice(i,1); |  | ||||||
|                     //break; |  | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|  |      | ||||||
|  |             var corsHandler = function(req,res,next) { next(); } | ||||||
|  |      | ||||||
|             if (RED.settings.httpNodeCors) { |             if (RED.settings.httpNodeCors) { | ||||||
|                 var routes = RED.httpNode.routes['options']; |                 corsHandler = cors(RED.settings.httpNodeCors); | ||||||
|  |                 RED.httpNode.options(this.url,corsHandler); | ||||||
|  |             } | ||||||
|  |      | ||||||
|  |             if (this.method == "get") { | ||||||
|  |                 RED.httpNode.get(this.url,corsHandler,this.callback,this.errorHandler); | ||||||
|  |             } else if (this.method == "post") { | ||||||
|  |                 RED.httpNode.post(this.url,corsHandler,jsonParser,urlencParser,rawBodyParser,this.callback,this.errorHandler); | ||||||
|  |             } else if (this.method == "put") { | ||||||
|  |                 RED.httpNode.put(this.url,corsHandler,jsonParser,urlencParser,rawBodyParser,this.callback,this.errorHandler); | ||||||
|  |             } else if (this.method == "delete") { | ||||||
|  |                 RED.httpNode.delete(this.url,corsHandler,this.callback,errorHandler); | ||||||
|  |             } | ||||||
|  |      | ||||||
|  |             this.on("close",function() { | ||||||
|  |                 var routes = RED.httpNode.routes[this.method]; | ||||||
|                 for (var i = 0; i<routes.length; i++) { |                 for (var i = 0; i<routes.length; i++) { | ||||||
|                     if (routes[i].path == this.url) { |                     if (routes[i].path == this.url) { | ||||||
|                         routes.splice(i,1); |                         routes.splice(i,1); | ||||||
|                         //break; |                         //break; | ||||||
|                     } |                     } | ||||||
|                 } |                 } | ||||||
|             } |                 if (RED.settings.httpNodeCors) { | ||||||
|         }); |                     var routes = RED.httpNode.routes['options']; | ||||||
|     } else { |                     for (var i = 0; i<routes.length; i++) { | ||||||
|         this.warn("Cannot create http-in node when httpNodeRoot set to false"); |                         if (routes[i].path == this.url) { | ||||||
|     } |                             routes.splice(i,1); | ||||||
| } |                             //break; | ||||||
| RED.nodes.registerType("http in",HTTPIn); |  | ||||||
|  |  | ||||||
|  |  | ||||||
| function HTTPOut(n) { |  | ||||||
|     RED.nodes.createNode(this,n); |  | ||||||
|     var node = this; |  | ||||||
|     this.on("input",function(msg) { |  | ||||||
|         if (msg.res) { |  | ||||||
|             if (msg.headers) { |  | ||||||
|                 msg.res.set(msg.headers); |  | ||||||
|             } |  | ||||||
|             var statusCode = msg.statusCode || 200; |  | ||||||
|             if (typeof msg.payload == "object" && !Buffer.isBuffer(msg.payload)) { |  | ||||||
|                 msg.res.jsonp(statusCode,msg.payload); |  | ||||||
|             } else { |  | ||||||
|                 msg.res.send(statusCode,msg.payload); |  | ||||||
|             } |  | ||||||
|         } else { |  | ||||||
|             node.warn("No response object"); |  | ||||||
|         } |  | ||||||
|     }); |  | ||||||
| } |  | ||||||
| RED.nodes.registerType("http response",HTTPOut); |  | ||||||
|  |  | ||||||
| function HTTPRequest(n) { |  | ||||||
|     RED.nodes.createNode(this,n); |  | ||||||
|     var nodeUrl = n.url; |  | ||||||
|     var isTemplatedUrl = (nodeUrl||"").indexOf("{{") != -1; |  | ||||||
|     var nodeMethod = n.method || "GET"; |  | ||||||
|     var node = this; |  | ||||||
|     var credentials = RED.nodes.getCredentials(n.id); |  | ||||||
|     this.on("input",function(msg) { |  | ||||||
|             var url; |  | ||||||
|             if (msg.url) { |  | ||||||
|                 url = msg.url; |  | ||||||
|             } else if (isTemplatedUrl) { |  | ||||||
|                 url = mustache.render(nodeUrl,msg); |  | ||||||
|             } else { |  | ||||||
|                 url = nodeUrl; |  | ||||||
|             } |  | ||||||
|             var method = (msg.method||nodeMethod).toUpperCase(); |  | ||||||
|             var opts = urllib.parse(url); |  | ||||||
|             opts.method = method; |  | ||||||
|             opts.headers = {}; |  | ||||||
|             if (msg.headers) { |  | ||||||
|                 for (var v in msg.headers) { |  | ||||||
|                     opts.headers[v.toLowerCase()] = msg.headers[v]; |  | ||||||
|                 } |  | ||||||
|             } |  | ||||||
|             if (credentials) { |  | ||||||
|                 opts.auth = credentials.user+":"+(credentials.password||""); |  | ||||||
|             } |  | ||||||
|              |  | ||||||
|             var payload = null; |  | ||||||
|              |  | ||||||
|             if (msg.payload && (method == "POST" || method == "PUT") ) { |  | ||||||
|                 if (typeof msg.payload === "string" || Buffer.isBuffer(msg.payload)) { |  | ||||||
|                     payload = msg.payload; |  | ||||||
|                 } else if (typeof msg.payload == "number") { |  | ||||||
|                     payload = msg.payload+""; |  | ||||||
|                 } else { |  | ||||||
|                     if (opts.headers['content-type'] == 'application/x-www-form-urlencoded') { |  | ||||||
|                         payload = querystring.stringify(msg.payload); |  | ||||||
|                     } else { |  | ||||||
|                         payload = JSON.stringify(msg.payload); |  | ||||||
|                         if (opts.headers['content-type'] == null) { |  | ||||||
|                             opts.headers['content-type'] = "application/json"; |  | ||||||
|                         } |                         } | ||||||
|                     } |                     } | ||||||
|                 } |                 } | ||||||
|                 if (opts.headers['content-length'] == null) { |             }); | ||||||
|                     opts.headers['content-length'] = Buffer.byteLength(payload); |         } else { | ||||||
|  |             this.warn("Cannot create http-in node when httpNodeRoot set to false"); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |     RED.nodes.registerType("http in",HTTPIn); | ||||||
|  |      | ||||||
|  |      | ||||||
|  |     function HTTPOut(n) { | ||||||
|  |         RED.nodes.createNode(this,n); | ||||||
|  |         var node = this; | ||||||
|  |         this.on("input",function(msg) { | ||||||
|  |             if (msg.res) { | ||||||
|  |                 if (msg.headers) { | ||||||
|  |                     msg.res.set(msg.headers); | ||||||
|                 } |                 } | ||||||
|  |                 var statusCode = msg.statusCode || 200; | ||||||
|  |                 if (typeof msg.payload == "object" && !Buffer.isBuffer(msg.payload)) { | ||||||
|  |                     msg.res.jsonp(statusCode,msg.payload); | ||||||
|  |                 } else { | ||||||
|  |                     msg.res.send(statusCode,msg.payload); | ||||||
|  |                 } | ||||||
|  |             } else { | ||||||
|  |                 node.warn("No response object"); | ||||||
|             } |             } | ||||||
|              |         }); | ||||||
|             var req = ((/^https/.test(url))?https:http).request(opts,function(res) { |     } | ||||||
|                 res.setEncoding('utf8'); |     RED.nodes.registerType("http response",HTTPOut); | ||||||
|                 msg.statusCode = res.statusCode; |      | ||||||
|                 msg.headers = res.headers; |     function HTTPRequest(n) { | ||||||
|                 msg.payload = ""; |         RED.nodes.createNode(this,n); | ||||||
|                 res.on('data',function(chunk) { |         var nodeUrl = n.url; | ||||||
|                     msg.payload += chunk; |         var isTemplatedUrl = (nodeUrl||"").indexOf("{{") != -1; | ||||||
|  |         var nodeMethod = n.method || "GET"; | ||||||
|  |         var node = this; | ||||||
|  |         var credentials = RED.nodes.getCredentials(n.id); | ||||||
|  |         this.on("input",function(msg) { | ||||||
|  |                 var url; | ||||||
|  |                 if (msg.url) { | ||||||
|  |                     url = msg.url; | ||||||
|  |                 } else if (isTemplatedUrl) { | ||||||
|  |                     url = mustache.render(nodeUrl,msg); | ||||||
|  |                 } else { | ||||||
|  |                     url = nodeUrl; | ||||||
|  |                 } | ||||||
|  |                 var method = (msg.method||nodeMethod).toUpperCase(); | ||||||
|  |                 var opts = urllib.parse(url); | ||||||
|  |                 opts.method = method; | ||||||
|  |                 opts.headers = {}; | ||||||
|  |                 if (msg.headers) { | ||||||
|  |                     for (var v in msg.headers) { | ||||||
|  |                         opts.headers[v.toLowerCase()] = msg.headers[v]; | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  |                 if (credentials) { | ||||||
|  |                     opts.auth = credentials.user+":"+(credentials.password||""); | ||||||
|  |                 } | ||||||
|  |                  | ||||||
|  |                 var payload = null; | ||||||
|  |                  | ||||||
|  |                 if (msg.payload && (method == "POST" || method == "PUT") ) { | ||||||
|  |                     if (typeof msg.payload === "string" || Buffer.isBuffer(msg.payload)) { | ||||||
|  |                         payload = msg.payload; | ||||||
|  |                     } else if (typeof msg.payload == "number") { | ||||||
|  |                         payload = msg.payload+""; | ||||||
|  |                     } else { | ||||||
|  |                         if (opts.headers['content-type'] == 'application/x-www-form-urlencoded') { | ||||||
|  |                             payload = querystring.stringify(msg.payload); | ||||||
|  |                         } else { | ||||||
|  |                             payload = JSON.stringify(msg.payload); | ||||||
|  |                             if (opts.headers['content-type'] == null) { | ||||||
|  |                                 opts.headers['content-type'] = "application/json"; | ||||||
|  |                             } | ||||||
|  |                         } | ||||||
|  |                     } | ||||||
|  |                     if (opts.headers['content-length'] == null) { | ||||||
|  |                         opts.headers['content-length'] = Buffer.byteLength(payload); | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  |                  | ||||||
|  |                 var req = ((/^https/.test(url))?https:http).request(opts,function(res) { | ||||||
|  |                     res.setEncoding('utf8'); | ||||||
|  |                     msg.statusCode = res.statusCode; | ||||||
|  |                     msg.headers = res.headers; | ||||||
|  |                     msg.payload = ""; | ||||||
|  |                     res.on('data',function(chunk) { | ||||||
|  |                         msg.payload += chunk; | ||||||
|  |                     }); | ||||||
|  |                     res.on('end',function() { | ||||||
|  |                         node.send(msg); | ||||||
|  |                     }); | ||||||
|                 }); |                 }); | ||||||
|                 res.on('end',function() { |                 req.on('error',function(err) { | ||||||
|  |                     msg.payload = err.toString(); | ||||||
|  |                     msg.statusCode = err.code; | ||||||
|                     node.send(msg); |                     node.send(msg); | ||||||
|                 }); |                 }); | ||||||
|             }); |                 if (payload) { | ||||||
|             req.on('error',function(err) { |                     req.write(payload); | ||||||
|                 msg.payload = err.toString(); |                 } | ||||||
|                 msg.statusCode = err.code; |                 req.end(); | ||||||
|                 node.send(msg); |         }); | ||||||
|             }); |  | ||||||
|             if (payload) { |  | ||||||
|                 req.write(payload); |  | ||||||
|             } |  | ||||||
|             req.end(); |  | ||||||
|     }); |  | ||||||
| } |  | ||||||
| RED.nodes.registerType("http request",HTTPRequest); |  | ||||||
|  |  | ||||||
| RED.httpAdmin.get('/http-request/: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.nodes.registerType("http request",HTTPRequest); | ||||||
|  |      | ||||||
| RED.httpAdmin.delete('/http-request/:id',function(req,res) { |     RED.httpAdmin.get('/http-request/:id',function(req,res) { | ||||||
|     RED.nodes.deleteCredentials(req.params.id); |         var credentials = RED.nodes.getCredentials(req.params.id); | ||||||
|     res.send(200); |         if (credentials) { | ||||||
| }); |             res.send(JSON.stringify({user:credentials.user,hasPassword:(credentials.password&&credentials.password!="")})); | ||||||
|  |         } else { | ||||||
| RED.httpAdmin.post('/http-request/:id',function(req,res) { |             res.send(JSON.stringify({})); | ||||||
|     var body = ""; |         } | ||||||
|     req.on('data', function(chunk) { |  | ||||||
|         body+=chunk; |  | ||||||
|     }); |     }); | ||||||
|     req.on('end', function(){ |      | ||||||
|         var newCreds = querystring.parse(body); |     RED.httpAdmin.delete('/http-request/:id',function(req,res) { | ||||||
|         var credentials = RED.nodes.getCredentials(req.params.id)||{}; |         RED.nodes.deleteCredentials(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); |         res.send(200); | ||||||
|     }); |     }); | ||||||
| }); |      | ||||||
|  |     RED.httpAdmin.post('/http-request/: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); | ||||||
|  |         }); | ||||||
|  |     }); | ||||||
|  | } | ||||||
|   | |||||||
| @@ -14,159 +14,160 @@ | |||||||
|  * limitations under the License. |  * limitations under the License. | ||||||
|  **/ |  **/ | ||||||
|  |  | ||||||
| // Require main module | module.exports = function(RED) { | ||||||
| var RED = require(process.env.NODE_RED_HOME+"/red/red"), |  | ||||||
|     ws = require("ws"), |  | ||||||
|     inspect = require("sys").inspect; |  | ||||||
|  |  | ||||||
| // A node red node that sets up a local websocket server |  | ||||||
| function WebSocketListenerNode(n) { |  | ||||||
|     // Create a RED node |  | ||||||
|     RED.nodes.createNode(this,n); |  | ||||||
|  |  | ||||||
|     var node = this; |  | ||||||
|  |  | ||||||
|     // Store local copies of the node configuration (as defined in the .html) |  | ||||||
|     node.path = n.path; |  | ||||||
|     node.wholemsg = (n.wholemsg === "true"); |  | ||||||
|      |      | ||||||
|     node._inputNodes = [];    // collection of nodes that want to receive events |     var ws = require("ws"), | ||||||
|  |         inspect = require("sys").inspect; | ||||||
|     var path = RED.settings.httpNodeRoot || "/"; |  | ||||||
|     path = path + (path.slice(-1) == "/" ? "":"/") + (node.path.charAt(0) == "/" ? node.path.substring(1) : node.path); |  | ||||||
|  |  | ||||||
|     // Workaround https://github.com/einaros/ws/pull/253 |  | ||||||
|     // Listen for 'newListener' events from RED.server |  | ||||||
|     node._serverListeners = {}; |  | ||||||
|  |  | ||||||
|     var storeListener = function(/*String*/event,/*function*/listener){ |  | ||||||
|         if(event == "error" || event == "upgrade" || event == "listening"){ |  | ||||||
|             node._serverListeners[event] = listener; |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     node._clients = {}; |  | ||||||
|      |      | ||||||
|     RED.server.addListener('newListener',storeListener); |     // A node red node that sets up a local websocket server | ||||||
|  |     function WebSocketListenerNode(n) { | ||||||
|     // Create a WebSocket Server |         // Create a RED node | ||||||
|     node.server = new ws.Server({server:RED.server,path:path}); |         RED.nodes.createNode(this,n); | ||||||
|  |      | ||||||
|     // Workaround https://github.com/einaros/ws/pull/253 |         var node = this; | ||||||
|     // Stop listening for new listener events |      | ||||||
|     RED.server.removeListener('newListener',storeListener); |         // Store local copies of the node configuration (as defined in the .html) | ||||||
|  |         node.path = n.path; | ||||||
|     node.server.on('connection', function(socket){ |         node.wholemsg = (n.wholemsg === "true"); | ||||||
|         var id = (1+Math.random()*4294967295).toString(16); |  | ||||||
|         node._clients[id] = socket; |  | ||||||
|          |          | ||||||
|         socket.on('close',function() { |         node._inputNodes = [];    // collection of nodes that want to receive events | ||||||
|             delete node._clients[id]; |      | ||||||
|         }); |         var path = RED.settings.httpNodeRoot || "/"; | ||||||
|         socket.on('message',function(data,flags){ |         path = path + (path.slice(-1) == "/" ? "":"/") + (node.path.charAt(0) == "/" ? node.path.substring(1) : node.path); | ||||||
|             node.handleEvent(id,socket,'message',data,flags); |      | ||||||
|         }); |  | ||||||
|         socket.on('error', function(err) { |  | ||||||
|             node.warn("An error occured on the ws connection: "+inspect(err)); |  | ||||||
|         }); |  | ||||||
|     }); |  | ||||||
|  |  | ||||||
|     node.on("close", function() { |  | ||||||
|         // Workaround https://github.com/einaros/ws/pull/253 |         // Workaround https://github.com/einaros/ws/pull/253 | ||||||
|         // Remove listeners from RED.server |         // Listen for 'newListener' events from RED.server | ||||||
|         var listener = null; |         node._serverListeners = {}; | ||||||
|         for(var event in node._serverListeners){ |      | ||||||
|             listener = node._serverListeners[event]; |         var storeListener = function(/*String*/event,/*function*/listener){ | ||||||
|             if(typeof listener === "function"){ |             if(event == "error" || event == "upgrade" || event == "listening"){ | ||||||
|                 RED.server.removeListener(event,listener); |                 node._serverListeners[event] = listener; | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|         node._serverListeners = {}; |      | ||||||
|  |         node._clients = {}; | ||||||
|         node.server.close(); |          | ||||||
|         node._inputNodes = []; |         RED.server.addListener('newListener',storeListener); | ||||||
|     }); |      | ||||||
| } |         // Create a WebSocket Server | ||||||
| RED.nodes.registerType("websocket-listener",WebSocketListenerNode); |         node.server = new ws.Server({server:RED.server,path:path}); | ||||||
|  |      | ||||||
| WebSocketListenerNode.prototype.registerInputNode = function(/*Node*/handler){ |         // Workaround https://github.com/einaros/ws/pull/253 | ||||||
|     this._inputNodes.push(handler); |         // Stop listening for new listener events | ||||||
| } |         RED.server.removeListener('newListener',storeListener); | ||||||
|  |      | ||||||
| WebSocketListenerNode.prototype.handleEvent = function(id,/*socket*/socket,/*String*/event,/*Object*/data,/*Object*/flags){ |         node.server.on('connection', function(socket){ | ||||||
|     var msg; |             var id = (1+Math.random()*4294967295).toString(16); | ||||||
|     if (this.wholemsg) { |             node._clients[id] = socket; | ||||||
|         msg = JSON.parse(data); |              | ||||||
|     } else { |             socket.on('close',function() { | ||||||
|         msg = { |                 delete node._clients[id]; | ||||||
|             payload:data |             }); | ||||||
|  |             socket.on('message',function(data,flags){ | ||||||
|  |                 node.handleEvent(id,socket,'message',data,flags); | ||||||
|  |             }); | ||||||
|  |             socket.on('error', function(err) { | ||||||
|  |                 node.warn("An error occured on the ws connection: "+inspect(err)); | ||||||
|  |             }); | ||||||
|  |         }); | ||||||
|  |      | ||||||
|  |         node.on("close", function() { | ||||||
|  |             // Workaround https://github.com/einaros/ws/pull/253 | ||||||
|  |             // Remove listeners from RED.server | ||||||
|  |             var listener = null; | ||||||
|  |             for(var event in node._serverListeners){ | ||||||
|  |                 listener = node._serverListeners[event]; | ||||||
|  |                 if(typeof listener === "function"){ | ||||||
|  |                     RED.server.removeListener(event,listener); | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |             node._serverListeners = {}; | ||||||
|  |      | ||||||
|  |             node.server.close(); | ||||||
|  |             node._inputNodes = []; | ||||||
|  |         }); | ||||||
|  |     } | ||||||
|  |     RED.nodes.registerType("websocket-listener",WebSocketListenerNode); | ||||||
|  |      | ||||||
|  |     WebSocketListenerNode.prototype.registerInputNode = function(/*Node*/handler){ | ||||||
|  |         this._inputNodes.push(handler); | ||||||
|  |     } | ||||||
|  |      | ||||||
|  |     WebSocketListenerNode.prototype.handleEvent = function(id,/*socket*/socket,/*String*/event,/*Object*/data,/*Object*/flags){ | ||||||
|  |         var msg; | ||||||
|  |         if (this.wholemsg) { | ||||||
|  |             msg = JSON.parse(data); | ||||||
|  |         } else { | ||||||
|  |             msg = { | ||||||
|  |                 payload:data | ||||||
|  |             }; | ||||||
|  |         } | ||||||
|  |         msg._session = {type:"websocket",id:id}; | ||||||
|  |          | ||||||
|  |         for (var i = 0; i < this._inputNodes.length; i++) { | ||||||
|  |             this._inputNodes[i].send(msg); | ||||||
|         }; |         }; | ||||||
|     } |     } | ||||||
|     msg._session = {type:"websocket",id:id}; |  | ||||||
|      |      | ||||||
|     for (var i = 0; i < this._inputNodes.length; i++) { |     WebSocketListenerNode.prototype.broadcast = function(data){ | ||||||
|         this._inputNodes[i].send(msg); |         for(var i in this.server.clients){ | ||||||
|     }; |             this.server.clients[i].send(data); | ||||||
| } |         }; | ||||||
|  |  | ||||||
| WebSocketListenerNode.prototype.broadcast = function(data){ |  | ||||||
|     for(var i in this.server.clients){ |  | ||||||
|         this.server.clients[i].send(data); |  | ||||||
|     }; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| WebSocketListenerNode.prototype.send = function(id,data){ |  | ||||||
|     var session = this._clients[id]; |  | ||||||
|     if (session) { |  | ||||||
|         session.send(data); |  | ||||||
|     } |     } | ||||||
| } |      | ||||||
|  |     WebSocketListenerNode.prototype.send = function(id,data){ | ||||||
| function WebSocketInNode(n) { |         var session = this._clients[id]; | ||||||
|     RED.nodes.createNode(this,n); |         if (session) { | ||||||
|     this.server = n.server; |             session.send(data); | ||||||
|     var node = this; |  | ||||||
|     this.serverConfig = RED.nodes.getNode(this.server); |  | ||||||
|     if (this.serverConfig) { |  | ||||||
|         this.serverConfig.registerInputNode(this); |  | ||||||
|     } else { |  | ||||||
|         this.error("Missing server configuration"); |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| RED.nodes.registerType("websocket in",WebSocketInNode); |  | ||||||
|  |  | ||||||
| function WebSocketOutNode(n) { |  | ||||||
|     RED.nodes.createNode(this,n); |  | ||||||
|     var node = this; |  | ||||||
|     this.server = n.server; |  | ||||||
|     this.serverConfig = RED.nodes.getNode(this.server); |  | ||||||
|     if (!this.serverConfig) { |  | ||||||
|         this.error("Missing server configuration"); |  | ||||||
|     } |  | ||||||
|     this.on("input", function(msg) { |  | ||||||
|         var payload; |  | ||||||
|         if (this.serverConfig.wholemsg) { |  | ||||||
|             delete msg._session; |  | ||||||
|             payload = JSON.stringify(msg); |  | ||||||
|         } else { |  | ||||||
|             payload = msg.payload; |  | ||||||
|             if (Buffer.isBuffer(payload)) { |  | ||||||
|                 payload = payload.toString(); |  | ||||||
|             } else if (typeof payload === "object") { |  | ||||||
|                 payload = JSON.stringify(payload); |  | ||||||
|             } else if (typeof payload !== "string") { |  | ||||||
|                 payload = ""+payload; |  | ||||||
|             } |  | ||||||
|         } |         } | ||||||
|         if (msg._session && msg._session.type == "websocket") { |     } | ||||||
|             node.serverConfig.send(msg._session.id,payload); |      | ||||||
|  |     function WebSocketInNode(n) { | ||||||
|  |         RED.nodes.createNode(this,n); | ||||||
|  |         this.server = n.server; | ||||||
|  |         var node = this; | ||||||
|  |         this.serverConfig = RED.nodes.getNode(this.server); | ||||||
|  |         if (this.serverConfig) { | ||||||
|  |             this.serverConfig.registerInputNode(this); | ||||||
|         } else { |         } else { | ||||||
|             node.serverConfig.broadcast(payload,function(error){ |             this.error("Missing server configuration"); | ||||||
|                 if(!!error){ |         } | ||||||
|                     node.warn("An error occurred while sending:" + inspect(error)); |     } | ||||||
|  |     RED.nodes.registerType("websocket in",WebSocketInNode); | ||||||
|  |      | ||||||
|  |     function WebSocketOutNode(n) { | ||||||
|  |         RED.nodes.createNode(this,n); | ||||||
|  |         var node = this; | ||||||
|  |         this.server = n.server; | ||||||
|  |         this.serverConfig = RED.nodes.getNode(this.server); | ||||||
|  |         if (!this.serverConfig) { | ||||||
|  |             this.error("Missing server configuration"); | ||||||
|  |         } | ||||||
|  |         this.on("input", function(msg) { | ||||||
|  |             var payload; | ||||||
|  |             if (this.serverConfig.wholemsg) { | ||||||
|  |                 delete msg._session; | ||||||
|  |                 payload = JSON.stringify(msg); | ||||||
|  |             } else { | ||||||
|  |                 payload = msg.payload; | ||||||
|  |                 if (Buffer.isBuffer(payload)) { | ||||||
|  |                     payload = payload.toString(); | ||||||
|  |                 } else if (typeof payload === "object") { | ||||||
|  |                     payload = JSON.stringify(payload); | ||||||
|  |                 } else if (typeof payload !== "string") { | ||||||
|  |                     payload = ""+payload; | ||||||
|                 } |                 } | ||||||
|             }); |             } | ||||||
|         } |             if (msg._session && msg._session.type == "websocket") { | ||||||
|     }); |                 node.serverConfig.send(msg._session.id,payload); | ||||||
|  |             } else { | ||||||
|  |                 node.serverConfig.broadcast(payload,function(error){ | ||||||
|  |                     if(!!error){ | ||||||
|  |                         node.warn("An error occurred while sending:" + inspect(error)); | ||||||
|  |                     } | ||||||
|  |                 }); | ||||||
|  |             } | ||||||
|  |         }); | ||||||
|  |     } | ||||||
|  |     RED.nodes.registerType("websocket out",WebSocketOutNode); | ||||||
| } | } | ||||||
| RED.nodes.registerType("websocket out",WebSocketOutNode); |  | ||||||
|   | |||||||
| @@ -14,29 +14,30 @@ | |||||||
|  * limitations under the License. |  * limitations under the License. | ||||||
|  **/ |  **/ | ||||||
|  |  | ||||||
| var RED = require(process.env.NODE_RED_HOME+"/red/red"); | module.exports = function(RED) { | ||||||
| var notify = require("fs.notify"); |     var notify = require("fs.notify"); | ||||||
| var fs = require("fs"); |     var fs = require("fs"); | ||||||
| var sep = require("path").sep; |     var sep = require("path").sep; | ||||||
|  |      | ||||||
| function WatchNode(n) { |     function WatchNode(n) { | ||||||
|     RED.nodes.createNode(this,n); |         RED.nodes.createNode(this,n); | ||||||
|  |      | ||||||
|     this.files = n.files.split(","); |         this.files = n.files.split(","); | ||||||
|     for (var f in this.files) { |         for (var f in this.files) { | ||||||
|         this.files[f] = this.files[f].trim(); |             this.files[f] = this.files[f].trim(); | ||||||
|     } |         } | ||||||
|     this.p = (this.files.length == 1) ? this.files[0] : JSON.stringify(this.files); |         this.p = (this.files.length == 1) ? this.files[0] : JSON.stringify(this.files); | ||||||
|     var node = this; |         var node = this; | ||||||
|     var notifications = new notify(node.files); |         var notifications = new notify(node.files); | ||||||
|     notifications.on('change', function (file, event, path) { |         notifications.on('change', function (file, event, path) { | ||||||
|         if (fs.statSync(path).isDirectory()) { path = path + sep + file; } |             if (fs.statSync(path).isDirectory()) { path = path + sep + file; } | ||||||
|         var msg = { payload: path, topic: node.p, file: file}; |             var msg = { payload: path, topic: node.p, file: file}; | ||||||
|         node.send(msg); |             node.send(msg); | ||||||
|     }); |         }); | ||||||
|  |      | ||||||
|     this.close = function() { |         this.close = function() { | ||||||
|         notifications.close(); |             notifications.close(); | ||||||
|  |         } | ||||||
|     } |     } | ||||||
|  |     RED.nodes.registerType("watch",WatchNode); | ||||||
| } | } | ||||||
| RED.nodes.registerType("watch",WatchNode); |  | ||||||
|   | |||||||
| @@ -14,199 +14,200 @@ | |||||||
| * limitations under the License. | * limitations under the License. | ||||||
| **/ | **/ | ||||||
|  |  | ||||||
| var RED = require(process.env.NODE_RED_HOME+"/red/red"); | module.exports = function(RED) { | ||||||
| var settings = RED.settings; |     var settings = RED.settings; | ||||||
| var events = require("events"); |     var events = require("events"); | ||||||
| var util = require("util"); |     var util = require("util"); | ||||||
| var serialp = require("serialport"); |     var serialp = require("serialport"); | ||||||
|  |      | ||||||
| // TODO: 'serialPool' should be encapsulated in SerialPortNode |     // TODO: 'serialPool' should be encapsulated in SerialPortNode | ||||||
|  |      | ||||||
| function SerialPortNode(n) { |     function SerialPortNode(n) { | ||||||
|     RED.nodes.createNode(this,n); |         RED.nodes.createNode(this,n); | ||||||
|     this.serialport = n.serialport; |         this.serialport = n.serialport; | ||||||
|     this.newline = n.newline; |         this.newline = n.newline; | ||||||
|     this.addchar = n.addchar || "false"; |         this.addchar = n.addchar || "false"; | ||||||
|  |      | ||||||
|     this.serialbaud = parseInt(n.serialbaud) || 57600; |         this.serialbaud = parseInt(n.serialbaud) || 57600; | ||||||
|     this.databits = parseInt(n.databits) || 8; |         this.databits = parseInt(n.databits) || 8; | ||||||
|     this.parity = n.parity || "none"; |         this.parity = n.parity || "none"; | ||||||
|     this.stopbits = parseInt(n.stopbits) || 1; |         this.stopbits = parseInt(n.stopbits) || 1; | ||||||
| } |  | ||||||
| RED.nodes.registerType("serial-port",SerialPortNode); |  | ||||||
|  |  | ||||||
| function SerialOutNode(n) { |  | ||||||
|     RED.nodes.createNode(this,n); |  | ||||||
|     this.serial = n.serial; |  | ||||||
|     this.serialConfig = RED.nodes.getNode(this.serial); |  | ||||||
|  |  | ||||||
|     if (this.serialConfig) { |  | ||||||
|         var node = this; |  | ||||||
|         node.port = serialPool.get(this.serialConfig.serialport, |  | ||||||
|             this.serialConfig.serialbaud, |  | ||||||
|             this.serialConfig.databits, |  | ||||||
|             this.serialConfig.parity, |  | ||||||
|             this.serialConfig.stopbits, |  | ||||||
|             this.serialConfig.newline); |  | ||||||
|         node.addCh = ""; |  | ||||||
|         if (node.serialConfig.addchar == "true") { |  | ||||||
|             node.addCh = this.serialConfig.newline.replace("\\n","\n").replace("\\r","\r"); |  | ||||||
|         } |  | ||||||
|         node.on("input",function(msg) { |  | ||||||
|             var payload = msg.payload; |  | ||||||
|             if (!Buffer.isBuffer(payload)) { |  | ||||||
|                 if (typeof payload === "object") { |  | ||||||
|                     payload = JSON.stringify(payload); |  | ||||||
|                 } else { |  | ||||||
|                     payload = new String(payload); |  | ||||||
|                 } |  | ||||||
|                 payload += node.addCh; |  | ||||||
|             } else if (node.addCh !== "") { |  | ||||||
|                 payload = Buffer.concat([payload,new Buffer(node.addCh)]); |  | ||||||
|             } |  | ||||||
|             node.port.write(payload,function(err,res) { |  | ||||||
|                 if (err) { |  | ||||||
|                     node.error(err); |  | ||||||
|                 } |  | ||||||
|             }); |  | ||||||
|         }); |  | ||||||
|     } else { |  | ||||||
|         this.error("missing serial config"); |  | ||||||
|     } |     } | ||||||
|  |     RED.nodes.registerType("serial-port",SerialPortNode); | ||||||
|     this.on("close", function() { |      | ||||||
|  |     function SerialOutNode(n) { | ||||||
|  |         RED.nodes.createNode(this,n); | ||||||
|  |         this.serial = n.serial; | ||||||
|  |         this.serialConfig = RED.nodes.getNode(this.serial); | ||||||
|  |      | ||||||
|         if (this.serialConfig) { |         if (this.serialConfig) { | ||||||
|             serialPool.close(this.serialConfig.serialport); |             var node = this; | ||||||
|         } |             node.port = serialPool.get(this.serialConfig.serialport, | ||||||
|     }); |                 this.serialConfig.serialbaud, | ||||||
| } |                 this.serialConfig.databits, | ||||||
| RED.nodes.registerType("serial out",SerialOutNode); |                 this.serialConfig.parity, | ||||||
|  |                 this.serialConfig.stopbits, | ||||||
| function SerialInNode(n) { |                 this.serialConfig.newline); | ||||||
|     RED.nodes.createNode(this,n); |             node.addCh = ""; | ||||||
|     this.serial = n.serial; |             if (node.serialConfig.addchar == "true") { | ||||||
|     this.serialConfig = RED.nodes.getNode(this.serial); |                 node.addCh = this.serialConfig.newline.replace("\\n","\n").replace("\\r","\r"); | ||||||
|  |  | ||||||
|     if (this.serialConfig) { |  | ||||||
|         var node = this; |  | ||||||
|         node.port = serialPool.get(this.serialConfig.serialport, |  | ||||||
|             this.serialConfig.serialbaud, |  | ||||||
|             this.serialConfig.databits, |  | ||||||
|             this.serialConfig.parity, |  | ||||||
|             this.serialConfig.stopbits, |  | ||||||
|             this.serialConfig.newline); |  | ||||||
|         this.port.on('data', function(msg) { |  | ||||||
|             node.send({ "payload": msg }); |  | ||||||
|         }); |  | ||||||
|     } else { |  | ||||||
|         this.error("missing serial config"); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     this.on("close", function() { |  | ||||||
|         if (this.serialConfig) { |  | ||||||
|             try { |  | ||||||
|                 serialPool.close(this.serialConfig.serialport); |  | ||||||
|             } catch(err) { |  | ||||||
|             } |             } | ||||||
|         } |             node.on("input",function(msg) { | ||||||
|     }); |                 var payload = msg.payload; | ||||||
| } |                 if (!Buffer.isBuffer(payload)) { | ||||||
| RED.nodes.registerType("serial in",SerialInNode); |                     if (typeof payload === "object") { | ||||||
|  |                         payload = JSON.stringify(payload); | ||||||
|  |                     } else { | ||||||
| var serialPool = function() { |                         payload = new String(payload); | ||||||
|     var connections = {}; |  | ||||||
|     return { |  | ||||||
|         get:function(port,baud,databits,parity,stopbits,newline,callback) { |  | ||||||
|             var id = port; |  | ||||||
|             if (!connections[id]) { |  | ||||||
|                 connections[id] = function() { |  | ||||||
|                     var obj = { |  | ||||||
|                         _emitter: new events.EventEmitter(), |  | ||||||
|                         serial: null, |  | ||||||
|                         _closing: false, |  | ||||||
|                         tout: null, |  | ||||||
|                         on: function(a,b) { this._emitter.on(a,b); }, |  | ||||||
|                         close: function(cb) { this.serial.close(cb); }, |  | ||||||
|                         write: function(m,cb) { this.serial.write(m,cb); }, |  | ||||||
|                     } |                     } | ||||||
|                     newline = newline.replace("\\n","\n").replace("\\r","\r"); |                     payload += node.addCh; | ||||||
|                     var setupSerial = function() { |                 } else if (node.addCh !== "") { | ||||||
|                         if (newline == "") { |                     payload = Buffer.concat([payload,new Buffer(node.addCh)]); | ||||||
|                             obj.serial = new serialp.SerialPort(port,{ |                 } | ||||||
|                                 baudrate: baud, |                 node.port.write(payload,function(err,res) { | ||||||
|                                 databits: databits, |                     if (err) { | ||||||
|                                 parity: parity, |                         node.error(err); | ||||||
|                                 stopbits: stopbits, |                     } | ||||||
|                                 parser: serialp.parsers.raw |                 }); | ||||||
|                             },true, function(err, results) { if (err) obj.serial.emit('error',err); }); |             }); | ||||||
|  |         } else { | ||||||
|  |             this.error("missing serial config"); | ||||||
|  |         } | ||||||
|  |      | ||||||
|  |         this.on("close", function() { | ||||||
|  |             if (this.serialConfig) { | ||||||
|  |                 serialPool.close(this.serialConfig.serialport); | ||||||
|  |             } | ||||||
|  |         }); | ||||||
|  |     } | ||||||
|  |     RED.nodes.registerType("serial out",SerialOutNode); | ||||||
|  |      | ||||||
|  |     function SerialInNode(n) { | ||||||
|  |         RED.nodes.createNode(this,n); | ||||||
|  |         this.serial = n.serial; | ||||||
|  |         this.serialConfig = RED.nodes.getNode(this.serial); | ||||||
|  |      | ||||||
|  |         if (this.serialConfig) { | ||||||
|  |             var node = this; | ||||||
|  |             node.port = serialPool.get(this.serialConfig.serialport, | ||||||
|  |                 this.serialConfig.serialbaud, | ||||||
|  |                 this.serialConfig.databits, | ||||||
|  |                 this.serialConfig.parity, | ||||||
|  |                 this.serialConfig.stopbits, | ||||||
|  |                 this.serialConfig.newline); | ||||||
|  |             this.port.on('data', function(msg) { | ||||||
|  |                 node.send({ "payload": msg }); | ||||||
|  |             }); | ||||||
|  |         } else { | ||||||
|  |             this.error("missing serial config"); | ||||||
|  |         } | ||||||
|  |      | ||||||
|  |         this.on("close", function() { | ||||||
|  |             if (this.serialConfig) { | ||||||
|  |                 try { | ||||||
|  |                     serialPool.close(this.serialConfig.serialport); | ||||||
|  |                 } catch(err) { | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |         }); | ||||||
|  |     } | ||||||
|  |     RED.nodes.registerType("serial in",SerialInNode); | ||||||
|  |      | ||||||
|  |      | ||||||
|  |     var serialPool = function() { | ||||||
|  |         var connections = {}; | ||||||
|  |         return { | ||||||
|  |             get:function(port,baud,databits,parity,stopbits,newline,callback) { | ||||||
|  |                 var id = port; | ||||||
|  |                 if (!connections[id]) { | ||||||
|  |                     connections[id] = function() { | ||||||
|  |                         var obj = { | ||||||
|  |                             _emitter: new events.EventEmitter(), | ||||||
|  |                             serial: null, | ||||||
|  |                             _closing: false, | ||||||
|  |                             tout: null, | ||||||
|  |                             on: function(a,b) { this._emitter.on(a,b); }, | ||||||
|  |                             close: function(cb) { this.serial.close(cb); }, | ||||||
|  |                             write: function(m,cb) { this.serial.write(m,cb); }, | ||||||
|                         } |                         } | ||||||
|                         else { |                         newline = newline.replace("\\n","\n").replace("\\r","\r"); | ||||||
|                             obj.serial = new serialp.SerialPort(port,{ |                         var setupSerial = function() { | ||||||
|                                 baudrate: baud, |                             if (newline == "") { | ||||||
|                                 databits: databits, |                                 obj.serial = new serialp.SerialPort(port,{ | ||||||
|                                 parity: parity, |                                     baudrate: baud, | ||||||
|                                 stopbits: stopbits, |                                     databits: databits, | ||||||
|                                 parser: serialp.parsers.readline(newline) |                                     parity: parity, | ||||||
|                             },true, function(err, results) { if (err) obj.serial.emit('error',err); }); |                                     stopbits: stopbits, | ||||||
|                         } |                                     parser: serialp.parsers.raw | ||||||
|                         obj.serial.on('error', function(err) { |                                 },true, function(err, results) { if (err) obj.serial.emit('error',err); }); | ||||||
|                             util.log("[serial] serial port "+port+" error "+err); |                             } | ||||||
|                             obj.tout = setTimeout(function() { |                             else { | ||||||
|                                 setupSerial(); |                                 obj.serial = new serialp.SerialPort(port,{ | ||||||
|                             }, settings.serialReconnectTime); |                                     baudrate: baud, | ||||||
|                         }); |                                     databits: databits, | ||||||
|                         obj.serial.on('close', function() { |                                     parity: parity, | ||||||
|                             if (!obj._closing) { |                                     stopbits: stopbits, | ||||||
|                                 util.log("[serial] serial port "+port+" closed unexpectedly"); |                                     parser: serialp.parsers.readline(newline) | ||||||
|  |                                 },true, function(err, results) { if (err) obj.serial.emit('error',err); }); | ||||||
|  |                             } | ||||||
|  |                             obj.serial.on('error', function(err) { | ||||||
|  |                                 util.log("[serial] serial port "+port+" error "+err); | ||||||
|                                 obj.tout = setTimeout(function() { |                                 obj.tout = setTimeout(function() { | ||||||
|                                     setupSerial(); |                                     setupSerial(); | ||||||
|                                 }, settings.serialReconnectTime); |                                 }, settings.serialReconnectTime); | ||||||
|                             } |                             }); | ||||||
|                         }); |                             obj.serial.on('close', function() { | ||||||
|                         obj.serial.on('open',function() { |                                 if (!obj._closing) { | ||||||
|                             util.log("[serial] serial port "+port+" opened at "+baud+" baud "+databits+""+parity.charAt(0).toUpperCase()+stopbits); |                                     util.log("[serial] serial port "+port+" closed unexpectedly"); | ||||||
|                             if (obj.tout) { clearTimeout(obj.tout); } |                                     obj.tout = setTimeout(function() { | ||||||
|                             //obj.serial.flush(); |                                         setupSerial(); | ||||||
|                             obj._emitter.emit('ready'); |                                     }, settings.serialReconnectTime); | ||||||
|                         }); |  | ||||||
|                         obj.serial.on('data',function(d) { |  | ||||||
|                             if (typeof d !== "string") { |  | ||||||
|                                 d = d.toString(); |  | ||||||
|                                 for (i=0; i<d.length; i++) { |  | ||||||
|                                     obj._emitter.emit('data',d.charAt(i)); |  | ||||||
|                                 } |                                 } | ||||||
|                             } |                             }); | ||||||
|                             else { |                             obj.serial.on('open',function() { | ||||||
|                                 obj._emitter.emit('data',d); |                                 util.log("[serial] serial port "+port+" opened at "+baud+" baud "+databits+""+parity.charAt(0).toUpperCase()+stopbits); | ||||||
|                             } |                                 if (obj.tout) { clearTimeout(obj.tout); } | ||||||
|  |                                 //obj.serial.flush(); | ||||||
|  |                                 obj._emitter.emit('ready'); | ||||||
|  |                             }); | ||||||
|  |                             obj.serial.on('data',function(d) { | ||||||
|  |                                 if (typeof d !== "string") { | ||||||
|  |                                     d = d.toString(); | ||||||
|  |                                     for (i=0; i<d.length; i++) { | ||||||
|  |                                         obj._emitter.emit('data',d.charAt(i)); | ||||||
|  |                                     } | ||||||
|  |                                 } | ||||||
|  |                                 else { | ||||||
|  |                                     obj._emitter.emit('data',d); | ||||||
|  |                                 } | ||||||
|  |                             }); | ||||||
|  |                         } | ||||||
|  |                         setupSerial(); | ||||||
|  |                         return obj; | ||||||
|  |                     }(); | ||||||
|  |                 } | ||||||
|  |                 return connections[id]; | ||||||
|  |             }, | ||||||
|  |             close: function(port) { | ||||||
|  |                 if (connections[port]) { | ||||||
|  |                     if (connections[port].tout != null) clearTimeout(connections[port].tout); | ||||||
|  |                     connections[port]._closing = true; | ||||||
|  |                     try { | ||||||
|  |                         connections[port].close(function() { | ||||||
|  |                             util.log("[serial] serial port closed"); | ||||||
|                         }); |                         }); | ||||||
|                     } |                     } catch(err) { }; | ||||||
|                     setupSerial(); |                 } | ||||||
|                     return obj; |                 delete connections[port]; | ||||||
|                 }(); |  | ||||||
|             } |             } | ||||||
|             return connections[id]; |  | ||||||
|         }, |  | ||||||
|         close: function(port) { |  | ||||||
|             if (connections[port]) { |  | ||||||
|                 if (connections[port].tout != null) clearTimeout(connections[port].tout); |  | ||||||
|                 connections[port]._closing = true; |  | ||||||
|                 try { |  | ||||||
|                     connections[port].close(function() { |  | ||||||
|                         util.log("[serial] serial port closed"); |  | ||||||
|                     }); |  | ||||||
|                 } catch(err) { }; |  | ||||||
|             } |  | ||||||
|             delete connections[port]; |  | ||||||
|         } |         } | ||||||
|     } |     }(); | ||||||
| }(); |      | ||||||
|  |     RED.httpAdmin.get("/serialports",function(req,res) { | ||||||
| RED.httpAdmin.get("/serialports",function(req,res) { |         serialp.list(function (err, ports) { | ||||||
|     serialp.list(function (err, ports) { |             res.writeHead(200, {'Content-Type': 'text/plain'}); | ||||||
|         res.writeHead(200, {'Content-Type': 'text/plain'}); |             res.write(JSON.stringify(ports)); | ||||||
|         res.write(JSON.stringify(ports)); |             res.end(); | ||||||
|         res.end(); |         }); | ||||||
|     }); |     }); | ||||||
| }); | } | ||||||
|   | |||||||
| @@ -14,229 +14,208 @@ | |||||||
|  * limitations under the License. |  * limitations under the License. | ||||||
|  **/ |  **/ | ||||||
|  |  | ||||||
| var RED = require(process.env.NODE_RED_HOME+"/red/red"); | module.exports = function(RED) { | ||||||
| var reconnectTime = RED.settings.socketReconnectTime||10000; |     var reconnectTime = RED.settings.socketReconnectTime||10000; | ||||||
| var socketTimeout = RED.settings.socketTimeout||null; |     var socketTimeout = RED.settings.socketTimeout||null; | ||||||
| var net = require('net'); |     var net = require('net'); | ||||||
|  |  | ||||||
| var connectionPool = {}; |  | ||||||
|  |  | ||||||
| function TcpIn(n) { |  | ||||||
|     RED.nodes.createNode(this,n); |  | ||||||
|     this.host = n.host; |  | ||||||
|     this.port = n.port * 1; |  | ||||||
|     this.topic = n.topic; |  | ||||||
|     this.stream = (!n.datamode||n.datamode=='stream'); /* stream,single*/ |  | ||||||
|     this.datatype = n.datatype||'buffer'; /* buffer,utf8,base64 */ |  | ||||||
|     this.newline = (n.newline||"").replace("\\n","\n").replace("\\r","\r"); |  | ||||||
|     this.base64 = n.base64; |  | ||||||
|     this.server = (typeof n.server == 'boolean')?n.server:(n.server == "server"); |  | ||||||
|     this.closing = false; |  | ||||||
|     var node = this; |  | ||||||
|  |  | ||||||
|     if (!node.server) { |  | ||||||
|         var buffer = null; |  | ||||||
|         var client; |  | ||||||
|         var reconnectTimeout; |  | ||||||
|         function setupTcpClient() { |  | ||||||
|             node.log("connecting to "+node.host+":"+node.port); |  | ||||||
|             var id = (1+Math.random()*4294967295).toString(16); |  | ||||||
|             client = net.connect(node.port, node.host, function() { |  | ||||||
|                 buffer = (node.datatype == 'buffer')? new Buffer(0):""; |  | ||||||
|                 node.log("connected to "+node.host+":"+node.port); |  | ||||||
|             }); |  | ||||||
|             connectionPool[id] = client; |  | ||||||
|  |  | ||||||
|             client.on('data', function (data) { |  | ||||||
|                 if (node.datatype != 'buffer') { |  | ||||||
|                     data = data.toString(node.datatype); |  | ||||||
|                 } |  | ||||||
|                 if (node.stream) { |  | ||||||
|                     if ((node.datatype) === "utf8" && node.newline != "") { |  | ||||||
|                         buffer = buffer+data; |  | ||||||
|                         var parts = buffer.split(node.newline); |  | ||||||
|                         for (var i = 0;i<parts.length-1;i+=1) { |  | ||||||
|                             var msg = {topic:node.topic, payload:parts[i]}; |  | ||||||
|                             msg._session = {type:"tcp",id:id}; |  | ||||||
|                             node.send(msg); |  | ||||||
|                         } |  | ||||||
|                         buffer = parts[parts.length-1]; |  | ||||||
|                     } else { |  | ||||||
|                         var msg = {topic:node.topic, payload:data}; |  | ||||||
|                         msg._session = {type:"tcp",id:id}; |  | ||||||
|                         node.send(msg); |  | ||||||
|                     } |  | ||||||
|                 } else { |  | ||||||
|                     if ((typeof data) === "string") { |  | ||||||
|                         buffer = buffer+data; |  | ||||||
|                     } else { |  | ||||||
|                         buffer = Buffer.concat([buffer,data],buffer.length+data.length); |  | ||||||
|                     } |  | ||||||
|                 } |  | ||||||
|             }); |  | ||||||
|             client.on('end', function() { |  | ||||||
|                 if (!node.stream || (node.datatype == "utf8" && node.newline != "" && buffer.length > 0)) { |  | ||||||
|                     var msg = {topic:node.topic,payload:buffer}; |  | ||||||
|                     msg._session = {type:"tcp",id:id}; |  | ||||||
|                     node.send(msg); |  | ||||||
|                     buffer = null; |  | ||||||
|                 } |  | ||||||
|             }); |  | ||||||
|             client.on('close', function() { |  | ||||||
|                 delete connectionPool[id]; |  | ||||||
|                 node.log("connection lost to "+node.host+":"+node.port); |  | ||||||
|                 if (!node.closing) { |  | ||||||
|                     reconnectTimeout = setTimeout(setupTcpClient, reconnectTime); |  | ||||||
|                 } |  | ||||||
|             }); |  | ||||||
|             client.on('error', function(err) { |  | ||||||
|                     node.log(err); |  | ||||||
|             }); |  | ||||||
|         } |  | ||||||
|         setupTcpClient(); |  | ||||||
|  |  | ||||||
|         this.on('close', function() { |  | ||||||
|             this.closing = true; |  | ||||||
|             client.end(); |  | ||||||
|             clearTimeout(reconnectTimeout); |  | ||||||
|         }); |  | ||||||
|     } else { |  | ||||||
|         var server = net.createServer(function (socket) { |  | ||||||
|             if (socketTimeout !== null) { socket.setTimeout(socketTimeout); } |  | ||||||
|             var id = (1+Math.random()*4294967295).toString(16); |  | ||||||
|             connectionPool[id] = socket; |  | ||||||
|  |  | ||||||
|             var buffer = (node.datatype == 'buffer')? new Buffer(0):""; |  | ||||||
|             socket.on('data', function (data) { |  | ||||||
|                 if (node.datatype != 'buffer') { |  | ||||||
|                     data = data.toString(node.datatype); |  | ||||||
|                 } |  | ||||||
|  |  | ||||||
|                 if (node.stream) { |  | ||||||
|                     if ((typeof data) === "string" && node.newline != "") { |  | ||||||
|                         buffer = buffer+data; |  | ||||||
|                         var parts = buffer.split(node.newline); |  | ||||||
|                         for (var i = 0;i<parts.length-1;i+=1) { |  | ||||||
|                             var msg = {topic:node.topic, payload:parts[i],ip:socket.remoteAddress,port:socket.remotePort}; |  | ||||||
|                             msg._session = {type:"tcp",id:id}; |  | ||||||
|                             node.send(msg); |  | ||||||
|                         } |  | ||||||
|                         buffer = parts[parts.length-1]; |  | ||||||
|                     } else { |  | ||||||
|                         var msg = {topic:node.topic, payload:data}; |  | ||||||
|                         msg._session = {type:"tcp",id:id}; |  | ||||||
|                         node.send(msg); |  | ||||||
|                     } |  | ||||||
|                 } else { |  | ||||||
|                     if ((typeof data) === "string") { |  | ||||||
|                         buffer = buffer+data; |  | ||||||
|                     } else { |  | ||||||
|                         buffer = Buffer.concat([buffer,data],buffer.length+data.length); |  | ||||||
|                     } |  | ||||||
|                 } |  | ||||||
|             }); |  | ||||||
|             socket.on('end', function() { |  | ||||||
|                 if (!node.stream || (node.datatype == "utf8" && node.newline != "" && buffer.length > 0)) { |  | ||||||
|                     var msg = {topic:node.topic,payload:buffer}; |  | ||||||
|                     msg._session = {type:"tcp",id:id}; |  | ||||||
|                     node.send(msg); |  | ||||||
|                     buffer = null; |  | ||||||
|                 } |  | ||||||
|             }); |  | ||||||
|             socket.on('timeout', function() { |  | ||||||
|                 node.log('timeout closed socket port '+node.port); |  | ||||||
|                 socket.end(); |  | ||||||
|             }); |  | ||||||
|             socket.on('close', function() { |  | ||||||
|                 delete connectionPool[id]; |  | ||||||
|             }); |  | ||||||
|             socket.on('error',function(err) { |  | ||||||
|                 node.log(err); |  | ||||||
|             }); |  | ||||||
|         }); |  | ||||||
|         server.on('error', function(err) { |  | ||||||
|             if (err) { |  | ||||||
|                 node.error('unable to listen on port '+node.port+' : '+err); |  | ||||||
|             } |  | ||||||
|         }); |  | ||||||
|         server.listen(node.port, function(err) { |  | ||||||
|             if (err) { |  | ||||||
|                 node.error('unable to listen on port '+node.port+' : '+err); |  | ||||||
|             } else { |  | ||||||
|                 node.log('listening on port '+node.port); |  | ||||||
|      |      | ||||||
|                 node.on('close', function() { |     var connectionPool = {}; | ||||||
|                     node.closing = true; |      | ||||||
|                     server.close(); |     function TcpIn(n) { | ||||||
|                     node.log('stopped listening on port '+node.port); |         RED.nodes.createNode(this,n); | ||||||
|  |         this.host = n.host; | ||||||
|  |         this.port = n.port * 1; | ||||||
|  |         this.topic = n.topic; | ||||||
|  |         this.stream = (!n.datamode||n.datamode=='stream'); /* stream,single*/ | ||||||
|  |         this.datatype = n.datatype||'buffer'; /* buffer,utf8,base64 */ | ||||||
|  |         this.newline = (n.newline||"").replace("\\n","\n").replace("\\r","\r"); | ||||||
|  |         this.base64 = n.base64; | ||||||
|  |         this.server = (typeof n.server == 'boolean')?n.server:(n.server == "server"); | ||||||
|  |         this.closing = false; | ||||||
|  |         var node = this; | ||||||
|  |      | ||||||
|  |         if (!node.server) { | ||||||
|  |             var buffer = null; | ||||||
|  |             var client; | ||||||
|  |             var reconnectTimeout; | ||||||
|  |             function setupTcpClient() { | ||||||
|  |                 node.log("connecting to "+node.host+":"+node.port); | ||||||
|  |                 var id = (1+Math.random()*4294967295).toString(16); | ||||||
|  |                 client = net.connect(node.port, node.host, function() { | ||||||
|  |                     buffer = (node.datatype == 'buffer')? new Buffer(0):""; | ||||||
|  |                     node.log("connected to "+node.host+":"+node.port); | ||||||
|  |                 }); | ||||||
|  |                 connectionPool[id] = client; | ||||||
|  |      | ||||||
|  |                 client.on('data', function (data) { | ||||||
|  |                     if (node.datatype != 'buffer') { | ||||||
|  |                         data = data.toString(node.datatype); | ||||||
|  |                     } | ||||||
|  |                     if (node.stream) { | ||||||
|  |                         if ((node.datatype) === "utf8" && node.newline != "") { | ||||||
|  |                             buffer = buffer+data; | ||||||
|  |                             var parts = buffer.split(node.newline); | ||||||
|  |                             for (var i = 0;i<parts.length-1;i+=1) { | ||||||
|  |                                 var msg = {topic:node.topic, payload:parts[i]}; | ||||||
|  |                                 msg._session = {type:"tcp",id:id}; | ||||||
|  |                                 node.send(msg); | ||||||
|  |                             } | ||||||
|  |                             buffer = parts[parts.length-1]; | ||||||
|  |                         } else { | ||||||
|  |                             var msg = {topic:node.topic, payload:data}; | ||||||
|  |                             msg._session = {type:"tcp",id:id}; | ||||||
|  |                             node.send(msg); | ||||||
|  |                         } | ||||||
|  |                     } else { | ||||||
|  |                         if ((typeof data) === "string") { | ||||||
|  |                             buffer = buffer+data; | ||||||
|  |                         } else { | ||||||
|  |                             buffer = Buffer.concat([buffer,data],buffer.length+data.length); | ||||||
|  |                         } | ||||||
|  |                     } | ||||||
|  |                 }); | ||||||
|  |                 client.on('end', function() { | ||||||
|  |                     if (!node.stream || (node.datatype == "utf8" && node.newline != "" && buffer.length > 0)) { | ||||||
|  |                         var msg = {topic:node.topic,payload:buffer}; | ||||||
|  |                         msg._session = {type:"tcp",id:id}; | ||||||
|  |                         node.send(msg); | ||||||
|  |                         buffer = null; | ||||||
|  |                     } | ||||||
|  |                 }); | ||||||
|  |                 client.on('close', function() { | ||||||
|  |                     delete connectionPool[id]; | ||||||
|  |                     node.log("connection lost to "+node.host+":"+node.port); | ||||||
|  |                     if (!node.closing) { | ||||||
|  |                         reconnectTimeout = setTimeout(setupTcpClient, reconnectTime); | ||||||
|  |                     } | ||||||
|  |                 }); | ||||||
|  |                 client.on('error', function(err) { | ||||||
|  |                         node.log(err); | ||||||
|                 }); |                 }); | ||||||
|             } |             } | ||||||
|         }); |             setupTcpClient(); | ||||||
|     } |      | ||||||
|  |             this.on('close', function() { | ||||||
| } |                 this.closing = true; | ||||||
| RED.nodes.registerType("tcp in",TcpIn); |                 client.end(); | ||||||
|  |                 clearTimeout(reconnectTimeout); | ||||||
| function TcpOut(n) { |  | ||||||
|     RED.nodes.createNode(this,n); |  | ||||||
|     this.host = n.host; |  | ||||||
|     this.port = n.port * 1; |  | ||||||
|     this.base64 = n.base64; |  | ||||||
|     this.beserver = n.beserver; |  | ||||||
|     this.name = n.name; |  | ||||||
|     this.closing = false; |  | ||||||
|     var node = this; |  | ||||||
|  |  | ||||||
|     if (!node.beserver||node.beserver=="client") { |  | ||||||
|         var reconnectTimeout; |  | ||||||
|         var client = null; |  | ||||||
|         var connected = false; |  | ||||||
|  |  | ||||||
|         function setupTcpClient() { |  | ||||||
|             node.log("connecting to "+node.host+":"+node.port); |  | ||||||
|             client = net.connect(node.port, node.host, function() { |  | ||||||
|                 connected = true; |  | ||||||
|                 node.log("connected to "+node.host+":"+node.port); |  | ||||||
|             }); |             }); | ||||||
|             client.on('error', function (err) { |         } else { | ||||||
|                 node.log('error : '+err); |             var server = net.createServer(function (socket) { | ||||||
|  |                 if (socketTimeout !== null) { socket.setTimeout(socketTimeout); } | ||||||
|  |                 var id = (1+Math.random()*4294967295).toString(16); | ||||||
|  |                 connectionPool[id] = socket; | ||||||
|  |      | ||||||
|  |                 var buffer = (node.datatype == 'buffer')? new Buffer(0):""; | ||||||
|  |                 socket.on('data', function (data) { | ||||||
|  |                     if (node.datatype != 'buffer') { | ||||||
|  |                         data = data.toString(node.datatype); | ||||||
|  |                     } | ||||||
|  |      | ||||||
|  |                     if (node.stream) { | ||||||
|  |                         if ((typeof data) === "string" && node.newline != "") { | ||||||
|  |                             buffer = buffer+data; | ||||||
|  |                             var parts = buffer.split(node.newline); | ||||||
|  |                             for (var i = 0;i<parts.length-1;i+=1) { | ||||||
|  |                                 var msg = {topic:node.topic, payload:parts[i],ip:socket.remoteAddress,port:socket.remotePort}; | ||||||
|  |                                 msg._session = {type:"tcp",id:id}; | ||||||
|  |                                 node.send(msg); | ||||||
|  |                             } | ||||||
|  |                             buffer = parts[parts.length-1]; | ||||||
|  |                         } else { | ||||||
|  |                             var msg = {topic:node.topic, payload:data}; | ||||||
|  |                             msg._session = {type:"tcp",id:id}; | ||||||
|  |                             node.send(msg); | ||||||
|  |                         } | ||||||
|  |                     } else { | ||||||
|  |                         if ((typeof data) === "string") { | ||||||
|  |                             buffer = buffer+data; | ||||||
|  |                         } else { | ||||||
|  |                             buffer = Buffer.concat([buffer,data],buffer.length+data.length); | ||||||
|  |                         } | ||||||
|  |                     } | ||||||
|  |                 }); | ||||||
|  |                 socket.on('end', function() { | ||||||
|  |                     if (!node.stream || (node.datatype == "utf8" && node.newline != "" && buffer.length > 0)) { | ||||||
|  |                         var msg = {topic:node.topic,payload:buffer}; | ||||||
|  |                         msg._session = {type:"tcp",id:id}; | ||||||
|  |                         node.send(msg); | ||||||
|  |                         buffer = null; | ||||||
|  |                     } | ||||||
|  |                 }); | ||||||
|  |                 socket.on('timeout', function() { | ||||||
|  |                     node.log('timeout closed socket port '+node.port); | ||||||
|  |                     socket.end(); | ||||||
|  |                 }); | ||||||
|  |                 socket.on('close', function() { | ||||||
|  |                     delete connectionPool[id]; | ||||||
|  |                 }); | ||||||
|  |                 socket.on('error',function(err) { | ||||||
|  |                     node.log(err); | ||||||
|  |                 }); | ||||||
|             }); |             }); | ||||||
|             client.on('end', function (err) { |             server.on('error', function(err) { | ||||||
|  |                 if (err) { | ||||||
|  |                     node.error('unable to listen on port '+node.port+' : '+err); | ||||||
|  |                 } | ||||||
|             }); |             }); | ||||||
|             client.on('close', function() { |             server.listen(node.port, function(err) { | ||||||
|                 node.log("connection lost to "+node.host+":"+node.port); |                 if (err) { | ||||||
|                 connected = false; |                     node.error('unable to listen on port '+node.port+' : '+err); | ||||||
|                 client.destroy(); |                 } else { | ||||||
|                 if (!node.closing) { |                     node.log('listening on port '+node.port); | ||||||
|                     reconnectTimeout = setTimeout(setupTcpClient,reconnectTime); |          | ||||||
|  |                     node.on('close', function() { | ||||||
|  |                         node.closing = true; | ||||||
|  |                         server.close(); | ||||||
|  |                         node.log('stopped listening on port '+node.port); | ||||||
|  |                     }); | ||||||
|                 } |                 } | ||||||
|             }); |             }); | ||||||
|         } |         } | ||||||
|         setupTcpClient(); |      | ||||||
|  |     } | ||||||
|         node.on("input", function(msg) { |     RED.nodes.registerType("tcp in",TcpIn); | ||||||
|             if (connected && msg.payload != null) { |      | ||||||
|                 if (Buffer.isBuffer(msg.payload)) { |     function TcpOut(n) { | ||||||
|                     client.write(msg.payload); |         RED.nodes.createNode(this,n); | ||||||
|                 } else if (typeof msg.payload === "string" && node.base64) { |         this.host = n.host; | ||||||
|                     client.write(new Buffer(msg.payload,'base64')); |         this.port = n.port * 1; | ||||||
|                 } else { |         this.base64 = n.base64; | ||||||
|                     client.write(new Buffer(""+msg.payload)); |         this.beserver = n.beserver; | ||||||
|                 } |         this.name = n.name; | ||||||
|  |         this.closing = false; | ||||||
|  |         var node = this; | ||||||
|  |      | ||||||
|  |         if (!node.beserver||node.beserver=="client") { | ||||||
|  |             var reconnectTimeout; | ||||||
|  |             var client = null; | ||||||
|  |             var connected = false; | ||||||
|  |      | ||||||
|  |             function setupTcpClient() { | ||||||
|  |                 node.log("connecting to "+node.host+":"+node.port); | ||||||
|  |                 client = net.connect(node.port, node.host, function() { | ||||||
|  |                     connected = true; | ||||||
|  |                     node.log("connected to "+node.host+":"+node.port); | ||||||
|  |                 }); | ||||||
|  |                 client.on('error', function (err) { | ||||||
|  |                     node.log('error : '+err); | ||||||
|  |                 }); | ||||||
|  |                 client.on('end', function (err) { | ||||||
|  |                 }); | ||||||
|  |                 client.on('close', function() { | ||||||
|  |                     node.log("connection lost to "+node.host+":"+node.port); | ||||||
|  |                     connected = false; | ||||||
|  |                     client.destroy(); | ||||||
|  |                     if (!node.closing) { | ||||||
|  |                         reconnectTimeout = setTimeout(setupTcpClient,reconnectTime); | ||||||
|  |                     } | ||||||
|  |                 }); | ||||||
|             } |             } | ||||||
|         }); |             setupTcpClient(); | ||||||
|  |      | ||||||
|         node.on("close", function() { |             node.on("input", function(msg) { | ||||||
|             this.closing = true; |                 if (connected && msg.payload != null) { | ||||||
|             client.end(); |  | ||||||
|             clearTimeout(reconnectTimeout); |  | ||||||
|         }); |  | ||||||
|  |  | ||||||
|     } else if (node.beserver == "reply") { |  | ||||||
|         node.on("input",function(msg) { |  | ||||||
|             if (msg._session && msg._session.type == "tcp") { |  | ||||||
|                 var client = connectionPool[msg._session.id]; |  | ||||||
|                 if (client) { |  | ||||||
|                     if (Buffer.isBuffer(msg.payload)) { |                     if (Buffer.isBuffer(msg.payload)) { | ||||||
|                         client.write(msg.payload); |                         client.write(msg.payload); | ||||||
|                     } else if (typeof msg.payload === "string" && node.base64) { |                     } else if (typeof msg.payload === "string" && node.base64) { | ||||||
| @@ -245,62 +224,84 @@ function TcpOut(n) { | |||||||
|                         client.write(new Buffer(""+msg.payload)); |                         client.write(new Buffer(""+msg.payload)); | ||||||
|                     } |                     } | ||||||
|                 } |                 } | ||||||
|             } |  | ||||||
|         }); |  | ||||||
|     } else { |  | ||||||
|         var connectedSockets = []; |  | ||||||
|         var server = net.createServer(function (socket) { |  | ||||||
|             if (socketTimeout !== null) { socket.setTimeout(socketTimeout); } |  | ||||||
|             var remoteDetails = socket.remoteAddress+":"+socket.remotePort; |  | ||||||
|             node.log("connection from "+remoteDetails); |  | ||||||
|             connectedSockets.push(socket); |  | ||||||
|             socket.on('timeout', function() { |  | ||||||
|                 node.log('timeout closed socket port '+node.port); |  | ||||||
|                 socket.end(); |  | ||||||
|             }); |             }); | ||||||
|             socket.on('close',function() { |      | ||||||
|                 node.log("connection closed from "+remoteDetails); |             node.on("close", function() { | ||||||
|                 connectedSockets.splice(connectedSockets.indexOf(socket),1); |                 this.closing = true; | ||||||
|  |                 client.end(); | ||||||
|  |                 clearTimeout(reconnectTimeout); | ||||||
|             }); |             }); | ||||||
|             socket.on('error',function() { |      | ||||||
|                 node.log("socket error from "+remoteDetails); |         } else if (node.beserver == "reply") { | ||||||
|                 connectedSockets.splice(connectedSockets.indexOf(socket),1); |             node.on("input",function(msg) { | ||||||
|             }); |                 if (msg._session && msg._session.type == "tcp") { | ||||||
|         }); |                     var client = connectionPool[msg._session.id]; | ||||||
|         node.on("input", function(msg) { |                     if (client) { | ||||||
|             if (msg.payload != null) { |                         if (Buffer.isBuffer(msg.payload)) { | ||||||
|                 var buffer; |                             client.write(msg.payload); | ||||||
|                 if (Buffer.isBuffer(msg.payload)) { |                         } else if (typeof msg.payload === "string" && node.base64) { | ||||||
|                     buffer = msg.payload; |                             client.write(new Buffer(msg.payload,'base64')); | ||||||
|                 } else if (typeof msg.payload === "string" && node.base64) { |                         } else { | ||||||
|                     buffer = new Buffer(msg.payload,'base64'); |                             client.write(new Buffer(""+msg.payload)); | ||||||
|                 } else { |                         } | ||||||
|                     buffer = new Buffer(""+msg.payload); |                     } | ||||||
|                 } |                 } | ||||||
|                 for (var i = 0; i<connectedSockets.length;i+=1) { |             }); | ||||||
|                     connectedSockets[i].write(buffer); |         } else { | ||||||
|                 } |             var connectedSockets = []; | ||||||
|             } |             var server = net.createServer(function (socket) { | ||||||
|         }); |                 if (socketTimeout !== null) { socket.setTimeout(socketTimeout); } | ||||||
|          |                 var remoteDetails = socket.remoteAddress+":"+socket.remotePort; | ||||||
|         server.on('error', function(err) { |                 node.log("connection from "+remoteDetails); | ||||||
|             if (err) { |                 connectedSockets.push(socket); | ||||||
|                 node.error('unable to listen on port '+node.port+' : '+err); |                 socket.on('timeout', function() { | ||||||
|             } |                     node.log('timeout closed socket port '+node.port); | ||||||
|         }); |                     socket.end(); | ||||||
|  |  | ||||||
|         server.listen(node.port, function(err) { |  | ||||||
|             if (err) { |  | ||||||
|                 node.error('unable to listen on port '+node.port+' : '+err); |  | ||||||
|             } else { |  | ||||||
|                 node.log('listening on port '+node.port); |  | ||||||
|                 node.on('close', function() { |  | ||||||
|                     server.close(); |  | ||||||
|                     node.log('stopped listening on port '+node.port); |  | ||||||
|                 }); |                 }); | ||||||
|             } |                 socket.on('close',function() { | ||||||
|         }); |                     node.log("connection closed from "+remoteDetails); | ||||||
|  |                     connectedSockets.splice(connectedSockets.indexOf(socket),1); | ||||||
|  |                 }); | ||||||
|  |                 socket.on('error',function() { | ||||||
|  |                     node.log("socket error from "+remoteDetails); | ||||||
|  |                     connectedSockets.splice(connectedSockets.indexOf(socket),1); | ||||||
|  |                 }); | ||||||
|  |             }); | ||||||
|  |             node.on("input", function(msg) { | ||||||
|  |                 if (msg.payload != null) { | ||||||
|  |                     var buffer; | ||||||
|  |                     if (Buffer.isBuffer(msg.payload)) { | ||||||
|  |                         buffer = msg.payload; | ||||||
|  |                     } else if (typeof msg.payload === "string" && node.base64) { | ||||||
|  |                         buffer = new Buffer(msg.payload,'base64'); | ||||||
|  |                     } else { | ||||||
|  |                         buffer = new Buffer(""+msg.payload); | ||||||
|  |                     } | ||||||
|  |                     for (var i = 0; i<connectedSockets.length;i+=1) { | ||||||
|  |                         connectedSockets[i].write(buffer); | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  |             }); | ||||||
|  |              | ||||||
|  |             server.on('error', function(err) { | ||||||
|  |                 if (err) { | ||||||
|  |                     node.error('unable to listen on port '+node.port+' : '+err); | ||||||
|  |                 } | ||||||
|  |             }); | ||||||
|  |      | ||||||
|  |             server.listen(node.port, function(err) { | ||||||
|  |                 if (err) { | ||||||
|  |                     node.error('unable to listen on port '+node.port+' : '+err); | ||||||
|  |                 } else { | ||||||
|  |                     node.log('listening on port '+node.port); | ||||||
|  |                     node.on('close', function() { | ||||||
|  |                         server.close(); | ||||||
|  |                         node.log('stopped listening on port '+node.port); | ||||||
|  |                     }); | ||||||
|  |                 } | ||||||
|  |             }); | ||||||
|  |         } | ||||||
|     } |     } | ||||||
|  |      | ||||||
|  |     RED.nodes.registerType("tcp out",TcpOut); | ||||||
| } | } | ||||||
|  |  | ||||||
| RED.nodes.registerType("tcp out",TcpOut); |  | ||||||
|   | |||||||
| @@ -14,102 +14,53 @@ | |||||||
|  * limitations under the License. |  * limitations under the License. | ||||||
|  **/ |  **/ | ||||||
|  |  | ||||||
| var RED = require(process.env.NODE_RED_HOME+"/red/red"); | module.exports = function(RED) { | ||||||
| var dgram = require('dgram'); |     var dgram = require('dgram'); | ||||||
|  |      | ||||||
| // The Input Node |     // The Input Node | ||||||
| function UDPin(n) { |     function UDPin(n) { | ||||||
|     RED.nodes.createNode(this,n); |         RED.nodes.createNode(this,n); | ||||||
|     this.group = n.group; |         this.group = n.group; | ||||||
|     this.port = n.port; |         this.port = n.port; | ||||||
|     this.datatype = n.datatype; |         this.datatype = n.datatype; | ||||||
|     this.iface = n.iface || null; |         this.iface = n.iface || null; | ||||||
|     this.multicast = n.multicast; |         this.multicast = n.multicast; | ||||||
|     var node = this; |         var node = this; | ||||||
|  |      | ||||||
|     var server = dgram.createSocket('udp4'); |         var server = dgram.createSocket('udp4'); | ||||||
|  |      | ||||||
|     server.on("error", function (err) { |         server.on("error", function (err) { | ||||||
|         if ((err.code == "EACCES") && (node.port < 1024)) { |             if ((err.code == "EACCES") && (node.port < 1024)) { | ||||||
|             node.error("UDP access error, you may need root access for ports below 1024"); |                 node.error("UDP access error, you may need root access for ports below 1024"); | ||||||
|         } else {  |             } else {  | ||||||
|             node.error("UDP error : "+err.code); |                 node.error("UDP error : "+err.code); | ||||||
|         } |  | ||||||
|         server.close(); |  | ||||||
|     }); |  | ||||||
|  |  | ||||||
|     server.on('message', function (message, remote) { |  | ||||||
|         var msg; |  | ||||||
|         if (node.datatype =="base64") { |  | ||||||
|             msg = { payload:message.toString('base64'), fromip:remote.address+':'+remote.port }; |  | ||||||
|         } else if (node.datatype =="utf8") { |  | ||||||
|             msg = { payload:message.toString('utf8'), fromip:remote.address+':'+remote.port }; |  | ||||||
|         } else { |  | ||||||
|             msg = { payload:message, fromip:remote.address+':'+remote.port, ip:remote.address, port:remote.port }; |  | ||||||
|         } |  | ||||||
|         node.send(msg); |  | ||||||
|     }); |  | ||||||
|  |  | ||||||
|     server.on('listening', function () { |  | ||||||
|         var address = server.address(); |  | ||||||
|         node.log('udp listener at ' + address.address + ":" + address.port); |  | ||||||
|         if (node.multicast == "true") { |  | ||||||
|             server.setBroadcast(true); |  | ||||||
|             try { |  | ||||||
|                 server.setMulticastTTL(128); |  | ||||||
|                 server.addMembership(node.group,node.iface); |  | ||||||
|                 node.log("udp multicast group "+node.group); |  | ||||||
|             } catch (e) { |  | ||||||
|                 if (e.errno == "EINVAL") {  |  | ||||||
|                     node.error("Bad Multicast Address"); |  | ||||||
|                 } else if (e.errno == "ENODEV") { |  | ||||||
|                     node.error("Must be ip address of the required interface"); |  | ||||||
|                 } else { |  | ||||||
|                     node.error("Error :"+e.errno); |  | ||||||
|                 } |  | ||||||
|             } |             } | ||||||
|         } |  | ||||||
|     }); |  | ||||||
|  |  | ||||||
|     node.on("close", function() { |  | ||||||
|         try { |  | ||||||
|             server.close(); |             server.close(); | ||||||
|             node.log('udp listener stopped'); |         }); | ||||||
|         } catch (err) { |      | ||||||
|             node.error(err); |         server.on('message', function (message, remote) { | ||||||
|         } |             var msg; | ||||||
|     }); |             if (node.datatype =="base64") { | ||||||
|  |                 msg = { payload:message.toString('base64'), fromip:remote.address+':'+remote.port }; | ||||||
|     server.bind(node.port,node.iface); |             } else if (node.datatype =="utf8") { | ||||||
| } |                 msg = { payload:message.toString('utf8'), fromip:remote.address+':'+remote.port }; | ||||||
| RED.nodes.registerType("udp in",UDPin); |             } else { | ||||||
|  |                 msg = { payload:message, fromip:remote.address+':'+remote.port, ip:remote.address, port:remote.port }; | ||||||
|  |             } | ||||||
| // The Output Node |             node.send(msg); | ||||||
| function UDPout(n) { |         }); | ||||||
|     RED.nodes.createNode(this,n); |      | ||||||
|     //this.group = n.group; |         server.on('listening', function () { | ||||||
|     this.port = n.port; |             var address = server.address(); | ||||||
|     this.outport = n.outport||""; |             node.log('udp listener at ' + address.address + ":" + address.port); | ||||||
|     this.base64 = n.base64; |             if (node.multicast == "true") { | ||||||
|     this.addr = n.addr; |                 server.setBroadcast(true); | ||||||
|     this.iface = n.iface || null; |  | ||||||
|     this.multicast = n.multicast; |  | ||||||
|     var node = this; |  | ||||||
|  |  | ||||||
|     var sock = dgram.createSocket('udp4');  // only use ipv4 for now |  | ||||||
|  |  | ||||||
|     if (node.multicast != "false") { |  | ||||||
|         if (node.outport == "") { node.outport = node.port; } |  | ||||||
|         sock.bind(node.outport, function() {    // have to bind before you can enable broadcast... |  | ||||||
|             sock.setBroadcast(true);            // turn on broadcast |  | ||||||
|             if (node.multicast == "multi") { |  | ||||||
|                 try { |                 try { | ||||||
|                     sock.setMulticastTTL(128); |                     server.setMulticastTTL(128); | ||||||
|                     sock.addMembership(node.addr,node.iface);   // Add to the multicast group |                     server.addMembership(node.group,node.iface); | ||||||
|                     node.log('udp multicast ready : '+node.outport+' -> '+node.addr+":"+node.port); |                     node.log("udp multicast group "+node.group); | ||||||
|                 } catch (e) { |                 } catch (e) { | ||||||
|                     if (e.errno == "EINVAL") { |                     if (e.errno == "EINVAL") {  | ||||||
|                         node.error("Bad Multicast Address"); |                         node.error("Bad Multicast Address"); | ||||||
|                     } else if (e.errno == "ENODEV") { |                     } else if (e.errno == "ENODEV") { | ||||||
|                         node.error("Must be ip address of the required interface"); |                         node.error("Must be ip address of the required interface"); | ||||||
| @@ -117,52 +68,102 @@ function UDPout(n) { | |||||||
|                         node.error("Error :"+e.errno); |                         node.error("Error :"+e.errno); | ||||||
|                     } |                     } | ||||||
|                 } |                 } | ||||||
|             } else { |  | ||||||
|                 node.log('udp broadcast ready : '+node.outport+' -> '+node.addr+":"+node.port); |  | ||||||
|             } |             } | ||||||
|         }); |         }); | ||||||
|     } else if (node.outport != "") { |      | ||||||
|         sock.bind(node.outport); |         node.on("close", function() { | ||||||
|         node.log('udp ready : '+node.outport+' -> '+node.addr+":"+node.port); |             try { | ||||||
|     } else { |                 server.close(); | ||||||
|         node.log('udp ready : '+node.addr+":"+node.port); |                 node.log('udp listener stopped'); | ||||||
|     } |             } catch (err) { | ||||||
|  |                 node.error(err); | ||||||
|     node.on("input", function(msg) { |  | ||||||
|         if (msg.payload != null) { |  | ||||||
|             var add = node.addr || msg.ip || ""; |  | ||||||
|             var por = node.port || msg.port || 0; |  | ||||||
|             if (add == "") { |  | ||||||
|                 node.warn("udp: ip address not set"); |  | ||||||
|             } else if (por == 0) { |  | ||||||
|                 node.warn("udp: port not set"); |  | ||||||
|             } else if (isNaN(por) || (por < 1) || (por > 65535)) { |  | ||||||
|                 node.warn("udp: port number not valid"); |  | ||||||
|             } else { |  | ||||||
|                 var message; |  | ||||||
|                 if (node.base64) { |  | ||||||
|                     message = new Buffer(b64string, 'base64'); |  | ||||||
|                 } else if (msg.payload instanceof Buffer) { |  | ||||||
|                     message = msg.payload; |  | ||||||
|                 } else { |  | ||||||
|                     message = new Buffer(""+msg.payload); |  | ||||||
|                 } |  | ||||||
|                 sock.send(message, 0, message.length, por, add, function(err, bytes) { |  | ||||||
|                     if (err) { |  | ||||||
|                         node.error("udp : "+err); |  | ||||||
|                     } |  | ||||||
|                 }); |  | ||||||
|             } |             } | ||||||
|  |         }); | ||||||
|  |      | ||||||
|  |         server.bind(node.port,node.iface); | ||||||
|  |     } | ||||||
|  |     RED.nodes.registerType("udp in",UDPin); | ||||||
|  |      | ||||||
|  |      | ||||||
|  |     // The Output Node | ||||||
|  |     function UDPout(n) { | ||||||
|  |         RED.nodes.createNode(this,n); | ||||||
|  |         //this.group = n.group; | ||||||
|  |         this.port = n.port; | ||||||
|  |         this.outport = n.outport||""; | ||||||
|  |         this.base64 = n.base64; | ||||||
|  |         this.addr = n.addr; | ||||||
|  |         this.iface = n.iface || null; | ||||||
|  |         this.multicast = n.multicast; | ||||||
|  |         var node = this; | ||||||
|  |      | ||||||
|  |         var sock = dgram.createSocket('udp4');  // only use ipv4 for now | ||||||
|  |      | ||||||
|  |         if (node.multicast != "false") { | ||||||
|  |             if (node.outport == "") { node.outport = node.port; } | ||||||
|  |             sock.bind(node.outport, function() {    // have to bind before you can enable broadcast... | ||||||
|  |                 sock.setBroadcast(true);            // turn on broadcast | ||||||
|  |                 if (node.multicast == "multi") { | ||||||
|  |                     try { | ||||||
|  |                         sock.setMulticastTTL(128); | ||||||
|  |                         sock.addMembership(node.addr,node.iface);   // Add to the multicast group | ||||||
|  |                         node.log('udp multicast ready : '+node.outport+' -> '+node.addr+":"+node.port); | ||||||
|  |                     } catch (e) { | ||||||
|  |                         if (e.errno == "EINVAL") { | ||||||
|  |                             node.error("Bad Multicast Address"); | ||||||
|  |                         } else if (e.errno == "ENODEV") { | ||||||
|  |                             node.error("Must be ip address of the required interface"); | ||||||
|  |                         } else { | ||||||
|  |                             node.error("Error :"+e.errno); | ||||||
|  |                         } | ||||||
|  |                     } | ||||||
|  |                 } else { | ||||||
|  |                     node.log('udp broadcast ready : '+node.outport+' -> '+node.addr+":"+node.port); | ||||||
|  |                 } | ||||||
|  |             }); | ||||||
|  |         } else if (node.outport != "") { | ||||||
|  |             sock.bind(node.outport); | ||||||
|  |             node.log('udp ready : '+node.outport+' -> '+node.addr+":"+node.port); | ||||||
|  |         } else { | ||||||
|  |             node.log('udp ready : '+node.addr+":"+node.port); | ||||||
|         } |         } | ||||||
|     }); |      | ||||||
|  |         node.on("input", function(msg) { | ||||||
|     node.on("close", function() { |             if (msg.payload != null) { | ||||||
|         try { |                 var add = node.addr || msg.ip || ""; | ||||||
|             sock.close(); |                 var por = node.port || msg.port || 0; | ||||||
|             node.log('udp output stopped'); |                 if (add == "") { | ||||||
|         } catch (err) { |                     node.warn("udp: ip address not set"); | ||||||
|             node.error(err); |                 } else if (por == 0) { | ||||||
|         } |                     node.warn("udp: port not set"); | ||||||
|     }); |                 } else if (isNaN(por) || (por < 1) || (por > 65535)) { | ||||||
|  |                     node.warn("udp: port number not valid"); | ||||||
|  |                 } else { | ||||||
|  |                     var message; | ||||||
|  |                     if (node.base64) { | ||||||
|  |                         message = new Buffer(b64string, 'base64'); | ||||||
|  |                     } else if (msg.payload instanceof Buffer) { | ||||||
|  |                         message = msg.payload; | ||||||
|  |                     } else { | ||||||
|  |                         message = new Buffer(""+msg.payload); | ||||||
|  |                     } | ||||||
|  |                     sock.send(message, 0, message.length, por, add, function(err, bytes) { | ||||||
|  |                         if (err) { | ||||||
|  |                             node.error("udp : "+err); | ||||||
|  |                         } | ||||||
|  |                     }); | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |         }); | ||||||
|  |      | ||||||
|  |         node.on("close", function() { | ||||||
|  |             try { | ||||||
|  |                 sock.close(); | ||||||
|  |                 node.log('udp output stopped'); | ||||||
|  |             } catch (err) { | ||||||
|  |                 node.error(err); | ||||||
|  |             } | ||||||
|  |         }); | ||||||
|  |     } | ||||||
|  |     RED.nodes.registerType("udp out",UDPout); | ||||||
| } | } | ||||||
| RED.nodes.registerType("udp out",UDPout); |  | ||||||
|   | |||||||
| @@ -14,60 +14,60 @@ | |||||||
|  * limitations under the License. |  * limitations under the License. | ||||||
|  **/ |  **/ | ||||||
|  |  | ||||||
| var RED = require(process.env.NODE_RED_HOME + "/red/red"); | module.exports = function(RED) { | ||||||
|  |     var operators = { | ||||||
| var operators = { |         'eq': function(a, b) { return a == b; }, | ||||||
|     'eq': function(a, b) { return a == b; }, |         'neq': function(a, b) { return a != b; }, | ||||||
|     'neq': function(a, b) { return a != b; }, |         'lt': function(a, b) { return a < b; }, | ||||||
|     'lt': function(a, b) { return a < b; }, |         'lte': function(a, b) { return a <= b; }, | ||||||
|     'lte': function(a, b) { return a <= b; }, |         'gt': function(a, b) { return a > b; }, | ||||||
|     'gt': function(a, b) { return a > b; }, |         'gte': function(a, b) { return a >= b; }, | ||||||
|     'gte': function(a, b) { return a >= b; }, |         'btwn': function(a, b, c) { return a >= b && a <= c; }, | ||||||
|     'btwn': function(a, b, c) { return a >= b && a <= c; }, |         'cont': function(a, b) { return (a + "").indexOf(b) != -1; }, | ||||||
|     'cont': function(a, b) { return (a + "").indexOf(b) != -1; }, |         'regex': function(a, b) { return (a + "").match(new RegExp(b)); }, | ||||||
|     'regex': function(a, b) { return (a + "").match(new RegExp(b)); }, |         'true': function(a) { return a === true; }, | ||||||
|     'true': function(a) { return a === true; }, |         'false': function(a) { return a === false; }, | ||||||
|     'false': function(a) { return a === false; }, |         'null': function(a) { return typeof a == "undefined"; }, | ||||||
|     'null': function(a) { return typeof a == "undefined"; }, |         'nnull': function(a) { return typeof a != "undefined"; }, | ||||||
|     'nnull': function(a) { return typeof a != "undefined"; }, |         'else': function(a) { return a === true; } | ||||||
|     'else': function(a) { return a === true; } |     }; | ||||||
| }; |      | ||||||
|  |     function SwitchNode(n) { | ||||||
| function SwitchNode(n) { |         RED.nodes.createNode(this, n); | ||||||
|     RED.nodes.createNode(this, n); |         this.rules = n.rules; | ||||||
|     this.rules = n.rules; |         this.property = n.property; | ||||||
|     this.property = n.property; |         this.checkall = n.checkall || "true"; | ||||||
|     this.checkall = n.checkall || "true"; |         var propertyParts = n.property.split("."), | ||||||
|     var propertyParts = n.property.split("."), |             node = this; | ||||||
|         node = this; |      | ||||||
|  |         for (var i=0; i<this.rules.length; i+=1) { | ||||||
|     for (var i=0; i<this.rules.length; i+=1) { |             var rule = this.rules[i]; | ||||||
|         var rule = this.rules[i]; |             if (!isNaN(Number(rule.v))) { | ||||||
|         if (!isNaN(Number(rule.v))) { |                 rule.v = Number(rule.v); | ||||||
|             rule.v = Number(rule.v); |                 rule.v2 = Number(rule.v2); | ||||||
|             rule.v2 = Number(rule.v2); |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     this.on('input', function (msg) { |  | ||||||
|         var onward = []; |  | ||||||
|         var prop = propertyParts.reduce(function (obj, i) { |  | ||||||
|             return obj[i] |  | ||||||
|         }, msg); |  | ||||||
|         var elseflag = true; |  | ||||||
|         for (var i=0; i<node.rules.length; i+=1) { |  | ||||||
|             var rule = node.rules[i]; |  | ||||||
|             var test = prop; |  | ||||||
|             if (rule.t == "else") { test = elseflag; elseflag = true; } |  | ||||||
|             if (operators[rule.t](test,rule.v, rule.v2)) { |  | ||||||
|                 onward.push(msg); |  | ||||||
|                 elseflag = false; |  | ||||||
|                 if (node.checkall == "false") { break; } |  | ||||||
|             } else { |  | ||||||
|                 onward.push(null); |  | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|         this.send(onward); |      | ||||||
|     }); |         this.on('input', function (msg) { | ||||||
|  |             var onward = []; | ||||||
|  |             var prop = propertyParts.reduce(function (obj, i) { | ||||||
|  |                 return obj[i] | ||||||
|  |             }, msg); | ||||||
|  |             var elseflag = true; | ||||||
|  |             for (var i=0; i<node.rules.length; i+=1) { | ||||||
|  |                 var rule = node.rules[i]; | ||||||
|  |                 var test = prop; | ||||||
|  |                 if (rule.t == "else") { test = elseflag; elseflag = true; } | ||||||
|  |                 if (operators[rule.t](test,rule.v, rule.v2)) { | ||||||
|  |                     onward.push(msg); | ||||||
|  |                     elseflag = false; | ||||||
|  |                     if (node.checkall == "false") { break; } | ||||||
|  |                 } else { | ||||||
|  |                     onward.push(null); | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |             this.send(onward); | ||||||
|  |         }); | ||||||
|  |     } | ||||||
|  |     RED.nodes.registerType("switch", SwitchNode); | ||||||
| } | } | ||||||
| RED.nodes.registerType("switch", SwitchNode); |  | ||||||
|   | |||||||
| @@ -14,60 +14,60 @@ | |||||||
|  * limitations under the License. |  * limitations under the License. | ||||||
|  **/ |  **/ | ||||||
|  |  | ||||||
| var RED = require(process.env.NODE_RED_HOME + "/red/red"); | module.exports = function(RED) { | ||||||
|  |     function ChangeNode(n) { | ||||||
| function ChangeNode(n) { |         RED.nodes.createNode(this, n); | ||||||
|     RED.nodes.createNode(this, n); |         this.action = n.action; | ||||||
|     this.action = n.action; |         this.property = n.property || ""; | ||||||
|     this.property = n.property || ""; |         this.from = n.from || " "; | ||||||
|     this.from = n.from || " "; |         this.to = n.to || " "; | ||||||
|     this.to = n.to || " "; |         this.reg = (n.reg === null || n.reg); | ||||||
|     this.reg = (n.reg === null || n.reg); |         var node = this; | ||||||
|     var node = this; |         if (node.reg === false) { | ||||||
|     if (node.reg === false) { |             this.from = this.from.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&"); | ||||||
|         this.from = this.from.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&"); |         } | ||||||
|  |         var makeNew = function( stem, path, value ) { | ||||||
|  |             var lastPart = (arguments.length === 3) ? path.pop() : false; | ||||||
|  |             for (var i = 0; i < path.length; i++) { | ||||||
|  |                 stem = stem[path[i]] = stem[path[i]] || {}; | ||||||
|  |             } | ||||||
|  |             if (lastPart) { stem = stem[lastPart] = value; } | ||||||
|  |             return stem; | ||||||
|  |         }; | ||||||
|  |      | ||||||
|  |         this.on('input', function (msg) { | ||||||
|  |             if (node.action == "change") { | ||||||
|  |                 try { | ||||||
|  |                     node.re = new RegExp(this.from, "g"); | ||||||
|  |                 } catch (e) { | ||||||
|  |                     node.error(e.message); | ||||||
|  |                 } | ||||||
|  |                 if (typeof msg[node.property] === "string") { | ||||||
|  |                     msg[node.property] = (msg[node.property]).replace(node.re, node.to); | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |             //else if (node.action == "replace") { | ||||||
|  |                 //if (node.to.indexOf("msg.") == 0) { | ||||||
|  |                     //msg[node.property] = eval(node.to); | ||||||
|  |                 //} | ||||||
|  |                 //else { | ||||||
|  |                     //msg[node.property] = node.to; | ||||||
|  |                 //} | ||||||
|  |             //} | ||||||
|  |             else if (node.action == "replace") { | ||||||
|  |                 if (node.to.indexOf("msg.") == 0) { | ||||||
|  |                     makeNew( msg, node.property.split("."), eval(node.to) ); | ||||||
|  |                 } | ||||||
|  |                 else { | ||||||
|  |                     makeNew( msg, node.property.split("."), node.to ); | ||||||
|  |                 } | ||||||
|  |                 //makeNew( msg, node.property.split("."), node.to ); | ||||||
|  |             } | ||||||
|  |             else if (node.action == "delete") { | ||||||
|  |                 delete(msg[node.property]); | ||||||
|  |             } | ||||||
|  |             node.send(msg); | ||||||
|  |         }); | ||||||
|     } |     } | ||||||
|     var makeNew = function( stem, path, value ) { |     RED.nodes.registerType("change", ChangeNode); | ||||||
|         var lastPart = (arguments.length === 3) ? path.pop() : false; |  | ||||||
|         for (var i = 0; i < path.length; i++) { |  | ||||||
|             stem = stem[path[i]] = stem[path[i]] || {}; |  | ||||||
|         } |  | ||||||
|         if (lastPart) { stem = stem[lastPart] = value; } |  | ||||||
|         return stem; |  | ||||||
|     }; |  | ||||||
|  |  | ||||||
|     this.on('input', function (msg) { |  | ||||||
|         if (node.action == "change") { |  | ||||||
|             try { |  | ||||||
|                 node.re = new RegExp(this.from, "g"); |  | ||||||
|             } catch (e) { |  | ||||||
|                 node.error(e.message); |  | ||||||
|             } |  | ||||||
|             if (typeof msg[node.property] === "string") { |  | ||||||
|                 msg[node.property] = (msg[node.property]).replace(node.re, node.to); |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|         //else if (node.action == "replace") { |  | ||||||
|             //if (node.to.indexOf("msg.") == 0) { |  | ||||||
|                 //msg[node.property] = eval(node.to); |  | ||||||
|             //} |  | ||||||
|             //else { |  | ||||||
|                 //msg[node.property] = node.to; |  | ||||||
|             //} |  | ||||||
|         //} |  | ||||||
|         else if (node.action == "replace") { |  | ||||||
|             if (node.to.indexOf("msg.") == 0) { |  | ||||||
|                 makeNew( msg, node.property.split("."), eval(node.to) ); |  | ||||||
|             } |  | ||||||
|             else { |  | ||||||
|                 makeNew( msg, node.property.split("."), node.to ); |  | ||||||
|             } |  | ||||||
|             //makeNew( msg, node.property.split("."), node.to ); |  | ||||||
|         } |  | ||||||
|         else if (node.action == "delete") { |  | ||||||
|             delete(msg[node.property]); |  | ||||||
|         } |  | ||||||
|         node.send(msg); |  | ||||||
|     }); |  | ||||||
| } | } | ||||||
| RED.nodes.registerType("change", ChangeNode); |  | ||||||
|   | |||||||
| @@ -14,34 +14,34 @@ | |||||||
|  * limitations under the License. |  * limitations under the License. | ||||||
|  **/ |  **/ | ||||||
|  |  | ||||||
| var RED = require(process.env.NODE_RED_HOME + "/red/red"); | module.exports = function(RED) { | ||||||
|  |     function RangeNode(n) { | ||||||
| function RangeNode(n) { |         RED.nodes.createNode(this, n); | ||||||
|     RED.nodes.createNode(this, n); |         this.action = n.action; | ||||||
|     this.action = n.action; |         this.round = n.round || false; | ||||||
|     this.round = n.round || false; |         this.minin = Number(n.minin); | ||||||
|     this.minin = Number(n.minin); |         this.maxin = Number(n.maxin); | ||||||
|     this.maxin = Number(n.maxin); |         this.minout = Number(n.minout); | ||||||
|     this.minout = Number(n.minout); |         this.maxout = Number(n.maxout); | ||||||
|     this.maxout = Number(n.maxout); |         var node = this; | ||||||
|     var node = this; |      | ||||||
|  |         this.on('input', function (msg) { | ||||||
|     this.on('input', function (msg) { |             var n = Number(msg.payload); | ||||||
|         var n = Number(msg.payload); |             if (!isNaN(n)) { | ||||||
|         if (!isNaN(n)) { |                 if (node.action == "clamp") { | ||||||
|             if (node.action == "clamp") { |                     if (n < node.minin) { n = node.minin; } | ||||||
|                 if (n < node.minin) { n = node.minin; } |                     if (n > node.maxin) { n = node.maxin; } | ||||||
|                 if (n > node.maxin) { n = node.maxin; } |                 } | ||||||
|  |                 if (node.action == "roll") { | ||||||
|  |                     if (n >= node.maxin) { n = (n - node.minin) % (node.maxin - node.minin) + node.minin; } | ||||||
|  |                     if (n <  node.minin) { n = (n - node.minin) % (node.maxin - node.minin) + node.maxin; } | ||||||
|  |                 } | ||||||
|  |                 msg.payload = ((n - node.minin) / (node.maxin - node.minin) * (node.maxout - node.minout)) + node.minout; | ||||||
|  |                 if (node.round) { msg.payload = Math.round(msg.payload); } | ||||||
|  |                 node.send(msg); | ||||||
|             } |             } | ||||||
|             if (node.action == "roll") { |             else { node.log("Not a number: "+msg.payload); } | ||||||
|                 if (n >= node.maxin) { n = (n - node.minin) % (node.maxin - node.minin) + node.minin; } |         }); | ||||||
|                 if (n <  node.minin) { n = (n - node.minin) % (node.maxin - node.minin) + node.maxin; } |     } | ||||||
|             } |     RED.nodes.registerType("range", RangeNode); | ||||||
|             msg.payload = ((n - node.minin) / (node.maxin - node.minin) * (node.maxout - node.minout)) + node.minout; |  | ||||||
|             if (node.round) { msg.payload = Math.round(msg.payload); } |  | ||||||
|             node.send(msg); |  | ||||||
|         } |  | ||||||
|         else { node.log("Not a number: "+msg.payload); } |  | ||||||
|     }); |  | ||||||
| } | } | ||||||
| RED.nodes.registerType("range", RangeNode); |  | ||||||
|   | |||||||
| @@ -14,65 +14,65 @@ | |||||||
|  * limitations under the License. |  * limitations under the License. | ||||||
|  **/ |  **/ | ||||||
|  |  | ||||||
| var RED = require(process.env.NODE_RED_HOME+"/red/red"); | module.exports = function(RED) { | ||||||
|  |     function CSVNode(n) { | ||||||
| function CSVNode(n) { |         RED.nodes.createNode(this,n); | ||||||
|     RED.nodes.createNode(this,n); |         this.template = n.temp.split(","); | ||||||
|     this.template = n.temp.split(","); |         this.sep = n.sep || ','; | ||||||
|     this.sep = n.sep || ','; |         this.sep = this.sep.replace("\\n","\n").replace("\\r","\r").replace("\\t","\t"); | ||||||
|     this.sep = this.sep.replace("\\n","\n").replace("\\r","\r").replace("\\t","\t"); |         this.quo = '"'; | ||||||
|     this.quo = '"'; |         var node = this; | ||||||
|     var node = this; |         this.on("input", function(msg) { | ||||||
|     this.on("input", function(msg) { |             if (msg.hasOwnProperty("payload")) { | ||||||
|         if (msg.hasOwnProperty("payload")) { |                 if (typeof msg.payload == "object") { // convert to csv | ||||||
|             if (typeof msg.payload == "object") { // convert to csv |                     try { | ||||||
|                 try { |                         var o = ""; | ||||||
|                     var o = ""; |                         for (var i in node.template) { | ||||||
|                     for (var i in node.template) { |                             if (msg.payload.hasOwnProperty(node.template[i])) { | ||||||
|                         if (msg.payload.hasOwnProperty(node.template[i])) { |                                 if (msg.payload[node.template[i]].indexOf(node.sep) != -1) { | ||||||
|                             if (msg.payload[node.template[i]].indexOf(node.sep) != -1) { |                                     o += node.quo + msg.payload[node.template[i]] + node.quo + node.sep; | ||||||
|                                 o += node.quo + msg.payload[node.template[i]] + node.quo + node.sep; |                                 } | ||||||
|  |                                 else if (msg.payload[node.template[i]].indexOf(node.quo) != -1) { | ||||||
|  |                                     msg.payload[node.template[i]] = msg.payload[node.template[i]].replace(/"/g, '""'); | ||||||
|  |                                     o += node.quo + msg.payload[node.template[i]] + node.quo + node.sep; | ||||||
|  |                                 } | ||||||
|  |                                 else { o += msg.payload[node.template[i]] + node.sep; } | ||||||
|                             } |                             } | ||||||
|                             else if (msg.payload[node.template[i]].indexOf(node.quo) != -1) { |                         } | ||||||
|                                 msg.payload[node.template[i]] = msg.payload[node.template[i]].replace(/"/g, '""'); |                         msg.payload = o.slice(0,-1); | ||||||
|                                 o += node.quo + msg.payload[node.template[i]] + node.quo + node.sep; |                         node.send(msg); | ||||||
|  |                     } | ||||||
|  |                     catch(e) { node.log(e); } | ||||||
|  |                 } | ||||||
|  |                 else if (typeof msg.payload == "string") { // convert to object | ||||||
|  |                     try { | ||||||
|  |                         var f = true; | ||||||
|  |                         var j = 0; | ||||||
|  |                         var k = [""]; | ||||||
|  |                         var o = {}; | ||||||
|  |                         for (var i = 0; i < msg.payload.length; i++) { | ||||||
|  |                             if (msg.payload[i] === node.quo) { | ||||||
|  |                                 f = !f; | ||||||
|  |                                 if (msg.payload[i-1] === node.quo) { k[j] += '\"'; } | ||||||
|  |                             } | ||||||
|  |                             else if ((msg.payload[i] === node.sep) && f) { | ||||||
|  |                                 if ( node.template[j] && (node.template[j] != "") ) { o[node.template[j]] = k[j]; } | ||||||
|  |                                 j += 1; | ||||||
|  |                                 k[j] = ""; | ||||||
|  |                             } | ||||||
|  |                             else { | ||||||
|  |                                 k[j] += msg.payload[i]; | ||||||
|                             } |                             } | ||||||
|                             else { o += msg.payload[node.template[i]] + node.sep; } |  | ||||||
|                         } |                         } | ||||||
|  |                         if ( node.template[j] && (node.template[j] != "") ) { o[node.template[j]] = k[j]; } | ||||||
|  |                         msg.payload = o; | ||||||
|  |                         node.send(msg); | ||||||
|                     } |                     } | ||||||
|                     msg.payload = o.slice(0,-1); |                     catch(e) { node.log(e); } | ||||||
|                     node.send(msg); |  | ||||||
|                 } |                 } | ||||||
|                 catch(e) { node.log(e); } |                 else { node.log("This node only handles csv strings or js objects."); } | ||||||
|             } |             } | ||||||
|             else if (typeof msg.payload == "string") { // convert to object |         }); | ||||||
|                 try { |     } | ||||||
|                     var f = true; |     RED.nodes.registerType("csv",CSVNode); | ||||||
|                     var j = 0; |  | ||||||
|                     var k = [""]; |  | ||||||
|                     var o = {}; |  | ||||||
|                     for (var i = 0; i < msg.payload.length; i++) { |  | ||||||
|                         if (msg.payload[i] === node.quo) { |  | ||||||
|                             f = !f; |  | ||||||
|                             if (msg.payload[i-1] === node.quo) { k[j] += '\"'; } |  | ||||||
|                         } |  | ||||||
|                         else if ((msg.payload[i] === node.sep) && f) { |  | ||||||
|                             if ( node.template[j] && (node.template[j] != "") ) { o[node.template[j]] = k[j]; } |  | ||||||
|                             j += 1; |  | ||||||
|                             k[j] = ""; |  | ||||||
|                         } |  | ||||||
|                         else { |  | ||||||
|                             k[j] += msg.payload[i]; |  | ||||||
|                         } |  | ||||||
|                     } |  | ||||||
|                     if ( node.template[j] && (node.template[j] != "") ) { o[node.template[j]] = k[j]; } |  | ||||||
|                     msg.payload = o; |  | ||||||
|                     node.send(msg); |  | ||||||
|                 } |  | ||||||
|                 catch(e) { node.log(e); } |  | ||||||
|             } |  | ||||||
|             else { node.log("This node only handles csv strings or js objects."); } |  | ||||||
|         } |  | ||||||
|     }); |  | ||||||
| } | } | ||||||
| RED.nodes.registerType("csv",CSVNode); |  | ||||||
|   | |||||||
| @@ -14,31 +14,32 @@ | |||||||
|  * limitations under the License. |  * limitations under the License. | ||||||
|  **/ |  **/ | ||||||
|  |  | ||||||
| var RED = require(process.env.NODE_RED_HOME+"/red/red"); | module.exports = function(RED) { | ||||||
| var util = require("util"); |     var util = require("util"); | ||||||
|  |      | ||||||
| function JSONNode(n) { |     function JSONNode(n) { | ||||||
|     RED.nodes.createNode(this,n); |         RED.nodes.createNode(this,n); | ||||||
|     var node = this; |         var node = this; | ||||||
|     this.on("input", function(msg) { |         this.on("input", function(msg) { | ||||||
|         if (msg.hasOwnProperty("payload")) { |             if (msg.hasOwnProperty("payload")) { | ||||||
|             if (typeof msg.payload === "string") { |                 if (typeof msg.payload === "string") { | ||||||
|                 try { |                     try { | ||||||
|                     msg.payload = JSON.parse(msg.payload); |                         msg.payload = JSON.parse(msg.payload); | ||||||
|                     node.send(msg); |  | ||||||
|                 } |  | ||||||
|                 catch(e) { node.log(e+ "\n"+msg.payload); } |  | ||||||
|             } |  | ||||||
|             else if (typeof msg.payload === "object") { |  | ||||||
|                 if (!Buffer.isBuffer(msg.payload) ) { |  | ||||||
|                     if (!util.isArray(msg.payload)) { |  | ||||||
|                         msg.payload = JSON.stringify(msg.payload); |  | ||||||
|                         node.send(msg); |                         node.send(msg); | ||||||
|                     } |                     } | ||||||
|  |                     catch(e) { node.log(e+ "\n"+msg.payload); } | ||||||
|                 } |                 } | ||||||
|  |                 else if (typeof msg.payload === "object") { | ||||||
|  |                     if (!Buffer.isBuffer(msg.payload) ) { | ||||||
|  |                         if (!util.isArray(msg.payload)) { | ||||||
|  |                             msg.payload = JSON.stringify(msg.payload); | ||||||
|  |                             node.send(msg); | ||||||
|  |                         } | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  |                 else { node.log("dropped: "+msg.payload); } | ||||||
|             } |             } | ||||||
|             else { node.log("dropped: "+msg.payload); } |         }); | ||||||
|         } |     } | ||||||
|     }); |     RED.nodes.registerType("json",JSONNode); | ||||||
| } | } | ||||||
| RED.nodes.registerType("json",JSONNode); |  | ||||||
|   | |||||||
| @@ -14,37 +14,38 @@ | |||||||
|  * limitations under the License. |  * limitations under the License. | ||||||
|  **/ |  **/ | ||||||
|  |  | ||||||
| var RED = require(process.env.NODE_RED_HOME+"/red/red"); | module.exports = function(RED) { | ||||||
| var xml2js = require('xml2js'); |     var xml2js = require('xml2js'); | ||||||
| var parseString = xml2js.parseString; |     var parseString = xml2js.parseString; | ||||||
| var builder = new xml2js.Builder({renderOpts:{pretty:false}}); |     var builder = new xml2js.Builder({renderOpts:{pretty:false}}); | ||||||
|  |      | ||||||
| function XMLNode(n) { |     function XMLNode(n) { | ||||||
|     RED.nodes.createNode(this,n); |         RED.nodes.createNode(this,n); | ||||||
|     var node = this; |         var node = this; | ||||||
|     this.on("input", function(msg) { |         this.on("input", function(msg) { | ||||||
|         if (msg.hasOwnProperty("payload")) { |             if (msg.hasOwnProperty("payload")) { | ||||||
|             if (typeof msg.payload == "object") { |                 if (typeof msg.payload == "object") { | ||||||
|                 try { |                     try { | ||||||
|                     msg.payload = builder.buildObject(msg.payload); |                         msg.payload = builder.buildObject(msg.payload); | ||||||
|                     node.send(msg); |                         node.send(msg); | ||||||
|  |                     } | ||||||
|  |                     catch(e) { node.log(e); } | ||||||
|                 } |                 } | ||||||
|                 catch(e) { node.log(e); } |                 else if (typeof msg.payload == "string") { | ||||||
|             } |                     try { | ||||||
|             else if (typeof msg.payload == "string") { |                         parseString(msg.payload, {strict:true,async:true}, function (err, result) { | ||||||
|                 try { |                             if (err) { node.error(err); } | ||||||
|                     parseString(msg.payload, {strict:true,async:true}, function (err, result) { |                             else { | ||||||
|                         if (err) { node.error(err); } |                                 msg.payload = result; | ||||||
|                         else { |                                 node.send(msg); | ||||||
|                             msg.payload = result; |                             } | ||||||
|                             node.send(msg); |                         }); | ||||||
|                         } |                     } | ||||||
|                     }); |                     catch(e) { node.log(e); } | ||||||
|                 } |                 } | ||||||
|                 catch(e) { node.log(e); } |                 else { node.log("This node only handles xml strings or js objects."); } | ||||||
|             } |             } | ||||||
|             else { node.log("This node only handles xml strings or js objects."); } |         }); | ||||||
|         } |     } | ||||||
|     }); |     RED.nodes.registerType("xml",XMLNode); | ||||||
| } | } | ||||||
| RED.nodes.registerType("xml",XMLNode); |  | ||||||
|   | |||||||
| @@ -14,82 +14,122 @@ | |||||||
|  * limitations under the License. |  * limitations under the License. | ||||||
|  **/ |  **/ | ||||||
|  |  | ||||||
| var RED = require(process.env.NODE_RED_HOME+"/red/red"); | module.exports = function(RED) { | ||||||
| var ntwitter = require('twitter-ng'); |     var ntwitter = require('twitter-ng'); | ||||||
| var OAuth= require('oauth').OAuth; |     var OAuth= require('oauth').OAuth; | ||||||
|  |      | ||||||
| function TwitterNode(n) { |     function TwitterNode(n) { | ||||||
|     RED.nodes.createNode(this,n); |         RED.nodes.createNode(this,n); | ||||||
|     this.screen_name = n.screen_name; |         this.screen_name = n.screen_name; | ||||||
| } |     } | ||||||
| RED.nodes.registerType("twitter-credentials",TwitterNode); |     RED.nodes.registerType("twitter-credentials",TwitterNode); | ||||||
|  |      | ||||||
| function TwitterInNode(n) { |     function TwitterInNode(n) { | ||||||
|     RED.nodes.createNode(this,n); |         RED.nodes.createNode(this,n); | ||||||
|     this.active = true; |         this.active = true; | ||||||
|     this.user = n.user; |         this.user = n.user; | ||||||
|     //this.tags = n.tags.replace(/ /g,''); |         //this.tags = n.tags.replace(/ /g,''); | ||||||
|     this.tags = n.tags; |         this.tags = n.tags; | ||||||
|     this.twitter = n.twitter; |         this.twitter = n.twitter; | ||||||
|     this.topic = n.topic||"tweets"; |         this.topic = n.topic||"tweets"; | ||||||
|     this.twitterConfig = RED.nodes.getNode(this.twitter); |         this.twitterConfig = RED.nodes.getNode(this.twitter); | ||||||
|     var credentials = RED.nodes.getCredentials(this.twitter); |         var credentials = RED.nodes.getCredentials(this.twitter); | ||||||
|  |      | ||||||
|     if (credentials && credentials.screen_name == this.twitterConfig.screen_name) { |         if (credentials && credentials.screen_name == this.twitterConfig.screen_name) { | ||||||
|         var twit = new ntwitter({ |             var twit = new ntwitter({ | ||||||
|             consumer_key: "OKjYEd1ef2bfFolV25G5nQ", |                 consumer_key: "OKjYEd1ef2bfFolV25G5nQ", | ||||||
|             consumer_secret: "meRsltCktVMUI8gmggpXett7WBLd1k0qidYazoML6g", |                 consumer_secret: "meRsltCktVMUI8gmggpXett7WBLd1k0qidYazoML6g", | ||||||
|             access_token_key: credentials.access_token, |                 access_token_key: credentials.access_token, | ||||||
|             access_token_secret: credentials.access_token_secret |                 access_token_secret: credentials.access_token_secret | ||||||
|         }); |             }); | ||||||
|  |      | ||||||
|          |              | ||||||
|         //setInterval(function() { |             //setInterval(function() { | ||||||
|         //        twit.get("/application/rate_limit_status.json",null,function(err,cb) { |             //        twit.get("/application/rate_limit_status.json",null,function(err,cb) { | ||||||
|         //                console.log("direct_messages:",cb["resources"]["direct_messages"]); |             //                console.log("direct_messages:",cb["resources"]["direct_messages"]); | ||||||
|         //        }); |             //        }); | ||||||
|         //         |             //         | ||||||
|         //},10000); |             //},10000); | ||||||
|          |              | ||||||
|         var node = this; |             var node = this; | ||||||
|         if (this.user === "user") { |             if (this.user === "user") { | ||||||
|             node.poll_ids = []; |                 node.poll_ids = []; | ||||||
|             node.since_ids = {}; |                 node.since_ids = {}; | ||||||
|             var users = node.tags.split(","); |                 var users = node.tags.split(","); | ||||||
|             for (var i=0;i<users.length;i++) { |                 for (var i=0;i<users.length;i++) { | ||||||
|                 var user = users[i].replace(" ",""); |                     var user = users[i].replace(" ",""); | ||||||
|                 twit.getUserTimeline({ |                     twit.getUserTimeline({ | ||||||
|                         screen_name:user, |                             screen_name:user, | ||||||
|  |                             trim_user:0, | ||||||
|  |                             count:1 | ||||||
|  |                     },function() {  | ||||||
|  |                         var u = user+""; | ||||||
|  |                         return function(err,cb) { | ||||||
|  |                             if (err) { | ||||||
|  |                                 node.error(err); | ||||||
|  |                                 return; | ||||||
|  |                             } | ||||||
|  |                             if (cb[0]) { | ||||||
|  |                                 node.since_ids[u] = cb[0].id_str; | ||||||
|  |                             } else { | ||||||
|  |                                 node.since_ids[u] = '0'; | ||||||
|  |                             } | ||||||
|  |                             node.poll_ids.push(setInterval(function() { | ||||||
|  |                                 twit.getUserTimeline({ | ||||||
|  |                                         screen_name:u, | ||||||
|  |                                         trim_user:0, | ||||||
|  |                                         since_id:node.since_ids[u] | ||||||
|  |                                 },function(err,cb) { | ||||||
|  |                                     if (cb) { | ||||||
|  |                                         for (var t=cb.length-1;t>=0;t-=1) { | ||||||
|  |                                             var tweet = cb[t]; | ||||||
|  |                                             var where = tweet.user.location||""; | ||||||
|  |                                             var la = tweet.lang || tweet.user.lang; | ||||||
|  |                                             //console.log(tweet.user.location,"=>",tweet.user.screen_name,"=>",pay); | ||||||
|  |                                             var msg = { topic:node.topic+"/"+tweet.user.screen_name, payload:tweet.text, location:where, lang:la, tweet:tweet }; | ||||||
|  |                                             node.send(msg); | ||||||
|  |                                             if (t == 0) { | ||||||
|  |                                                 node.since_ids[u] = tweet.id_str; | ||||||
|  |                                             } | ||||||
|  |                                         } | ||||||
|  |                                     } | ||||||
|  |                                     if (err) { | ||||||
|  |                                         node.error(err); | ||||||
|  |                                     } | ||||||
|  |                                 }); | ||||||
|  |                             },60000)); | ||||||
|  |                         } | ||||||
|  |                     }()); | ||||||
|  |                 } | ||||||
|  |             } else if (this.user === "dm") { | ||||||
|  |                 node.poll_ids = []; | ||||||
|  |                 twit.getDirectMessages({ | ||||||
|  |                         screen_name:node.twitterConfig.screen_name, | ||||||
|                         trim_user:0, |                         trim_user:0, | ||||||
|                         count:1 |                         count:1 | ||||||
|                 },function() {  |                 },function(err,cb) { | ||||||
|                     var u = user+""; |                     if (err) { | ||||||
|                     return function(err,cb) { |                         node.error(err); | ||||||
|                         if (err) { |                         return; | ||||||
|                             node.error(err); |                     } | ||||||
|                             return; |                     if (cb[0]) { | ||||||
|                         } |                         node.since_id = cb[0].id_str; | ||||||
|                         if (cb[0]) { |                     } else { | ||||||
|                             node.since_ids[u] = cb[0].id_str; |                         node.since_id = '0'; | ||||||
|                         } else { |                     } | ||||||
|                             node.since_ids[u] = '0'; |                     node.poll_ids.push(setInterval(function() { | ||||||
|                         } |                             twit.getDirectMessages({ | ||||||
|                         node.poll_ids.push(setInterval(function() { |                                     screen_name:node.twitterConfig.screen_name, | ||||||
|                             twit.getUserTimeline({ |  | ||||||
|                                     screen_name:u, |  | ||||||
|                                     trim_user:0, |                                     trim_user:0, | ||||||
|                                     since_id:node.since_ids[u] |                                     since_id:node.since_id | ||||||
|                             },function(err,cb) { |                             },function(err,cb) { | ||||||
|                                 if (cb) { |                                 if (cb) { | ||||||
|                                     for (var t=cb.length-1;t>=0;t-=1) { |                                     for (var t=cb.length-1;t>=0;t-=1) { | ||||||
|                                         var tweet = cb[t]; |                                         var tweet = cb[t]; | ||||||
|                                         var where = tweet.user.location||""; |                                         var msg = { topic:node.topic+"/"+tweet.sender.screen_name, payload:tweet.text, tweet:tweet }; | ||||||
|                                         var la = tweet.lang || tweet.user.lang; |  | ||||||
|                                         //console.log(tweet.user.location,"=>",tweet.user.screen_name,"=>",pay); |  | ||||||
|                                         var msg = { topic:node.topic+"/"+tweet.user.screen_name, payload:tweet.text, location:where, lang:la, tweet:tweet }; |  | ||||||
|                                         node.send(msg); |                                         node.send(msg); | ||||||
|                                         if (t == 0) { |                                         if (t == 0) { | ||||||
|                                             node.since_ids[u] = tweet.id_str; |                                             node.since_id = tweet.id_str; | ||||||
|                                         } |                                         } | ||||||
|                                     } |                                     } | ||||||
|                                 } |                                 } | ||||||
| @@ -97,226 +137,187 @@ function TwitterInNode(n) { | |||||||
|                                     node.error(err); |                                     node.error(err); | ||||||
|                                 } |                                 } | ||||||
|                             }); |                             }); | ||||||
|                         },60000)); |                     },120000)); | ||||||
|  |                 }); | ||||||
|  |                  | ||||||
|  |             } else if (this.tags !== "") { | ||||||
|  |                 try { | ||||||
|  |                     var thing = 'statuses/filter'; | ||||||
|  |                     if (this.user === "true") { thing = 'user'; } | ||||||
|  |                     var st = { track: [node.tags] }; | ||||||
|  |                     var bits = node.tags.split(","); | ||||||
|  |                     if ((bits.length > 0) && (bits.length % 4 == 0)) { | ||||||
|  |                         if ((Number(bits[0]) < Number(bits[2])) && (Number(bits[1]) < Number(bits[3]))) { | ||||||
|  |                             st = { locations: node.tags }; | ||||||
|  |                         } | ||||||
|  |                         else { | ||||||
|  |                             node.warn("twitter: possible bad geo area format. Should be lower-left lon,lat, upper-right lon,lat"); | ||||||
|  |                         } | ||||||
|                     } |                     } | ||||||
|                 }()); |      | ||||||
|             } |                     function setupStream() { | ||||||
|         } else if (this.user === "dm") { |                         if (node.active) { | ||||||
|             node.poll_ids = []; |                             twit.stream(thing, st, function(stream) { | ||||||
|             twit.getDirectMessages({ |                                 //console.log(st); | ||||||
|                     screen_name:node.twitterConfig.screen_name, |                                 //twit.stream('user', { track: [node.tags] }, function(stream) { | ||||||
|                     trim_user:0, |                                 //twit.stream('site', { track: [node.tags] }, function(stream) { | ||||||
|                     count:1 |                                 //twit.stream('statuses/filter', { track: [node.tags] }, function(stream) { | ||||||
|             },function(err,cb) { |                                 node.stream = stream; | ||||||
|                 if (err) { |                                 stream.on('data', function(tweet) { | ||||||
|                     node.error(err); |                                     //console.log(tweet.user); | ||||||
|                     return; |                                     if (tweet.user !== undefined) { | ||||||
|                 } |                                         var where = tweet.user.location||""; | ||||||
|                 if (cb[0]) { |                                         var la = tweet.lang || tweet.user.lang; | ||||||
|                     node.since_id = cb[0].id_str; |                                         //console.log(tweet.user.location,"=>",tweet.user.screen_name,"=>",pay); | ||||||
|                 } else { |                                         var msg = { topic:node.topic+"/"+tweet.user.screen_name, payload:tweet.text, location:where, lang:la, tweet:tweet }; | ||||||
|                     node.since_id = '0'; |                                         node.send(msg); | ||||||
|                 } |  | ||||||
|                 node.poll_ids.push(setInterval(function() { |  | ||||||
|                         twit.getDirectMessages({ |  | ||||||
|                                 screen_name:node.twitterConfig.screen_name, |  | ||||||
|                                 trim_user:0, |  | ||||||
|                                 since_id:node.since_id |  | ||||||
|                         },function(err,cb) { |  | ||||||
|                             if (cb) { |  | ||||||
|                                 for (var t=cb.length-1;t>=0;t-=1) { |  | ||||||
|                                     var tweet = cb[t]; |  | ||||||
|                                     var msg = { topic:node.topic+"/"+tweet.sender.screen_name, payload:tweet.text, tweet:tweet }; |  | ||||||
|                                     node.send(msg); |  | ||||||
|                                     if (t == 0) { |  | ||||||
|                                         node.since_id = tweet.id_str; |  | ||||||
|                                     } |                                     } | ||||||
|                                 } |                                 }); | ||||||
|                             } |                                 stream.on('limit', function(tweet) { | ||||||
|                             if (err) { |                                     node.log("tweet rate limit hit"); | ||||||
|                                 node.error(err); |                                 }); | ||||||
|                             } |                                 stream.on('error', function(tweet,rc) { | ||||||
|                         }); |                                     node.warn(tweet); | ||||||
|                 },120000)); |  | ||||||
|             }); |  | ||||||
|              |  | ||||||
|         } else if (this.tags !== "") { |  | ||||||
|             try { |  | ||||||
|                 var thing = 'statuses/filter'; |  | ||||||
|                 if (this.user === "true") { thing = 'user'; } |  | ||||||
|                 var st = { track: [node.tags] }; |  | ||||||
|                 var bits = node.tags.split(","); |  | ||||||
|                 if ((bits.length > 0) && (bits.length % 4 == 0)) { |  | ||||||
|                     if ((Number(bits[0]) < Number(bits[2])) && (Number(bits[1]) < Number(bits[3]))) { |  | ||||||
|                         st = { locations: node.tags }; |  | ||||||
|                     } |  | ||||||
|                     else { |  | ||||||
|                         node.warn("twitter: possible bad geo area format. Should be lower-left lon,lat, upper-right lon,lat"); |  | ||||||
|                     } |  | ||||||
|                 } |  | ||||||
|  |  | ||||||
|                 function setupStream() { |  | ||||||
|                     if (node.active) { |  | ||||||
|                         twit.stream(thing, st, function(stream) { |  | ||||||
|                             //console.log(st); |  | ||||||
|                             //twit.stream('user', { track: [node.tags] }, function(stream) { |  | ||||||
|                             //twit.stream('site', { track: [node.tags] }, function(stream) { |  | ||||||
|                             //twit.stream('statuses/filter', { track: [node.tags] }, function(stream) { |  | ||||||
|                             node.stream = stream; |  | ||||||
|                             stream.on('data', function(tweet) { |  | ||||||
|                                 //console.log(tweet.user); |  | ||||||
|                                 if (tweet.user !== undefined) { |  | ||||||
|                                     var where = tweet.user.location||""; |  | ||||||
|                                     var la = tweet.lang || tweet.user.lang; |  | ||||||
|                                     //console.log(tweet.user.location,"=>",tweet.user.screen_name,"=>",pay); |  | ||||||
|                                     var msg = { topic:node.topic+"/"+tweet.user.screen_name, payload:tweet.text, location:where, lang:la, tweet:tweet }; |  | ||||||
|                                     node.send(msg); |  | ||||||
|                                 } |  | ||||||
|                             }); |  | ||||||
|                             stream.on('limit', function(tweet) { |  | ||||||
|                                 node.log("tweet rate limit hit"); |  | ||||||
|                             }); |  | ||||||
|                             stream.on('error', function(tweet,rc) { |  | ||||||
|                                 node.warn(tweet); |  | ||||||
|                                 setTimeout(setupStream,10000); |  | ||||||
|                             }); |  | ||||||
|                             stream.on('destroy', function (response) { |  | ||||||
|                                 if (this.active) { |  | ||||||
|                                     node.warn("twitter ended unexpectedly"); |  | ||||||
|                                     setTimeout(setupStream,10000); |                                     setTimeout(setupStream,10000); | ||||||
|                                 } |                                 }); | ||||||
|  |                                 stream.on('destroy', function (response) { | ||||||
|  |                                     if (this.active) { | ||||||
|  |                                         node.warn("twitter ended unexpectedly"); | ||||||
|  |                                         setTimeout(setupStream,10000); | ||||||
|  |                                     } | ||||||
|  |                                 }); | ||||||
|                             }); |                             }); | ||||||
|                         }); |                         } | ||||||
|                     } |                     } | ||||||
|  |                     setupStream(); | ||||||
|                 } |                 } | ||||||
|                 setupStream(); |                 catch (err) { | ||||||
|             } |                     node.error(err); | ||||||
|             catch (err) { |                 } | ||||||
|                 node.error(err); |             } else { | ||||||
|  |                 this.error("Invalid tag property"); | ||||||
|             } |             } | ||||||
|         } else { |         } else { | ||||||
|             this.error("Invalid tag property"); |             this.error("missing twitter credentials"); | ||||||
|         } |         } | ||||||
|     } else { |      | ||||||
|         this.error("missing twitter credentials"); |         this.on('close', function() { | ||||||
|     } |             if (this.stream) { | ||||||
|  |                 this.active = false; | ||||||
|     this.on('close', function() { |                 this.stream.destroy(); | ||||||
|         if (this.stream) { |  | ||||||
|             this.active = false; |  | ||||||
|             this.stream.destroy(); |  | ||||||
|         } |  | ||||||
|         if (this.poll_ids) { |  | ||||||
|             for (var i=0;i<this.poll_ids.length;i++) { |  | ||||||
|                 clearInterval(this.poll_ids[i]); |  | ||||||
|             } |             } | ||||||
|         } |             if (this.poll_ids) { | ||||||
|     }); |                 for (var i=0;i<this.poll_ids.length;i++) { | ||||||
| } |                     clearInterval(this.poll_ids[i]); | ||||||
| RED.nodes.registerType("twitter in",TwitterInNode); |                 } | ||||||
|  |  | ||||||
|  |  | ||||||
| function TwitterOutNode(n) { |  | ||||||
|     RED.nodes.createNode(this,n); |  | ||||||
|     this.topic = n.topic; |  | ||||||
|     this.twitter = n.twitter; |  | ||||||
|     this.twitterConfig = RED.nodes.getNode(this.twitter); |  | ||||||
|     var credentials = RED.nodes.getCredentials(this.twitter); |  | ||||||
|     var node = this; |  | ||||||
|  |  | ||||||
|     if (credentials && credentials.screen_name == this.twitterConfig.screen_name) { |  | ||||||
|         var twit = new ntwitter({ |  | ||||||
|             consumer_key: "OKjYEd1ef2bfFolV25G5nQ", |  | ||||||
|             consumer_secret: "meRsltCktVMUI8gmggpXett7WBLd1k0qidYazoML6g", |  | ||||||
|             access_token_key: credentials.access_token, |  | ||||||
|             access_token_secret: credentials.access_token_secret |  | ||||||
|         }).verifyCredentials(function (err, data) { |  | ||||||
|             if (err) { |  | ||||||
|                 node.error("Error verifying credentials: " + err); |  | ||||||
|             } else { |  | ||||||
|                 node.on("input", function(msg) { |  | ||||||
|                     if (msg != null) { |  | ||||||
|                         if (msg.payload.length > 140) { |  | ||||||
|                             msg.payload = msg.payload.slice(0,139); |  | ||||||
|                             node.warn("Tweet greater than 140 : truncated"); |  | ||||||
|                         } |  | ||||||
|                         twit.updateStatus(msg.payload, function (err, data) { |  | ||||||
|                             if (err) node.error(err); |  | ||||||
|                         }); |  | ||||||
|                     } |  | ||||||
|                 }); |  | ||||||
|             } |             } | ||||||
|         }); |         }); | ||||||
|     } |     } | ||||||
| } |     RED.nodes.registerType("twitter in",TwitterInNode); | ||||||
| RED.nodes.registerType("twitter out",TwitterOutNode); |      | ||||||
|  |      | ||||||
| var oa = new OAuth( |     function TwitterOutNode(n) { | ||||||
|     "https://api.twitter.com/oauth/request_token", |         RED.nodes.createNode(this,n); | ||||||
|     "https://api.twitter.com/oauth/access_token", |         this.topic = n.topic; | ||||||
|     "OKjYEd1ef2bfFolV25G5nQ", |         this.twitter = n.twitter; | ||||||
|     "meRsltCktVMUI8gmggpXett7WBLd1k0qidYazoML6g", |         this.twitterConfig = RED.nodes.getNode(this.twitter); | ||||||
|     "1.0", |         var credentials = RED.nodes.getCredentials(this.twitter); | ||||||
|     null, |         var node = this; | ||||||
|     "HMAC-SHA1" |      | ||||||
| ); |         if (credentials && credentials.screen_name == this.twitterConfig.screen_name) { | ||||||
|  |             var twit = new ntwitter({ | ||||||
| var credentials = {}; |                 consumer_key: "OKjYEd1ef2bfFolV25G5nQ", | ||||||
|  |                 consumer_secret: "meRsltCktVMUI8gmggpXett7WBLd1k0qidYazoML6g", | ||||||
| RED.httpAdmin.get('/twitter/:id', function(req,res) { |                 access_token_key: credentials.access_token, | ||||||
|     var credentials = RED.nodes.getCredentials(req.params.id); |                 access_token_secret: credentials.access_token_secret | ||||||
|     if (credentials) { |             }).verifyCredentials(function (err, data) { | ||||||
|         res.send(JSON.stringify({sn:credentials.screen_name})); |                 if (err) { | ||||||
|     } else { |                     node.error("Error verifying credentials: " + err); | ||||||
|         res.send(JSON.stringify({})); |                 } else { | ||||||
|  |                     node.on("input", function(msg) { | ||||||
|  |                         if (msg != null) { | ||||||
|  |                             if (msg.payload.length > 140) { | ||||||
|  |                                 msg.payload = msg.payload.slice(0,139); | ||||||
|  |                                 node.warn("Tweet greater than 140 : truncated"); | ||||||
|  |                             } | ||||||
|  |                             twit.updateStatus(msg.payload, function (err, data) { | ||||||
|  |                                 if (err) node.error(err); | ||||||
|  |                             }); | ||||||
|  |                         } | ||||||
|  |                     }); | ||||||
|  |                 } | ||||||
|  |             }); | ||||||
|  |         } | ||||||
|     } |     } | ||||||
| }); |     RED.nodes.registerType("twitter out",TwitterOutNode); | ||||||
|  |      | ||||||
| RED.httpAdmin.delete('/twitter/:id', function(req,res) { |     var oa = new OAuth( | ||||||
|     RED.nodes.deleteCredentials(req.params.id); |         "https://api.twitter.com/oauth/request_token", | ||||||
|     res.send(200); |         "https://api.twitter.com/oauth/access_token", | ||||||
| }); |         "OKjYEd1ef2bfFolV25G5nQ", | ||||||
|  |         "meRsltCktVMUI8gmggpXett7WBLd1k0qidYazoML6g", | ||||||
| RED.httpAdmin.get('/twitter/:id/auth', function(req, res){ |         "1.0", | ||||||
|  |         null, | ||||||
|  |         "HMAC-SHA1" | ||||||
|  |     ); | ||||||
|  |      | ||||||
|     var credentials = {}; |     var credentials = {}; | ||||||
|     oa.getOAuthRequestToken({ |      | ||||||
|             oauth_callback: req.query.callback |     RED.httpAdmin.get('/twitter/:id', function(req,res) { | ||||||
|     },function(error, oauth_token, oauth_token_secret, results){ |         var credentials = RED.nodes.getCredentials(req.params.id); | ||||||
|         if (error) { |         if (credentials) { | ||||||
|             var resp = '<h2>Oh no!</h2>'+ |             res.send(JSON.stringify({sn:credentials.screen_name})); | ||||||
|             '<p>Something went wrong with the authentication process. The following error was returned:<p>'+ |  | ||||||
|             '<p><b>'+error.statusCode+'</b>: '+error.data+'</p>'+ |  | ||||||
|             '<p>One known cause of this type of failure is if the clock is wrong on system running Node-RED.'; |  | ||||||
|             res.send(resp) |  | ||||||
|         } else { |         } else { | ||||||
|             credentials.oauth_token = oauth_token; |             res.send(JSON.stringify({})); | ||||||
|             credentials.oauth_token_secret = oauth_token_secret; |  | ||||||
|             res.redirect('https://twitter.com/oauth/authorize?oauth_token='+oauth_token) |  | ||||||
|             RED.nodes.addCredentials(req.params.id,credentials); |  | ||||||
|         } |         } | ||||||
|     }); |     }); | ||||||
| }); |      | ||||||
|  |     RED.httpAdmin.delete('/twitter/:id', function(req,res) { | ||||||
| RED.httpAdmin.get('/twitter/:id/auth/callback', function(req, res, next){ |         RED.nodes.deleteCredentials(req.params.id); | ||||||
|     var credentials = RED.nodes.getCredentials(req.params.id); |         res.send(200); | ||||||
|     credentials.oauth_verifier = req.query.oauth_verifier; |     }); | ||||||
|  |      | ||||||
|     oa.getOAuthAccessToken( |     RED.httpAdmin.get('/twitter/:id/auth', function(req, res){ | ||||||
|         credentials.oauth_token, |         var credentials = {}; | ||||||
|         credentials.token_secret, |         oa.getOAuthRequestToken({ | ||||||
|         credentials.oauth_verifier, |                 oauth_callback: req.query.callback | ||||||
|         function(error, oauth_access_token, oauth_access_token_secret, results){ |         },function(error, oauth_token, oauth_token_secret, results){ | ||||||
|             if (error){ |             if (error) { | ||||||
|                 console.log(error); |                 var resp = '<h2>Oh no!</h2>'+ | ||||||
|                 res.send("yeah something broke."); |                 '<p>Something went wrong with the authentication process. The following error was returned:<p>'+ | ||||||
|  |                 '<p><b>'+error.statusCode+'</b>: '+error.data+'</p>'+ | ||||||
|  |                 '<p>One known cause of this type of failure is if the clock is wrong on system running Node-RED.'; | ||||||
|  |                 res.send(resp) | ||||||
|             } else { |             } else { | ||||||
|                 credentials = {}; |                 credentials.oauth_token = oauth_token; | ||||||
|                 credentials.access_token = oauth_access_token; |                 credentials.oauth_token_secret = oauth_token_secret; | ||||||
|                 credentials.access_token_secret = oauth_access_token_secret; |                 res.redirect('https://twitter.com/oauth/authorize?oauth_token='+oauth_token) | ||||||
|                 credentials.screen_name = "@"+results.screen_name; |  | ||||||
|                 RED.nodes.addCredentials(req.params.id,credentials); |                 RED.nodes.addCredentials(req.params.id,credentials); | ||||||
|                 res.send("<html><head></head><body>Authorised - you can close this window and return to Node-RED</body></html>"); |  | ||||||
|             } |             } | ||||||
|         } |         }); | ||||||
|     ); |     }); | ||||||
| }); |      | ||||||
|  |     RED.httpAdmin.get('/twitter/:id/auth/callback', function(req, res, next){ | ||||||
|  |         var credentials = RED.nodes.getCredentials(req.params.id); | ||||||
|  |         credentials.oauth_verifier = req.query.oauth_verifier; | ||||||
|  |      | ||||||
|  |         oa.getOAuthAccessToken( | ||||||
|  |             credentials.oauth_token, | ||||||
|  |             credentials.token_secret, | ||||||
|  |             credentials.oauth_verifier, | ||||||
|  |             function(error, oauth_access_token, oauth_access_token_secret, results){ | ||||||
|  |                 if (error){ | ||||||
|  |                     console.log(error); | ||||||
|  |                     res.send("yeah something broke."); | ||||||
|  |                 } else { | ||||||
|  |                     credentials = {}; | ||||||
|  |                     credentials.access_token = oauth_access_token; | ||||||
|  |                     credentials.access_token_secret = oauth_access_token_secret; | ||||||
|  |                     credentials.screen_name = "@"+results.screen_name; | ||||||
|  |                     RED.nodes.addCredentials(req.params.id,credentials); | ||||||
|  |                     res.send("<html><head></head><body>Authorised - you can close this window and return to Node-RED</body></html>"); | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |         ); | ||||||
|  |     }); | ||||||
|  | } | ||||||
|   | |||||||
| @@ -14,58 +14,58 @@ | |||||||
|  * limitations under the License. |  * limitations under the License. | ||||||
|  **/ |  **/ | ||||||
|  |  | ||||||
| var RED = require(process.env.NODE_RED_HOME+"/red/red"); | module.exports = function(RED) { | ||||||
| var FeedParser = require("feedparser"); |     var FeedParser = require("feedparser"); | ||||||
| var request = require("request"); |     var request = require("request"); | ||||||
|  |      | ||||||
| function FeedParseNode(n) { |     function FeedParseNode(n) { | ||||||
| 	RED.nodes.createNode(this,n); |         RED.nodes.createNode(this,n); | ||||||
| 	this.url = n.url; |         this.url = n.url; | ||||||
| 	this.interval = (parseInt(n.interval)||15)*60000; |         this.interval = (parseInt(n.interval)||15)*60000; | ||||||
| 	var node = this; |         var node = this; | ||||||
| 	this.interval_id = null; |         this.interval_id = null; | ||||||
| 	this.seen = {}; |         this.seen = {}; | ||||||
| 	if (this.url !== "") { |         if (this.url !== "") { | ||||||
| 	    var getFeed = function() { |             var getFeed = function() { | ||||||
|             request(node.url,function(err) { |                 request(node.url,function(err) { | ||||||
|                     if (err) node.error(err); |                         if (err) node.error(err); | ||||||
|             }) |  | ||||||
|                 .pipe(new FeedParser({feedurl:node.url})) |  | ||||||
|                 .on('error', function(error) { |  | ||||||
|                         node.error(error); |  | ||||||
|                 }) |                 }) | ||||||
|                 .on('meta', function (meta) {}) |                     .pipe(new FeedParser({feedurl:node.url})) | ||||||
|                 .on('readable', function () { |                     .on('error', function(error) { | ||||||
|                         var stream = this, article; |                             node.error(error); | ||||||
|                         while (article = stream.read()) { |                     }) | ||||||
|                             if (!(article.guid in node.seen) || ( node.seen[article.guid] != 0 && node.seen[article.guid] != article.date.getTime())) { |                     .on('meta', function (meta) {}) | ||||||
|                                 node.seen[article.guid] = article.date?article.date.getTime():0; |                     .on('readable', function () { | ||||||
|                                 var msg = { |                             var stream = this, article; | ||||||
|                                     topic:article.origlink||article.link, |                             while (article = stream.read()) { | ||||||
|                                     payload: article.description, |                                 if (!(article.guid in node.seen) || ( node.seen[article.guid] != 0 && node.seen[article.guid] != article.date.getTime())) { | ||||||
|                                     article: article |                                     node.seen[article.guid] = article.date?article.date.getTime():0; | ||||||
|                                 }; |                                     var msg = { | ||||||
|                                 node.send(msg); |                                         topic:article.origlink||article.link, | ||||||
|  |                                         payload: article.description, | ||||||
|  |                                         article: article | ||||||
|  |                                     }; | ||||||
|  |                                     node.send(msg); | ||||||
|  |                                 } | ||||||
|                             } |                             } | ||||||
|                         } |                     }) | ||||||
|                 }) |                     .on('end', function () { | ||||||
|                 .on('end', function () { |                     }); | ||||||
|                 }); |             }; | ||||||
|         }; |             this.interval_id = setInterval(getFeed,node.interval); | ||||||
| 	    this.interval_id = setInterval(getFeed,node.interval); |             getFeed(); | ||||||
| 	    getFeed(); |      | ||||||
|  |         } else { | ||||||
| 	} else { |             this.error("Invalid url"); | ||||||
| 	    this.error("Invalid url"); |         } | ||||||
| 	} |  | ||||||
| } |  | ||||||
|  |  | ||||||
| RED.nodes.registerType("feedparse",FeedParseNode); |  | ||||||
|  |  | ||||||
| FeedParseNode.prototype.close = function() { |  | ||||||
|     if (this.interval_id != null) { |  | ||||||
|         clearInterval(this.interval_id); |  | ||||||
|     } |     } | ||||||
| } |      | ||||||
|  |     RED.nodes.registerType("feedparse",FeedParseNode); | ||||||
|  |      | ||||||
|  |     FeedParseNode.prototype.close = function() { | ||||||
|  |         if (this.interval_id != null) { | ||||||
|  |             clearInterval(this.interval_id); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | }     | ||||||
|  |  | ||||||
|   | |||||||
| @@ -14,247 +14,248 @@ | |||||||
|  * limitations under the License. |  * limitations under the License. | ||||||
|  **/ |  **/ | ||||||
|  |  | ||||||
| var RED = require(process.env.NODE_RED_HOME+"/red/red"); | module.exports = function(RED) { | ||||||
| var util = require('util'); |     var util = require('util'); | ||||||
| var nodemailer = require("nodemailer"); |     var nodemailer = require("nodemailer"); | ||||||
| var Imap = null; |     var Imap = null; | ||||||
| try { |     try { | ||||||
|     Imap = require('imap'); |         Imap = require('imap'); | ||||||
| } catch (e) { |     } catch (e) { | ||||||
|     util.log("[61-email.js] - imap npm not installed - no inbound email available"); |         util.log("[61-email.js] - imap npm not installed - no inbound email available"); | ||||||
| } |  | ||||||
|  |  | ||||||
| //console.log(nodemailer.Transport.transports.SMTP.wellKnownHosts); |  | ||||||
|  |  | ||||||
| // module.exports = { service: "Gmail", user: "blahblah@gmail.com", pass: "password", server: "imap.gmail.com", port: "993" } |  | ||||||
| try { var globalkeys = RED.settings.email || require(process.env.NODE_RED_HOME+"/../emailkeys.js"); } |  | ||||||
| catch(err) { } |  | ||||||
|  |  | ||||||
| function EmailNode(n) { |  | ||||||
|     RED.nodes.createNode(this,n); |  | ||||||
|     this.topic = n.topic; |  | ||||||
|     this.name = n.name; |  | ||||||
|     this.outserver = n.server; |  | ||||||
|     this.outport = n.port; |  | ||||||
|     var flag = false; |  | ||||||
|     var credentials = RED.nodes.getCredentials(n.id); |  | ||||||
|     if ((credentials) && (credentials.hasOwnProperty("userid"))) { this.userid = credentials.userid; } |  | ||||||
|     else { |  | ||||||
|         if (globalkeys) { this.userid = globalkeys.user; flag = true; } |  | ||||||
|         else { this.error("No e-mail userid set"); } |  | ||||||
|     } |     } | ||||||
|     if ((credentials) && (credentials.hasOwnProperty("password"))) { this.password = credentials.password; } |      | ||||||
|     else { |     //console.log(nodemailer.Transport.transports.SMTP.wellKnownHosts); | ||||||
|         if (globalkeys) { this.password = globalkeys.pass; flag = true; } |      | ||||||
|         else { this.error("No e-mail password set"); } |     // module.exports = { service: "Gmail", user: "blahblah@gmail.com", pass: "password", server: "imap.gmail.com", port: "993" } | ||||||
|     } |     try { var globalkeys = RED.settings.email || require(process.env.NODE_RED_HOME+"/../emailkeys.js"); } | ||||||
|     if (flag) { RED.nodes.addCredentials(n.id,{userid:this.userid, password:this.password, global:true}); } |     catch(err) { } | ||||||
|     var node = this; |      | ||||||
|  |     function EmailNode(n) { | ||||||
|     var smtpTransport = nodemailer.createTransport("SMTP",{ |         RED.nodes.createNode(this,n); | ||||||
|         //service: emailkey.service, |         this.topic = n.topic; | ||||||
|         // { |         this.name = n.name; | ||||||
|         //transport: 'SMTP', |         this.outserver = n.server; | ||||||
|         host: node.outserver, |         this.outport = n.port; | ||||||
|         port: node.outport, |         var flag = false; | ||||||
|         requiresAuth: true, |         var credentials = RED.nodes.getCredentials(n.id); | ||||||
|         secureConnection: true, |         if ((credentials) && (credentials.hasOwnProperty("userid"))) { this.userid = credentials.userid; } | ||||||
|         //domains: [ 'gmail.com', 'googlemail.com' ], |         else { | ||||||
|         //}, |             if (globalkeys) { this.userid = globalkeys.user; flag = true; } | ||||||
|         auth: { |             else { this.error("No e-mail userid set"); } | ||||||
|             user: node.userid, |  | ||||||
|             pass: node.password |  | ||||||
|         } |         } | ||||||
|     }); |         if ((credentials) && (credentials.hasOwnProperty("password"))) { this.password = credentials.password; } | ||||||
|  |         else { | ||||||
|     this.on("input", function(msg) { |             if (globalkeys) { this.password = globalkeys.pass; flag = true; } | ||||||
|         //node.log("email :",this.id,this.topic," received",msg.payload); |             else { this.error("No e-mail password set"); } | ||||||
|         if (msg != null) { |         } | ||||||
|             if (smtpTransport) { |         if (flag) { RED.nodes.addCredentials(n.id,{userid:this.userid, password:this.password, global:true}); } | ||||||
|                 smtpTransport.sendMail({ |         var node = this; | ||||||
|                     from: node.userid, // sender address |      | ||||||
|                     to: node.name, // comma separated list of receivers |         var smtpTransport = nodemailer.createTransport("SMTP",{ | ||||||
|                     subject: msg.topic, // subject line |             //service: emailkey.service, | ||||||
|                     text: msg.payload // plaintext body |             // { | ||||||
|                 }, function(error, response) { |             //transport: 'SMTP', | ||||||
|                     if (error) { |             host: node.outserver, | ||||||
|                         node.error(error); |             port: node.outport, | ||||||
|                     } else { |             requiresAuth: true, | ||||||
|                         node.log("Message sent: " + response.message); |             secureConnection: true, | ||||||
|  |             //domains: [ 'gmail.com', 'googlemail.com' ], | ||||||
|  |             //}, | ||||||
|  |             auth: { | ||||||
|  |                 user: node.userid, | ||||||
|  |                 pass: node.password | ||||||
|  |             } | ||||||
|  |         }); | ||||||
|  |      | ||||||
|  |         this.on("input", function(msg) { | ||||||
|  |             //node.log("email :",this.id,this.topic," received",msg.payload); | ||||||
|  |             if (msg != null) { | ||||||
|  |                 if (smtpTransport) { | ||||||
|  |                     smtpTransport.sendMail({ | ||||||
|  |                         from: node.userid, // sender address | ||||||
|  |                         to: node.name, // comma separated list of receivers | ||||||
|  |                         subject: msg.topic, // subject line | ||||||
|  |                         text: msg.payload // plaintext body | ||||||
|  |                     }, function(error, response) { | ||||||
|  |                         if (error) { | ||||||
|  |                             node.error(error); | ||||||
|  |                         } else { | ||||||
|  |                             node.log("Message sent: " + response.message); | ||||||
|  |                         } | ||||||
|  |                     }); | ||||||
|  |                 } | ||||||
|  |                 else { node.warn("No Email credentials found. See info panel."); } | ||||||
|  |             } | ||||||
|  |         }); | ||||||
|  |     } | ||||||
|  |     RED.nodes.registerType("e-mail",EmailNode); | ||||||
|  |      | ||||||
|  |     function EmailInNode(n) { | ||||||
|  |         RED.nodes.createNode(this,n); | ||||||
|  |         this.name = n.name; | ||||||
|  |         this.repeat = n.repeat * 1000 || 300000; | ||||||
|  |         this.inserver = n.server || emailkey.server || "imap.gmail.com"; | ||||||
|  |         this.inport = n.port || emailkey.port || "993"; | ||||||
|  |         var flag = false; | ||||||
|  |         var credentials = RED.nodes.getCredentials(n.id); | ||||||
|  |         if ((credentials) && (credentials.hasOwnProperty("userid"))) { this.userid = credentials.userid; } | ||||||
|  |         else { | ||||||
|  |             if (globalkeys) { this.userid = globalkeys.user; flag = true; } | ||||||
|  |             else { this.error("No e-mail userid set"); } | ||||||
|  |         } | ||||||
|  |         if ((credentials) && (credentials.hasOwnProperty("password"))) { this.password = credentials.password; } | ||||||
|  |         else { | ||||||
|  |             if (globalkeys) { this.password = globalkeys.pass; flag = true; } | ||||||
|  |             else { this.error("No e-mail password set"); } | ||||||
|  |         } | ||||||
|  |         if (flag) { RED.nodes.addCredentials(n.id,{userid:this.userid, password:this.password, global:true}); } | ||||||
|  |         var node = this; | ||||||
|  |         this.interval_id = null; | ||||||
|  |         var oldmail = {}; | ||||||
|  |      | ||||||
|  |         var imap = new Imap({ | ||||||
|  |             user: node.userid, | ||||||
|  |             password: node.password, | ||||||
|  |             host: node.inserver, | ||||||
|  |             port: node.inport, | ||||||
|  |             tls: true, | ||||||
|  |             tlsOptions: { rejectUnauthorized: false }, | ||||||
|  |             connTimeout: node.repeat, | ||||||
|  |             authTimeout: node.repeat | ||||||
|  |         }); | ||||||
|  |      | ||||||
|  |         if (!isNaN(this.repeat) && this.repeat > 0) { | ||||||
|  |             node.log("repeat = "+this.repeat); | ||||||
|  |             this.interval_id = setInterval( function() { | ||||||
|  |                 node.emit("input",{}); | ||||||
|  |             }, this.repeat ); | ||||||
|  |         } | ||||||
|  |      | ||||||
|  |         this.on("input", function(msg) { | ||||||
|  |             imap.once('ready', function() { | ||||||
|  |                 var pay = {}; | ||||||
|  |                 imap.openBox('INBOX', true, function(err, box) { | ||||||
|  |                     if (box.messages.total > 0) { | ||||||
|  |                         var f = imap.seq.fetch(box.messages.total + ':*', { bodies: ['HEADER.FIELDS (FROM SUBJECT DATE)','TEXT'] }); | ||||||
|  |                         f.on('message', function(msg, seqno) { | ||||||
|  |                             node.log('message: #'+ seqno); | ||||||
|  |                             var prefix = '(#' + seqno + ') '; | ||||||
|  |                             msg.on('body', function(stream, info) { | ||||||
|  |                                 var buffer = ''; | ||||||
|  |                                 stream.on('data', function(chunk) { | ||||||
|  |                                     buffer += chunk.toString('utf8'); | ||||||
|  |                                 }); | ||||||
|  |                                 stream.on('end', function() { | ||||||
|  |                                     if (info.which !== 'TEXT') { | ||||||
|  |                                         pay.from = Imap.parseHeader(buffer).from[0]; | ||||||
|  |                                         pay.topic = Imap.parseHeader(buffer).subject[0]; | ||||||
|  |                                         pay.date = Imap.parseHeader(buffer).date[0]; | ||||||
|  |                                     } else { | ||||||
|  |                                         var parts = buffer.split("Content-Type"); | ||||||
|  |                                         for (var p in parts) { | ||||||
|  |                                             if (parts[p].indexOf("text/plain") >= 0) { | ||||||
|  |                                                 pay.payload = parts[p].split("\n").slice(1,-2).join("\n").trim(); | ||||||
|  |                                             } | ||||||
|  |                                             if (parts[p].indexOf("text/html") >= 0) { | ||||||
|  |                                                 pay.html = parts[p].split("\n").slice(1,-2).join("\n").trim(); | ||||||
|  |                                             } | ||||||
|  |                                         } | ||||||
|  |                                         //pay.body = buffer; | ||||||
|  |                                     } | ||||||
|  |                                 }); | ||||||
|  |                             }); | ||||||
|  |                             msg.on('end', function() { | ||||||
|  |                                 //node.log('Finished: '+prefix); | ||||||
|  |                             }); | ||||||
|  |                         }); | ||||||
|  |                         f.on('error', function(err) { | ||||||
|  |                             node.warn('fetch error: ' + err); | ||||||
|  |                         }); | ||||||
|  |                         f.on('end', function() { | ||||||
|  |                             if (JSON.stringify(pay) !== oldmail) { | ||||||
|  |                                 node.send(pay); | ||||||
|  |                                 oldmail = JSON.stringify(pay); | ||||||
|  |                                 node.log('received new email: '+pay.topic); | ||||||
|  |                             } | ||||||
|  |                             else { node.log('duplicate not sent: '+pay.topic); } | ||||||
|  |                             imap.end(); | ||||||
|  |                         }); | ||||||
|  |                     } | ||||||
|  |                     else { | ||||||
|  |                         node.log("you have achieved inbox zero"); | ||||||
|  |                         imap.end(); | ||||||
|                     } |                     } | ||||||
|                 }); |                 }); | ||||||
|             } |  | ||||||
|             else { node.warn("No Email credentials found. See info panel."); } |  | ||||||
|         } |  | ||||||
|     }); |  | ||||||
| } |  | ||||||
| RED.nodes.registerType("e-mail",EmailNode); |  | ||||||
|  |  | ||||||
| function EmailInNode(n) { |  | ||||||
|     RED.nodes.createNode(this,n); |  | ||||||
|     this.name = n.name; |  | ||||||
|     this.repeat = n.repeat * 1000 || 300000; |  | ||||||
|     this.inserver = n.server || emailkey.server || "imap.gmail.com"; |  | ||||||
|     this.inport = n.port || emailkey.port || "993"; |  | ||||||
|     var flag = false; |  | ||||||
|     var credentials = RED.nodes.getCredentials(n.id); |  | ||||||
|     if ((credentials) && (credentials.hasOwnProperty("userid"))) { this.userid = credentials.userid; } |  | ||||||
|     else { |  | ||||||
|         if (globalkeys) { this.userid = globalkeys.user; flag = true; } |  | ||||||
|         else { this.error("No e-mail userid set"); } |  | ||||||
|     } |  | ||||||
|     if ((credentials) && (credentials.hasOwnProperty("password"))) { this.password = credentials.password; } |  | ||||||
|     else { |  | ||||||
|         if (globalkeys) { this.password = globalkeys.pass; flag = true; } |  | ||||||
|         else { this.error("No e-mail password set"); } |  | ||||||
|     } |  | ||||||
|     if (flag) { RED.nodes.addCredentials(n.id,{userid:this.userid, password:this.password, global:true}); } |  | ||||||
|     var node = this; |  | ||||||
|     this.interval_id = null; |  | ||||||
|     var oldmail = {}; |  | ||||||
|  |  | ||||||
|     var imap = new Imap({ |  | ||||||
|         user: node.userid, |  | ||||||
|         password: node.password, |  | ||||||
|         host: node.inserver, |  | ||||||
|         port: node.inport, |  | ||||||
|         tls: true, |  | ||||||
|         tlsOptions: { rejectUnauthorized: false }, |  | ||||||
|         connTimeout: node.repeat, |  | ||||||
|         authTimeout: node.repeat |  | ||||||
|     }); |  | ||||||
|  |  | ||||||
|     if (!isNaN(this.repeat) && this.repeat > 0) { |  | ||||||
|         node.log("repeat = "+this.repeat); |  | ||||||
|         this.interval_id = setInterval( function() { |  | ||||||
|             node.emit("input",{}); |  | ||||||
|         }, this.repeat ); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     this.on("input", function(msg) { |  | ||||||
|         imap.once('ready', function() { |  | ||||||
|             var pay = {}; |  | ||||||
|             imap.openBox('INBOX', true, function(err, box) { |  | ||||||
|                 if (box.messages.total > 0) { |  | ||||||
|                     var f = imap.seq.fetch(box.messages.total + ':*', { bodies: ['HEADER.FIELDS (FROM SUBJECT DATE)','TEXT'] }); |  | ||||||
|                     f.on('message', function(msg, seqno) { |  | ||||||
|                         node.log('message: #'+ seqno); |  | ||||||
|                         var prefix = '(#' + seqno + ') '; |  | ||||||
|                         msg.on('body', function(stream, info) { |  | ||||||
|                             var buffer = ''; |  | ||||||
|                             stream.on('data', function(chunk) { |  | ||||||
|                                 buffer += chunk.toString('utf8'); |  | ||||||
|                             }); |  | ||||||
|                             stream.on('end', function() { |  | ||||||
|                                 if (info.which !== 'TEXT') { |  | ||||||
|                                     pay.from = Imap.parseHeader(buffer).from[0]; |  | ||||||
|                                     pay.topic = Imap.parseHeader(buffer).subject[0]; |  | ||||||
|                                     pay.date = Imap.parseHeader(buffer).date[0]; |  | ||||||
|                                 } else { |  | ||||||
|                                     var parts = buffer.split("Content-Type"); |  | ||||||
|                                     for (var p in parts) { |  | ||||||
|                                         if (parts[p].indexOf("text/plain") >= 0) { |  | ||||||
|                                             pay.payload = parts[p].split("\n").slice(1,-2).join("\n").trim(); |  | ||||||
|                                         } |  | ||||||
|                                         if (parts[p].indexOf("text/html") >= 0) { |  | ||||||
|                                             pay.html = parts[p].split("\n").slice(1,-2).join("\n").trim(); |  | ||||||
|                                         } |  | ||||||
|                                     } |  | ||||||
|                                     //pay.body = buffer; |  | ||||||
|                                 } |  | ||||||
|                             }); |  | ||||||
|                         }); |  | ||||||
|                         msg.on('end', function() { |  | ||||||
|                             //node.log('Finished: '+prefix); |  | ||||||
|                         }); |  | ||||||
|                     }); |  | ||||||
|                     f.on('error', function(err) { |  | ||||||
|                         node.warn('fetch error: ' + err); |  | ||||||
|                     }); |  | ||||||
|                     f.on('end', function() { |  | ||||||
|                         if (JSON.stringify(pay) !== oldmail) { |  | ||||||
|                             node.send(pay); |  | ||||||
|                             oldmail = JSON.stringify(pay); |  | ||||||
|                             node.log('received new email: '+pay.topic); |  | ||||||
|                         } |  | ||||||
|                         else { node.log('duplicate not sent: '+pay.topic); } |  | ||||||
|                         imap.end(); |  | ||||||
|                     }); |  | ||||||
|                 } |  | ||||||
|                 else { |  | ||||||
|                     node.log("you have achieved inbox zero"); |  | ||||||
|                     imap.end(); |  | ||||||
|                 } |  | ||||||
|             }); |             }); | ||||||
|  |             imap.on('error', function(err) { | ||||||
|  |                 node.log(err); | ||||||
|  |             }); | ||||||
|  |             imap.connect(); | ||||||
|         }); |         }); | ||||||
|         imap.on('error', function(err) { |      | ||||||
|             node.log(err); |         this.on("error", function(err) { | ||||||
|  |             node.log("error: ",err); | ||||||
|         }); |         }); | ||||||
|         imap.connect(); |      | ||||||
|     }); |         this.on("close", function() { | ||||||
|  |             if (this.interval_id != null) { | ||||||
|     this.on("error", function(err) { |                 clearInterval(this.interval_id); | ||||||
|         node.log("error: ",err); |             } | ||||||
|     }); |             if (imap) { imap.destroy(); } | ||||||
|  |         }); | ||||||
|     this.on("close", function() { |      | ||||||
|         if (this.interval_id != null) { |         node.emit("input",{}); | ||||||
|             clearInterval(this.interval_id); |  | ||||||
|         } |  | ||||||
|         if (imap) { imap.destroy(); } |  | ||||||
|     }); |  | ||||||
|  |  | ||||||
|     node.emit("input",{}); |  | ||||||
| } |  | ||||||
| if (Imap != null) { |  | ||||||
| RED.nodes.registerType("e-mail in",EmailInNode); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| var querystring = require('querystring'); |  | ||||||
|  |  | ||||||
| RED.httpAdmin.get('/email/global',function(req,res) { |  | ||||||
|     res.send(JSON.stringify({hasToken:!(globalkeys && globalkeys.userid && globalkeys.password)})); |  | ||||||
| }); |  | ||||||
|  |  | ||||||
| RED.httpAdmin.get('/email/:id',function(req,res) { |  | ||||||
|     var credentials = RED.nodes.getCredentials(req.params.id); |  | ||||||
|     if (credentials) { |  | ||||||
|         res.send(JSON.stringify({userid:credentials.userid,hasPassword:(credentials.password&&credentials.password!="")})); |  | ||||||
|     } |     } | ||||||
|     else if (globalkeys && globalkeys.user && globalkeys.pass) { |     if (Imap != null) { | ||||||
|         RED.nodes.addCredentials(req.params.id,{userid:globalkeys.user, password:globalkeys.pass, global:true}); |     RED.nodes.registerType("e-mail in",EmailInNode); | ||||||
|         credentials = RED.nodes.getCredentials(req.params.id); |  | ||||||
|         res.send(JSON.stringify({userid:credentials.userid,global:credentials.global,hasPassword:(credentials.password&&credentials.password!="")})); |  | ||||||
|     } |     } | ||||||
|     else { |      | ||||||
|         res.send(JSON.stringify({})); |     var querystring = require('querystring'); | ||||||
|     } |      | ||||||
| }); |     RED.httpAdmin.get('/email/global',function(req,res) { | ||||||
|  |         res.send(JSON.stringify({hasToken:!(globalkeys && globalkeys.userid && globalkeys.password)})); | ||||||
| RED.httpAdmin.delete('/email/:id',function(req,res) { |  | ||||||
|     RED.nodes.deleteCredentials(req.params.id); |  | ||||||
|     res.send(200); |  | ||||||
| }); |  | ||||||
|  |  | ||||||
| RED.httpAdmin.post('/email/:id',function(req,res) { |  | ||||||
|     var body = ""; |  | ||||||
|     req.on('data', function(chunk) { |  | ||||||
|         body+=chunk; |  | ||||||
|     }); |     }); | ||||||
|     req.on('end', function(){ |      | ||||||
|         var newCreds = querystring.parse(body); |     RED.httpAdmin.get('/email/:id',function(req,res) { | ||||||
|         var credentials = RED.nodes.getCredentials(req.params.id)||{}; |         var credentials = RED.nodes.getCredentials(req.params.id); | ||||||
|         if (newCreds.userid == null || newCreds.userid == "") { |         if (credentials) { | ||||||
|             delete credentials.userid; |             res.send(JSON.stringify({userid:credentials.userid,hasPassword:(credentials.password&&credentials.password!="")})); | ||||||
|         } else { |  | ||||||
|             credentials.userid = newCreds.userid; |  | ||||||
|         } |         } | ||||||
|         if (newCreds.password == "") { |         else if (globalkeys && globalkeys.user && globalkeys.pass) { | ||||||
|             delete credentials.password; |             RED.nodes.addCredentials(req.params.id,{userid:globalkeys.user, password:globalkeys.pass, global:true}); | ||||||
|         } else { |             credentials = RED.nodes.getCredentials(req.params.id); | ||||||
|             credentials.password = newCreds.password||credentials.password; |             res.send(JSON.stringify({userid:credentials.userid,global:credentials.global,hasPassword:(credentials.password&&credentials.password!="")})); | ||||||
|         } |         } | ||||||
|         RED.nodes.addCredentials(req.params.id,credentials); |         else { | ||||||
|  |             res.send(JSON.stringify({})); | ||||||
|  |         } | ||||||
|  |     }); | ||||||
|  |      | ||||||
|  |     RED.httpAdmin.delete('/email/:id',function(req,res) { | ||||||
|  |         RED.nodes.deleteCredentials(req.params.id); | ||||||
|         res.send(200); |         res.send(200); | ||||||
|     }); |     }); | ||||||
| }); |      | ||||||
|  |     RED.httpAdmin.post('/email/: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.userid == null || newCreds.userid == "") { | ||||||
|  |                 delete credentials.userid; | ||||||
|  |             } else { | ||||||
|  |                 credentials.userid = newCreds.userid; | ||||||
|  |             } | ||||||
|  |             if (newCreds.password == "") { | ||||||
|  |                 delete credentials.password; | ||||||
|  |             } else { | ||||||
|  |                 credentials.password = newCreds.password||credentials.password; | ||||||
|  |             } | ||||||
|  |             RED.nodes.addCredentials(req.params.id,credentials); | ||||||
|  |             res.send(200); | ||||||
|  |         }); | ||||||
|  |     }); | ||||||
|  | } | ||||||
|   | |||||||
| @@ -14,127 +14,128 @@ | |||||||
|  * limitations under the License. |  * limitations under the License. | ||||||
|  **/ |  **/ | ||||||
|  |  | ||||||
| var RED = require(process.env.NODE_RED_HOME+"/red/red"); | module.exports = function(RED) { | ||||||
| var irc = require("irc"); |     var irc = require("irc"); | ||||||
| var util = require("util"); |     var util = require("util"); | ||||||
|  |      | ||||||
| // The Server Definition - this opens (and closes) the connection |     // The Server Definition - this opens (and closes) the connection | ||||||
| function IRCServerNode(n) { |     function IRCServerNode(n) { | ||||||
|     RED.nodes.createNode(this,n); |         RED.nodes.createNode(this,n); | ||||||
|     this.server = n.server; |         this.server = n.server; | ||||||
|     this.channel = n.channel; |         this.channel = n.channel; | ||||||
|     this.nickname = n.nickname; |         this.nickname = n.nickname; | ||||||
|     this.ircclient = null; |         this.ircclient = null; | ||||||
|     this.on("close", function() { |         this.on("close", function() { | ||||||
|         if (this.ircclient != null) { |             if (this.ircclient != null) { | ||||||
|             this.ircclient.disconnect(); |                 this.ircclient.disconnect(); | ||||||
|         } |  | ||||||
|     }); |  | ||||||
| } |  | ||||||
| RED.nodes.registerType("irc-server",IRCServerNode); |  | ||||||
|  |  | ||||||
|  |  | ||||||
| // The Input Node |  | ||||||
| function IrcInNode(n) { |  | ||||||
|     RED.nodes.createNode(this,n); |  | ||||||
|     this.ircserver = n.ircserver; |  | ||||||
|     this.serverConfig = RED.nodes.getNode(this.ircserver); |  | ||||||
|     this.channel = n.channel || this.serverConfig.channel; |  | ||||||
|     if (this.serverConfig.ircclient == null) { |  | ||||||
|         this.serverConfig.ircclient = new irc.Client(this.serverConfig.server, this.serverConfig.nickname, { |  | ||||||
|             channels: [this.channel] |  | ||||||
|         }); |  | ||||||
|         this.serverConfig.ircclient.addListener('error', function(message) { |  | ||||||
|             util.log('[irc] '+ JSON.stringify(message)); |  | ||||||
|         }); |  | ||||||
|     } |  | ||||||
|     this.ircclient = this.serverConfig.ircclient; |  | ||||||
|     var node = this; |  | ||||||
|  |  | ||||||
|     this.ircclient.addListener('message', function (from, to, message) { |  | ||||||
|         //util.log(from + ' => ' + to + ': ' + message); |  | ||||||
|         var msg = { "topic":from, "from":from, "to":to, "payload":message }; |  | ||||||
|         node.send([msg,null]); |  | ||||||
|     }); |  | ||||||
|     this.ircclient.addListener('pm', function(from, message) { |  | ||||||
|         var msg = { "topic":from, "from":from, "to":"PRIV", "payload":message }; |  | ||||||
|         node.send([msg,null]); |  | ||||||
|     }); |  | ||||||
|  |  | ||||||
|     this.ircclient.addListener('join', function(channel, who) { |  | ||||||
|         var msg = { "payload": { "type":"join", "who":who, "channel":channel } }; |  | ||||||
|         node.send([null,msg]); |  | ||||||
|         node.log(who+' has joined '+channel); |  | ||||||
|     }); |  | ||||||
|     this.ircclient.addListener('invite', function(channel, from, message) { |  | ||||||
|         var msg = { "payload": { "type":"invite", "who":from, "channel":channel, "message":message } }; |  | ||||||
|         node.send([null,msg]); |  | ||||||
|         node.log(from+' sent invite to '+channel+': '+message); |  | ||||||
|     }); |  | ||||||
|     this.ircclient.addListener('part', function(channel, who, reason) { |  | ||||||
|         var msg = { "payload": { "type":"part", "who":who, "channel":channel, "reason":reason } }; |  | ||||||
|         node.send([null,msg]); |  | ||||||
|         node.log(who+'has left '+channel+': '+reason); |  | ||||||
|     }); |  | ||||||
|     this.ircclient.addListener('quit', function(nick, reason, channels, message) { |  | ||||||
|         var msg = { "payload": { "type":"quit", "who":nick, "channel":channels, "reason":reason } }; |  | ||||||
|         node.send([null,msg]); |  | ||||||
|         node.log(nick+'has quit '+channels+': '+reason); |  | ||||||
|     }); |  | ||||||
|     this.ircclient.addListener('kick', function(channel, who, by, reason) { |  | ||||||
|         var msg = { "payload": { "type":"kick", "who":who, "channel":channel, "by":by, "reason":reason } }; |  | ||||||
|         node.send([null,msg]); |  | ||||||
|         node.log(who+' was kicked from '+channel+' by '+by+': '+reason); |  | ||||||
|     }); |  | ||||||
|  |  | ||||||
| } |  | ||||||
| RED.nodes.registerType("irc in",IrcInNode); |  | ||||||
|  |  | ||||||
|  |  | ||||||
| // The Output Node |  | ||||||
| function IrcOutNode(n) { |  | ||||||
|     RED.nodes.createNode(this,n); |  | ||||||
|     this.sendAll = n.sendObject; |  | ||||||
|     this.ircserver = n.ircserver; |  | ||||||
|     this.serverConfig = RED.nodes.getNode(this.ircserver); |  | ||||||
|     this.channel = n.channel || this.serverConfig.channel; |  | ||||||
|     if (this.serverConfig.ircclient == null) { |  | ||||||
|         this.serverConfig.ircclient = new irc.Client(this.serverConfig.server, this.serverConfig.nickname, { |  | ||||||
|             channels: [this.channel] |  | ||||||
|         }); |  | ||||||
|         this.serverConfig.ircclient.addListener('error', function(message) { |  | ||||||
|             util.log('[irc] '+ JSON.stringify(message)); |  | ||||||
|         }); |  | ||||||
|     } |  | ||||||
|     this.ircclient = this.serverConfig.ircclient; |  | ||||||
|     var node = this; |  | ||||||
|  |  | ||||||
|     this.on("input", function(msg) { |  | ||||||
|         if (Object.prototype.toString.call( msg.raw ) === '[object Array]') { |  | ||||||
|             var m = msg.raw; |  | ||||||
|             for (var i = 0; i < 10; i++) { |  | ||||||
|                 if (typeof m[i] !== "string") { m[i] = ""; } |  | ||||||
|                 m[i] = m[i].replace(/"/g, ""); |  | ||||||
|             } |             } | ||||||
|             util.log("[irc] RAW command:"+m); |         }); | ||||||
|             node.ircclient.send(m[0],m[1],m[2],m[3],m[4],m[5],m[6],m[7],m[8],m[9]); |     } | ||||||
|  |     RED.nodes.registerType("irc-server",IRCServerNode); | ||||||
|  |      | ||||||
|  |      | ||||||
|  |     // The Input Node | ||||||
|  |     function IrcInNode(n) { | ||||||
|  |         RED.nodes.createNode(this,n); | ||||||
|  |         this.ircserver = n.ircserver; | ||||||
|  |         this.serverConfig = RED.nodes.getNode(this.ircserver); | ||||||
|  |         this.channel = n.channel || this.serverConfig.channel; | ||||||
|  |         if (this.serverConfig.ircclient == null) { | ||||||
|  |             this.serverConfig.ircclient = new irc.Client(this.serverConfig.server, this.serverConfig.nickname, { | ||||||
|  |                 channels: [this.channel] | ||||||
|  |             }); | ||||||
|  |             this.serverConfig.ircclient.addListener('error', function(message) { | ||||||
|  |                 util.log('[irc] '+ JSON.stringify(message)); | ||||||
|  |             }); | ||||||
|         } |         } | ||||||
|         else { |         this.ircclient = this.serverConfig.ircclient; | ||||||
|             if (msg._topic) { delete msg._topic; } |         var node = this; | ||||||
|             if (node.sendAll == "false") { |      | ||||||
|                 node.ircclient.say(node.channel, JSON.stringify(msg)); |         this.ircclient.addListener('message', function (from, to, message) { | ||||||
|  |             //util.log(from + ' => ' + to + ': ' + message); | ||||||
|  |             var msg = { "topic":from, "from":from, "to":to, "payload":message }; | ||||||
|  |             node.send([msg,null]); | ||||||
|  |         }); | ||||||
|  |         this.ircclient.addListener('pm', function(from, message) { | ||||||
|  |             var msg = { "topic":from, "from":from, "to":"PRIV", "payload":message }; | ||||||
|  |             node.send([msg,null]); | ||||||
|  |         }); | ||||||
|  |      | ||||||
|  |         this.ircclient.addListener('join', function(channel, who) { | ||||||
|  |             var msg = { "payload": { "type":"join", "who":who, "channel":channel } }; | ||||||
|  |             node.send([null,msg]); | ||||||
|  |             node.log(who+' has joined '+channel); | ||||||
|  |         }); | ||||||
|  |         this.ircclient.addListener('invite', function(channel, from, message) { | ||||||
|  |             var msg = { "payload": { "type":"invite", "who":from, "channel":channel, "message":message } }; | ||||||
|  |             node.send([null,msg]); | ||||||
|  |             node.log(from+' sent invite to '+channel+': '+message); | ||||||
|  |         }); | ||||||
|  |         this.ircclient.addListener('part', function(channel, who, reason) { | ||||||
|  |             var msg = { "payload": { "type":"part", "who":who, "channel":channel, "reason":reason } }; | ||||||
|  |             node.send([null,msg]); | ||||||
|  |             node.log(who+'has left '+channel+': '+reason); | ||||||
|  |         }); | ||||||
|  |         this.ircclient.addListener('quit', function(nick, reason, channels, message) { | ||||||
|  |             var msg = { "payload": { "type":"quit", "who":nick, "channel":channels, "reason":reason } }; | ||||||
|  |             node.send([null,msg]); | ||||||
|  |             node.log(nick+'has quit '+channels+': '+reason); | ||||||
|  |         }); | ||||||
|  |         this.ircclient.addListener('kick', function(channel, who, by, reason) { | ||||||
|  |             var msg = { "payload": { "type":"kick", "who":who, "channel":channel, "by":by, "reason":reason } }; | ||||||
|  |             node.send([null,msg]); | ||||||
|  |             node.log(who+' was kicked from '+channel+' by '+by+': '+reason); | ||||||
|  |         }); | ||||||
|  |      | ||||||
|  |     } | ||||||
|  |     RED.nodes.registerType("irc in",IrcInNode); | ||||||
|  |      | ||||||
|  |      | ||||||
|  |     // The Output Node | ||||||
|  |     function IrcOutNode(n) { | ||||||
|  |         RED.nodes.createNode(this,n); | ||||||
|  |         this.sendAll = n.sendObject; | ||||||
|  |         this.ircserver = n.ircserver; | ||||||
|  |         this.serverConfig = RED.nodes.getNode(this.ircserver); | ||||||
|  |         this.channel = n.channel || this.serverConfig.channel; | ||||||
|  |         if (this.serverConfig.ircclient == null) { | ||||||
|  |             this.serverConfig.ircclient = new irc.Client(this.serverConfig.server, this.serverConfig.nickname, { | ||||||
|  |                 channels: [this.channel] | ||||||
|  |             }); | ||||||
|  |             this.serverConfig.ircclient.addListener('error', function(message) { | ||||||
|  |                 util.log('[irc] '+ JSON.stringify(message)); | ||||||
|  |             }); | ||||||
|  |         } | ||||||
|  |         this.ircclient = this.serverConfig.ircclient; | ||||||
|  |         var node = this; | ||||||
|  |      | ||||||
|  |         this.on("input", function(msg) { | ||||||
|  |             if (Object.prototype.toString.call( msg.raw ) === '[object Array]') { | ||||||
|  |                 var m = msg.raw; | ||||||
|  |                 for (var i = 0; i < 10; i++) { | ||||||
|  |                     if (typeof m[i] !== "string") { m[i] = ""; } | ||||||
|  |                     m[i] = m[i].replace(/"/g, ""); | ||||||
|  |                 } | ||||||
|  |                 util.log("[irc] RAW command:"+m); | ||||||
|  |                 node.ircclient.send(m[0],m[1],m[2],m[3],m[4],m[5],m[6],m[7],m[8],m[9]); | ||||||
|             } |             } | ||||||
|             else { |             else { | ||||||
|                 if (typeof msg.payload === "object") { msg.payload = JSON.stringify(msg.payload); } |                 if (msg._topic) { delete msg._topic; } | ||||||
|                 if (node.sendAll == "pay") { |                 if (node.sendAll == "false") { | ||||||
|                     node.ircclient.say(node.channel, msg.payload); |                     node.ircclient.say(node.channel, JSON.stringify(msg)); | ||||||
|                 } |                 } | ||||||
|                 else { |                 else { | ||||||
|                     var to = msg.topic || node.channel; |                     if (typeof msg.payload === "object") { msg.payload = JSON.stringify(msg.payload); } | ||||||
|                     node.ircclient.say(to, msg.payload); |                     if (node.sendAll == "pay") { | ||||||
|  |                         node.ircclient.say(node.channel, msg.payload); | ||||||
|  |                     } | ||||||
|  |                     else { | ||||||
|  |                         var to = msg.topic || node.channel; | ||||||
|  |                         node.ircclient.say(to, msg.payload); | ||||||
|  |                     } | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|         } |         }); | ||||||
|     }); |     } | ||||||
|  |     RED.nodes.registerType("irc out",IrcOutNode); | ||||||
| } | } | ||||||
| RED.nodes.registerType("irc out",IrcOutNode); |  | ||||||
|   | |||||||
| @@ -14,43 +14,44 @@ | |||||||
|  * limitations under the License. |  * limitations under the License. | ||||||
|  **/ |  **/ | ||||||
|  |  | ||||||
| var RED = require(process.env.NODE_RED_HOME+"/red/red"); | module.exports = function(RED) { | ||||||
| var fs = require("fs"); |     var fs = require("fs"); | ||||||
| var spawn = require('child_process').spawn; |     var spawn = require('child_process').spawn; | ||||||
|  |      | ||||||
| function TailNode(n) { |     function TailNode(n) { | ||||||
|     RED.nodes.createNode(this,n); |         RED.nodes.createNode(this,n); | ||||||
|  |      | ||||||
|     this.filename = n.filename; |         this.filename = n.filename; | ||||||
|     this.split = n.split; |         this.split = n.split; | ||||||
|     var node = this; |         var node = this; | ||||||
|  |      | ||||||
|     var err = ""; |         var err = ""; | ||||||
|     var tail = spawn("tail", ["-f", this.filename]); |         var tail = spawn("tail", ["-f", this.filename]); | ||||||
|     tail.stdout.on("data", function (data) { |         tail.stdout.on("data", function (data) { | ||||||
|         var msg = {topic:node.filename}; |             var msg = {topic:node.filename}; | ||||||
|         if (node.split) { |             if (node.split) { | ||||||
|             var strings = data.toString().split("\n"); |                 var strings = data.toString().split("\n"); | ||||||
|             for (s in strings) { |                 for (s in strings) { | ||||||
|                 if (strings[s] != "") { |                     if (strings[s] != "") { | ||||||
|                     msg.payload = strings[s]; |                         msg.payload = strings[s]; | ||||||
|                     node.send(msg); |                         node.send(msg); | ||||||
|  |                     } | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|         } |             else { | ||||||
|         else { |                 msg.payload = data.toString(); | ||||||
|             msg.payload = data.toString(); |                 node.send(msg); | ||||||
|             node.send(msg); |             } | ||||||
|         } |         }); | ||||||
|     }); |      | ||||||
|  |         tail.stderr.on("data", function(data) { | ||||||
|     tail.stderr.on("data", function(data) { |             node.warn(data.toString()); | ||||||
|         node.warn(data.toString()); |         }); | ||||||
|     }); |      | ||||||
|  |         this.on("close", function() { | ||||||
|     this.on("close", function() { |             if (tail) tail.kill(); | ||||||
|         if (tail) tail.kill(); |         }); | ||||||
|     }); |     } | ||||||
|  |      | ||||||
|  |     RED.nodes.registerType("tail",TailNode); | ||||||
| } | } | ||||||
|  |  | ||||||
| RED.nodes.registerType("tail",TailNode); |  | ||||||
|   | |||||||
| @@ -14,77 +14,78 @@ | |||||||
|  * limitations under the License. |  * limitations under the License. | ||||||
|  **/ |  **/ | ||||||
|  |  | ||||||
| var RED = require(process.env.NODE_RED_HOME+"/red/red"); | module.exports = function(RED) { | ||||||
| var fs = require("fs"); |     var fs = require("fs"); | ||||||
|  |      | ||||||
| function FileNode(n) { |     function FileNode(n) { | ||||||
|     RED.nodes.createNode(this,n); |         RED.nodes.createNode(this,n); | ||||||
|  |      | ||||||
|     this.filename = n.filename; |         this.filename = n.filename; | ||||||
|     this.appendNewline = n.appendNewline; |         this.appendNewline = n.appendNewline; | ||||||
|     this.overwriteFile = n.overwriteFile; |         this.overwriteFile = n.overwriteFile; | ||||||
|     var node = this; |         var node = this; | ||||||
|     this.on("input",function(msg) { |         this.on("input",function(msg) { | ||||||
|         var filename = msg.filename || this.filename; |             var filename = msg.filename || this.filename; | ||||||
|  |      | ||||||
|         if (filename == "") { |             if (filename == "") { | ||||||
|             node.warn('No filename specified'); |                 node.warn('No filename specified'); | ||||||
|         } else if (typeof msg.payload != "undefined") { |             } else if (typeof msg.payload != "undefined") { | ||||||
|             var data = msg.payload; |                 var data = msg.payload; | ||||||
|             if (typeof data == "object") { data = JSON.stringify(data); } |                 if (typeof data == "object") { data = JSON.stringify(data); } | ||||||
|             if (typeof data == "boolean") { data = data.toString(); } |                 if (typeof data == "boolean") { data = data.toString(); } | ||||||
|             if (this.appendNewline) { |                 if (this.appendNewline) { | ||||||
|                 data += "\n"; |                     data += "\n"; | ||||||
|             } |                 } | ||||||
|             if (msg.hasOwnProperty('delete')) { |                 if (msg.hasOwnProperty('delete')) { | ||||||
|                 fs.unlink(filename, function (err) { |                     fs.unlink(filename, function (err) { | ||||||
|                     if (err) node.warn('Failed to delete file : '+err); |                         if (err) node.warn('Failed to delete file : '+err); | ||||||
|                     //console.log('Deleted file",filename); |                         //console.log('Deleted file",filename); | ||||||
|                 }); |  | ||||||
|             } |  | ||||||
|             else { |  | ||||||
|                 if (this.overwriteFile) { |  | ||||||
|                     fs.writeFile(filename, data, function (err) { |  | ||||||
|                         if (err) node.warn('Failed to write to file : '+err); |  | ||||||
|                         //console.log('Message written to file',filename); |  | ||||||
|                     }); |                     }); | ||||||
|                 } |                 } | ||||||
|                 else { |                 else { | ||||||
|                     fs.appendFile(filename, data, function (err) { |                     if (this.overwriteFile) { | ||||||
|                         if (err) node.warn('Failed to append to file : '+err); |                         fs.writeFile(filename, data, function (err) { | ||||||
|                         //console.log('Message appended to file',filename); |                             if (err) node.warn('Failed to write to file : '+err); | ||||||
|                     }); |                             //console.log('Message written to file',filename); | ||||||
|  |                         }); | ||||||
|  |                     } | ||||||
|  |                     else { | ||||||
|  |                         fs.appendFile(filename, data, function (err) { | ||||||
|  |                             if (err) node.warn('Failed to append to file : '+err); | ||||||
|  |                             //console.log('Message appended to file',filename); | ||||||
|  |                         }); | ||||||
|  |                     } | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|         } |         }); | ||||||
|     }); |  | ||||||
| } |  | ||||||
| RED.nodes.registerType("file",FileNode); |  | ||||||
|  |  | ||||||
| function FileInNode(n) { |  | ||||||
|     RED.nodes.createNode(this,n); |  | ||||||
|  |  | ||||||
|     this.filename = n.filename; |  | ||||||
|     this.format = n.format; |  | ||||||
|     var node = this; |  | ||||||
|     var options = {}; |  | ||||||
|     if (this.format) { |  | ||||||
|         options['encoding'] = this.format; |  | ||||||
|     } |     } | ||||||
|     this.on("input",function(msg) { |     RED.nodes.registerType("file",FileNode); | ||||||
|         var filename = msg.filename || this.filename; |      | ||||||
|  |     function FileInNode(n) { | ||||||
|         if (filename == "") { |         RED.nodes.createNode(this,n); | ||||||
|             node.warn('No filename specified'); |      | ||||||
|         } else { |         this.filename = n.filename; | ||||||
|             fs.readFile(filename,options,function(err,data) { |         this.format = n.format; | ||||||
|                 if (err) { |         var node = this; | ||||||
|                     node.warn(err); |         var options = {}; | ||||||
|                 } else { |         if (this.format) { | ||||||
|                     node.send({payload:data}); |             options['encoding'] = this.format; | ||||||
|                 } |  | ||||||
|             }); |  | ||||||
|         } |         } | ||||||
|     }); |         this.on("input",function(msg) { | ||||||
|  |             var filename = msg.filename || this.filename; | ||||||
|  |      | ||||||
|  |             if (filename == "") { | ||||||
|  |                 node.warn('No filename specified'); | ||||||
|  |             } else { | ||||||
|  |                 fs.readFile(filename,options,function(err,data) { | ||||||
|  |                     if (err) { | ||||||
|  |                         node.warn(err); | ||||||
|  |                     } else { | ||||||
|  |                         node.send({payload:data}); | ||||||
|  |                     } | ||||||
|  |                 }); | ||||||
|  |             } | ||||||
|  |         }); | ||||||
|  |     } | ||||||
|  |     RED.nodes.registerType("file in",FileInNode); | ||||||
| } | } | ||||||
| RED.nodes.registerType("file in",FileInNode); |  | ||||||
|   | |||||||
| @@ -14,83 +14,84 @@ | |||||||
|  * limitations under the License. |  * limitations under the License. | ||||||
|  **/ |  **/ | ||||||
|  |  | ||||||
| var RED = require(process.env.NODE_RED_HOME+"/red/red"); | module.exports = function(RED) { | ||||||
| var util = require("util"); |     var util = require("util"); | ||||||
| var redis = require("redis"); |     var redis = require("redis"); | ||||||
|  |      | ||||||
| var hashFieldRE = /^([^=]+)=(.*)$/; |     var hashFieldRE = /^([^=]+)=(.*)$/; | ||||||
|  |      | ||||||
| var redisConnectionPool = function() { |     var redisConnectionPool = function() { | ||||||
|     var connections = {}; |         var connections = {}; | ||||||
|     var obj = { |         var obj = { | ||||||
|         get: function(host,port) { |             get: function(host,port) { | ||||||
|             var id = host+":"+port; |                 var id = host+":"+port; | ||||||
|             if (!connections[id]) { |                 if (!connections[id]) { | ||||||
|                 connections[id] = redis.createClient(port,host); |                     connections[id] = redis.createClient(port,host); | ||||||
|                 connections[id].on("error",function(err) { |                     connections[id].on("error",function(err) { | ||||||
|                         util.log("[redis] "+err); |                             util.log("[redis] "+err); | ||||||
|                 }); |                     }); | ||||||
|                 connections[id].on("connect",function() { |                     connections[id].on("connect",function() { | ||||||
|                         util.log("[redis] connected to "+host+":"+port); |                             util.log("[redis] connected to "+host+":"+port); | ||||||
|                 }); |                     }); | ||||||
|                 connections[id]._id = id; |                     connections[id]._id = id; | ||||||
|                 connections[id]._nodeCount = 0; |                     connections[id]._nodeCount = 0; | ||||||
|             } |  | ||||||
|             connections[id]._nodeCount += 1; |  | ||||||
|             return connections[id]; |  | ||||||
|         }, |  | ||||||
|         close: function(connection) { |  | ||||||
|             connection._nodeCount -= 1; |  | ||||||
|             if (connection._nodeCount == 0) { |  | ||||||
|                 if (connection) { |  | ||||||
|                     clearTimeout(connection.retry_timer); |  | ||||||
|                     connection.end(); |  | ||||||
|                 } |                 } | ||||||
|                 delete connections[connection._id]; |                 connections[id]._nodeCount += 1; | ||||||
|             } |                 return connections[id]; | ||||||
|         } |             }, | ||||||
|     }; |             close: function(connection) { | ||||||
|     return obj; |                 connection._nodeCount -= 1; | ||||||
| }(); |                 if (connection._nodeCount == 0) { | ||||||
|  |                     if (connection) { | ||||||
|  |                         clearTimeout(connection.retry_timer); | ||||||
| function RedisOutNode(n) { |                         connection.end(); | ||||||
|     RED.nodes.createNode(this,n); |  | ||||||
|     this.port = n.port||"6379"; |  | ||||||
|     this.hostname = n.hostname||"127.0.0.1"; |  | ||||||
|     this.key = n.key; |  | ||||||
|     this.structtype = n.structtype; |  | ||||||
|  |  | ||||||
|     this.client = redisConnectionPool.get(this.hostname,this.port); |  | ||||||
|  |  | ||||||
|     this.on("input", function(msg) { |  | ||||||
|             if (msg != null) { |  | ||||||
|                 var k = this.key || msg.topic; |  | ||||||
|                 if (k) { |  | ||||||
|                     if (this.structtype == "string") { |  | ||||||
|                         this.client.set(k,msg.payload); |  | ||||||
|                     } else if (this.structtype == "hash") { |  | ||||||
|                         var r = hashFieldRE.exec(msg.payload); |  | ||||||
|                         if (r) { |  | ||||||
|                             this.client.hset(k,r[1],r[2]); |  | ||||||
|                         } else { |  | ||||||
|                             this.warn("Invalid payload for redis hash"); |  | ||||||
|                         } |  | ||||||
|                     } else if (this.structtype == "set") { |  | ||||||
|                         this.client.sadd(k,msg.payload); |  | ||||||
|                     } else if (this.structtype == "list") { |  | ||||||
|                         this.client.rpush(k,msg.payload); |  | ||||||
|                     } |                     } | ||||||
|                 } else { |                     delete connections[connection._id]; | ||||||
|                     this.warn("No key or topic set"); |  | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|     }); |         }; | ||||||
| } |         return obj; | ||||||
|  |     }(); | ||||||
| RED.nodes.registerType("redis out",RedisOutNode); |      | ||||||
|  |      | ||||||
| RedisOutNode.prototype.close = function() { |     function RedisOutNode(n) { | ||||||
|     redisConnectionPool.close(this.client); |         RED.nodes.createNode(this,n); | ||||||
|  |         this.port = n.port||"6379"; | ||||||
|  |         this.hostname = n.hostname||"127.0.0.1"; | ||||||
|  |         this.key = n.key; | ||||||
|  |         this.structtype = n.structtype; | ||||||
|  |      | ||||||
|  |         this.client = redisConnectionPool.get(this.hostname,this.port); | ||||||
|  |      | ||||||
|  |         this.on("input", function(msg) { | ||||||
|  |                 if (msg != null) { | ||||||
|  |                     var k = this.key || msg.topic; | ||||||
|  |                     if (k) { | ||||||
|  |                         if (this.structtype == "string") { | ||||||
|  |                             this.client.set(k,msg.payload); | ||||||
|  |                         } else if (this.structtype == "hash") { | ||||||
|  |                             var r = hashFieldRE.exec(msg.payload); | ||||||
|  |                             if (r) { | ||||||
|  |                                 this.client.hset(k,r[1],r[2]); | ||||||
|  |                             } else { | ||||||
|  |                                 this.warn("Invalid payload for redis hash"); | ||||||
|  |                             } | ||||||
|  |                         } else if (this.structtype == "set") { | ||||||
|  |                             this.client.sadd(k,msg.payload); | ||||||
|  |                         } else if (this.structtype == "list") { | ||||||
|  |                             this.client.rpush(k,msg.payload); | ||||||
|  |                         } | ||||||
|  |                     } else { | ||||||
|  |                         this.warn("No key or topic set"); | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  |         }); | ||||||
|  |     } | ||||||
|  |      | ||||||
|  |     RED.nodes.registerType("redis out",RedisOutNode); | ||||||
|  |      | ||||||
|  |     RedisOutNode.prototype.close = function() { | ||||||
|  |         redisConnectionPool.close(this.client); | ||||||
|  |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -14,165 +14,166 @@ | |||||||
|  * limitations under the License. |  * limitations under the License. | ||||||
|  **/ |  **/ | ||||||
|  |  | ||||||
| var RED = require(process.env.NODE_RED_HOME+"/red/red"); | module.exports = function(RED) { | ||||||
| var mongo = require('mongodb'); |     var mongo = require('mongodb'); | ||||||
| var MongoClient = mongo.MongoClient; |     var MongoClient = mongo.MongoClient; | ||||||
|  |      | ||||||
| function MongoNode(n) { |     function MongoNode(n) { | ||||||
|     RED.nodes.createNode(this,n); |         RED.nodes.createNode(this,n); | ||||||
|     this.hostname = n.hostname; |         this.hostname = n.hostname; | ||||||
|     this.port = n.port; |         this.port = n.port; | ||||||
|     this.db = n.db; |         this.db = n.db; | ||||||
|     this.name = n.name; |         this.name = n.name; | ||||||
|     var credentials = RED.nodes.getCredentials(n.id); |         var credentials = RED.nodes.getCredentials(n.id); | ||||||
|     if (credentials) { |         if (credentials) { | ||||||
|         this.username = credentials.user; |             this.username = credentials.user; | ||||||
|         this.password = credentials.password; |             this.password = credentials.password; | ||||||
|  |         } | ||||||
|  |          | ||||||
|  |         var url = "mongodb://"; | ||||||
|  |         if (this.username && this.password) { | ||||||
|  |             url += this.username+":"+this.password+"@"; | ||||||
|  |         } | ||||||
|  |         url += this.hostname+":"+this.port+"/"+this.db; | ||||||
|  |          | ||||||
|  |         this.url = url; | ||||||
|     } |     } | ||||||
|      |      | ||||||
|     var url = "mongodb://"; |     RED.nodes.registerType("mongodb",MongoNode); | ||||||
|     if (this.username && this.password) { |  | ||||||
|         url += this.username+":"+this.password+"@"; |  | ||||||
|     } |  | ||||||
|     url += this.hostname+":"+this.port+"/"+this.db; |  | ||||||
|      |      | ||||||
|     this.url = url; |     var querystring = require('querystring'); | ||||||
| } |      | ||||||
|  |     RED.httpAdmin.get('/mongodb/:id',function(req,res) { | ||||||
| RED.nodes.registerType("mongodb",MongoNode); |         var credentials = RED.nodes.getCredentials(req.params.id); | ||||||
|  |         if (credentials) { | ||||||
| var querystring = require('querystring'); |             res.send(JSON.stringify({user:credentials.user,hasPassword:(credentials.password&&credentials.password!="")})); | ||||||
|  |         } else { | ||||||
| RED.httpAdmin.get('/mongodb/:id',function(req,res) { |             res.send(JSON.stringify({})); | ||||||
|     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.httpAdmin.delete('/mongodb/:id',function(req,res) { |  | ||||||
|     RED.nodes.deleteCredentials(req.params.id); |  | ||||||
|     res.send(200); |  | ||||||
| }); |  | ||||||
|  |  | ||||||
| RED.httpAdmin.post('/mongodb/:id',function(req,res) { |  | ||||||
|     var body = ""; |  | ||||||
|     req.on('data', function(chunk) { |  | ||||||
|         body+=chunk; |  | ||||||
|     }); |     }); | ||||||
|     req.on('end', function(){ |      | ||||||
|         var newCreds = querystring.parse(body); |     RED.httpAdmin.delete('/mongodb/:id',function(req,res) { | ||||||
|         var credentials = RED.nodes.getCredentials(req.params.id)||{}; |         RED.nodes.deleteCredentials(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); |         res.send(200); | ||||||
|     }); |     }); | ||||||
| }); |      | ||||||
|  |     RED.httpAdmin.post('/mongodb/:id',function(req,res) { | ||||||
|  |         var body = ""; | ||||||
| function MongoOutNode(n) { |         req.on('data', function(chunk) { | ||||||
|     RED.nodes.createNode(this,n); |             body+=chunk; | ||||||
|     this.collection = n.collection; |  | ||||||
|     this.mongodb = n.mongodb; |  | ||||||
|     this.payonly = n.payonly || false; |  | ||||||
|     this.operation = n.operation; |  | ||||||
|     this.mongoConfig = RED.nodes.getNode(this.mongodb); |  | ||||||
|  |  | ||||||
|     if (this.mongoConfig) { |  | ||||||
|         var node = this; |  | ||||||
|         MongoClient.connect(this.mongoConfig.url, function(err,db) { |  | ||||||
|             if (err) { |  | ||||||
|                 node.error(err); |  | ||||||
|             } else { |  | ||||||
|                 node.clientDb = db; |  | ||||||
|                 var coll = db.collection(node.collection); |  | ||||||
|                 node.on("input",function(msg) { |  | ||||||
|                     if (node.operation == "store") { |  | ||||||
|                         delete msg._topic; |  | ||||||
|                         if (node.payonly) { |  | ||||||
|                             if (typeof msg.payload !== "object") { msg.payload = {"payload":msg.payload}; } |  | ||||||
|                             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 if (node.operation == "insert") { |  | ||||||
|                         delete msg._topic; |  | ||||||
|                         if (node.payonly) { |  | ||||||
|                             if (typeof msg.payload !== "object") { msg.payload = {"payload":msg.payload}; } |  | ||||||
|                             coll.insert(msg.payload,function(err,item){ if (err){node.error(err);} }); |  | ||||||
|                         } else { |  | ||||||
|                             coll.insert(msg,function(err,item){if (err){node.error(err);}}); |  | ||||||
|                         } |  | ||||||
|                     } |  | ||||||
|                     if (node.operation == "delete") { |  | ||||||
|                         coll.remove(msg.payload, {w:1}, function(err, items){ if (err) node.error(err); }); |  | ||||||
|                     } |  | ||||||
|                 }); |  | ||||||
|             } |  | ||||||
|         }); |         }); | ||||||
|     } else { |         req.on('end', function(){ | ||||||
|         this.error("missing mongodb configuration"); |             var newCreds = querystring.parse(body); | ||||||
|     } |             var credentials = RED.nodes.getCredentials(req.params.id)||{}; | ||||||
|  |             if (newCreds.user == null || newCreds.user == "") { | ||||||
|     this.on("close", function() { |                 delete credentials.user; | ||||||
|         if (this.clientDb) { |  | ||||||
|             this.clientDb.close(); |  | ||||||
|         } |  | ||||||
|     }); |  | ||||||
| } |  | ||||||
| RED.nodes.registerType("mongodb out",MongoOutNode); |  | ||||||
|  |  | ||||||
|  |  | ||||||
| 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; |  | ||||||
|         MongoClient.connect(this.mongoConfig.url, function(err,db) { |  | ||||||
|             if (err) { |  | ||||||
|                 node.error(err); |  | ||||||
|             } else { |             } else { | ||||||
|                 node.clientDb = db; |                 credentials.user = newCreds.user; | ||||||
|                 var coll = db.collection(node.collection); |             } | ||||||
|                 node.on("input",function(msg) { |             if (newCreds.password == "") { | ||||||
|                     msg.projection = msg.projection || {}; |                 delete credentials.password; | ||||||
|                     coll.find(msg.payload,msg.projection).sort(msg.sort).limit(msg.limit).toArray(function(err, items) { |             } else { | ||||||
|                         if (err) { |                 credentials.password = newCreds.password||credentials.password; | ||||||
|                             node.error(err); |             } | ||||||
|                         } else { |             RED.nodes.addCredentials(req.params.id,credentials); | ||||||
|                             msg.payload = items; |             res.send(200); | ||||||
|                             delete msg.projection; |         }); | ||||||
|                             delete msg.sort; |     }); | ||||||
|                             delete msg.limit; |      | ||||||
|                             node.send(msg); |      | ||||||
|  |     function MongoOutNode(n) { | ||||||
|  |         RED.nodes.createNode(this,n); | ||||||
|  |         this.collection = n.collection; | ||||||
|  |         this.mongodb = n.mongodb; | ||||||
|  |         this.payonly = n.payonly || false; | ||||||
|  |         this.operation = n.operation; | ||||||
|  |         this.mongoConfig = RED.nodes.getNode(this.mongodb); | ||||||
|  |      | ||||||
|  |         if (this.mongoConfig) { | ||||||
|  |             var node = this; | ||||||
|  |             MongoClient.connect(this.mongoConfig.url, function(err,db) { | ||||||
|  |                 if (err) { | ||||||
|  |                     node.error(err); | ||||||
|  |                 } else { | ||||||
|  |                     node.clientDb = db; | ||||||
|  |                     var coll = db.collection(node.collection); | ||||||
|  |                     node.on("input",function(msg) { | ||||||
|  |                         if (node.operation == "store") { | ||||||
|  |                             delete msg._topic; | ||||||
|  |                             if (node.payonly) { | ||||||
|  |                                 if (typeof msg.payload !== "object") { msg.payload = {"payload":msg.payload}; } | ||||||
|  |                                 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 if (node.operation == "insert") { | ||||||
|  |                             delete msg._topic; | ||||||
|  |                             if (node.payonly) { | ||||||
|  |                                 if (typeof msg.payload !== "object") { msg.payload = {"payload":msg.payload}; } | ||||||
|  |                                 coll.insert(msg.payload,function(err,item){ if (err){node.error(err);} }); | ||||||
|  |                             } else { | ||||||
|  |                                 coll.insert(msg,function(err,item){if (err){node.error(err);}}); | ||||||
|  |                             } | ||||||
|  |                         } | ||||||
|  |                         if (node.operation == "delete") { | ||||||
|  |                             coll.remove(msg.payload, {w:1}, function(err, items){ if (err) node.error(err); }); | ||||||
|                         } |                         } | ||||||
|                     }); |                     }); | ||||||
|                 }); |                 } | ||||||
|  |             }); | ||||||
|  |         } else { | ||||||
|  |             this.error("missing mongodb configuration"); | ||||||
|  |         } | ||||||
|  |      | ||||||
|  |         this.on("close", function() { | ||||||
|  |             if (this.clientDb) { | ||||||
|  |                 this.clientDb.close(); | ||||||
|             } |             } | ||||||
|         }); |         }); | ||||||
|     } else { |  | ||||||
|         this.error("missing mongodb configuration"); |  | ||||||
|     } |     } | ||||||
|  |     RED.nodes.registerType("mongodb out",MongoOutNode); | ||||||
|     this.on("close", function() { |      | ||||||
|         if (this.clientDb) { |      | ||||||
|             this.clientDb.close(); |     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; | ||||||
|  |             MongoClient.connect(this.mongoConfig.url, function(err,db) { | ||||||
|  |                 if (err) { | ||||||
|  |                     node.error(err); | ||||||
|  |                 } else { | ||||||
|  |                     node.clientDb = db; | ||||||
|  |                     var coll = db.collection(node.collection); | ||||||
|  |                     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); | ||||||
|  |                             } else { | ||||||
|  |                                 msg.payload = items; | ||||||
|  |                                 delete msg.projection; | ||||||
|  |                                 delete msg.sort; | ||||||
|  |                                 delete msg.limit; | ||||||
|  |                                 node.send(msg); | ||||||
|  |                             } | ||||||
|  |                         }); | ||||||
|  |                     }); | ||||||
|  |                 } | ||||||
|  |             }); | ||||||
|  |         } else { | ||||||
|  |             this.error("missing mongodb configuration"); | ||||||
|         } |         } | ||||||
|     }); |      | ||||||
|  |         this.on("close", function() { | ||||||
|  |             if (this.clientDb) { | ||||||
|  |                 this.clientDb.close(); | ||||||
|  |             } | ||||||
|  |         }); | ||||||
|  |     } | ||||||
|  |     RED.nodes.registerType("mongodb in",MongoInNode); | ||||||
| } | } | ||||||
| RED.nodes.registerType("mongodb in",MongoInNode); |  | ||||||
|   | |||||||
| @@ -54,7 +54,7 @@ function loadNode(nodeDir, nodeFn) { | |||||||
|         var r = require(nodeFilename); |         var r = require(nodeFilename); | ||||||
|         if (typeof r === "function") { |         if (typeof r === "function") { | ||||||
|             try { |             try { | ||||||
|                 var promise = r(RED); |                 var promise = r(require('../red')); | ||||||
|                 if (promise != null && typeof promise.then === "function") { |                 if (promise != null && typeof promise.then === "function") { | ||||||
|                     promise.then(function() { |                     promise.then(function() { | ||||||
|                         resolve(loadTemplate(templateFilename)); |                         resolve(loadTemplate(templateFilename)); | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user