From 45e4c6d9d44b4e62b4be6b3e04728ebe306579f2 Mon Sep 17 00:00:00 2001
From: Schreck1985 <41887216+Schreck1985@users.noreply.github.com>
Date: Wed, 22 Aug 2018 14:57:42 +0200
Subject: [PATCH 01/24] Node red mail usetls (#480)
* Default value for tls, checking if tls is set to false
---
social/email/61-email.html | 6 ++++++
social/email/61-email.js | 7 ++++++-
social/email/locales/en-US/61-email.json | 1 +
3 files changed, 13 insertions(+), 1 deletion(-)
diff --git a/social/email/61-email.html b/social/email/61-email.html
index 0d684a43..52e4c38d 100644
--- a/social/email/61-email.html
+++ b/social/email/61-email.html
@@ -49,6 +49,10 @@
+
+
+
+
@@ -69,6 +73,7 @@
Alternatively you may provide msg.attachments
which should contain an array of one or
more attachments in nodemailer format.
If required by your recipient you may also pass in a msg.envelope
object, typically containing extra from and to properties.
+
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.
Note: uses SMTP with SSL to port 465.
@@ -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:""}
},
diff --git a/social/email/61-email.js b/social/email/61-email.js
index 92a7cdea..e3e6a0fa 100644
--- a/social/email/61-email.js
+++ b/social/email/61-email.js
@@ -30,6 +30,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 +51,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) {
diff --git a/social/email/locales/en-US/61-email.json b/social/email/locales/en-US/61-email.json
index fbe47766..d3f05375 100644
--- a/social/email/locales/en-US/61-email.json
+++ b/social/email/locales/en-US/61-email.json
@@ -13,6 +13,7 @@
"folder": "Folder",
"protocol": "Protocol",
"useSSL": "Use SSL?",
+ "useTLS": "Use TLS?",
"disposition": "Disposition",
"none": "None",
"read": "Mark Read",
From 1b0f573f4e1f9e71b91c402e2c4061478a81315f Mon Sep 17 00:00:00 2001
From: Dave Conway-Jones
Date: Wed, 22 Aug 2018 13:58:55 +0100
Subject: [PATCH 02/24] let sqlite add extensions
---
storage/sqlite/README.md | 2 ++
storage/sqlite/package.json | 2 +-
storage/sqlite/sqlite.html | 2 ++
storage/sqlite/sqlite.js | 39 ++++++++++++++++++++++++-------------
4 files changed, 30 insertions(+), 15 deletions(-)
diff --git a/storage/sqlite/README.md b/storage/sqlite/README.md
index 9d2b8d3c..ae94aee3 100644
--- a/storage/sqlite/README.md
+++ b/storage/sqlite/README.md
@@ -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 msg.extension
property containing the full path and filename.
+
The reconnect timeout in milliseconds can be changed by adding a line to **settings.js**
sqliteReconnectTime: 20000,
diff --git a/storage/sqlite/package.json b/storage/sqlite/package.json
index 7bf56945..c671502c 100644
--- a/storage/sqlite/package.json
+++ b/storage/sqlite/package.json
@@ -1,6 +1,6 @@
{
"name": "node-red-node-sqlite",
- "version": "0.3.2",
+ "version": "0.3.3",
"description": "A sqlite node for Node-RED",
"dependencies": {
"sqlite3": "^4.0.2"
diff --git a/storage/sqlite/sqlite.html b/storage/sqlite/sqlite.html
index 923f817c..28d5d966 100644
--- a/storage/sqlite/sqlite.html
+++ b/storage/sqlite/sqlite.html
@@ -77,6 +77,8 @@
be sure to include $ on the parameter object key.
Using any SQL Query, the result is returned in msg.payload
Typically the returned payload will be an array of the result rows, (or an error).
+ You can load sqlite extensions by inputting a msg.extension
property containing the full
+ path and filename.
The reconnect timeout in milliseconds can be changed by adding a line to settings.js
sqliteReconnectTime: 20000,
diff --git a/storage/sqlite/sqlite.js b/storage/sqlite/sqlite.js
index c5ec8e0b..39c0bc68 100644
--- a/storage/sqlite/sqlite.js
+++ b/storage/sqlite/sqlite.js
@@ -43,12 +43,13 @@ 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) {
@@ -64,7 +65,7 @@ module.exports = function(RED) {
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);}
@@ -79,10 +80,10 @@ module.exports = function(RED) {
node.status({fill:"red", shape:"dot",text:"msg.topic error"});
}
}
- if (this.sqlquery == "fixed"){
- if (typeof this.sql === 'string'){
+ if (node.sqlquery == "fixed"){
+ if (typeof node.sql === 'string'){
bind = Array.isArray(msg.payload) ? msg.payload : [];
- 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); }
else {
msg.payload = row;
@@ -91,15 +92,15 @@ module.exports = function(RED) {
});
}
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 (node.sqlquery == "prepared"){
+ if (typeof node.sql === 'string' && typeof msg.params !== "undefined" && typeof msg.params === "object"){
+ node.mydbConfig.db.all(node.sql, msg.params, function(err, row) {
if (err) { node.error(err,msg); }
else {
msg.payload = row;
@@ -108,7 +109,7 @@ module.exports = function(RED) {
});
}
else{
- if (this.sql === null || this.sql == ""){
+ 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"});
}
@@ -122,10 +123,20 @@ module.exports = function(RED) {
}
}
}
+ }
+
+ 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);
From 0b65cd86528993d7bcce7c20007241016744c189 Mon Sep 17 00:00:00 2001
From: Dave Conway-Jones
Date: Wed, 22 Aug 2018 23:47:03 +0100
Subject: [PATCH 03/24] sqlite - better handle extensions timing
---
storage/sqlite/package.json | 2 +-
storage/sqlite/sqlite.js | 82 ++++++++++++++++++++-----------------
2 files changed, 46 insertions(+), 38 deletions(-)
diff --git a/storage/sqlite/package.json b/storage/sqlite/package.json
index c671502c..cc31580a 100644
--- a/storage/sqlite/package.json
+++ b/storage/sqlite/package.json
@@ -1,6 +1,6 @@
{
"name": "node-red-node-sqlite",
- "version": "0.3.3",
+ "version": "0.3.4",
"description": "A sqlite node for Node-RED",
"dependencies": {
"sqlite3": "^4.0.2"
diff --git a/storage/sqlite/sqlite.js b/storage/sqlite/sqlite.js
index 39c0bc68..540e21e4 100644
--- a/storage/sqlite/sqlite.js
+++ b/storage/sqlite/sqlite.js
@@ -51,14 +51,16 @@ module.exports = function(RED) {
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);
@@ -67,13 +69,15 @@ module.exports = function(RED) {
}
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);
@@ -81,43 +85,47 @@ module.exports = function(RED) {
}
}
if (node.sqlquery == "fixed"){
- if (typeof node.sql === 'string'){
- bind = Array.isArray(msg.payload) ? msg.payload : [];
- node.mydbConfig.db.all(node.sql, bind, function(err, row) {
- if (err) { node.error(err,msg); }
- else {
- msg.payload = row;
- node.send(msg);
- }
- });
+ if (typeof node.sql === 'string') {
+ if (msg.payload && msg.payload.length > 0) {
+ bind = Array.isArray(msg.payload) ? msg.payload : [];
+ 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 (node.sql === null || node.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 (node.sqlquery == "prepared"){
- if (typeof node.sql === 'string' && typeof msg.params !== "undefined" && typeof msg.params === "object"){
- node.mydbConfig.db.all(node.sql, msg.params, function(err, row) {
- if (err) { node.error(err,msg); }
- else {
- msg.payload = row;
- node.send(msg);
- }
- });
+ 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 (node.sql === null || node.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"});
}
From 6d36f5db8a20fee08870254bbc5d0b0f29d48ef1 Mon Sep 17 00:00:00 2001
From: Dave Conway-Jones
Date: Thu, 23 Aug 2018 08:55:51 +0100
Subject: [PATCH 04/24] sqlite - add test extension - half.c
---
storage/sqlite/ext/half.c | 30 ++++++++++++++++++++++++++++++
storage/sqlite/ext/half.dylib | Bin 0 -> 4616 bytes
2 files changed, 30 insertions(+)
create mode 100644 storage/sqlite/ext/half.c
create mode 100755 storage/sqlite/ext/half.dylib
diff --git a/storage/sqlite/ext/half.c b/storage/sqlite/ext/half.c
new file mode 100644
index 00000000..5c746314
--- /dev/null
+++ b/storage/sqlite/ext/half.c
@@ -0,0 +1,30 @@
+/* Add your header comment here */
+
+#include
+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;
+}
diff --git a/storage/sqlite/ext/half.dylib b/storage/sqlite/ext/half.dylib
new file mode 100755
index 0000000000000000000000000000000000000000..50bf666d04b3878bf6bb9755ca67e970bf774dc0
GIT binary patch
literal 4616
zcmeHLO=uHA6rR}D|C%Zk6cvL6|G;c&E4CMHrI8VT5Ntsa8QLbPE6t|uCRz`LLKR%1
zP{e}=&+4(@rQQ_9suz0@@!%n#f(HdHBI3dNeVdtf4Jw{xAG~?<&HJ18W)FFJ{{7>R
zB|=1Mgb<6t_24OhOQHcgA=ZH}M}$zSD|MpFKl*j4m@S-XjF_ShT&p!o6*41*1+(gS
zldCGauiAvz`1(h+Voa-ip;TYqaTfws$Ga1)STEI1#H{g8gm`XY*mnB0L3O-I9gj7U
z46Yy{7MYEfN)?^+wv$%2lg;C-I^L9yC$&9sb&Oz0zQYYaPG?6~M?hoxZ)8BlE#HB4
z;|YCY-*UOUqap6~`*@~rvpQk@6QHxknp=3ZJZ)kX4N!C3t6
zwt?4HouBC$$R^Sk2JBuaK%0daOIEgjUy+Y?Ovjk5z^fr8miv$^z{kKOetKlu!t9rO
z0sa%MhZXb0UR-H;Io&os;q8^nM-QEfn%R}h_H(8
zu!XA0$1k{rOfIoM*oQ5!W!xkdzSVY(S!YOL2f_}79SA!Rb|CCP*nzMEVF&(~4s=WJ
zogDwrF0a;oMosrPLv&1WDoZszO?l4_U#+(Rq&NCadc{xD>wYgwV6SlvOl7HYg)gq1
z@db?@!=~>+~KR@n+<7Eq}2KIo%oeM<7{BmFH%fo_eX*-V-_gsQvWAEGQA(bdh#K
z-zUk0UhzvMU*j!?C|w)DFM3%*l2YAu|71*JmXf6-xYIItl%@9^9VI81JwU}}G6NpquVFJus>
zfU`9bapleEDVoqJfyK=E>|Q*8sgHwop}zf590oD{+jTuRwZFl}-)|0d#Pm0qFA@VA
zqCU+<(_P3_z$PC180BZB=P9O*LT~QB6&P?nLQKr}kv*FSRSm@?n^tb2*sFT+=Rjsy
zScTl6CHyJ3Pgv)AhOKOV01DSiDywazZK!Xk`RpENPk%0XcBpk%&due{w
Date: Thu, 23 Aug 2018 08:57:15 +0100
Subject: [PATCH 05/24] Daemon - allow manual start rather than always auto
to close #479
---
utility/daemon/daemon.html | 13 +++++++++++--
utility/daemon/daemon.js | 2 ++
utility/daemon/package.json | 2 +-
3 files changed, 14 insertions(+), 3 deletions(-)
diff --git a/utility/daemon/daemon.html b/utility/daemon/daemon.html
index 58bf99f6..bdd5f28d 100644
--- a/utility/daemon/daemon.html
+++ b/utility/daemon/daemon.html
@@ -11,12 +11,17 @@
-
+
+
+
+
+
+
-
+
+
+
+
+
@@ -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,
diff --git a/hardware/mcp3008/pimcp3008.js b/hardware/mcp3008/pimcp3008.js
index ee5e835f..492f8d6b 100644
--- a/hardware/mcp3008/pimcp3008.js
+++ b/hardware/mcp3008/pimcp3008.js
@@ -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
Date: Sun, 23 Sep 2018 20:32:11 +0100
Subject: [PATCH 21/24] check for correct version of neopixel library
---
hardware/neopixel/neopixel.js | 2 +-
hardware/neopixel/package.json | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
mode change 100755 => 100644 hardware/neopixel/neopixel.js
diff --git a/hardware/neopixel/neopixel.js b/hardware/neopixel/neopixel.js
old mode 100755
new mode 100644
index c8781367..815326e3
--- a/hardware/neopixel/neopixel.js
+++ b/hardware/neopixel/neopixel.js
@@ -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;
}
diff --git a/hardware/neopixel/package.json b/hardware/neopixel/package.json
index eca2cf6b..a9bf250a 100644
--- a/hardware/neopixel/package.json
+++ b/hardware/neopixel/package.json
@@ -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" : {
},
From d32f11910bc28a77557755c9f9544f3dedd7dd39 Mon Sep 17 00:00:00 2001
From: Dave Conway-Jones
Date: Mon, 24 Sep 2018 19:40:33 +0100
Subject: [PATCH 22/24] clarify random node info language
---
function/random/package.json | 2 +-
function/random/random.html | 6 ++++--
function/random/random.js | 4 ++--
3 files changed, 7 insertions(+), 5 deletions(-)
diff --git a/function/random/package.json b/function/random/package.json
index 4898c021..ee980c8d 100644
--- a/function/random/package.json
+++ b/function/random/package.json
@@ -1,6 +1,6 @@
{
"name" : "node-red-node-random",
- "version" : "0.1.0",
+ "version" : "0.1.1",
"description" : "A Node-RED node that when triggered generates a random number between two values.",
"dependencies" : {
},
diff --git a/function/random/random.html b/function/random/random.html
index 0f2c3824..3e103aef 100644
--- a/function/random/random.html
+++ b/function/random/random.html
@@ -28,8 +28,10 @@
70%