1
0
mirror of https://github.com/node-red/node-red-nodes.git synced 2023-10-10 13:36:58 +02:00
Conflicts:
	hardware/BBB/README.md
This commit is contained in:
Maxwell Hadley 2014-03-03 20:39:09 +00:00
commit 982a68d8eb
23 changed files with 849 additions and 111 deletions

View File

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

View File

@ -63,7 +63,6 @@ of the pulse, or by both edges. Two outputs are provided:
Separate scaling factors are applied to each output. Output messages are generated
at regular intervals, controlled by an internal timer. The count can be cleared
or set to an arbitrary value by an input message who's topic contains 'load'.
Useful for energy monitoring, e.g. electricty meter pulse outputs.
The 'instantaneous' pulse rate is derived from either the time between the last two

View File

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

120
io/emoncms/88-emoncms.html Normal file
View File

@ -0,0 +1,120 @@
<!--
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.
-->
<script type="text/x-red" data-template-name="emoncms">
<div class="form-row">
<label for="node-input-emonServer"><i class="icon-globe"></i> Emoncms server</label>
<input type="text" id="node-input-emonServer">
</div>
<div class="form-row">
<label for="node-input-topic"><i class="icon-tasks"></i> Topic</label>
<input type="text" id="node-input-topic" placeholder="">
</div>
<div class="form-row">
<label for="node-input-nodegroup"><i class="icon-tag"></i> Node Group</label>
<input type="text" id="node-input-nodegroup" placeholder="">
</div>
<div class="form-row">
<label for="node-input-name"><i class="icon-tag"></i> Name</label>
<input type="text" id="node-input-name" placeholder="Emoncms">
</div>
<div class="form-tips">Topic is not mandatory, if Topic is left blank <b>msg.topic</b> will used. Topic overrides <b>msg.topic</b></br>
Node Group (numeric) is not mandatory, if Node Group is left blank <b>msg.nodegrpup</b> will used. Node Group overrides <b>msg.nodegroup</b></div>
</script>
<script type="text/x-red" data-help-name="emoncms">
<p>Performs post to Emoncms.</p>
<p>Topic is not mandatory, if Topic is left blank <b>msg.topic</b> will used. Topic overrides <b>msg.topic</b></p>
<p>Node Group (numeric) is not mandatory, if Node Group is left blank <b>msg.nodegrpup</b> will used. Node overrides <b>msg.nodegrpup</b></p>
</script>
<script type="text/javascript">
RED.nodes.registerType('emoncms',{
category: 'output',
color:"rgb(91, 192, 222)",
defaults: {
name: {value:"Emoncms"},
emonServer: {type:"emoncms-server", required:true},
topic: {value:""},
nodegroup: {value:""}
},
inputs:1,
outputs:0,
icon: "emoncms.png",
align: "right",
label: function() {
return this.name||this.baseurl;
},
labelStyle: function() {
return this.name?"node_label_italic":"";
}
});
</script>
<script type="text/x-red" data-template-name="emoncms-server">
<div class="form-row">
<label for="node-config-input-server"><i class="icon-globe"></i> Base URL</label>
<input type="text" id="node-config-input-server">
</div>
<div class="form-row">
<label for="node-config-input-apikey"><i class="icon-tasks"></i> API key</label>
<input type="text" id="node-config-input-apikey">
</div>
<div class="form-row">
<label for="node-config-input-name"><i class="icon-tag"></i> Name</label>
<input type="text" id="node-config-input-name">
</div>
<div class="form-tips">The <b>Base URL</b> is the URL to the Emoncms root directory.</div>
</script>
<script type="text/javascript">
RED.nodes.registerType('emoncms-server',{
category: 'config',
defaults: {
server: {value:"http://localhost",required:true},
// apikey: {value:"",required:true},
name: {value:""}
},
label: function() {
return this.name||this.server;
},
oneditprepare: function() {
$.getJSON('emoncms-server/'+this.id,function(data) {
if (data.apikey) {
$('#node-config-input-apikey').val(data.apikey);
}
});
},
oneditsave: function() {
var newApikey = $('#node-config-input-apikey').val();
var credentials = {};
credentials.apikey = newApikey;
$.ajax({
url: 'emoncms-server/'+this.id,
type: 'POST',
data: credentials,
success:function(result){}
});
},
ondelete: function() {
$.ajax({
url: 'emoncms-server/'+this.id,
type: 'DELETE',
success: function(result) {}
});
}
});
</script>

111
io/emoncms/88-emoncms.js Normal file
View File

@ -0,0 +1,111 @@
/**
* 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.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;
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;
var nodegroup = this.nodegroup || msg.nodegroup;
this.url = this.baseurl + '/input/post.json?json={' + topic + ':' + msg.payload+'}&apikey='+this.apikey;
if(nodegroup != ""){
this.url += '&node='+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);

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 933 B

View File

@ -29,14 +29,12 @@
</div>
</script>
<!-- Next, some simple help text is provided for the node. -->
<script type="text/x-red" data-help-name="ping">
<p>Pings a machine and returns the trip time in mS.</p>
<p>Returns <b>false</b> if no response received within 3 seconds, or if the host is unresolveable.</p>
<p>Default ping is every 20 seconds but can be configured.</p>
</script>
<!-- Finally, the node type is registered along with all of its properties -->
<script type="text/javascript">
RED.nodes.registerType('ping',{
category: 'advanced-input',

View File

@ -30,12 +30,12 @@ function PingNode(n) {
else if (plat.match(/^win/)) ex = spawn('ping', ['-n', '1', '-w', '5000', node.host]);
else if (plat == "darwin") ex = spawn('ping', ['-n', '-t', '5', '-c', '1', node.host]);
else node.error("Sorry - your platform - "+plat+" - is not recognised.");
var res = "";
var res = false;
ex.stdout.on('data', function (data) {
//console.log('[ping] stdout: ' + data.toString());
var regex = /time.(.*)ms/;
var m = regex.exec(data.toString())||[""];
res = Number(m[1]);
var regex = /from.*time.(.*)ms/;
var m = regex.exec(data.toString())||"";
if (m != '') { res = Number(m[1]); }
});
ex.stderr.on('data', function (data) {
//console.log('[ping] stderr: ' + data);

View File

@ -28,7 +28,7 @@ exec("which mpd",function(err,stdout,stderr) {
exec("netstat -an | grep LISTEN | grep 6600",function(err,stdout,stderr) {
if (stdout.indexOf('6600') == -1) {
util.log('[69-mpd.js] Error: MPD daemon not listening on port 6600. Please start MPD.');
util.log('[69-mpd.js] Warning: MPD daemon not listening on port 6600. Please start MPD.');
return;
}
komponist.createConnection(6600, 'localhost', function(err, client) {

View File

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

View File

@ -26,12 +26,13 @@
</script>
<script type="text/x-red" data-help-name="pushbullet">
<p>Uses PushBullet to push the <b>msg.payload</b> to an Android device that has PushBullet app installed.</p>
<p>Optionally uses <b>msg.topic</b> to set the title, if not already set in the properties.</p>
<p>You MUST configure both your API key and the target device ID. Either into settings.js like this</p>
<p><pre>pushbullet: { pushbullet:'My-API-KEY', deviceid:'12345' },</pre></p>
<p>Or as a pushkey.js file in the directory <b>above</b> node-red.<p>
<p><pre>module.exports = { pushbullet:'My-API-KEY', deviceid:'12345' }</pre></p>
<p>Uses PushBullet to push the <b>msg.payload</b> to an Android device that has PushBullet app installed.</p>
<p>Optionally uses <b>msg.topic</b> to set the title, if not already set in the properties.</p>
<p>You MUST configure both your API key and the target device ID. Either into settings.js like this</p>
<p><pre>pushbullet: { pushbullet:'My-API-KEY', deviceid:'xyzzyWabc' },</pre></p>
<p>Or as a pushkey.js file in the directory <b>above</b> node-red.<p>
<p><pre>module.exports = { pushbullet:'My-API-KEY', deviceid:'xyzzyWabc' }</pre></p>
<p>The deviceid can be found by hovering over you required device on the <a href="https://www.pushbullet.com/">PushBullet website</a>.</p>
</script>
<script type="text/javascript">

View File

@ -24,41 +24,42 @@ var util = require('util');
// module.exports = {pushbullet:'My-API-KEY', deviceid:'12345'}
try {
var pushkey = RED.settings.pushbullet || require(process.env.NODE_RED_HOME+"/../pushkey.js");
var pushkey = RED.settings.pushbullet || require(process.env.NODE_RED_HOME+"/../pushkey.js");
}
catch(err) {
util.log("[57-pushbullet.js] Error: Failed to load PushBullet credentials");
util.log("[57-pushbullet.js] Error: Failed to load PushBullet credentials");
}
if (pushkey) {
var pusher = new PushBullet(pushkey.pushbullet);
var deviceId = pushkey.deviceid;
var pusher = new PushBullet(pushkey.pushbullet);
var deviceId = pushkey.deviceid;
}
function PushbulletNode(n) {
RED.nodes.createNode(this,n);
this.title = n.title;
var node = this;
this.on("input",function(msg) {
var titl = this.title||msg.topic||"Node-RED";
if (typeof(msg.payload) == 'object') {
msg.payload = JSON.stringify(msg.payload);
}
if (pushkey) {
try {
pusher.note(deviceId, titl, msg.payload, function(err, response) {
if (err) node.error(err);
console.log(response);
});
}
catch (err) {
node.error(err);
}
}
else {
node.warn("Pushbullet credentials not set/found. See node info.");
}
});
RED.nodes.createNode(this,n);
this.title = n.title;
var node = this;
this.on("input",function(msg) {
var titl = this.title||msg.topic||"Node-RED";
if (typeof(msg.payload) == 'object') {
msg.payload = JSON.stringify(msg.payload);
}
if (pushkey.pushbullet && pushkey.deviceid) {
try {
if (!isNaN(deviceId)) { deviceId = Number(deviceId); }
pusher.note(deviceId, titl, msg.payload, function(err, response) {
if (err) node.error(err);
console.log(response);
});
}
catch (err) {
node.error(err);
}
}
else {
node.warn("Pushbullet credentials not set/found. See node info.");
}
});
}
RED.nodes.registerType("pushbullet",PushbulletNode);

View File

@ -15,31 +15,32 @@
limitations under the License.
-->
<script type="text/x-red" data-template-name="twilio">
<script type="text/x-red" data-template-name="twilio out">
<div class="form-row">
<label for="node-input-title"><i class="icon-flag"></i> Title</label>
<input type="text" id="node-input-title" placeholder="Node-RED">
<label for="node-input-number"><i class="icon-envelope"></i> SMS to</label>
<input type="text" id="node-input-number" placeholder="01234 5678901">
</div>
<div class="form-row">
<label for="node-input-name"><i class="icon-tag"></i> Name</label>
<input type="text" id="node-input-name" placeholder="Name">
</div>
<div class="form-tips">Tip - leave Number blank to use <b>msg.topic</b> to set the number.</div>
</script>
<script type="text/x-red" data-help-name="twilio out">
<p>Uses Twilio to send the <b>msg.payload</b> as a SMS to the configured number.</p>
<p>Uses <b>msg.topic</b> to set the phone number, if not already set in the properties.</p>
<p>You MUST configure both your Account SID and the Auth Token. Either into settings.js like this</p>
<p><pre>twilio: { account:'My-ACCOUNT-SID', authtoken:'TWILIO-TOKEN', from:'FROM-NUMBER' },</pre></p>
<p>Or as a twiliokey.js file in the directory <b>above</b> node-red.<p>
<p><pre>module.exports = { account:'My-ACCOUNT-SID', authtoken:'TWILIO-TOKEN',from:'FROM-NUMBER' }</pre></p>
<p>Uses Twilio to send the <b>msg.payload</b> as a SMS to the configured number.</p>
<p>Uses <b>msg.topic</b> to set the phone number, if not already set in the properties.</p>
<p>You MUST configure both your Account SID and the Auth Token. Either into settings.js like this</p>
<p><pre>twilio: { account:'My-ACCOUNT-SID', authtoken:'TWILIO-TOKEN', from:'FROM-NUMBER' },</pre></p>
<p>Or as a twiliokey.js file in the directory <b>above</b> node-red.<p>
<p><pre>module.exports = { account:'My-ACCOUNT-SID', authtoken:'TWILIO-TOKEN',from:'FROM-NUMBER' }</pre></p>
</script>
<script type="text/javascript">
RED.nodes.registerType('twilio out',{
category: 'output',
defaults: {
title: {value:""},
number: {value:""},
name: {value:""}
},
color:"#ed1c24",
@ -48,7 +49,7 @@
icon: "twilio.png",
align: "right",
label: function() {
return this.name||this.title||"twilio out";
return this.name||this.title||"twilio";
},
labelStyle: function() {
return this.name?"node_label_italic":"";

View File

@ -24,41 +24,41 @@ var util = require('util');
// module.exports = { account:'My-ACCOUNT-SID', authtoken:'TWILIO-TOKEN',from:'FROM-NUMBER' }
try {
var twiliokey = RED.settings.twilio || require(process.env.NODE_RED_HOME+"/../twiliokey.js");
var twiliokey = RED.settings.twilio || require(process.env.NODE_RED_HOME+"/../twiliokey.js");
}
catch(err) {
util.log("[56-twilio.js] Error: Failed to load Twilio credentials");
util.log("[56-twilio.js] Error: Failed to load Twilio credentials");
}
if (twiliokey) {
var twilioClient = require('twilio')(twiliokey.account, twiliokey.authtoken);
var fromNumber = twiliokey.from;
var twilioClient = require('twilio')(twiliokey.account, twiliokey.authtoken);
var fromNumber = twiliokey.from;
}
function TwilioOutNode(n) {
RED.nodes.createNode(this,n);
this.title = n.title;
var node = this;
this.on("input",function(msg) {
if (typeof(msg.payload) == 'object') {
msg.payload = JSON.stringify(msg.payload);
}
if (twiliokey) {
try {
// Send SMS
twilioClient.sendMessage( {to: msg.topic, from: fromNumber, body: msg.payload}, function(err, response) {
if (err) node.error(err);
//console.log(response);
});
}
catch (err) {
node.error(err);
}
}
else {
node.warn("Twilio credentials not set/found. See node info.");
}
});
RED.nodes.createNode(this,n);
this.number = n.number;
var node = this;
this.on("input",function(msg) {
if (typeof(msg.payload) == 'object') {
msg.payload = JSON.stringify(msg.payload);
}
if (twiliokey) {
try {
// Send SMS
var tonum = node.number || msg.topic;
twilioClient.sendMessage( {to: tonum, from: fromNumber, body: msg.payload}, function(err, response) {
if (err) node.error(err);
//console.log(response);
});
}
catch (err) {
node.error(err);
}
}
else {
node.warn("Twilio credentials not set/found. See node info.");
}
});
}
RED.nodes.registerType("twilio out",TwilioOutNode);

Binary file not shown.

Before

Width:  |  Height:  |  Size: 717 B

After

Width:  |  Height:  |  Size: 553 B

View File

@ -0,0 +1,58 @@
<!--
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.
-->
<script type="text/x-red" data-template-name="ddb out">
<div class="form-row">
<label for="node-input-credentials"><i class="icon-tag"></i> Credentials</label>
<input type="text" id="node-input-credentials">
</div>
<div class="form-row">
<label for="node-input-region"><i class="icon-th"></i> Region</label>
<input type="text" id="node-input-region">
</div>
<div class="form-row">
<label for="node-input-table"><i class="icon-tasks"></i> Table</label>
<input type="text" id="node-input-table" placeholder="Table">
</div>
<div class="form-row">
<label for="node-input-name"><i class="icon-tag"></i> Name</label>
<input type="text" id="node-input-name" placeholder="Name">
</div>
</script>
<script type="text/x-red" data-help-name="ddb out">
<p>A Amazon DynamoDB output node.</p>
</script>
<script type="text/javascript">
RED.nodes.registerType("ddb out", {
category: "storage-output",
color: "#ffaaaa",
defaults: {
credentials: { type: "aws credentials", required: true },
region: { value: "us-east-1", required: true },
table: { value: "", required: true },
name: { value: "" }
},
inputs: 1,
outputs: 0,
icon: "db.png",
align: "right",
label: function() {
return this.name || this.table + " (" + this.region + ")";
}
});
</script>

44
storage/ddb/69-ddbout.js Normal file
View File

@ -0,0 +1,44 @@
/**
* 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.credentials = RED.nodes.getNode(n.credentials);
this.region = n.region || "us-east-1";
this.table = n.table;
aws.config.update({ accessKeyId: this.credentials.accessKey,
secretAccessKey: this.credentials.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);

68
storage/ddb/aws.html Normal file
View File

@ -0,0 +1,68 @@
<!--
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.
-->
<script type="text/x-red" data-template-name="aws credentials">
<div class="form-row">
<label for="node-config-input-accessKey"><i class="icon-briefcase"></i> Access Key</label>
<input type="text" id="node-config-input-accessKey" placeholder="Access Key">
</div>
<div class="form-row">
<label for="node-config-input-secretAccessKey"><i class="icon-briefcase"></i> Secret Access Key</label>
<input type="text" id="node-config-input-secretAccessKey" placeholder="Secret Access Key">
</div>
</script>
<script type="text/javascript">
RED.nodes.registerType("aws credentials", {
category: "config",
label: function() {
return this.accessKey;
},
defaults: {
accessKey: { value: "", required: true }
},
oneditprepare: function() {
$.getJSON("aws-credentials/" + this.id, function(data) {
if (data.accessKey) {
$("#node-config-input-accessKey").val(data.accessKey);
}
if (data.secretAccessKey) {
$("#node-config-input-secretAccessKey").val(data.secretAccessKey);
}
});
},
oneditsave: function() {
var newAccessKey = $("#node-config-input-accessKey").val();
var newSecretAccessKey = $("#node-config-input-secretAccessKey").val();
var credentials = {};
credentials.accessKey = newAccessKey;
credentials.secretAccessKey = newSecretAccessKey;
$.ajax({
url: "aws-credentials/" + this.id,
type: "POST",
data: credentials,
success: function(result) {}
});
},
ondelete: function() {
$.ajax({
url: "aws-credentials/" + this.id,
type: "DELETE",
success: function(result) {}
});
}
});
</script>

65
storage/ddb/aws.js Normal file
View File

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

View File

@ -0,0 +1,146 @@
<!--
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.
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.
-->
<script type="text/x-red" data-template-name="postgresdb">
<div class="form-row">
<label for="node-config-input-hostname"><i class="icon-bookmark"></i> Host</label>
<input class="input-append-left" type="text" id="node-config-input-hostname" placeholder="localhost" style="width: 40%;" >
<label for="node-config-input-port" style="margin-left: 10px; width: 35px; "> Port</label>
<input type="text" id="node-config-input-port" placeholder="5432" style="width:45px">
</div>
<div class="form-row">
<label for="node-config-input-db"><i class="icon-briefcase"></i> Database</label>
<input type="text" id="node-config-input-db" placeholder="test">
</div>
<div class="form-row">
<label for="node-config-input-name"><i class="icon-user"></i> Username</label>
<input type="text" id="node-config-input-user" placeholder="postgres">
<label for="node-config-input-password"><i class="icon-lock"></i> Password</label>
<input type="password" id="node-config-input-password" placeholder="postgres">
</div>
</script>
<script type="text/javascript">
RED.nodes.registerType('postgresdb',{
category: 'config',
color:"rgb(218, 196, 180)",
defaults: {
hostname: { value:"localhost",required:true},
port: { value: 5432,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) {}
});
}
});
</script>
<script type="text/x-red" data-template-name="postgres">
<div class="form-row">
<label for="node-input-name"><i class="icon-tag"></i> Name</label>
<input type="text" id="node-input-name" placeholder="Name">
</div>
<div class="form-row">
<label for="node-input-postgresdb"><i class="icon-tag"></i> Server</label>
<input type="text" id="node-input-postgresdb">
</div>
<div class="form-row">
<label>&nbsp;</label>
<input type="checkbox" id="node-input-output" placeholder="once" style="display: inline-block; width: auto; vertical-align: top;">
<label for="node-input-output" style="width: 70%;">Receive query output ?</label>
</div>
</script>
<script type="text/x-red" data-help-name="postgres">
<p>A PostgreSql I/O node. </p>
<p>Executes the query specified in msg.payload with optional query parameters in msg.queryParameters</p>
<p>The queryParameters in the query must be specified as $propertyname</p>
<p>See the node-postgres-named package for more info</p>
<p>When receiving data from the query, the msg.payload on the output will be a json array of the returned records</p>
</script>
<script type="text/javascript">
RED.nodes.registerType('postgres',{
category: 'storage-output',
color:"rgb(148, 226, 252)",
defaults: {
postgresdb: { type:"postgresdb",required:true},
name: {value:""},
output: {value:false},
outputs: {value:0}
},
inputs: 1,
outputs: 0,
icon: "postgres.png",
align: "right",
label: function() {
return this.name||(this.sqlquery?this.sqlquery:"postgres");
},
labelStyle: function() {
return this.name?"node_label_italic":"";
},
oneditprepare: function() {
$( "#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;
}
});
</script>

View File

@ -0,0 +1,123 @@
/**
* 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.
* 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 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;
var credentials = RED.nodes.getCredentials(n.id);
if (credentials) {
this.user = credentials.user;
this.password = credentials.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.output = n.output;
var node = this;
if(this.postgresConfig)
{
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);
node.clientdb.connect(function(err){
if(err) { node.error(err); }
else {
node.on('input',
function(msg){
if(!msg.queryParameters) msg.queryParameters={};
node.clientdb.query(msg.payload,
msg.queryParameters,
function (err, results) {
if(err) { node.error(err); }
else {
if(node.output)
{
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);

Binary file not shown.

After

Width:  |  Height:  |  Size: 625 B