Merge branch 'master' of github.com:node-red/node-red-nodes

This commit is contained in:
Nick O'Leary 2018-09-26 16:06:38 +01:00
commit 1f34239fbb
No known key found for this signature in database
GPG Key ID: 4F2157149161A6C9
40 changed files with 2603 additions and 653 deletions

View File

@ -4,7 +4,6 @@ matrix:
include:
- node_js: 8
- node_js: 10
- node_js: 6
- python: 2.7
language: python
before_script: pip install flake8

View File

@ -9,15 +9,17 @@ Install
Run the following command in your Node-RED user directory - typically `~/.node-red`
npm install node-red-node-random
Usage
-----
A simple node to generate a random number when triggered.
If integer mode is selected (default) it will return an integer **between and including** the two values given - so selecting 1 to 6 will return values 1,2,3,4,5 or 6.
If you return an integer it can include both the low and high values.
`min <= n <= max` - so selecting 1 to 6 will return values 1,2,3,4,5 or 6.
If floating point mode is selected then it will return a number **between** the two values given - so selecting 1 to 6 will return values 1 < x < 6 .
If you return a floating point value it will be from the low value, up to, but
not including the high value. `min <= n < max` - so selecting 1 to 6 will return values 1 <= n < 6 .
**Note:** This generates **numbers**.

View File

@ -1,6 +1,6 @@
{
"name" : "node-red-node-random",
"version" : "0.1.0",
"version" : "0.1.2",
"description" : "A Node-RED node that when triggered generates a random number between two values.",
"dependencies" : {
},

View File

@ -28,8 +28,10 @@
70%
<script type="text/x-red" data-help-name="random">
<p>Generates a random number between a low and high value.</p>
<p>If you return an integer it can <i>include</i> both the low and high values.</p>
<p>If you return a floating point value it will be <i>between</i> the low and high values.</p>
<p>If you return an integer it can <i>include</i> both the low and high values.
<code>min <= n <= max</code></p>
<p>If you return a floating point value it will be from the low value, up to, but
not including the high value. <code>min <= n < max</code></p>
</script>
<script type="text/javascript">

View File

@ -11,10 +11,10 @@ module.exports = function(RED) {
this.on("input", function(msg) {
var value;
if (node.inte == "true" || node.inte === true) {
value = Math.round(Number(Math.random()) * (node.high - node.low + 1) + node.low - 0.5);
value = Math.round(Math.random() * (node.high - node.low + 1) + node.low - 0.5);
}
else {
value = Number(Math.random()) * (node.high - node.low) + node.low;
value = Math.random() * (node.high - node.low) + node.low;
}
RED.util.setMessageProperty(msg,node.property,value);
node.send(msg);

View File

@ -37,6 +37,8 @@ select the channel dynamically. If so then the payload must be a value from 0 to
You can also select device id 0 or 1 (CE0 or CE1) depending on how you have wired up your device. Defaults to CE0.
And you can also select the SPI bus number 0 or 1 depending on how you have wired up your device. Defaults to 0 for spidev0.
Outputs a numeric `msg.payload` with a range of 0 to 1023, where 0 = 0V and 1023 = 3.3V (assuming you use the default 3.3V voltage reference).
**Hint**: use a `range` node to adjust the values to the range you want.

View File

@ -1,9 +1,9 @@
{
"name" : "node-red-node-pi-mcp3008",
"version" : "0.1.1",
"version" : "0.2.0",
"description" : "A Node-RED node to read from the MCP3008 Analogue to Digital Converter",
"dependencies" : {
"mcp-spi-adc": "^1.0.0"
"mcp-spi-adc": "^2.0.3"
},
"repository" : {
"type":"git",

View File

@ -33,6 +33,13 @@
<option value=1>CE1</option>
</select>
</div>
<div class="form-row">
<label for="node-input-bus"><i class="fa fa-toggle-on"></i> SPI bus</label>
<select type="text" id="node-input-bus" style="width:150px;">
<option value=0>0</option>
<option value=1>1</option>
</select>
</div>
<div class="form-row">
<label for="node-input-name"><i class="fa fa-tag"></i> Name</label>
<input type="text" id="node-input-name" placeholder="Name"/>
@ -61,7 +68,8 @@
name: {value:""},
dev: {value:"3008"},
pin: {value:0, required:true},
dnum: {value:0}
dnum: {value:0},
bus: {value:0}
},
inputs: 1,
outputs: 1,

View File

@ -19,14 +19,15 @@ module.exports = function(RED) {
this.pin = n.pin || 0;
this.interval = n.interval || 1000;
this.dnum = parseInt(n.dnum || 0);
this.bus = parseInt(n.bus || 0);
this.dev = n.dev || "3008";
var node = this;
var cb = function (err) { if (err) { node.error("Error: "+err); } };
var opt = { speedHz:20000, deviceNumber:node.dnum };
var opt = { speedHz:20000, deviceNumber:node.dnum, busNumber:node.bus };
var chans = parseInt(this.dev.substr(3));
try {
fs.statSync("/dev/spidev0."+node.dnum);
fs.statSync("/dev/spidev"+node.bus+"."+node.dnum);
if (mcp3xxx.length === 0) {
for (var i=0; i<chans; i++) {
if (node.dev === "3002") { mcp3xxx.push(mcpadc.openMcp3002(i, opt, cb)); }

0
hardware/neopixel/neopixel.html Executable file → Normal file
View File

2
hardware/neopixel/neopixel.js Executable file → Normal file
View File

@ -14,7 +14,7 @@ module.exports = function(RED) {
RED.log.warn("rpi-neopixels : "+RED._("node-red:rpi-gpio.errors.ignorenode"));
allOK = false;
}
else if (execSync('python -c "import neopixel"').toString() !== "") {
else if (execSync('python -c "import rpi_ws281x"').toString() !== "") {
RED.log.warn("rpi-neopixels : Can't find neopixel python library");
allOK = false;
}

2
hardware/neopixel/package.json Executable file → Normal file
View File

@ -1,6 +1,6 @@
{
"name" : "node-red-node-pi-neopixel",
"version" : "0.0.21",
"version" : "0.0.22",
"description" : "A Node-RED node to output to a neopixel (ws2812) string of LEDS from a Raspberry Pi.",
"dependencies" : {
},

View File

@ -2,7 +2,7 @@
module.exports = function(RED) {
"use strict";
var wol = require('wake_on_lan');
var chk = /^([0-9A-F]{2}[:-]){5}([0-9A-F]{2})$/;
var chk = /^([0-9A-Fa-f]{2}[:-]){5}([0-9A-Fa-f]{2})$/;
function WOLnode(n) {
RED.nodes.createNode(this,n);
@ -17,9 +17,13 @@ module.exports = function(RED) {
if (chk.test(mac)) {
try {
wol.wake(mac, {address: host}, function(error) {
if (error) { node.warn(error); }
if (error) {
node.warn(error);
node.status({fill:"red",shape:"ring",text:" "});
}
else if (RED.settings.verbose) {
node.log("sent WOL magic packet");
node.status({fill:"green",shape:"dot",text:" "});
}
});
}
@ -31,6 +35,10 @@ module.exports = function(RED) {
}
else { node.warn("WOL: no mac address specified"); }
});
this.on("close", function () {
node.status({});
})
}
RED.nodes.registerType("wake on lan",WOLnode);
}

View File

@ -1,9 +1,9 @@
{
"name" : "node-red-node-wol",
"version" : "0.0.8",
"version" : "0.0.9",
"description" : "A Node-RED node to send Wake-On-LAN (WOL) magic packets",
"dependencies" : {
"wake_on_lan" : "0.0.4"
"wake_on_lan" : "1.0.0"
},
"repository" : {
"type":"git",

2857
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -32,30 +32,30 @@
],
"devDependencies": {
"exif": "^0.6.0",
"grunt": "~1.0.3",
"grunt-cli": "^1.2.0",
"grunt-contrib-jshint": "^1.1.0",
"grunt": "^1.0.3",
"grunt-cli": "^1.3.1",
"grunt-contrib-jshint": "^2.0.0",
"grunt-jscs": "^3.0.1",
"grunt-lint-inline": "^1.0.0",
"grunt-simple-mocha": "^0.4.1",
"imap": "^0.8.19",
"mailparser": "^0.6.2",
"mocha": "~5.1.1",
"mailparser-mit": "^0.6.2",
"mocha": "^5.2.0",
"msgpack-lite": "^0.1.26",
"multilang-sentiment": "^1.1.6",
"ngeohash": "^0.6.0",
"node-red": "*",
"node-red-node-test-helper": "*",
"nodemailer": "~4.6.7",
"nodemailer": "^4.6.8",
"poplib": "^0.1.7",
"proxyquire": "^2.0.1",
"pushbullet": "~2.2.0",
"should": "~13.2.3",
"sinon": "~5.0.10",
"supertest": "~3.1.0",
"proxyquire": "^2.1.0",
"pushbullet": "^2.3.0",
"should": "^13.2.3",
"sinon": "^6.3.4",
"supertest": "^3.3.0",
"when": "^3.7.8"
},
"engines": {
"node": ">=6.0.0"
"node": ">=8.0.0"
}
}

View File

@ -49,6 +49,10 @@
<input type="password" id="node-input-password">
</div>
<br/>
<div class="form-row">
<label for="node-input-useTLS"><i class="fa fa-lock"></i> <span data-i18n="email.label.useTLS"></label>
<input type="checkbox" id="node-input-tls" style="display:inline-block; width:20px; vertical-align:baseline;">
</div>
<div class="form-row">
<label for="node-input-dname"><i class="fa fa-tag"></i> <span data-i18n="node-red:common.label.name"></span></label>
<input type="text" id="node-input-dname" data-i18n="[placeholder]node-red:common.label.name">
@ -69,6 +73,7 @@
<p>Alternatively you may provide <code>msg.attachments</code> which should contain an array of one or
more attachments in <a href="https://www.npmjs.com/package/nodemailer#attachments" target="_new">nodemailer</a> format.</p>
<p>If required by your recipient you may also pass in a <code>msg.envelope</code> object, typically containing extra from and to properties.</p>
<p>If you have own signed certificates, Nodemailer can complain about that and refuse sending the message. In this case you can try switching off TLS.</p>
<p>Note: uses SMTP with SSL to port 465.</p>
</script>
@ -81,6 +86,7 @@
server: {value:"smtp.gmail.com",required:true},
port: {value:"465",required:true},
secure: {value: true},
tls: {value: true},
name: {value:""},
dname: {value:""}
},

View File

@ -14,9 +14,13 @@ module.exports = function(RED) {
var nodemailer = require("nodemailer");
var Imap = require('imap');
var POP3Client = require("poplib");
var MailParser = require("mailparser").MailParser;
var MailParser = require("mailparser-mit").MailParser;
var util = require("util");
if (parseInt(process.version.split("v")[1].split(".")[0]) < 8) {
throw "Error : Requires nodejs version >= 8.";
}
try {
var globalkeys = RED.settings.email || require(process.env.NODE_RED_HOME+"/../emailkeys.js");
}
@ -30,6 +34,7 @@ module.exports = function(RED) {
this.outserver = n.server;
this.outport = n.port;
this.secure = n.secure;
this.tls = true;
var flag = false;
if (this.credentials && this.credentials.hasOwnProperty("userid")) {
this.userid = this.credentials.userid;
@ -50,12 +55,16 @@ module.exports = function(RED) {
if (flag) {
RED.nodes.addCredentials(n.id,{userid:this.userid, password:this.password, global:true});
}
if (n.tls === false){
this.tls = false;
}
var node = this;
var smtpOptions = {
host: node.outserver,
port: node.outport,
secure: node.secure
secure: node.secure,
tls: {rejectUnauthorized: node.tls}
}
if (this.userid && this.password) {
@ -185,7 +194,7 @@ module.exports = function(RED) {
// will be used to populate the email.
// DCJ NOTE: - heirachical multipart mime parsers seem to not exist - this one is barely functional.
function processNewMessage(msg, mailMessage) {
msg = JSON.parse(JSON.stringify(msg)); // Clone the message
msg = RED.util.cloneMessage(msg); // Clone the message
// Populate the msg fields from the content of the email message
// that we have just parsed.
msg.payload = mailMessage.text;
@ -193,9 +202,9 @@ module.exports = function(RED) {
msg.date = mailMessage.date;
msg.header = mailMessage.headers;
if (mailMessage.html) { msg.html = mailMessage.html; }
if (mailMessage.to && mailMessage.from.to > 0) { msg.to = mailMessage.to; }
if (mailMessage.cc && mailMessage.from.cc > 0) { msg.cc = mailMessage.cc; }
if (mailMessage.bcc && mailMessage.from.bcc > 0) { msg.bcc = mailMessage.bcc; }
if (mailMessage.to && mailMessage.to.length > 0) { msg.to = mailMessage.to; }
if (mailMessage.cc && mailMessage.cc.length > 0) { msg.cc = mailMessage.cc; }
if (mailMessage.bcc && mailMessage.bcc.length > 0) { msg.bcc = mailMessage.bcc; }
if (mailMessage.from && mailMessage.from.length > 0) { msg.from = mailMessage.from[0].address; }
if (mailMessage.attachments) { msg.attachments = mailMessage.attachments; }
else { msg.attachments = []; }
@ -221,6 +230,7 @@ module.exports = function(RED) {
function nextMessage() {
if (currentMessage > maxMessage) {
pop3Client.quit();
setInputRepeatTimeout();
return;
}
pop3Client.retr(currentMessage);
@ -243,6 +253,7 @@ module.exports = function(RED) {
});
pop3Client.on("error", function(err) {
setInputRepeatTimeout();
node.log("error: " + JSON.stringify(err));
});
@ -258,6 +269,7 @@ module.exports = function(RED) {
} else {
node.log(util.format("login error: %s %j", status, rawData));
pop3Client.quit();
setInputRepeatTimeout();
}
});
@ -279,6 +291,7 @@ module.exports = function(RED) {
else {
node.log(util.format("retr error: %s %j", status, rawData));
pop3Client.quit();
setInputRepeatTimeout();
}
});
@ -318,6 +331,7 @@ module.exports = function(RED) {
node.status({fill:"red", shape:"ring", text:"email.status.foldererror"});
node.error(RED._("email.errors.fetchfail", {folder:node.box}),err);
imap.end();
setInputRepeatTimeout();
return;
}
//console.log("> search - err=%j, results=%j", err, results);
@ -325,6 +339,7 @@ module.exports = function(RED) {
//console.log(" [X] - Nothing to fetch");
node.status({});
imap.end();
setInputRepeatTimeout();
return;
}
@ -372,10 +387,12 @@ module.exports = function(RED) {
} else {
cleanup();
}
setInputRepeatTimeout();
});
fetch.once('error', function(err) {
console.log('Fetch error: ' + err);
setInputRepeatTimeout();
});
}); // End of imap->search
}); // End of imap->openInbox
@ -419,16 +436,19 @@ module.exports = function(RED) {
this.on("close", function() {
if (this.interval_id != null) {
clearInterval(this.interval_id);
clearTimeout(this.interval_id);
}
if (imap) { imap.destroy(); }
});
// Set the repetition timer as needed
if (!isNaN(this.repeat) && this.repeat > 0) {
this.interval_id = setInterval( function() {
node.emit("input",{});
}, this.repeat );
function setInputRepeatTimeout()
{
// Set the repetition timer as needed
if (!isNaN(node.repeat) && node.repeat > 0) {
node.interval_id = setTimeout( function() {
node.emit("input",{});
}, node.repeat );
}
}
node.emit("input",{});

View File

@ -1,7 +1,7 @@
node-red-node-email
===================
<a href="http://nodered.org" target="_new">Node-RED</a> nodes to send and receive simple emails.
<a href="http://nodered.org" target="info">Node-RED</a> nodes to send and receive simple emails.
Pre-requisite
@ -9,7 +9,7 @@ Pre-requisite
You will need valid email credentials for your email server.
**Note :** Version 1.x of this node requires Node.js v6 or newer.
**Note :** Version 1.x of this node requires **Node.js v8** or newer.
Install
@ -18,10 +18,12 @@ Install
Version 0.x of this node is usually installed by default by Node-RED.
To install version 1.x you need to uninstall the existing version.
sudo npm uninstall -g node-red-node-email
cd /usr/lib/node_modules/node-red
sudo npm uninstall --unsafe-perm node-red-node-email
Then run the following command in your Node-RED user directory - typically `~/.node-red`
cd ~/.node-red
npm i node-red-node-email
**Note :** this installs the new version locally rather than globally. This can then be managed by the palette manager.

View File

@ -13,6 +13,7 @@
"folder": "Folder",
"protocol": "Protocol",
"useSSL": "Use SSL?",
"useTLS": "Use TLS?",
"disposition": "Disposition",
"none": "None",
"read": "Mark Read",

View File

@ -1,11 +1,11 @@
{
"name": "node-red-node-email",
"version": "1.0.0",
"version": "1.0.4",
"description": "Node-RED nodes to send and receive simple emails",
"dependencies": {
"imap": "^0.8.19",
"mailparser": "^0.6.2",
"nodemailer": "^4.6.4",
"mailparser-mit": "^0.6.2",
"nodemailer": "^4.6.8",
"poplib": "^0.1.7"
},
"repository": {
@ -30,6 +30,6 @@
"url": "http://nodered.org"
},
"engines": {
"node": ">=6.0.0"
"node": ">=8.0.0"
}
}

View File

@ -22,7 +22,7 @@ module.exports = function(RED) {
var req = request(node.url, {timeout:10000, pool:false});
//req.setMaxListeners(50);
req.setHeader('user-agent', 'Mozilla/5.0 (Node-RED)');
req.setHeader('accept', 'text/html,application/xhtml+xml');
req.setHeader('accept', 'application/rss+xml,text/html,application/xhtml+xml');
var feedparser = new FeedParser();

View File

@ -1,10 +1,10 @@
{
"name": "node-red-node-feedparser",
"version": "0.1.13",
"version": "0.1.14",
"description": "A Node-RED node to get RSS Atom feeds.",
"dependencies": {
"feedparser": "^2.2.9",
"request": "^2.83.0"
"request": "^2.88.0"
},
"repository": {
"type": "git",

View File

@ -1,5 +1,5 @@
<script type="text/x-red" data-template-name="notify">
<script type="text/x-red" data-template-name="nnotify">
<div class="form-row">
<label for="node-input-title"><i class="fa fa-flag"></i> Title</label>
<input type="text" id="node-input-title" placeholder="Node-RED">
@ -10,15 +10,15 @@
</div>
</script>
<script type="text/x-red" data-help-name="notify">
<p>Uses Growl to provide a desktop popup containing the <code>msg.payload</code>. Only useful on the local machine.</p>
<p>Optionally uses <code>msg.topic</code> as the title.</p>
<p>Uses Growl so should work cross platform but will need pre-reqs installed... see <i><a href="https://npmjs.org/package/growl" target="_new">this link.</a></i></p>
<p>If installing on Windows you MUST read the install instructions ... especially the bit about adding growlnotify to your path... or it WILL NOT work.</p>
<script type="text/x-red" data-help-name="nnotify">
<p>Uses node-notifier to provide a desktop popup containing the <code>msg.payload</code>. Only useful on the local machine.</p>
<p>Optionally uses <code>msg.topic</code> as the title, and <code>msg.icon</code> as the full path to an icon file to display.</p>
<p>Uses node-notifier so should work cross platform but may need to intall pre-reqs... see <i><a href="https://www.npmjs.com/package/node-notifier" target="_new">this link.</a></i></p>
<p>If installing on Windows you MUST read the install instructions... or it WILL NOT work.</p>
</script>
<script type="text/javascript">
RED.nodes.registerType('notify',{
RED.nodes.registerType('nnotify',{
category: 'output',
defaults: {
title: {value:""},
@ -29,6 +29,7 @@
outputs:0,
icon: "alert.png",
align: "right",
paletteLabel: "notify",
label: function() {
return this.name||this.title||"notify";
},

View File

@ -1,26 +1,35 @@
module.exports = function(RED) {
"use strict";
var growl = require('growl');
var imagefile = process.env.NODE_RED_HOME+"/public/node-red.png";
var notifier = require('node-notifier');
var path = require('path');
var fs = require('fs');
var image = path.join(__dirname, "/node-red.png");
function NotifyNode(n) {
RED.nodes.createNode(this,n);
this.title = n.title;
var node = this;
node.on("input",function(msg) {
var titl = node.title || msg.topic;
if (typeof(msg.payload) == 'object') {
var title = node.title || msg.topic;
if (typeof msg.payload === 'object') {
msg.payload = JSON.stringify(msg.payload);
}
if (typeof(titl) != 'undefined') {
growl(msg.payload, { title: titl, image: imagefile });
var icon = image;
if (msg.icon) {
if (fs.existsSync(msg.icon)) { icon = msg.icon; }
else { node.error("Bad Icon file: "+msg.icon,msg); }
}
var icon = msg.icon || image;
if (typeof(title) !== 'undefined') {
notifier.notify({ message:msg.payload, title:title, icon:icon });
}
else {
growl(msg.payload, { image: imagefile });
notifier.notify({ message:msg.payload, icon:imagefile });
}
});
}
RED.nodes.registerType("notify",NotifyNode);
RED.nodes.registerType("nnotify",NotifyNode);
}

BIN
social/notify/node-red.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1019 B

View File

@ -1,17 +1,17 @@
{
"name" : "node-red-node-notify",
"version" : "0.0.5",
"version" : "0.1.1",
"description" : "A Node-RED node to send local popup Notify alerts",
"dependencies" : {
"growl" : "1.8.1"
"node-notifier" : "5.2.1"
},
"repository" : {
"type":"git",
"url":"https://github.com/node-red/node-red-nodes.git",
"path":"/tree/master/social/growl"
"path":"/tree/master/social/notify"
},
"license": "Apache-2.0",
"keywords": [ "node-red", "growl", "notify"],
"keywords": [ "node-red", "notify", "growl"],
"node-red" : {
"nodes" : {
"notify": "57-notify.js"

View File

@ -1,9 +1,9 @@
{
"name" : "node-red-node-pushbullet",
"version" : "0.0.13",
"version" : "0.0.14",
"description" : "A Node-RED node to send alerts via Pushbullet",
"dependencies" : {
"pushbullet": "~2.2.0",
"pushbullet": "^2.3.0",
"when": "^3.7.8"
},
"repository" : {

View File

@ -73,10 +73,15 @@
</script>
<script type="text/x-red" data-help-name="pushover">
<p>Uses Pushover to push the <code>msg.payload</code> to a device that has the Pushover app installed.</p>
<p>Optionally uses <code>msg.topic</code> to set the title, <code>msg.device</code> to set the device,
<code>msg.priority</code> to set the priority, <code>msg.url</code> to add a web address and <code>msg.url_title</code>
to add a url title if not already set in the properties.</p>
<p>Uses Pushover to push the msg.payload to a device that has the Pushover app installed.</p>
<br>
<p>Optionally uses msg.topic to set the configuration:</p>
<p><code>msg.topic</code>: set the title</p>
<p><code>msg.device</code>: set the device</p>
<p><code>msg.priority</code>: set the priority</p>
<p><code>msg.url</code>: to add a web address</p>
<p><code>msg.url_title</code>: to add a url title if not already set in the properties</p>
<p><code>msg.sound</code>: set the notification sound, <i><a href="https://pushover.net/api#sounds" target="_new">see the available options</a></i></p>
<p>Uses Pushover. See <i><a href="https://pushover.net" target="_new">this link</a></i> for more details.</p>
</script>

View File

@ -16,12 +16,14 @@ Usage
Uses Pushover to push the `msg.payload` to a device that has the Pushover app installed.
Optionally uses `msg.topic` to set the title, `msg.device` to set the device
and `msg.priority` to set the priority, if not already set in the properties.
Optionally uses `msg.topic` to set the title, `msg.device` to set the device,
`msg.priority` to set the priority, `msg.url` to add a web address and `msg.url_title`
to add a url title - if not already set in the properties.
Optionally uses `msg.topic` to set the configuration, if not already set in the properties:
- `msg.device`: to set the device
- `msg.priority`: to set the priority
- `msg.topic`: to set the title
- `msg.url`: to add a web address
- `msg.url_title`: to add a url title
- `msg.sound`: to set the alert sound, see the [available options](https://pushover.net/api#sounds)
The User-key and API-token are stored in a separate credentials file.

View File

@ -1,6 +1,6 @@
{
"name" : "node-red-node-pushover",
"version" : "0.0.12",
"version" : "0.0.13",
"description" : "A Node-RED node to send alerts via Pushover",
"dependencies" : {
"pushover-notifications" : "~0.2.4"

View File

@ -25,6 +25,8 @@ By it's very nature it is SQL injection... so *be careful* out there...
Typically the returned payload will be an array of the result rows, (or an error).
You can load sqlite extensions by inputting a <code>msg.extension</code> property containing the full path and filename.
The reconnect timeout in milliseconds can be changed by adding a line to **settings.js**
sqliteReconnectTime: 20000,

30
storage/sqlite/ext/half.c Normal file
View File

@ -0,0 +1,30 @@
/* Add your header comment here */
#include <sqlite3ext.h>
SQLITE_EXTENSION_INIT1
/*
** The half() SQL function returns half of its input value.
*/
static void halfFunc(
sqlite3_context *context,
int argc,
sqlite3_value **argv
){
sqlite3_result_double(context, 0.5*sqlite3_value_double(argv[0]));
}
/* SQLite invokes this routine once when it loads the extension.
** Create new functions, collating sequences, and virtual table
** modules here. This is usually the only exported symbol in
** the shared library.
*/
int sqlite3_extension_init(
sqlite3 *db,
char **pzErrMsg,
const sqlite3_api_routines *pApi
){
SQLITE_EXTENSION_INIT2(pApi)
sqlite3_create_function(db, "half", 1, SQLITE_ANY, 0, halfFunc, 0, 0);
return 0;
}

BIN
storage/sqlite/ext/half.dylib Executable file

Binary file not shown.

View File

@ -1,6 +1,6 @@
{
"name": "node-red-node-sqlite",
"version": "0.3.2",
"version": "0.3.5",
"description": "A sqlite node for Node-RED",
"dependencies": {
"sqlite3": "^4.0.2"

View File

@ -77,6 +77,8 @@
be sure to include $ on the parameter object key.</p>
<p>Using any SQL Query, the result is returned in <code>msg.payload</code></p>
<p>Typically the returned payload will be an array of the result rows, (or an error).</p>
<p>You can load sqlite extensions by inputting a <code>msg.extension</code> property containing the full
path and filename.</p>
<p>The reconnect timeout in milliseconds can be changed by adding a line to <b>settings.js</b>
<pre>sqliteReconnectTime: 20000,</pre></p>
</script>

View File

@ -43,89 +43,107 @@ module.exports = function(RED) {
var node = this;
node.status({});
if (this.mydbConfig) {
this.mydbConfig.doConnect();
if (node.mydbConfig) {
node.mydbConfig.doConnect();
node.status({fill:"green",shape:"dot",text:this.mydbConfig.mod});
var bind = [];
node.on("input", function(msg) {
if (this.sqlquery == "msg.topic"){
var doQuery = function(msg) {
if (node.sqlquery == "msg.topic"){
if (typeof msg.topic === 'string') {
bind = Array.isArray(msg.payload) ? msg.payload : [];
node.mydbConfig.db.all(msg.topic, bind, function(err, row) {
if (err) { node.error(err,msg); }
else {
msg.payload = row;
node.send(msg);
}
});
if (msg.topic.length > 0) {
bind = Array.isArray(msg.payload) ? msg.payload : [];
node.mydbConfig.db.all(msg.topic, bind, function(err, row) {
if (err) { node.error(err,msg); }
else {
msg.payload = row;
node.send(msg);
}
});
}
}
else {
node.error("msg.topic : the query is not defined as a string",msg);
node.status({fill:"red",shape:"dot",text:"msg.topic error"});
}
}
if (this.sqlquery == "batch") {
if (node.sqlquery == "batch") {
if (typeof msg.topic === 'string') {
node.mydbConfig.db.exec(msg.topic, function(err) {
if (err) { node.error(err,msg);}
else {
msg.payload = [];
node.send(msg);
}
});
if (msg.topic.length > 0) {
node.mydbConfig.db.exec(msg.topic, function(err) {
if (err) { node.error(err,msg);}
else {
msg.payload = [];
node.send(msg);
}
});
}
}
else {
node.error("msg.topic : the query is not defined as string", msg);
node.status({fill:"red", shape:"dot",text:"msg.topic error"});
}
}
if (this.sqlquery == "fixed"){
if (typeof this.sql === 'string'){
bind = Array.isArray(msg.payload) ? msg.payload : [];
node.mydbConfig.db.all(this.sql, bind, function(err, row) {
if (err) { node.error(err,msg); }
else {
msg.payload = row;
node.send(msg);
}
});
if (node.sqlquery == "fixed"){
if (typeof node.sql === 'string') {
if (node.sql.length > 0) {
node.mydbConfig.db.all(node.sql, bind, function(err, row) {
if (err) { node.error(err,msg); }
else {
msg.payload = row;
node.send(msg);
}
});
}
}
else{
if (this.sql === null || this.sql == ""){
if (node.sql === null || node.sql == "") {
node.error("SQL statement config not set up",msg);
node.status({fill:"red",shape:"dot",text:"SQL config not set up"});
}
}
}
if (this.sqlquery == "prepared"){
if (typeof this.sql === 'string' && typeof msg.params !== "undefined" && typeof msg.params === "object"){
node.mydbConfig.db.all(this.sql, msg.params, function(err, row) {
if (err) { node.error(err,msg); }
else {
msg.payload = row;
node.send(msg);
}
});
if (node.sqlquery == "prepared"){
if (typeof node.sql === 'string' && typeof msg.params !== "undefined" && typeof msg.params === "object") {
if (node.sql.length > 0) {
node.mydbConfig.db.all(node.sql, msg.params, function(err, row) {
if (err) { node.error(err,msg); }
else {
msg.payload = row;
node.send(msg);
}
});
}
}
else{
if (this.sql === null || this.sql == ""){
else {
if (node.sql === null || node.sql == "") {
node.error("Prepared statement config not set up",msg);
node.status({fill:"red",shape:"dot",text:"Prepared statement not set up"});
}
if (typeof msg.params == "undefined"){
if (typeof msg.params == "undefined") {
node.error("msg.params not passed");
node.status({fill:"red",shape:"dot",text:"msg.params not defined"});
}
else if (typeof msg.params != "object"){
else if (typeof msg.params != "object") {
node.error("msg.params not an object");
node.status({fill:"red",shape:"dot",text:"msg.params not an object"});
}
}
}
}
node.on("input", function(msg) {
if (msg.hasOwnProperty("extension")) {
node.mydbConfig.db.loadExtension(msg.extension, function(err) {
if (err) { node.error(err,msg); }
else { doQuery(msg); }
});
}
else { doQuery(msg); }
});
}
else {
this.error("Sqlite database not configured");
node.error("Sqlite database not configured");
}
}
RED.nodes.registerType("sqlite",SqliteNodeIn);

View File

@ -11,12 +11,17 @@
</div>
<div class="form-row">
<label>&nbsp;</label>
<input type="checkbox" id="node-input-cr" style="display: inline-block; width: auto; vertical-align: top;">
<input type="checkbox" id="node-input-autorun" style="display:inline-block; width: auto; vertical-align:baseline;">
<label for="node-input-autorun" style="width: 70%;">Auto-start daemon on deploy ?</label>
</div>
<div class="form-row">
<label>&nbsp;</label>
<input type="checkbox" id="node-input-cr" style="display:inline-block; width:auto; vertical-align:baseline;">
<label for="node-input-cr" style="width: 70%;">Add [enter] to every message sent ?</label>
</div>
<div class="form-row">
<label>&nbsp;</label>
<input type="checkbox" id="node-input-redo" style="display: inline-block; width: auto; vertical-align: top;">
<input type="checkbox" id="node-input-redo" style="display:inline-block; width:auto; vertical-align:baseline;">
<label for="node-input-redo" style="width: 70%;">Relaunch command on exit or error ?</label>
</div>
<div class="form-row">
@ -62,6 +67,7 @@
name: {value:""},
command: {value:"",required:true},
args: {value:""},
autorun: {value:true},
cr: {value:false},
redo: {value:true},
op: {value:"string"},
@ -77,6 +83,9 @@
},
labelStyle: function() {
return this.name?"node_label_italic":"";
},
oneditprepare: function() {
if (this.autorun === undefined) { $("#node-input-autorun").prop('checked', true); }
}
});
</script>

View File

@ -12,6 +12,8 @@ module.exports = function(RED) {
this.redo = n.redo;
this.running = false;
this.closer = n.closer || "SIGKILL";
this.autorun = true;
if (n.autorun === false) { this.autorun = false; }
var node = this;
function inputlistener(msg) {

View File

@ -1,6 +1,6 @@
{
"name" : "node-red-node-daemon",
"version" : "0.0.21",
"version" : "0.0.22",
"description" : "A Node-RED node that runs and monitors a long running system command.",
"dependencies" : {
},