From 8a8b9bf7d82c0c4c375f0125922b6e9ab5b7ca3f Mon Sep 17 00:00:00 2001
From: Wolfgang Nagele
Date: Mon, 9 Dec 2013 21:45:15 +1100
Subject: [PATCH 01/24] Implementation for Amazon DynamoDB
---
README.md | 2 ++
storage/ddb/69-ddbout.html | 72 ++++++++++++++++++++++++++++++++++++++
storage/ddb/69-ddbout.js | 45 ++++++++++++++++++++++++
3 files changed, 119 insertions(+)
create mode 100644 storage/ddb/69-ddbout.html
create mode 100644 storage/ddb/69-ddbout.js
diff --git a/README.md b/README.md
index 5c150f4c..fa93915e 100644
--- a/README.md
+++ b/README.md
@@ -96,6 +96,8 @@ Uses a simple read of the serial port as a file to input data. You **must** set
**68-mysql** - Allows basic access to a MySQL database. This node uses the **query** operation against the configured database. This does allow both INSERTS and DELETES. By it's very nature it allows SQL injection... *so be careful out there...*
+**69-ddbout** - Support output to Amazon DynamoDB.
+
### Time
**79-suncalc** - Uses the suncalc module to generate an output at sunrise and sunset based on a specified location. Several choices of definition of sunrise and sunset are available,
diff --git a/storage/ddb/69-ddbout.html b/storage/ddb/69-ddbout.html
new file mode 100644
index 00000000..70235393
--- /dev/null
+++ b/storage/ddb/69-ddbout.html
@@ -0,0 +1,72 @@
+
+
+
+
+
+
+
diff --git a/storage/ddb/69-ddbout.js b/storage/ddb/69-ddbout.js
new file mode 100644
index 00000000..8f51576b
--- /dev/null
+++ b/storage/ddb/69-ddbout.js
@@ -0,0 +1,45 @@
+/**
+ * Copyright 2013 Wolfgang Nagele
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ **/
+
+var RED = require(process.env.NODE_RED_HOME+"/red/red");
+var util = require("util");
+var aws = require("aws-sdk");
+var attrWrapper = require("dynamodb-data-types").AttributeValue;
+
+function DDBOutNode(n) {
+ RED.nodes.createNode(this, n);
+ this.accessKey = n.accessKey;
+ this.secretAccessKey = n.secretAccessKey;
+ this.region = n.region || "us-east-1";
+ this.table = n.table;
+
+ aws.config.update({ accessKeyId: this.accessKey,
+ secretAccessKey: this.secretAccessKey,
+ region: this.region });
+
+ var ddb = new aws.DynamoDB();
+
+ this.on("input", function(msg) {
+ if (msg != null) {
+ ddb.putItem({ "TableName": this.table,
+ "Item": attrWrapper.wrap(msg.payload) },
+ function(err, data) {
+ err && util.log(err);
+ });
+ }
+ });
+}
+RED.nodes.registerType("ddb out", DDBOutNode);
From 17a040adfe3103200da5b2336584683401a35a57 Mon Sep 17 00:00:00 2001
From: Wolfgang Nagele
Date: Thu, 19 Dec 2013 13:07:40 +1100
Subject: [PATCH 02/24] Support external credentials Add base node with
credentials
---
storage/ddb/69-ddbout.html | 65 +++++++++++++++++++++++++++++++++-----
storage/ddb/69-ddbout.js | 55 +++++++++++++++++++++++++++++---
2 files changed, 108 insertions(+), 12 deletions(-)
diff --git a/storage/ddb/69-ddbout.html b/storage/ddb/69-ddbout.html
index 70235393..33b5463e 100644
--- a/storage/ddb/69-ddbout.html
+++ b/storage/ddb/69-ddbout.html
@@ -16,12 +16,8 @@
+
+
+
+
diff --git a/storage/ddb/69-ddbout.js b/storage/ddb/69-ddbout.js
index 8f51576b..8cf0d753 100644
--- a/storage/ddb/69-ddbout.js
+++ b/storage/ddb/69-ddbout.js
@@ -16,18 +16,65 @@
var RED = require(process.env.NODE_RED_HOME+"/red/red");
var util = require("util");
+var querystring = require('querystring');
var aws = require("aws-sdk");
var attrWrapper = require("dynamodb-data-types").AttributeValue;
+function DDBNode(n) {
+ RED.nodes.createNode(this, n);
+ var credentials = RED.nodes.getCredentials(n.id);
+ if (credentials) {
+ this.accessKey = credentials.accessKey;
+ this.secretAccessKey = credentials.secretAccessKey;
+ }
+}
+RED.nodes.registerType("awscredentials", DDBNode);
+
+RED.app.get('/awscredentials/:id', function(req, res) {
+ var credentials = RED.nodes.getCredentials(req.params.id);
+ if (credentials) {
+ res.send(JSON.stringify({ accessKey: credentials.accessKey, secretAccessKey: credentials.secretAccessKey }));
+ } else {
+ res.send(JSON.stringify({}));
+ }
+});
+
+RED.app.delete('/awscredentials/:id', function(req, res) {
+ RED.nodes.deleteCredentials(req.params.id);
+ res.send(200);
+});
+
+RED.app.post('/awscredentials/: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.accessKey == null || newCreds.accessKey == "") {
+ delete credentials.accessKey;
+ } else {
+ credentials.accessKey = newCreds.accessKey || credentials.accessKey;
+ }
+ if (newCreds.secretAccessKey == null || newCreds.secretAccessKey == "") {
+ delete credentials.secretAccessKey;
+ } else {
+ credentials.secretAccessKey = newCreds.secretAccessKey || credentials.secretAccessKey;
+ }
+ RED.nodes.addCredentials(req.params.id, credentials);
+ res.send(200);
+ });
+});
+
function DDBOutNode(n) {
RED.nodes.createNode(this, n);
- this.accessKey = n.accessKey;
- this.secretAccessKey = n.secretAccessKey;
+ this.credentials = RED.nodes.getNode(n.credentials);
this.region = n.region || "us-east-1";
this.table = n.table;
- aws.config.update({ accessKeyId: this.accessKey,
- secretAccessKey: this.secretAccessKey,
+ aws.config.update({ accessKeyId: this.credentials.accessKey,
+ secretAccessKey: this.credentials.secretAccessKey,
region: this.region });
var ddb = new aws.DynamoDB();
From fe109f15d84f3627b3c9867afdedc6de9351941a Mon Sep 17 00:00:00 2001
From: Kris Daniels
Date: Fri, 20 Dec 2013 10:00:35 +0100
Subject: [PATCH 03/24] added postgres node
---
storage/postgres/110-postgresout.html | 148 ++++++++++++++++++++++++++
storage/postgres/110-postgresout.js | 83 +++++++++++++++
storage/postgres/icons/postgres.png | Bin 0 -> 625 bytes
3 files changed, 231 insertions(+)
create mode 100644 storage/postgres/110-postgresout.html
create mode 100644 storage/postgres/110-postgresout.js
create mode 100644 storage/postgres/icons/postgres.png
diff --git a/storage/postgres/110-postgresout.html b/storage/postgres/110-postgresout.html
new file mode 100644
index 00000000..ab3291cc
--- /dev/null
+++ b/storage/postgres/110-postgresout.html
@@ -0,0 +1,148 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/storage/postgres/110-postgresout.js b/storage/postgres/110-postgresout.js
new file mode 100644
index 00000000..bf882b6a
--- /dev/null
+++ b/storage/postgres/110-postgresout.js
@@ -0,0 +1,83 @@
+/**
+ * Copyright 2013 IBM Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ **/
+
+// If you use this as a template, replace IBM Corp. with your own name.
+
+// Sample Node-RED node file
+
+// Require main module
+var RED = require(process.env.NODE_RED_HOME+"/red/red");
+var pg=require('pg');
+var named=require('node-postgres-named');
+
+function PostgresDatabaseNode(n) {
+ RED.nodes.createNode(this,n);
+ this.hostname = n.hostname;
+ this.port = n.port;
+ this.db = n.db;
+ this.username = n.username;
+ this.password = n.password;
+}
+
+RED.nodes.registerType("postgresdb",PostgresDatabaseNode);
+
+function PostgresNode(n) {
+ RED.nodes.createNode(this,n);
+
+ this.topic = n.topic;
+ this.postgresdb = n.postgresdb;
+ this.postgresConfig = RED.nodes.getNode(this.postgresdb);
+ this.sqlquery = n.sqlquery;
+ this.outputs = n.outputs;
+
+ var node = this;
+ if(this.postgresConfig)
+ {
+
+ var conString = 'postgres://'+this.postgresConfig.username +':' + this.postgresConfig.password + '@' + this.postgresConfig.hostname + ':' + this.postgresConfig.port + '/' + this.postgresConfig.db;
+ node.clientdb = new pg.Client(conString);
+ named.patch(node.clientdb);
+
+ node.clientdb.connect(function(err){
+ if(err) { node.error(err); }
+ else {
+ node.on('input',
+ function(msg){
+ node.clientdb.query(node.sqlquery,
+ msg.payload,
+ function (err, results) {
+ if(err) { node.error(err); }
+ else {
+ if(node.outputs>0)
+ {
+ msg.payload = results.rows;
+ node.send(msg);
+ }
+ }
+ });
+ });
+ }
+ });
+ } else {
+ this.error("missing postgres configuration");
+ }
+
+ this.on("close", function() {
+ if(node.clientdb) node.clientdb.end();
+ });
+}
+
+RED.nodes.registerType("postgres",PostgresNode);
diff --git a/storage/postgres/icons/postgres.png b/storage/postgres/icons/postgres.png
new file mode 100644
index 0000000000000000000000000000000000000000..e46c31696bc4e2240ffe3450323e74c6ae0bbe33
GIT binary patch
literal 625
zcmV-%0*?KOP)HWn7*8>A2=
zPoR*(#?ID4Ng-Z2`D|v#*^}9G_Q^$X!NAO#%Ubi#|Ib1tYvF+7Tk2bNTU{%hi%RaO
z+0u;pmE@e8iN6ygs6-Pu4SWN3*>3`iz|YLz01Lo(U>VqnYtwxb;8(jiL}viLR)SqD
z1S78h0gQn!z`a63fA^_p)z^KPtEWoPRNA)M6#TZ38nckHwYMK?4KOY25eQ8(I4au(
z9s{?_>Cc9%ou8YeFVsS8^B56MPbce|0o0Y21)zP49ZV{twXZ5lU%F6
zJHXY#;uYZ09EXQYVxc4p3Xj~jvHH0{@5uleslHJ!m#W36qDQlmG~}C8-7M_g)8Q0&
z3as_KWBZ|>2c8dv_gehW?Sr&0d(}_s{jC1=-ELH=nfn4h$;NjxSWG^E8l+1-g}qaN
z`?N%Xbv4~C#$ue>0`QxNagEwd@_w%dR+aT6nOr8t8`f+T2{!M~)G3zp*z~Z)vf&@w
ze-m)ypaJJ4O^qDmNd0h}kP55
Date: Fri, 20 Dec 2013 10:18:22 +0100
Subject: [PATCH 04/24] added examples to node documentation
---
storage/postgres/110-postgresout.html | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/storage/postgres/110-postgresout.html b/storage/postgres/110-postgresout.html
index ab3291cc..4e984f5a 100644
--- a/storage/postgres/110-postgresout.html
+++ b/storage/postgres/110-postgresout.html
@@ -78,6 +78,16 @@
This node can be used to write and read from a Postgres database
To receive the results from a query, simply set the outputs to 1 and connect a node
The msg.payload on the output will be a json array of the returned records
+
+
Insert exampleb>
+
msg.payload = { 'sensorid': 1, 'value': 2 }
+
insert into table (field1, field2) values ($sensorid, $value)
+
+
+
Select exampleb>
+
msg.payload = { 'sensorid': 1, 'value': 2 }
+
select * from table where field1=$sensorid order by time desc limit 1
+
diff --git a/storage/postgres/110-postgres.js b/storage/postgres/110-postgres.js
index bf882b6a..36e02b05 100644
--- a/storage/postgres/110-postgres.js
+++ b/storage/postgres/110-postgres.js
@@ -1,5 +1,5 @@
/**
- * Copyright 2013 IBM Corp.
+ * Copyright 2013 Kris Daniels.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -14,11 +14,6 @@
* limitations under the License.
**/
-// If you use this as a template, replace IBM Corp. with your own name.
-
-// Sample Node-RED node file
-
-// Require main module
var RED = require(process.env.NODE_RED_HOME+"/red/red");
var pg=require('pg');
var named=require('node-postgres-named');
From 43c6bdb95ad71b9f7e691de467e8634e053c4f97 Mon Sep 17 00:00:00 2001
From: Kris Daniels
Date: Sat, 21 Dec 2013 09:23:46 +0100
Subject: [PATCH 07/24] removed script editor from node config added support
for script in msg.payload added support for query parameters in
msg.queryParameters
---
storage/postgres/110-postgres.html | 83 +++++-------------------------
storage/postgres/110-postgres.js | 9 ++--
2 files changed, 17 insertions(+), 75 deletions(-)
diff --git a/storage/postgres/110-postgres.html b/storage/postgres/110-postgres.html
index 09a887a8..033cc990 100644
--- a/storage/postgres/110-postgres.html
+++ b/storage/postgres/110-postgres.html
@@ -60,43 +60,18 @@
-
-
-
-
-
-
-
+
+
+
@@ -107,8 +82,7 @@ limit 1
defaults: {
postgresdb: { type:"postgresdb",required:true},
name: {value:""},
- sqlquery: {value:"",required:true},
- outputs: {value:0}
+ output: {value:false}
},
inputs:1,
outputs:0,
@@ -121,47 +95,14 @@ limit 1
return this.name?"node_label_italic":"";
},
oneditprepare: function() {
- $( "#node-input-outputs" ).spinner({
- min:0,
- max:1
- });
- $( "#node-input-outputs" ).spinner( "value", this.outputs );
+ $( "#node-input-output" ).prop( "checked", this.output );
+ $("#node-input-name").focus();
- function functionDialogResize(ev,ui) {
- $("#node-input-sqlquery-editor").css("height",(ui.size.height-235)+"px");
- };
-
- $( "#dialog" ).on("dialogresize", functionDialogResize);
- $( "#dialog" ).one("dialogopen", function(ev) {
- var size = $( "#dialog" ).dialog('option','sizeCache-function');
- if (size) {
- functionDialogResize(null,{size:size});
- }
- });
- $( "#dialog" ).one("dialogclose", function(ev,ui) {
- var height = $( "#dialog" ).dialog('option','height');
- $( "#dialog" ).off("dialogresize",functionDialogResize);
- });
- var that = this;
- require(["orion/editor/edit"], function(edit) {
- that.editor = edit({
- parent:document.getElementById('node-input-sqlquery-editor'),
- lang:"sql",
- contents: $("#node-input-sqlquery").val()
- });
- RED.library.create({
- url:"storage", // where to get the data from
- type:"postgres", // the type of object the library is for
- editor:that.editor, // the field name the main text body goes to
- fields:['name','outputs']
- });
- $("#node-input-name").focus();
-
- });
},
oneditsave: function() {
- $("#node-input-sqlquery").val(this.editor.getText())
+ var hasOutput = $( "#node-input-output" ).prop( "checked" );
+ this.outputs = hasOutput ? 1: 0;
delete this.editor;
}
});
diff --git a/storage/postgres/110-postgres.js b/storage/postgres/110-postgres.js
index 36e02b05..edd42c88 100644
--- a/storage/postgres/110-postgres.js
+++ b/storage/postgres/110-postgres.js
@@ -36,7 +36,7 @@ function PostgresNode(n) {
this.postgresdb = n.postgresdb;
this.postgresConfig = RED.nodes.getNode(this.postgresdb);
this.sqlquery = n.sqlquery;
- this.outputs = n.outputs;
+ this.output = n.output;
var node = this;
if(this.postgresConfig)
@@ -51,12 +51,13 @@ function PostgresNode(n) {
else {
node.on('input',
function(msg){
- node.clientdb.query(node.sqlquery,
- msg.payload,
+ if(!msg.queryParameters) msg.queryParameters={};
+ node.clientdb.query(msg.payload,
+ msg.queryParameters,
function (err, results) {
if(err) { node.error(err); }
else {
- if(node.outputs>0)
+ if(node.output)
{
msg.payload = results.rows;
node.send(msg);
From 497f08bba93a001872ffa01907fac99d3adbccfb Mon Sep 17 00:00:00 2001
From: Kris Daniels
Date: Sat, 21 Dec 2013 11:01:19 +0100
Subject: [PATCH 08/24] moved credtials from config to credential store
---
storage/postgres/110-postgres.html | 47 ++++++++++++++++++++++++----
storage/postgres/110-postgres.js | 50 ++++++++++++++++++++++++++++--
2 files changed, 88 insertions(+), 9 deletions(-)
diff --git a/storage/postgres/110-postgres.html b/storage/postgres/110-postgres.html
index 033cc990..a4ea5e57 100644
--- a/storage/postgres/110-postgres.html
+++ b/storage/postgres/110-postgres.html
@@ -27,7 +27,7 @@
-
+
@@ -40,12 +40,46 @@
defaults: {
hostname: { value:"localhost",required:true},
port: { value: 5432,required:true},
- db: { value:"postgres",required:true},
- username: { value:"postgres", required:true },
- password: { value:"postgres", required:true }
+ db: { value:"postgres",required:true}
},
label: function() {
return this.name||this.hostname+":"+this.port+"/"+this.db;
+ },
+ oneditprepare: function() {
+
+ $.getJSON('postgresdb/'+this.id,function(data) {
+ if (data.user) {
+ $('#node-config-input-user').val(data.user);
+ }
+ if (data.hasPassword) {
+ $('#node-config-input-password').val('__PWRD__');
+ } else {
+ $('#node-config-input-password').val('');
+ }
+ });
+ },
+ oneditsave: function() {
+
+ var newUser = $('#node-config-input-user').val();
+ var newPass = $('#node-config-input-password').val();
+ var credentials = {};
+ credentials.user = newUser;
+ if (newPass != '__PWRD__') {
+ credentials.password = newPass;
+ }
+ $.ajax({
+ url: 'postgresdb/'+this.id,
+ type: 'POST',
+ data: credentials,
+ success:function(result){}
+ });
+ },
+ ondelete: function() {
+ $.ajax({
+ url: 'postgresdb/'+this.id,
+ type: 'DELETE',
+ success: function(result) {}
+ });
}
});
@@ -98,12 +132,13 @@
$( "#node-input-output" ).prop( "checked", this.output );
$("#node-input-name").focus();
-
+
},
oneditsave: function() {
+
var hasOutput = $( "#node-input-output" ).prop( "checked" );
this.outputs = hasOutput ? 1: 0;
- delete this.editor;
+
}
});
diff --git a/storage/postgres/110-postgres.js b/storage/postgres/110-postgres.js
index edd42c88..4e2d41ee 100644
--- a/storage/postgres/110-postgres.js
+++ b/storage/postgres/110-postgres.js
@@ -17,14 +17,57 @@
var RED = require(process.env.NODE_RED_HOME+"/red/red");
var pg=require('pg');
var named=require('node-postgres-named');
+var querystring = require('querystring');
+
+RED.app.get('/postgresdb/:id',function(req,res) {
+ var credentials = RED.nodes.getCredentials(req.params.id);
+ if (credentials) {
+ res.send(JSON.stringify({user:credentials.user,hasPassword:(credentials.password&&credentials.password!="")}));
+ } else {
+ res.send(JSON.stringify({}));
+ }
+});
+
+RED.app.delete('/postgresdb/:id',function(req,res) {
+ RED.nodes.deleteCredentials(req.params.id);
+ res.send(200);
+});
+
+RED.app.post('/postgresdb/:id',function(req,res) {
+ var body = "";
+ req.on('data', function(chunk) {
+ body+=chunk;
+ });
+ req.on('end', function(){
+ var newCreds = querystring.parse(body);
+ var credentials = RED.nodes.getCredentials(req.params.id)||{};
+ if (newCreds.user == null || newCreds.user == "") {
+ delete credentials.user;
+ } else {
+ credentials.user = newCreds.user;
+ }
+ if (newCreds.password == "") {
+ delete credentials.password;
+ } else {
+ credentials.password = newCreds.password||credentials.password;
+ }
+ RED.nodes.addCredentials(req.params.id,credentials);
+ res.send(200);
+ });
+});
+
function PostgresDatabaseNode(n) {
RED.nodes.createNode(this,n);
this.hostname = n.hostname;
this.port = n.port;
this.db = n.db;
- this.username = n.username;
- this.password = n.password;
+
+ var credentials = RED.nodes.getCredentials(n.id);
+ if (credentials) {
+ this.user = credentials.user;
+ this.password = credentials.password;
+ }
}
RED.nodes.registerType("postgresdb",PostgresDatabaseNode);
@@ -39,10 +82,11 @@ function PostgresNode(n) {
this.output = n.output;
var node = this;
+
if(this.postgresConfig)
{
- var conString = 'postgres://'+this.postgresConfig.username +':' + this.postgresConfig.password + '@' + this.postgresConfig.hostname + ':' + this.postgresConfig.port + '/' + this.postgresConfig.db;
+ var conString = 'postgres://'+this.postgresConfig.user +':' + this.postgresConfig.password + '@' + this.postgresConfig.hostname + ':' + this.postgresConfig.port + '/' + this.postgresConfig.db;
node.clientdb = new pg.Client(conString);
named.patch(node.clientdb);
From e72ced85e6f5ec18b8e6c3489a9d565ccba7a934 Mon Sep 17 00:00:00 2001
From: Kris Daniels
Date: Sat, 21 Dec 2013 16:55:44 +0100
Subject: [PATCH 09/24] fixed bug with outputs not being set correctly after
initial load
---
storage/postgres/110-postgres.html | 60 +++++++++++++++---------------
1 file changed, 31 insertions(+), 29 deletions(-)
diff --git a/storage/postgres/110-postgres.html b/storage/postgres/110-postgres.html
index a4ea5e57..6fae6ac1 100644
--- a/storage/postgres/110-postgres.html
+++ b/storage/postgres/110-postgres.html
@@ -111,34 +111,36 @@
From 243fc9ffd4da4de5e73d2252aba892abb18581e5 Mon Sep 17 00:00:00 2001
From: Wolfgang Nagele
Date: Sat, 21 Dec 2013 18:44:50 +0100
Subject: [PATCH 10/24] Setting defaults with credentials fields persists them
in the flows file. Fixed.
---
storage/ddb/69-ddbout.html | 4 ----
1 file changed, 4 deletions(-)
diff --git a/storage/ddb/69-ddbout.html b/storage/ddb/69-ddbout.html
index 33b5463e..dfe8dac0 100644
--- a/storage/ddb/69-ddbout.html
+++ b/storage/ddb/69-ddbout.html
@@ -80,10 +80,6 @@
+
+
diff --git a/lib/aws.js b/lib/aws.js
new file mode 100644
index 00000000..9997b676
--- /dev/null
+++ b/lib/aws.js
@@ -0,0 +1,65 @@
+/**
+ * Copyright 2013 Wolfgang Nagele
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ **/
+
+var RED = require(process.env.NODE_RED_HOME+"/red/red");
+var querystring = require('querystring');
+
+function AWSCredentialsNode(n) {
+ RED.nodes.createNode(this, n);
+ var credentials = RED.nodes.getCredentials(n.id);
+ if (credentials) {
+ this.accessKey = credentials.accessKey;
+ this.secretAccessKey = credentials.secretAccessKey;
+ }
+}
+RED.nodes.registerType("aws credentials", AWSCredentialsNode);
+
+RED.app.get('/aws-credentials/:id', function(req, res) {
+ var credentials = RED.nodes.getCredentials(req.params.id);
+ if (credentials) {
+ res.send(JSON.stringify({ accessKey: credentials.accessKey, secretAccessKey: credentials.secretAccessKey }));
+ } else {
+ res.send(JSON.stringify({}));
+ }
+});
+
+RED.app.delete('/aws-credentials/:id', function(req, res) {
+ RED.nodes.deleteCredentials(req.params.id);
+ res.send(200);
+});
+
+RED.app.post('/aws-credentials/: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.accessKey == null || newCreds.accessKey == "") {
+ delete credentials.accessKey;
+ } else {
+ credentials.accessKey = newCreds.accessKey || credentials.accessKey;
+ }
+ if (newCreds.secretAccessKey == null || newCreds.secretAccessKey == "") {
+ delete credentials.secretAccessKey;
+ } else {
+ credentials.secretAccessKey = newCreds.secretAccessKey || credentials.secretAccessKey;
+ }
+ RED.nodes.addCredentials(req.params.id, credentials);
+ res.send(200);
+ });
+});
diff --git a/storage/ddb/69-ddbout.html b/storage/ddb/69-ddbout.html
index dfe8dac0..4262ea5a 100644
--- a/storage/ddb/69-ddbout.html
+++ b/storage/ddb/69-ddbout.html
@@ -51,7 +51,7 @@
category: "storage-output",
color: "#ffaaaa",
defaults: {
- credentials: { type: "awscredentials", required: true },
+ credentials: { type: "aws credentials", required: true },
region: { value: "us-east-1" },
table: { value: "", required: true },
name: { value: "" }
@@ -65,53 +65,3 @@
}
});
-
-
-
-
diff --git a/storage/ddb/69-ddbout.js b/storage/ddb/69-ddbout.js
index 8cf0d753..3a9120d5 100644
--- a/storage/ddb/69-ddbout.js
+++ b/storage/ddb/69-ddbout.js
@@ -15,58 +15,11 @@
**/
var RED = require(process.env.NODE_RED_HOME+"/red/red");
+require("../../lib/aws");
var util = require("util");
-var querystring = require('querystring');
var aws = require("aws-sdk");
var attrWrapper = require("dynamodb-data-types").AttributeValue;
-function DDBNode(n) {
- RED.nodes.createNode(this, n);
- var credentials = RED.nodes.getCredentials(n.id);
- if (credentials) {
- this.accessKey = credentials.accessKey;
- this.secretAccessKey = credentials.secretAccessKey;
- }
-}
-RED.nodes.registerType("awscredentials", DDBNode);
-
-RED.app.get('/awscredentials/:id', function(req, res) {
- var credentials = RED.nodes.getCredentials(req.params.id);
- if (credentials) {
- res.send(JSON.stringify({ accessKey: credentials.accessKey, secretAccessKey: credentials.secretAccessKey }));
- } else {
- res.send(JSON.stringify({}));
- }
-});
-
-RED.app.delete('/awscredentials/:id', function(req, res) {
- RED.nodes.deleteCredentials(req.params.id);
- res.send(200);
-});
-
-RED.app.post('/awscredentials/: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.accessKey == null || newCreds.accessKey == "") {
- delete credentials.accessKey;
- } else {
- credentials.accessKey = newCreds.accessKey || credentials.accessKey;
- }
- if (newCreds.secretAccessKey == null || newCreds.secretAccessKey == "") {
- delete credentials.secretAccessKey;
- } else {
- credentials.secretAccessKey = newCreds.secretAccessKey || credentials.secretAccessKey;
- }
- RED.nodes.addCredentials(req.params.id, credentials);
- res.send(200);
- });
-});
-
function DDBOutNode(n) {
RED.nodes.createNode(this, n);
this.credentials = RED.nodes.getNode(n.credentials);
From 4e20f70bfde35b31427f36ca1231322252f69985 Mon Sep 17 00:00:00 2001
From: Wolfgang Nagele
Date: Sun, 22 Dec 2013 08:48:02 +0100
Subject: [PATCH 12/24] Leave region selection open so new regions are quicker
to use.
---
storage/ddb/69-ddbout.html | 13 ++-----------
1 file changed, 2 insertions(+), 11 deletions(-)
diff --git a/storage/ddb/69-ddbout.html b/storage/ddb/69-ddbout.html
index 4262ea5a..3f0859bd 100644
--- a/storage/ddb/69-ddbout.html
+++ b/storage/ddb/69-ddbout.html
@@ -21,16 +21,7 @@
-
+
@@ -52,7 +43,7 @@
color: "#ffaaaa",
defaults: {
credentials: { type: "aws credentials", required: true },
- region: { value: "us-east-1" },
+ region: { value: "us-east-1", required: true },
table: { value: "", required: true },
name: { value: "" }
},
From 5342637132108a6914f99c2960088d72edadc0ee Mon Sep 17 00:00:00 2001
From: Wolfgang Nagele
Date: Tue, 24 Dec 2013 17:21:22 +0100
Subject: [PATCH 13/24] Need to retain the accessKey defaults to be able to
show them in the UI
---
lib/aws.html | 3 +++
1 file changed, 3 insertions(+)
diff --git a/lib/aws.html b/lib/aws.html
index da463c52..5c26c904 100644
--- a/lib/aws.html
+++ b/lib/aws.html
@@ -31,6 +31,9 @@
label: function() {
return this.accessKey;
},
+ defaults: {
+ accessKey: { value: "", required: true }
+ },
oneditprepare: function() {
$.getJSON("aws-credentials/" + this.id, function(data) {
if (data.accessKey) {
From efb9fbb92b10dee2d8c93b0f9a29745db8970f46 Mon Sep 17 00:00:00 2001
From: Wolfgang Nagele
Date: Sun, 2 Feb 2014 21:52:08 +1100
Subject: [PATCH 14/24] Move AWS credentials to DDB node
---
storage/ddb/69-ddbout.js | 1 -
{lib => storage/ddb}/aws.html | 0
{lib => storage/ddb}/aws.js | 0
3 files changed, 1 deletion(-)
rename {lib => storage/ddb}/aws.html (100%)
rename {lib => storage/ddb}/aws.js (100%)
diff --git a/storage/ddb/69-ddbout.js b/storage/ddb/69-ddbout.js
index 3a9120d5..939d7d23 100644
--- a/storage/ddb/69-ddbout.js
+++ b/storage/ddb/69-ddbout.js
@@ -15,7 +15,6 @@
**/
var RED = require(process.env.NODE_RED_HOME+"/red/red");
-require("../../lib/aws");
var util = require("util");
var aws = require("aws-sdk");
var attrWrapper = require("dynamodb-data-types").AttributeValue;
diff --git a/lib/aws.html b/storage/ddb/aws.html
similarity index 100%
rename from lib/aws.html
rename to storage/ddb/aws.html
diff --git a/lib/aws.js b/storage/ddb/aws.js
similarity index 100%
rename from lib/aws.js
rename to storage/ddb/aws.js
From 2723210922fc84e93905bdf33730a44320ca0d8c Mon Sep 17 00:00:00 2001
From: Ben Hardill
Date: Wed, 5 Feb 2014 11:15:37 +0000
Subject: [PATCH 15/24] fixed typo in Temperature topic (sensorTag/Tempature to
sensorTag/Temperature)
This will break existing flows that are filtering on topic
---
hardware/sensorTag/79-sensorTag.js | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/hardware/sensorTag/79-sensorTag.js b/hardware/sensorTag/79-sensorTag.js
index 61dbc24b..91d40b07 100644
--- a/hardware/sensorTag/79-sensorTag.js
+++ b/hardware/sensorTag/79-sensorTag.js
@@ -51,7 +51,7 @@ function sensorTagNode(n) {
sensorTag.enableIrTemperature(function(){});
sensorTag.on('irTemperatureChange',
function(objectTemperature, ambientTemperature){
- var msg = {'topic': node.topic + '/tempature'};
+ var msg = {'topic': node.topic + '/temperature'};
msg.payload = {'object': objectTemperature.toFixed(1),
'ambient':ambientTemperature.toFixed(1)
};
From 2f07bb7d135931d3c5d57c440d6906f0fa5ffec5 Mon Sep 17 00:00:00 2001
From: Dave C-J
Date: Wed, 5 Feb 2014 18:36:29 +0000
Subject: [PATCH 16/24] Fix ping error response on Pi - Fixes Issue #23
---
io/ping/88-ping.html | 2 --
io/ping/88-ping.js | 8 ++++----
2 files changed, 4 insertions(+), 6 deletions(-)
diff --git a/io/ping/88-ping.html b/io/ping/88-ping.html
index f171c2c5..06e3028f 100644
--- a/io/ping/88-ping.html
+++ b/io/ping/88-ping.html
@@ -29,14 +29,12 @@
-
-
+
+
+
+
+
+
+
+
diff --git a/io/emoncms/88-emoncms.js b/io/emoncms/88-emoncms.js
new file mode 100644
index 00000000..a40ee9a5
--- /dev/null
+++ b/io/emoncms/88-emoncms.js
@@ -0,0 +1,71 @@
+/**
+ * Copyright 2013 Henrik Olsson henols@gmail.com
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+var RED = require(process.env.NODE_RED_HOME+"/red/red");
+//The Server Definition - this opens (and closes) the connection
+function EmoncmsServerNode(n) {
+ RED.nodes.createNode(this,n);
+ this.server = n.server;
+ this.apikey = n.apikey;
+ this.name = n.name;
+}
+RED.nodes.registerType("emoncms-server",EmoncmsServerNode);
+
+function Emoncms(n) {
+ RED.nodes.createNode(this,n);
+ this.emonServer = n.emonServer;
+ var sc = RED.nodes.getNode(this.emonServer);
+
+ this.baseurl = sc.server;
+ this.apikey = sc.apikey;
+
+ this.topic = n.topic ||"";
+ this.nodegroup = n.nodegroup || "";
+ var node = this;
+ if (this.baseurl.substring(0,5) === "https") { var http = require("https"); }
+ else { var http = require("http"); }
+ this.on("input", function(msg) {
+
+ var topic = this.topic || msg.topic;
+ this.url = this.baseurl + '/input/post.json?json={' + topic + ':' + msg.payload+'}&apikey='+this.apikey;
+ if(this.nodegroup != ""){
+ this.url += '&node='+this.nodegroup;
+ }
+ node.log("[emoncms] "+this.url);
+ http.get(this.url, function(res) {
+ node.log("Http response: " + res.statusCode);
+ msg.rc = res.statusCode;
+ msg.payload = "";
+ if ((msg.rc != 200) && (msg.rc != 404)) {
+ node.send(msg);
+ }
+ res.setEncoding('utf8');
+ res.on('data', function(chunk) {
+ msg.payload += chunk;
+ });
+ res.on('end', function() {
+ node.send(msg);
+ });
+ }).on('error', function(e) {
+ // node.error(e);
+ msg.rc = 503;
+ msg.payload = e;
+ node.send(msg);
+ });
+ });
+}
+
+RED.nodes.registerType("emoncms",Emoncms);
diff --git a/io/emoncms/icons/emoncms-logo.png b/io/emoncms/icons/emoncms-logo.png
new file mode 100644
index 0000000000000000000000000000000000000000..8cde78715855be139d55b070f2f3bd97fb28b410
GIT binary patch
literal 1418
zcmV;51$Fv~P)(^b8FWQhbW?9;ba!ELWdL_~cP?peYja~^
zaAhuUa%Y?FJQ@H11qVq)K~zYIwU$e4RM#DczjN+$#$(SbeheOi85@%{kPzA;<4`M2
zLVyTxB1KLXRg>-#q;9fFltr3dqApr>m#S)|c2iYiL#%cMrFEJ(AvPG8$k>R7J=haG
zhVi@~_i?(gu^^&Rk;0LFyL-M*_kSM$Ba~7+%po5t{XqpIBO|S&qobh*nIpcdL`RMs
z=@vq~0X%CM=C(*AY%8V6=kqn!^)4&r|5FI@=drP|#RnD~K7908TU+b<0|VPT13??7
z=}@g!5mM3;45H~em2z3l&dx4ZtCbJN#>PJWzXT&ABb$8RKb}gZcE;oJ(Cpl0BH=LI
z$s~zH0;S;QH(72hE>bKM8Q4BRHk&Oi%wJDyn)b?x6DOAbr(kq+)T}oeGf(V%GF2!R
zP`+aDg`-^cqTKXas0)j~U4gjXU{|QZv(ekk{p%A<)4&b{RXTlPu3ReZIDPuGdxv??
zB9}^~-}I&Wx)+xg+5UsaNId^@PC0#Kv@YC06eG}ruv@q#Bb+RE@$S`rZa(!oTlxmL
zefyT!vZZ&kZQCE-&D;#$p6)I}mJX`NhG52cNv(AN--St1F&cS)p(5K~_W*!?Mv$8_l$khKV#R
zl)e^WSV+S{nl{tb2+eKJkj-XECVS#asgLgw2qA=F7@hTco#CJC!)lH4;#Qqq?GmXQ
z2+aV^0IA~&9Zwqg(g4lm3F{W!xv%*9`6Y&)9>R4TG+pn$N3ehY{(fCIbkB9^O!hMM
z=}Ep>%Fq+Gc_}664-1r#ctX-t5*JCzEb`du8Pe%AOT{J&MHefYz;#_r!!!>ZIItB!
z2XGu`k71Z$$7v!$F#;{E{PoxG&>DS&y)TZk>!*i#Jg)KCP3Y2UY$>KWcQuQKLJA2&
zB7|h7AgI-9n5Gpj6jt{D*K`0W<)eThghT?54?Ra}=MOplyI-;V^#o(*|APp$k=oqD
z&=;R`#R;Rw_MoiR_07H(UkRiX0Jad?_Kgy`t~*hwlq5J%?0@@7+UDv5Msud~aJCt
zc^;akF+Dwa%FE7tktJRmY+3e5y`}^aXrlFK#
zCAYks&1T=e!xc&?gb*5F?%uuo)kq}z+qSkgb7duWZGL|KtxP791GM#s_4A_u5Ac%7
zWM^-0@9#T0I(qV}g?eE%f9&kpv!4J>rIdHiZ7PH?1_y`!t<807*qoM6N<$f*O9OkpKVy
literal 0
HcmV?d00001
From b1b230eb37759bae0e05b07624c2f76557b1b5e5 Mon Sep 17 00:00:00 2001
From: Dave C-J
Date: Sat, 8 Feb 2014 13:31:00 +0000
Subject: [PATCH 19/24] Forced payload to be strings for Prowl node Fixes #26
---
social/prowl/57-prowl.js | 61 ++++++++++++++++++++--------------------
1 file changed, 31 insertions(+), 30 deletions(-)
diff --git a/social/prowl/57-prowl.js b/social/prowl/57-prowl.js
index 15be6f2a..9d8801bc 100644
--- a/social/prowl/57-prowl.js
+++ b/social/prowl/57-prowl.js
@@ -24,44 +24,45 @@ var util = require('util');
// module.exports = {prowlkey:'My-API-KEY'}
try {
- var pushkey = RED.settings.prowl || require(process.env.NODE_RED_HOME+"/../pushkey.js");
+ var pushkey = RED.settings.prowl || require(process.env.NODE_RED_HOME+"/../pushkey.js");
}
catch(err) {
- util.log("[57-prowl.js] Error: Failed to load Prowl credentials");
+ util.log("[57-prowl.js] Error: Failed to load Prowl credentials");
}
if (pushkey) {
- var prowl = new Prowl(pushkey.prowlkey);
+ var prowl = new Prowl(pushkey.prowlkey);
}
function ProwlNode(n) {
- RED.nodes.createNode(this,n);
- this.title = n.title;
- this.priority = parseInt(n.priority);
- if (this.priority > 2) this.priority = 2;
- if (this.priority < -2) this.priority = -2;
- var node = this;
- this.on("input",function(msg) {
- var titl = this.title||msg.topic||"Node-RED";
- var pri = msg.priority||this.priority;
- if (typeof(msg.payload) == 'object') {
- msg.payload = JSON.stringify(msg.payload);
- }
- if (pushkey) {
- try {
- prowl.push(msg.payload, titl, { priority: pri }, function(err, remaining) {
- if (err) node.error(err);
- node.log( remaining + ' calls to Prowl api during current hour.' );
- });
- }
- catch (err) {
- node.error(err);
- }
- }
- else {
- node.warn("Prowl credentials not set/found. See node info.");
- }
- });
+ RED.nodes.createNode(this,n);
+ this.title = n.title;
+ this.priority = parseInt(n.priority);
+ if (this.priority > 2) this.priority = 2;
+ if (this.priority < -2) this.priority = -2;
+ var node = this;
+ this.on("input",function(msg) {
+ var titl = this.title||msg.topic||"Node-RED";
+ var pri = msg.priority||this.priority;
+ if (typeof(msg.payload) == 'object') {
+ msg.payload = JSON.stringify(msg.payload);
+ }
+ else { msg.payload = msg.payload.toString(); }
+ if (pushkey) {
+ try {
+ prowl.push(msg.payload, titl, { priority: pri }, function(err, remaining) {
+ if (err) node.error(err);
+ node.log( remaining + ' calls to Prowl api during current hour.' );
+ });
+ }
+ catch (err) {
+ node.error(err);
+ }
+ }
+ else {
+ node.warn("Prowl credentials not set/found. See node info.");
+ }
+ });
}
RED.nodes.registerType("prowl",ProwlNode);
From dc13290f97e227076fdcd4517b67ee2c5665e62b Mon Sep 17 00:00:00 2001
From: henols
Date: Sun, 9 Feb 2014 00:21:17 +0100
Subject: [PATCH 20/24] Some usage clarifications
---
io/emoncms/88-emoncms.html | 15 ++++++++-------
io/emoncms/88-emoncms.js | 5 +++--
2 files changed, 11 insertions(+), 9 deletions(-)
diff --git a/io/emoncms/88-emoncms.html b/io/emoncms/88-emoncms.html
index ff71828b..b179b7af 100644
--- a/io/emoncms/88-emoncms.html
+++ b/io/emoncms/88-emoncms.html
@@ -23,21 +23,22 @@
+
+
+
+
-
-
-
-
-
If Topic is left blank the output Topic is the same as the input Topic.
+
Topic is not mandatory, if Topic is left blank msg.topic will used. Topic overrides msg.topic
+ Node Group (numeric) is not mandatory, if Node Group is left blank msg.nodegrpup will used. Node Group overrides msg.nodegroup
diff --git a/io/emoncms/88-emoncms.js b/io/emoncms/88-emoncms.js
index a007d3d5..74ad43a4 100644
--- a/io/emoncms/88-emoncms.js
+++ b/io/emoncms/88-emoncms.js
@@ -19,11 +19,50 @@ var RED = require(process.env.NODE_RED_HOME+"/red/red");
function EmoncmsServerNode(n) {
RED.nodes.createNode(this,n);
this.server = n.server;
- this.apikey = n.apikey;
this.name = n.name;
+ var credentials = RED.nodes.getCredentials(n.id);
+ if (credentials) {
+ this.apikey = credentials.apikey;
+ }
+
}
RED.nodes.registerType("emoncms-server",EmoncmsServerNode);
+var querystring = require('querystring');
+
+RED.app.get('/emoncms-server/:id',function(req,res) {
+ var credentials = RED.nodes.getCredentials(req.params.id);
+ if (credentials) {
+ res.send(JSON.stringify({apikey:credentials.apikey}));
+ } else {
+ res.send(JSON.stringify({}));
+ }
+});
+
+RED.app.delete('/emoncms-server/:id',function(req,res) {
+ RED.nodes.deleteCredentials(req.params.id);
+ res.send(200);
+});
+
+RED.app.post('/emoncms-server/: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.apikey == null || newCreds.apikey == "") {
+ delete credentials.apikey;
+ } else {
+ credentials.apikey = newCreds.apikey;
+ }
+ RED.nodes.addCredentials(req.params.id,credentials);
+ res.send(200);
+ });
+});
+
function Emoncms(n) {
RED.nodes.createNode(this,n);
this.emonServer = n.emonServer;
From 4a53c20792ebb4220fcbf534cfe804f7f849d292 Mon Sep 17 00:00:00 2001
From: Dave C-J
Date: Fri, 14 Feb 2014 20:38:39 +0000
Subject: [PATCH 23/24] Update pushbullet to use latest 0.4 npm and allow iden
as well as id
---
social/pushbullet/57-pushbullet.html | 13 ++++---
social/pushbullet/57-pushbullet.js | 55 ++++++++++++++--------------
2 files changed, 35 insertions(+), 33 deletions(-)
diff --git a/social/pushbullet/57-pushbullet.html b/social/pushbullet/57-pushbullet.html
index 32020297..dda75be5 100644
--- a/social/pushbullet/57-pushbullet.html
+++ b/social/pushbullet/57-pushbullet.html
@@ -26,12 +26,13 @@