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

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: include:
- node_js: 8 - node_js: 8
- node_js: 10 - node_js: 10
- node_js: 6
- python: 2.7 - python: 2.7
language: python language: python
before_script: pip install flake8 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` Run the following command in your Node-RED user directory - typically `~/.node-red`
npm install node-red-node-random npm install node-red-node-random
Usage Usage
----- -----
A simple node to generate a random number when triggered. 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**. **Note:** This generates **numbers**.

View File

@ -1,6 +1,6 @@
{ {
"name" : "node-red-node-random", "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.", "description" : "A Node-RED node that when triggered generates a random number between two values.",
"dependencies" : { "dependencies" : {
}, },

View File

@ -28,8 +28,10 @@
70% 70%
<script type="text/x-red" data-help-name="random"> <script type="text/x-red" data-help-name="random">
<p>Generates a random number between a low and high value.</p> <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 an integer it can <i>include</i> both the low and high values.
<p>If you return a floating point value it will be <i>between</i> the low and high values.</p> <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>
<script type="text/javascript"> <script type="text/javascript">

View File

@ -11,10 +11,10 @@ module.exports = function(RED) {
this.on("input", function(msg) { this.on("input", function(msg) {
var value; var value;
if (node.inte == "true" || node.inte === true) { 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 { 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); RED.util.setMessageProperty(msg,node.property,value);
node.send(msg); 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. 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). 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. **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", "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", "description" : "A Node-RED node to read from the MCP3008 Analogue to Digital Converter",
"dependencies" : { "dependencies" : {
"mcp-spi-adc": "^1.0.0" "mcp-spi-adc": "^2.0.3"
}, },
"repository" : { "repository" : {
"type":"git", "type":"git",

View File

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

View File

@ -19,14 +19,15 @@ module.exports = function(RED) {
this.pin = n.pin || 0; this.pin = n.pin || 0;
this.interval = n.interval || 1000; this.interval = n.interval || 1000;
this.dnum = parseInt(n.dnum || 0); this.dnum = parseInt(n.dnum || 0);
this.bus = parseInt(n.bus || 0);
this.dev = n.dev || "3008"; this.dev = n.dev || "3008";
var node = this; var node = this;
var cb = function (err) { if (err) { node.error("Error: "+err); } }; 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)); var chans = parseInt(this.dev.substr(3));
try { try {
fs.statSync("/dev/spidev0."+node.dnum); fs.statSync("/dev/spidev"+node.bus+"."+node.dnum);
if (mcp3xxx.length === 0) { if (mcp3xxx.length === 0) {
for (var i=0; i<chans; i++) { for (var i=0; i<chans; i++) {
if (node.dev === "3002") { mcp3xxx.push(mcpadc.openMcp3002(i, opt, cb)); } 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")); RED.log.warn("rpi-neopixels : "+RED._("node-red:rpi-gpio.errors.ignorenode"));
allOK = false; 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"); RED.log.warn("rpi-neopixels : Can't find neopixel python library");
allOK = false; allOK = false;
} }

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

@ -1,6 +1,6 @@
{ {
"name" : "node-red-node-pi-neopixel", "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.", "description" : "A Node-RED node to output to a neopixel (ws2812) string of LEDS from a Raspberry Pi.",
"dependencies" : { "dependencies" : {
}, },

View File

@ -2,7 +2,7 @@
module.exports = function(RED) { module.exports = function(RED) {
"use strict"; "use strict";
var wol = require('wake_on_lan'); 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) { function WOLnode(n) {
RED.nodes.createNode(this,n); RED.nodes.createNode(this,n);
@ -17,9 +17,13 @@ module.exports = function(RED) {
if (chk.test(mac)) { if (chk.test(mac)) {
try { try {
wol.wake(mac, {address: host}, function(error) { 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) { else if (RED.settings.verbose) {
node.log("sent WOL magic packet"); 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"); } else { node.warn("WOL: no mac address specified"); }
}); });
this.on("close", function () {
node.status({});
})
} }
RED.nodes.registerType("wake on lan",WOLnode); RED.nodes.registerType("wake on lan",WOLnode);
} }

View File

@ -1,9 +1,9 @@
{ {
"name" : "node-red-node-wol", "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", "description" : "A Node-RED node to send Wake-On-LAN (WOL) magic packets",
"dependencies" : { "dependencies" : {
"wake_on_lan" : "0.0.4" "wake_on_lan" : "1.0.0"
}, },
"repository" : { "repository" : {
"type":"git", "type":"git",

2857
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

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

View File

@ -49,6 +49,10 @@
<input type="password" id="node-input-password"> <input type="password" id="node-input-password">
</div> </div>
<br/> <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"> <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> <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"> <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 <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> 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 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> <p>Note: uses SMTP with SSL to port 465.</p>
</script> </script>
@ -81,6 +86,7 @@
server: {value:"smtp.gmail.com",required:true}, server: {value:"smtp.gmail.com",required:true},
port: {value:"465",required:true}, port: {value:"465",required:true},
secure: {value: true}, secure: {value: true},
tls: {value: true},
name: {value:""}, name: {value:""},
dname: {value:""} dname: {value:""}
}, },

View File

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

View File

@ -1,7 +1,7 @@
node-red-node-email 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 Pre-requisite
@ -9,7 +9,7 @@ Pre-requisite
You will need valid email credentials for your email server. 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 Install
@ -18,10 +18,12 @@ Install
Version 0.x of this node is usually installed by default by Node-RED. 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. 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` Then run the following command in your Node-RED user directory - typically `~/.node-red`
cd ~/.node-red
npm i node-red-node-email 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. **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", "folder": "Folder",
"protocol": "Protocol", "protocol": "Protocol",
"useSSL": "Use SSL?", "useSSL": "Use SSL?",
"useTLS": "Use TLS?",
"disposition": "Disposition", "disposition": "Disposition",
"none": "None", "none": "None",
"read": "Mark Read", "read": "Mark Read",

View File

@ -1,11 +1,11 @@
{ {
"name": "node-red-node-email", "name": "node-red-node-email",
"version": "1.0.0", "version": "1.0.4",
"description": "Node-RED nodes to send and receive simple emails", "description": "Node-RED nodes to send and receive simple emails",
"dependencies": { "dependencies": {
"imap": "^0.8.19", "imap": "^0.8.19",
"mailparser": "^0.6.2", "mailparser-mit": "^0.6.2",
"nodemailer": "^4.6.4", "nodemailer": "^4.6.8",
"poplib": "^0.1.7" "poplib": "^0.1.7"
}, },
"repository": { "repository": {
@ -30,6 +30,6 @@
"url": "http://nodered.org" "url": "http://nodered.org"
}, },
"engines": { "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}); var req = request(node.url, {timeout:10000, pool:false});
//req.setMaxListeners(50); //req.setMaxListeners(50);
req.setHeader('user-agent', 'Mozilla/5.0 (Node-RED)'); 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(); var feedparser = new FeedParser();

View File

@ -1,10 +1,10 @@
{ {
"name": "node-red-node-feedparser", "name": "node-red-node-feedparser",
"version": "0.1.13", "version": "0.1.14",
"description": "A Node-RED node to get RSS Atom feeds.", "description": "A Node-RED node to get RSS Atom feeds.",
"dependencies": { "dependencies": {
"feedparser": "^2.2.9", "feedparser": "^2.2.9",
"request": "^2.83.0" "request": "^2.88.0"
}, },
"repository": { "repository": {
"type": "git", "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"> <div class="form-row">
<label for="node-input-title"><i class="fa fa-flag"></i> Title</label> <label for="node-input-title"><i class="fa fa-flag"></i> Title</label>
<input type="text" id="node-input-title" placeholder="Node-RED"> <input type="text" id="node-input-title" placeholder="Node-RED">
@ -10,15 +10,15 @@
</div> </div>
</script> </script>
<script type="text/x-red" data-help-name="notify"> <script type="text/x-red" data-help-name="nnotify">
<p>Uses Growl to provide a desktop popup containing the <code>msg.payload</code>. Only useful on the local machine.</p> <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.</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 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>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 ... especially the bit about adding growlnotify to your path... or it WILL NOT work.</p> <p>If installing on Windows you MUST read the install instructions... or it WILL NOT work.</p>
</script> </script>
<script type="text/javascript"> <script type="text/javascript">
RED.nodes.registerType('notify',{ RED.nodes.registerType('nnotify',{
category: 'output', category: 'output',
defaults: { defaults: {
title: {value:""}, title: {value:""},
@ -29,6 +29,7 @@
outputs:0, outputs:0,
icon: "alert.png", icon: "alert.png",
align: "right", align: "right",
paletteLabel: "notify",
label: function() { label: function() {
return this.name||this.title||"notify"; return this.name||this.title||"notify";
}, },

View File

@ -1,26 +1,35 @@
module.exports = function(RED) { module.exports = function(RED) {
"use strict"; "use strict";
var growl = require('growl'); var notifier = require('node-notifier');
var imagefile = process.env.NODE_RED_HOME+"/public/node-red.png"; var path = require('path');
var fs = require('fs');
var image = path.join(__dirname, "/node-red.png");
function NotifyNode(n) { function NotifyNode(n) {
RED.nodes.createNode(this,n); RED.nodes.createNode(this,n);
this.title = n.title; this.title = n.title;
var node = this; var node = this;
node.on("input",function(msg) { node.on("input",function(msg) {
var titl = node.title || msg.topic; var title = node.title || msg.topic;
if (typeof(msg.payload) == 'object') { if (typeof msg.payload === 'object') {
msg.payload = JSON.stringify(msg.payload); msg.payload = JSON.stringify(msg.payload);
} }
if (typeof(titl) != 'undefined') { var icon = image;
growl(msg.payload, { title: titl, image: imagefile }); 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 { 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", "name" : "node-red-node-notify",
"version" : "0.0.5", "version" : "0.1.1",
"description" : "A Node-RED node to send local popup Notify alerts", "description" : "A Node-RED node to send local popup Notify alerts",
"dependencies" : { "dependencies" : {
"growl" : "1.8.1" "node-notifier" : "5.2.1"
}, },
"repository" : { "repository" : {
"type":"git", "type":"git",
"url":"https://github.com/node-red/node-red-nodes.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", "license": "Apache-2.0",
"keywords": [ "node-red", "growl", "notify"], "keywords": [ "node-red", "notify", "growl"],
"node-red" : { "node-red" : {
"nodes" : { "nodes" : {
"notify": "57-notify.js" "notify": "57-notify.js"

View File

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

View File

@ -73,10 +73,15 @@
</script> </script>
<script type="text/x-red" data-help-name="pushover"> <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>Uses Pushover to push the msg.payload 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, <br>
<code>msg.priority</code> to set the priority, <code>msg.url</code> to add a web address and <code>msg.url_title</code> <p>Optionally uses msg.topic to set the configuration:</p>
to add a url title if not already set in the properties.</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> <p>Uses Pushover. See <i><a href="https://pushover.net" target="_new">this link</a></i> for more details.</p>
</script> </script>

View File

@ -16,12 +16,14 @@ Usage
Uses Pushover to push the `msg.payload` to a device that has the Pushover app installed. 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, Optionally uses `msg.topic` to set the configuration, if not already set in the properties:
`msg.priority` to set the priority, `msg.url` to add a web address and `msg.url_title` - `msg.device`: to set the device
to add a url title - if not already set in the properties. - `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. The User-key and API-token are stored in a separate credentials file.

View File

@ -1,6 +1,6 @@
{ {
"name" : "node-red-node-pushover", "name" : "node-red-node-pushover",
"version" : "0.0.12", "version" : "0.0.13",
"description" : "A Node-RED node to send alerts via Pushover", "description" : "A Node-RED node to send alerts via Pushover",
"dependencies" : { "dependencies" : {
"pushover-notifications" : "~0.2.4" "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). 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** The reconnect timeout in milliseconds can be changed by adding a line to **settings.js**
sqliteReconnectTime: 20000, 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", "name": "node-red-node-sqlite",
"version": "0.3.2", "version": "0.3.5",
"description": "A sqlite node for Node-RED", "description": "A sqlite node for Node-RED",
"dependencies": { "dependencies": {
"sqlite3": "^4.0.2" "sqlite3": "^4.0.2"

View File

@ -77,6 +77,8 @@
be sure to include $ on the parameter object key.</p> 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>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>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> <p>The reconnect timeout in milliseconds can be changed by adding a line to <b>settings.js</b>
<pre>sqliteReconnectTime: 20000,</pre></p> <pre>sqliteReconnectTime: 20000,</pre></p>
</script> </script>

View File

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

View File

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

View File

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

View File

@ -1,6 +1,6 @@
{ {
"name" : "node-red-node-daemon", "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.", "description" : "A Node-RED node that runs and monitors a long running system command.",
"dependencies" : { "dependencies" : {
}, },