1
0
mirror of https://github.com/node-red/node-red.git synced 2023-10-10 13:36:53 +02:00

Migrate to new node function style

This commit is contained in:
Nick O'Leary 2014-05-03 23:32:04 +01:00
parent 5afc5857c4
commit ff49d2b217
37 changed files with 3194 additions and 3170 deletions

View File

@ -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. -->

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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);
}
});

View File

@ -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); }
}
});

View File

@ -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);

View File

@ -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");

View File

@ -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");

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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();
}
} }
} }

View File

@ -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);
});
});
}

View File

@ -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);

View File

@ -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);

View File

@ -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(); });
}); });
}); }

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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>");
}
}
);
});
}

View File

@ -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);
}
}
}

View File

@ -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);
});
});
}

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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);
}
} }

View File

@ -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);

View File

@ -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));