1
0
mirror of https://github.com/node-red/node-red-nodes.git synced 2023-10-10 13:36:58 +02:00
This commit is contained in:
Charalampos Doukas 2013-11-11 14:51:46 +01:00
commit 85797eb7fc
19 changed files with 498 additions and 379 deletions

View File

@ -1,6 +1,6 @@
# Node-RED Nodes # Node-RED Nodes
A collection of nodes for [Node-RED](http://nodered.org). A collection of nodes for [Node-RED](http://nodered.org). See below for a list.
## Installation ## Installation
@ -27,9 +27,9 @@ The key points are:
### Contributor License Agreement ### Contributor License Agreement
In order for us to accept pull-requests, the contributor must first complete In order for us to accept pull-requests, the contributor must first complete
a Contributor License Agreement (CLA). This clarifies the intellectual a Contributor License Agreement (CLA). This clarifies the intellectual
property license granted with any contribution. It is for your protection as a property license granted with any contribution. It is for your protection as a
Contributor as well as the protection of IBM and its customers; it does not Contributor as well as the protection of IBM and its customers; it does not
change your rights to use your own Contributions for any other purpose. change your rights to use your own Contributions for any other purpose.
Once you have created a pull-request, we'll provide a link to the appropriate Once you have created a pull-request, we'll provide a link to the appropriate
@ -42,3 +42,64 @@ slightly different.
## Copyright and license ## Copyright and license
Copyright 2013 IBM Corp. under [the Apache 2.0 license](LICENSE). Copyright 2013 IBM Corp. under [the Apache 2.0 license](LICENSE).
# Extra Node Information
### Analysis
**72-wordpos** - Analyses the payload and classifies the part-of-speech of each word. The resulting message has msg.pos added with the results. A word may appear in multiple categories (eg, 'great' is both a noun and an adjective).
**74-swearfilter** - Analyses the payload and tries to filter out any messages containing bad swear words. This only operates on payloads of type string. Everything else is blocked.
### Hardware
**37-rpi-piface** - Adds support for the PiFace interface module for Raspberry Pi.
**78-ledborg** - A simple driver for the LEDborg plug on module for Raspberry Pi.
**60-wemo** - Basic node to drive a WeMo socket and switch. Does not use discovery.
**76-blinkstick** - Provides support for the BlinkStick USB LED device.
**77-blink1** - Provides support for the Blink1 USB LED from ThingM.
**78-digiRGB** - Provides support for the DigiSpark RGB USB LED.
**79-sensorTag** - Reads data from the Ti BLE SensorTag device.
**101-scanBLE** - Scans for a particular Bluetooth Low Energy (BLE) device.
### IO
**26-rawserial** - Only really needed for Windows boxes without serialport npm module installed.
Uses a simple read of the serial port as a file to input data. You **must** set the baud rate etc externally *before* starting Node-RED. This node does not implement pooling of connections so only one instance of each port may be used - so in **or** out but **not** both.
**39-wol** - Sends a Wake-On-LAN magic packet to the mac address specified. You may instead set msg.mac to dynamically set the target device mac to wake up.
**88-ping** - Pings a machine and returns the trip time in mS. Returns false if no response received within 3 seconds, or if the host is unresolveable. Default ping is every 20 seconds but can be configured.
### Social
**69-mpd** - MPD music control nodes. Output node expects payload to be a valid mpc command. Currently only simple commands that expect no reply are supported. Input node creates a payload object with Artist, Album, Title, Genre and Date.
**57-notify** - Uses Growl to provide a desktop popup containing the payload. Only useful on the local machine.
**57-prowl** - Uses Prowl to push the payload to an Apple device that has the Prowl app installed.
**57-pushbullet** - Uses PushBullet to push the payload to an Android device that has the PushBullet app installed.
**92-xmpp** - Connects to an XMPP server to send and receive messages.
### Storage
**67-leveldb** - Uses LevelDB for a simple key value pair database.
**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...*
### 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,
### Misc
**99-sample** - A sample node with more comments than most to try to help you get started without any other docs...

View File

@ -22,7 +22,8 @@
</script> </script>
<script type="text/x-red" data-help-name="badwords"> <script type="text/x-red" data-help-name="badwords">
<p>Analyses the <b>msg.payload</b> and tries to filter out any messages containing bad swear words...</p> <p>Analyses the <b>msg.payload</b> and tries to filter out any messages containing bad swear words...</p>
<p><b>Note:</b> this only operates on payloads of type <b>string</b>. Everything else is blocked.</p>
</script> </script>
<script type="text/javascript"> <script type="text/javascript">
@ -30,7 +31,7 @@
category: 'analysis-function', category: 'analysis-function',
color:"#E6E0F8", color:"#E6E0F8",
defaults: { defaults: {
name: {value:""}, name: {value:""}
}, },
inputs:1, inputs:1,
outputs:1, outputs:1,
@ -42,5 +43,4 @@
return this.name?"node_label_italic":""; return this.name?"node_label_italic":"";
} }
}); });
</script> </script>

View File

@ -21,8 +21,9 @@ function BadwordsNode(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 (badwords.ok(msg.payload)) { node.send(msg); } if (typeof msg.payload == "string") {
if (badwords.ok(msg.payload)) { node.send(msg); }
}
}); });
} }
RED.nodes.registerType("badwords",BadwordsNode); RED.nodes.registerType("badwords",BadwordsNode);

View File

@ -24,14 +24,14 @@
</script> </script>
<script type="text/x-red" data-help-name="wordpos"> <script type="text/x-red" data-help-name="wordpos">
<p>Analyses <b>msg.payload</b> and classifies the part-of-speech of each word.</p> <p>Analyses <b>msg.payload</b> and classifies the part-of-speech of each word.</p>
<p>The resulting message has <b>msg.pos</b> added with the results:</p> <p>The resulting message has <b>msg.pos</b> added with the results:</p>
<pre>{ <pre>{
nouns:[], nouns:[],
verbs:[], verbs:[],
adjectives:[], adjectives:[],
adverbs:[], adverbs:[],
rest:[] rest:[]
}</pre> }</pre>
<p>Note: a word may appear in multiple POS (eg, 'great' is both a noun and an adjective)</p> <p>Note: a word may appear in multiple POS (eg, 'great' is both a noun and an adjective)</p>
</script> </script>
@ -53,5 +53,4 @@
return this.name?"node_label_italic":""; return this.name?"node_label_italic":"";
} }
}); });
</script> </script>

View File

@ -15,20 +15,17 @@
**/ **/
var RED = require(process.env.NODE_RED_HOME+"/red/red"); var RED = require(process.env.NODE_RED_HOME+"/red/red");
var util = require("util");
var WordPos = require('wordpos'); var WordPos = require('wordpos');
var wordpos = new WordPos(); var wordpos = new WordPos();
function WordPOSNode(n) { function WordPOSNode(n) {
RED.nodes.createNode(this,n); RED.nodes.createNode(this,n);
this.on("input", function(msg) { this.on("input", function(msg) {
var node = this; var node = this;
wordpos.getPOS(msg.payload, function (result) { wordpos.getPOS(msg.payload, function (result) {
msg.pos = result; msg.pos = result;
node.send(msg); node.send(msg);
}); });
}); });
} }
RED.nodes.registerType("wordpos",WordPOSNode); RED.nodes.registerType("wordpos",WordPOSNode);

View File

@ -20,7 +20,7 @@ var fs = require('fs');
// check if /dev/ledborg exists - if not then don't even show the node. // check if /dev/ledborg exists - if not then don't even show the node.
if (!fs.existsSync("/dev/ledborg")) { if (!fs.existsSync("/dev/ledborg")) {
util.log("[78-ledborg.js] Error: PiBorg hardware : LedBorg not found"); util.log("[78-ledborg.js] Warning: PiBorg hardware : LedBorg not found");
return; return;
} }
@ -49,5 +49,4 @@ function LedBorgNode(n) {
} }
}); });
} }
RED.nodes.registerType("ledborg",LedBorgNode); RED.nodes.registerType("ledborg",LedBorgNode);

View File

@ -27,7 +27,7 @@
</script> </script>
<script type="text/x-red" data-help-name="blink1"> <script type="text/x-red" data-help-name="blink1">
<p>Thingm Blink1 output node. Expects a msg.payload with a three part csv string of r,g,b.</p> <p>ThingM Blink1 output node. Expects a msg.payload with a three part csv string of r,g,b.</p>
</script> </script>
<script type="text/javascript"> <script type="text/javascript">
@ -46,7 +46,7 @@
return this.name||"blink1"; return this.name||"blink1";
}, },
labelStyle: function() { labelStyle: function() {
return (this.name||!this.topic)?"node_label_italic":""; return this.name?"node_label_italic":"";
} }
}); });
</script> </script>

View File

@ -18,43 +18,42 @@ var RED = require(process.env.NODE_RED_HOME+"/red/red");
var Blink1 = require("node-blink1"); var Blink1 = require("node-blink1");
function Blink1Node(n) { function Blink1Node(n) {
RED.nodes.createNode(this,n); RED.nodes.createNode(this,n);
this.fade = n.fade||0; this.fade = n.fade||0;
var node = this; var node = this;
try { try {
var p1 = /^\#[A-Fa-f0-9]{6}$/ var p1 = /^\#[A-Fa-f0-9]{6}$/
var p2 = /[0-9]+,[0-9]+,[0-9]+/ var p2 = /[0-9]+,[0-9]+,[0-9]+/
this.on("input", function(msg) { this.on("input", function(msg) {
if (blink1) { if (blink1) {
if (p1.test(msg.payload)) { if (p1.test(msg.payload)) {
// if it is a hex colour string // if it is a hex colour string
var r = parseInt(msg.payload.slice(1,3),16); var r = parseInt(msg.payload.slice(1,3),16);
var g = parseInt(msg.payload.slice(3,5),16); var g = parseInt(msg.payload.slice(3,5),16);
var b = parseInt(msg.payload.slice(5),16); var b = parseInt(msg.payload.slice(5),16);
if (node.fade == 0) { blink1.setRGB( r, g, b ); } if (node.fade == 0) { blink1.setRGB( r, g, b ); }
else { blink1.fadeToRGB(node.fade, r, g, b ); } else { blink1.fadeToRGB(node.fade, r, g, b ); }
} }
else if (p2.test(msg.payload)) { else if (p2.test(msg.payload)) {
// if it is a r,g,b triple // if it is a r,g,b triple
var rgb = msg.payload.split(','); var rgb = msg.payload.split(',');
if (node.fade == 0) { blink1.setRGB(parseInt(rgb[0])&255, parseInt(rgb[1])&255, parseInt(rgb[2])&255); } if (node.fade == 0) { blink1.setRGB(parseInt(rgb[0])&255, parseInt(rgb[1])&255, parseInt(rgb[2])&255); }
else { blink1.fadeToRGB(node.fade, parseInt(rgb[0])&255, parseInt(rgb[1])&255, parseInt(rgb[2])&255); } else { blink1.fadeToRGB(node.fade, parseInt(rgb[0])&255, parseInt(rgb[1])&255, parseInt(rgb[2])&255); }
} }
else { else {
// you can do fancy colours by name here if you want... // you can add fancy colours by name here if you want...
node.warn("Blink1 : invalid msg : "+msg.payload); node.warn("Blink1 : invalid msg : "+msg.payload);
} }
} }
else { else {
node.warn("No Blink1 found"); node.warn("No Blink1 found");
} }
}); });
var blink1 = new Blink1.Blink1(); var blink1 = new Blink1.Blink1();
} }
catch(e) { catch(e) {
node.error("No Blink1 found"); node.error("No Blink1 found");
} }
} }
RED.nodes.registerType("blink1",Blink1Node); RED.nodes.registerType("blink1",Blink1Node);

View File

@ -14,55 +14,34 @@
limitations under the License. limitations under the License.
--> -->
<!-- First, the content of the edit dialog is defined. -->
<script type="text/x-red" data-template-name="digiRGB"> <script type="text/x-red" data-template-name="digiRGB">
<!-- data-template-name identifies the node type this is for -->
<!-- Each of the following divs creates a field in the edit dialog. -->
<!-- Generally, there should be an input for each property of the node. -->
<!-- The for and id attributes identify the corresponding property -->
<!-- (with the 'node-input-' prefix). -->
<!-- The available icon classes are defined in Twitter Bootstrap -->
<!-- By convention, most nodes have a 'name' property. The following div -->
<!-- provides the necessary field. -->
<div class="form-row"> <div class="form-row">
<label for="node-input-name"><i class="icon-tag"></i> Name</label> <label for="node-input-name"><i class="icon-tag"></i> Name</label>
<input type="text" id="node-input-name" placeholder="Name"> <input type="text" id="node-input-name" placeholder="DigiSpark">
</div> </div>
<div class="form-tips">Expects a msg.payload with three part csv string of r,g,b.</div> <div class="form-tips">Expects a msg.payload with three part csv string of r,g,b.</div>
</script> </script>
<!-- Next, some simple help text is provided for the node. -->
<script type="text/x-red" data-help-name="digiRGB"> <script type="text/x-red" data-help-name="digiRGB">
<!-- data-help-name identifies the node type this help is for --> <p>Simple output node to drive digispark RGB</p>
<!-- This content appears in the Info sidebar when a node is selected --> <p>Requires <b>msg.payload</b> to be of the form 'r,g,b'</p>
<!-- The first <p> is used as the pop-up tool tip when hovering over a -->
<!-- node in the palette. -->
<p>Simple output node to drive digispark RGB</p>
<p>Requires msg.payload to be of the form 'r,g,b'</p>
</script> </script>
<!-- Finally, the node type is registered along with all of its properties -->
<!-- The example below shows a small subset of the properties that can be set-->
<script type="text/javascript"> <script type="text/javascript">
RED.nodes.registerType('digiRGB',{ RED.nodes.registerType('digiRGB',{
category: 'output', // the palette category category: 'output',
color:"GoldenRod", color:"GoldenRod",
defaults: { // defines the editable properties of the node defaults: {
name: {value:"digiSparkRGB"} // along with default values. name: {value:""}
}, },
inputs:1, // set the number of inputs - only 0 or 1 inputs:1,
outputs:0, // set the number of outputs - 0 to n outputs:0,
icon: "light.png", // set the icon (held in public/icons) icon: "light.png",
align: "right", align: "right",
label: function() { // sets the default label contents label: function() {
return this.name||this.topic||"sample"; return this.name||"digiSparkRGB";
}, },
labelStyle: function() { // sets the class to apply to the label labelStyle: function() {
return this.name?"node_label_italic":""; return this.name?"node_label_italic":"";
} }
}); });

View File

@ -14,70 +14,56 @@
* limitations under the License. * limitations under the License.
**/ **/
// Sample Node-RED node file
// Require main module
var RED = require(process.env.NODE_RED_HOME+"/red/red"); var RED = require(process.env.NODE_RED_HOME+"/red/red");
var HID = require('node-hid'); var HID = require('node-hid');
var device; var device;
var node; var node;
// The main node definition - most things happen in here
function DigiRGBNode(n) { function DigiRGBNode(n) {
// Create a RED node
RED.nodes.createNode(this,n); RED.nodes.createNode(this,n);
node=this; node=this;
var devices = HID.devices(0x16c0,0x05df); var devices = HID.devices(0x16c0,0x05df);
for (var i=0; i< devices.length; i++) { for (var i=0; i< devices.length; i++) {
if (devices[i].product == 'DigiUSB') { if (devices[i].product == 'DigiUSB') {
path = devices[i].path; path = devices[i].path;
node.log("found: " + path); node.log("found: " + path);
try { try {
device = new HID.HID(devices[i].path); device = new HID.HID(devices[i].path);
break; break;
} catch (e) { } catch (e) {
node.log(e) node.log(e)
}
}
}
var p1 = /^\#[A-Fa-f0-9]{6}$/
var p2 = /[0-9]+,[0-9]+,[0-9]+/
if (device) {
this.on("input", function(msg) {
if (msg != null) {
if (p1.test(msg.payload)) {
var r = parseInt(msg.payload.slice(1,3),16);
var g = parseInt(msg.payload.slice(3,5),16);
var b = parseInt(msg.payload.slice(5),16);
device.sendFeatureReport([115,r,g,b]);
} else if (p2.test(msg.payload)) {
var args = msg.payload.split(',');
if (args.length == 3) {
device.sendFeatureReport([115,parseInt(args[0]),parseInt(args[1]),parseInt(args[2])]);
} }
} else {
node.warn("incompatable input - " + msg.payload);
}
} }
});
} else {
node.warn("no digispark RGB found");
}
}
// Register the node by name. This must be called before overriding any of the
// Node functions.
RED.nodes.registerType("digiRGB",DigiRGBNode);
DigiRGBNode.prototype.close = function() {
// Called when the node is shutdown - eg on redeploy.
// Allows ports to be closed, connections dropped etc.
// eg: this.client.disconnect();
if (device) {
device.close();
} }
var p1 = /^\#[A-Fa-f0-9]{6}$/
var p2 = /[0-9]+,[0-9]+,[0-9]+/
if (device) {
this.on("input", function(msg) {
if (msg != null) {
if (p1.test(msg.payload)) {
var r = parseInt(msg.payload.slice(1,3),16);
var g = parseInt(msg.payload.slice(3,5),16);
var b = parseInt(msg.payload.slice(5),16);
device.sendFeatureReport([115,r,g,b]);
} else if (p2.test(msg.payload)) {
var args = msg.payload.split(',');
if (args.length == 3) {
device.sendFeatureReport([115,parseInt(args[0]),parseInt(args[1]),parseInt(args[2])]);
}
} else {
node.warn("incompatable input - " + msg.payload);
}
}
});
} else {
node.warn("no digispark RGB found");
}
this.on('close', function() {
if (device) { device.close(); }
});
} }
RED.nodes.registerType("digiRGB",DigiRGBNode);

View File

@ -0,0 +1,90 @@
<!--
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.
-->
<script type="text/x-red" data-template-name="wemo out">
<div class="form-row">
<label for="node-input-ipaddr"><i class="icon-globe"></i> IP Address</label>
<input type="text" id="node-input-ipaddr" placeholder="192.168.1.100">
</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">Expects a msg.payload with either 1/0, on/off, or true/false</div>
</script>
<script type="text/x-red" data-help-name="wemo out">
<p>Wemo output node. Expects a <b>msg.payload</b> with either 1/0, on/off or true/false.</p>
<p>It doesn't yet do any ip address discovery of the wemo devices.</p>
</script>
<script type="text/javascript">
RED.nodes.registerType('wemo out',{
category: 'advanced-output',
color:"GoldenRod",
defaults: {
ipaddr: {value:"",required:true},
name: {value:""}
},
inputs:1,
outputs:0,
icon: "light.png",
align: "right",
label: function() {
return this.name||"wemo";
},
labelStyle: function() {
return this.name?"node_label_italic":"";
}
});
</script>
<script type="text/x-red" data-template-name="wemo in">
<div class="form-row">
<label for="node-input-ipaddr"><i class="icon-globe"></i> IP Address</label>
<input type="text" id="node-input-ipaddr" placeholder="192.168.1.100">
</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">Creates a msg.payload with either 1, 0, nc or na.</div>
</script>
<script type="text/x-red" data-help-name="wemo in">
<p>Wemo input node. Creates a <b>msg.payload</b> with either 1, 0, nc (no change), or na (not available).</p>
<p>It doesn't yet do any ip address discovery of the wemo devices.</p>
</script>
<script type="text/javascript">
RED.nodes.registerType('wemo in',{
category: 'advanced-input',
color:"GoldenRod",
defaults: {
ipaddr: {value:"",required:true},
name: {value:""}
},
inputs:0,
outputs:1,
icon: "light.png",
label: function() {
return this.name||"wemo";
},
labelStyle: function() {
return this.name?"node_label_italic":"";
}
});
</script>

60
hardware/wemo/60-wemo.js Normal file
View File

@ -0,0 +1,60 @@
/**
* Copyright 2013 IBM Corp.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
**/
var RED = require(process.env.NODE_RED_HOME+"/red/red");
var WeMo = new require('wemo');
function WeMoOut(n) {
RED.nodes.createNode(this,n);
this.ipaddr = n.ipaddr;
this.wemoSwitch = new WeMo(n.ipaddr);
var node = this;
this.on("input", function(msg) {
if (msg != null) {
var state = 0;
if ( msg.payload == 1 || msg.payload == true || msg.payload == "on" ) { var state = 1; }
node.wemoSwitch.setBinaryState(state, function(err, result) {
if (err) node.warn(err);
//else { node.log(result); }
});
}
});
}
RED.nodes.registerType("wemo out",WeMoOut);
function WeMoIn(n) {
RED.nodes.createNode(this,n);
this.ipaddr = n.ipaddr;
this.wemoSwitch = new WeMo(n.ipaddr);
this.wemoSwitch.state = 0;
var node = this;
var tick = setInterval(function() {
wemoSwitch.getBinaryState(function(err, result) {
if (err) node.warn(err);
if (parseInt(result) != wemoSwitch.state) {
wemoSwitch.state = parseInt(result);
node.send({payload:wemoSwitch.state,topic:"wemo/"+node.ipaddr});
}
});
}, 2000);
this.on("close", function() {
clearInterval(tick);
});
}
RED.nodes.registerType("wemo in",WeMoOut);

View File

@ -15,18 +15,18 @@
--> -->
<script type="text/x-red" data-template-name="ping"> <script type="text/x-red" data-template-name="ping">
<div class="form-row"> <div class="form-row">
<label for="node-input-host"><i class="icon-tasks"></i> Target</label> <label for="node-input-host"><i class="icon-tasks"></i> Target</label>
<input type="text" id="node-input-host" placeholder="www.google.com"> <input type="text" id="node-input-host" placeholder="www.google.com">
</div> </div>
<div class="form-row"> <div class="form-row">
<label for="node-input-timer"><i class="icon-tasks"></i> Ping (S)</label> <label for="node-input-timer"><i class="icon-tasks"></i> Ping (S)</label>
<input type="text" id="node-input-timer" placeholder="20"> <input type="text" id="node-input-timer" placeholder="20">
</div> </div>
<div class="form-row"> <div class="form-row">
<label for="node-input-name"><i class="icon-tag"></i> Name</label> <label for="node-input-name"><i class="icon-tag"></i> Name</label>
<input type="text" id="node-input-name" placeholder="Name"> <input type="text" id="node-input-name" placeholder="Name">
</div> </div>
</script> </script>
<!-- Next, some simple help text is provided for the node. --> <!-- Next, some simple help text is provided for the node. -->

View File

@ -51,7 +51,5 @@ function PingNode(n) {
this.on("close", function() { this.on("close", function() {
clearInterval(this.tout); clearInterval(this.tout);
}); });
} }
RED.nodes.registerType("ping",PingNode); RED.nodes.registerType("ping",PingNode);

View File

@ -15,18 +15,18 @@
--> -->
<script type="text/x-red" data-template-name="rawserial in"> <script type="text/x-red" data-template-name="rawserial in">
<div class="form-row"> <div class="form-row">
<label for="node-input-port"><i class="icon-random"></i> Port</label> <label for="node-input-port"><i class="icon-random"></i> Port</label>
<input type="text" id="node-input-port" placeholder="COM1"> <input type="text" id="node-input-port" placeholder="COM1">
</div> </div>
<div class="form-row"> <div class="form-row">
<label for="node-input-split"><i class="icon-edit"></i> Split on</label> <label for="node-input-split"><i class="icon-edit"></i> Split on</label>
<input type="text" id="node-input-split" placeholder="\n"> <input type="text" id="node-input-split" placeholder="\n">
</div> </div>
<div class="form-row"> <div class="form-row">
<label for="node-input-name"><i class="icon-tag"></i> Name</label> <label for="node-input-name"><i class="icon-tag"></i> Name</label>
<input type="text" id="node-input-name" placeholder="Name"> <input type="text" id="node-input-name" placeholder="Name">
</div> </div>
</script> </script>
<script type="text/x-red" data-help-name="rawserial in"> <script type="text/x-red" data-help-name="rawserial in">
@ -60,14 +60,14 @@
</script> </script>
<script type="text/x-red" data-template-name="rawserial out"> <script type="text/x-red" data-template-name="rawserial out">
<div class="form-row"> <div class="form-row">
<label for="node-input-port"><i class="icon-random"></i> Port</label> <label for="node-input-port"><i class="icon-random"></i> Port</label>
<input type="text" id="node-input-port" placeholder="COM1"> <input type="text" id="node-input-port" placeholder="COM1">
</div> </div>
<div class="form-row"> <div class="form-row">
<label for="node-input-name"><i class="icon-tag"></i> Name</label> <label for="node-input-name"><i class="icon-tag"></i> Name</label>
<input type="text" id="node-input-name" placeholder="Name"> <input type="text" id="node-input-name" placeholder="Name">
</div> </div>
</script> </script>
<script type="text/x-red" data-help-name="rawserial out"> <script type="text/x-red" data-help-name="rawserial out">

View File

@ -23,7 +23,7 @@
</script> </script>
<script type="text/x-red" data-help-name="mpd out"> <script type="text/x-red" data-help-name="mpd out">
<p>MPD music control output node</p> <p>MPD music control output node.</p>
<p>Expects <b>msg.payload</b> to be a valid mpc command. Currently only simple commands that expect no reply are supported.</p> <p>Expects <b>msg.payload</b> to be a valid mpc command. Currently only simple commands that expect no reply are supported.</p>
</script> </script>

View File

@ -15,108 +15,108 @@
--> -->
<script type="text/x-red" data-template-name="leveldbase"> <script type="text/x-red" data-template-name="leveldbase">
<div class="form-row"> <div class="form-row">
<label for="node-config-input-db"><i class="icon-briefcase"></i> Database</label> <label for="node-config-input-db"><i class="icon-briefcase"></i> Database</label>
<input type="text" id="node-config-input-db" placeholder="database path/name"> <input type="text" id="node-config-input-db" placeholder="database path/name">
</div> </div>
</script> </script>
<script type="text/javascript"> <script type="text/javascript">
RED.nodes.registerType('leveldbase',{ RED.nodes.registerType('leveldbase',{
category: 'config', category: 'config',
defaults: { defaults: {
db: {value:"",required:true} db: {value:"",required:true}
}, },
label: function() { label: function() {
return this.db; return this.db;
} }
}); });
</script> </script>
<script type="text/x-red" data-template-name="leveldb in"> <script type="text/x-red" data-template-name="leveldb in">
<div class="form-row node-input-level"> <div class="form-row node-input-level">
<label for="node-input-level"><i class="icon-briefcase"></i> Database</label> <label for="node-input-level"><i class="icon-briefcase"></i> Database</label>
<input type="text" id="node-input-level"> <input type="text" id="node-input-level">
</div> </div>
<div class="form-row"> <div class="form-row">
<label for="node-input-name"><i class="icon-tag"></i> Name</label> <label for="node-input-name"><i class="icon-tag"></i> Name</label>
<input type="text" id="node-input-name" placeholder="Name"> <input type="text" id="node-input-name" placeholder="Name">
</div> </div>
</script> </script>
<script type="text/x-red" data-help-name="leveldb in"> <script type="text/x-red" data-help-name="leveldb in">
<p>Uses <a href="https://code.google.com/p/leveldb/" target="_new"><i>LevelDB</i></a> for a simple key value pair database.</p> <p>Uses <a href="https://code.google.com/p/leveldb/" target="_new"><i>LevelDB</i></a> for a simple key value pair database.</p>
<p>Use this node to <b>get</b>, or retrieve the data already saved in the database.</p> <p>Use this node to <b>get</b>, or retrieve the data already saved in the database.</p>
<p><b>msg.topic</b> must hold the <i>key</i> for the database, and the result is returned in <b>msg.payload</b>.</p> <p><b>msg.topic</b> must hold the <i>key</i> for the database, and the result is returned in <b>msg.payload</b>.</p>
<p>If nothing is found for the key then <i>null</i> is returned,</p> <p>If nothing is found for the key then <i>null</i> is returned,</p>
</script> </script>
<script type="text/javascript"> <script type="text/javascript">
RED.nodes.registerType('leveldb in',{ RED.nodes.registerType('leveldb in',{
category: 'storage-input', category: 'storage-input',
color:"#dbb84d", color:"#dbb84d",
defaults: { defaults: {
level: {type:"leveldbase",required:true}, level: {type:"leveldbase",required:true},
name: {value:""} name: {value:""}
}, },
inputs:1, inputs:1,
outputs:1, outputs:1,
icon: "leveldb.png", icon: "leveldb.png",
label: function() { label: function() {
var levelNode = RED.nodes.node(this.level); var levelNode = RED.nodes.node(this.level);
return this.name||(levelNode?levelNode.label():"leveldb"); return this.name||(levelNode?levelNode.label():"leveldb");
}, },
labelStyle: function() { labelStyle: function() {
return this.name?"node_label_italic":""; return this.name?"node_label_italic":"";
} }
}); });
</script> </script>
<script type="text/x-red" data-template-name="leveldb out"> <script type="text/x-red" data-template-name="leveldb out">
<div class="form-row node-input-level"> <div class="form-row node-input-level">
<label for="node-input-level"><i class="icon-briefcase"></i> Database</label> <label for="node-input-level"><i class="icon-briefcase"></i> Database</label>
<input type="text" id="node-input-level"> <input type="text" id="node-input-level">
</div> </div>
<div class="form-row"> <div class="form-row">
<label for="node-input-operation"><i class="icon-wrench"></i> Operation</label> <label for="node-input-operation"><i class="icon-wrench"></i> Operation</label>
<select type="text" id="node-input-operation" style="display: inline-block; vertical-align: top;"> <select type="text" id="node-input-operation" style="display: inline-block; vertical-align: top;">
<option value="store">Store</option> <option value="store">Store</option>
<option value="delete">Delete</option> <option value="delete">Delete</option>
</select> </select>
</div> </div>
<div class="form-row"> <div class="form-row">
<label for="node-input-name"><i class="icon-tag"></i> Name</label> <label for="node-input-name"><i class="icon-tag"></i> Name</label>
<input type="text" id="node-input-name" placeholder="Name"> <input type="text" id="node-input-name" placeholder="Name">
</div> </div>
</script> </script>
<script type="text/x-red" data-help-name="leveldb out"> <script type="text/x-red" data-help-name="leveldb out">
<p>Uses <a href="https://code.google.com/p/leveldb/" target="_new"><i>LevelDB</i></a> for a simple key value pair database.</p> <p>Uses <a href="https://code.google.com/p/leveldb/" target="_new"><i>LevelDB</i></a> for a simple key value pair database.</p>
<p>Use this node to either <b>put</b> (store) the <b>msg.payload</b> to the named database file, using <b>msg.topic</b> as the key.</p> <p>Use this node to either <b>put</b> (store) the <b>msg.payload</b> to the named database file, using <b>msg.topic</b> as the key.</p>
<p>To <b>delete</b> information select delete in the properties dialogue and again use <b>msg.topic</b> as the key.</b>.</p> <p>To <b>delete</b> information select delete in the properties dialogue and again use <b>msg.topic</b> as the key.</b>.</p>
</script> </script>
<script type="text/javascript"> <script type="text/javascript">
RED.nodes.registerType('leveldb out',{ RED.nodes.registerType('leveldb out',{
category: 'storage-output', category: 'storage-output',
color:"#dbb84d", color:"#dbb84d",
defaults: { defaults: {
level: {type:"leveldbase",required:true}, level: {type:"leveldbase",required:true},
operation: {value:"store"}, operation: {value:"store"},
name: {value:""} name: {value:""}
}, },
inputs:1, inputs:1,
outputs:0, outputs:0,
icon: "leveldb.png", icon: "leveldb.png",
align: "right", align: "right",
label: function() { label: function() {
var levelNode = RED.nodes.node(this.level); var levelNode = RED.nodes.node(this.level);
return this.name||(levelNode?levelNode.label():"leveldb"); return this.name||(levelNode?levelNode.label():"leveldb");
}, },
labelStyle: function() { labelStyle: function() {
return this.name?"node_label_italic":""; return this.name?"node_label_italic":"";
} }
}); });
</script> </script>

View File

@ -18,76 +18,77 @@ var RED = require(process.env.NODE_RED_HOME+"/red/red");
var lvldb = require('level'); var lvldb = require('level');
function LevelNode(n) { function LevelNode(n) {
RED.nodes.createNode(this,n); RED.nodes.createNode(this,n);
this.dbname = n.db; this.dbname = n.db;
var node = this; var node = this;
lvldb(this.dbname, function(err, db) { lvldb(this.dbname, function(err, db) {
if (err) node.error(err); if (err) node.error(err);
node.db = db; node.db = db;
}); });
this.on('close', function() {
if (node.db) { node.db.close(); }
});
} }
RED.nodes.registerType("leveldbase",LevelNode); RED.nodes.registerType("leveldbase",LevelNode);
LevelNode.prototype.close = function() {
this.db.close();
}
function LevelDBNodeIn(n) { function LevelDBNodeIn(n) {
RED.nodes.createNode(this,n); RED.nodes.createNode(this,n);
this.level = n.level; this.level = n.level;
this.levelConfig = RED.nodes.getNode(this.level); this.levelConfig = RED.nodes.getNode(this.level);
if (this.levelConfig) { if (this.levelConfig) {
var node = this; var node = this;
node.on("input", function(msg) { node.on("input", function(msg) {
if (typeof msg.topic === 'string') { if (typeof msg.topic === 'string') {
node.levelConfig.db.get(msg.topic, function(err, value) { node.levelConfig.db.get(msg.topic, function(err, value) {
if (err) { if (err) {
//node.warn(err); //node.warn(err);
// for some reason they treat nothing found as an error... // for some reason they treat nothing found as an error...
msg.payload = null; // so we should return null msg.payload = null; // so we should return null
} }
else { msg.payload = value; } else { msg.payload = value; }
node.send(msg); node.send(msg);
}); });
} }
else { else {
if (typeof msg.topic !== 'string') node.error("msg.topic (the key is not defined"); if (typeof msg.topic !== 'string') node.error("msg.topic (the key is not defined");
} }
}); });
} }
else { else {
this.error("LevelDB database name not configured"); this.error("LevelDB database name not configured");
} }
} }
RED.nodes.registerType("leveldb in",LevelDBNodeIn); RED.nodes.registerType("leveldb in",LevelDBNodeIn);
function LevelDBNodeOut(n) { function LevelDBNodeOut(n) {
RED.nodes.createNode(this,n); RED.nodes.createNode(this,n);
this.level = n.level; this.level = n.level;
this.operation = n.operation; this.operation = n.operation;
this.levelConfig = RED.nodes.getNode(this.level); this.levelConfig = RED.nodes.getNode(this.level);
if (this.levelConfig) { if (this.levelConfig) {
var node = this; var node = this;
node.on("input", function(msg) { node.on("input", function(msg) {
if (typeof msg.topic === 'string') { if (typeof msg.topic === 'string') {
if (node.operation === "delete") { if (node.operation === "delete") {
node.levelConfig.db.del(msg.topic); node.levelConfig.db.del(msg.topic);
} }
else { else {
node.levelConfig.db.put(msg.topic, msg.payload, function(err) { node.levelConfig.db.put(msg.topic, msg.payload, function(err) {
if (err) node.error(err); if (err) node.error(err);
}); });
} }
} }
else { else {
if (typeof msg.topic !== 'string') node.error("msg.topic (the key is not defined"); if (typeof msg.topic !== 'string') node.error("msg.topic (the key is not defined");
} }
}); });
} }
else { else {
this.error("LevelDB database name not configured"); this.error("LevelDB database name not configured");
} }
} }
RED.nodes.registerType("leveldb out",LevelDBNodeOut); RED.nodes.registerType("leveldb out",LevelDBNodeOut);

View File

@ -54,7 +54,6 @@
</script> </script>
<script type="text/x-red" data-template-name="mysql"> <script type="text/x-red" data-template-name="mysql">
<div class="form-row"> <div class="form-row">
<label for="node-input-mydb"><i class="icon-briefcase"></i> Database</label> <label for="node-input-mydb"><i class="icon-briefcase"></i> Database</label>
@ -95,53 +94,3 @@
} }
}); });
</script> </script>
<!--
<script type="text/x-red" data-template-name="mysql out">
<div class="form-row node-input-level">
<label for="node-input-level"><i class="icon-briefcase"></i> Database</label>
<input type="text" id="node-input-level">
</div>
<div class="form-row">
<label for="node-input-operation"><i class="icon-wrench"></i> Operation</label>
<select type="text" id="node-input-operation" style="display: inline-block; vertical-align: top;">
<option value="store">Store</option>
<option value="delete">Delete</option>
</select>
</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="mysql out">
<p>Allows access to a MySQL database.</p>
<p>Use this node to either <b>put</b> (store) the <b>msg.payload</b> to the named database file, using <b>msg.topic</b> as the key.</p>
<p>To <b>delete</b> information select delete in the properties dialogue and again use <b>msg.topic</b> as the key.</b>.</p>
</script>
<script type="text/javascript">
RED.nodes.registerType('mysql out',{
category: 'storage-output',
color:"#e97b00",
defaults: {
level: {type:"MySQLdatabase",required:true},
operation: {value:"store"},
name: {value:""}
},
inputs:1,
outputs:0,
icon: "db.png",
align: "right",
label: function() {
var levelNode = RED.nodes.node(this.level);
return this.name||(levelNode?levelNode.label():"mysql");
},
labelStyle: function() {
return this.name?"node_label_italic":"";
}
});
</script>
-->