From 4b99a5f4d13041510fe0e8bcb98b33fa02a42456 Mon Sep 17 00:00:00 2001
From: andres <999999999e9@gmail.com>
Date: Sat, 24 Oct 2020 11:07:16 +1000
Subject: [PATCH 01/86] Added support for V3
Added support for version 3.
All the existing issues with v1 and v2c are also with v3 e.g.
https://github.com/node-red/node-red-nodes/issues/679
snmp walker will not return more than 1000 objects, all following objects cannot be accessed
Incorrect encryption (privacy) passphrase gives a timeout and not an error (protocol limitation?)
Incorrect community string gives a timeout and not an error (protocol limitation?)
Changes to the node are made with following details:
Node-red v1.2.2
Node.js v12.6.0
Windows_NT 10.0.19841 x64 LE
---
io/snmp/README.md | 82 +++++++++--
io/snmp/package.json | 7 +-
io/snmp/snmp.html | 328 +++++++++++++++++++++++++++++++++++++------
io/snmp/snmp.js | 207 ++++++++++++++++++++++++---
4 files changed, 545 insertions(+), 79 deletions(-)
diff --git a/io/snmp/README.md b/io/snmp/README.md
index 5067b11b..8caa1b28 100644
--- a/io/snmp/README.md
+++ b/io/snmp/README.md
@@ -18,9 +18,15 @@ Usage
SNMP oids fetcher. Can fetch a single or comma separated list of oids. Triggered by any input.
-`msg.host` may contain the host.
+`msg.host` may contain the host including the port.
-`msg.community` may contain the community.
+`msg.community` may contain the community. (v1 and v2c only)
+
+`msg.username` may contain the username. (v3 only)
+
+`msg.authkey` may contain the digest security key. (v3 only)
+
+`msg.privkey` may contain the encryption security key. (v3 only)
`msg.oid` may contain a comma separated list of oids to search for. (no spaces)
@@ -28,6 +34,12 @@ The host configured in the edit config will override `msg.host`. Leave blank if
The community configured in the edit config will override `msg.community`. Leave blank if you want to use `msg.community` to provide input.
+The username configured in the edit config will override `msg.username`. Leave blank if you want to use `msg.username` to provide input.
+
+The digest security key configured in the edit config will override `msg.authkey`. Leave blank if you want to use `msg.authkey` to provide input.
+
+The encryption security key configured in the edit config will override `msg.privkey`. Leave blank if you want to use `msg.privkey` to provide input.
+
The oids configured in the edit config will override `msg.oid`. Leave blank if you
want to use `msg.oid` to provide input.
@@ -38,9 +50,15 @@ Values depends on the oids being requested.
SNMP sets the value of one or more OIDs.
-`msg.host` may contain the host.
+`msg.host` may contain the host including the port.
-`msg.community` may contain the community.
+`msg.community` may contain the community. (v1 and v2c only)
+
+`msg.username` may contain the username. (v3 only)
+
+`msg.authkey` may contain the digest security key. (v3 only)
+
+`msg.privkey` may contain the encryption security key. (v3 only)
`msg.varbinds` may contain an array of varbind JSON objects e.g.:
```
@@ -81,6 +99,12 @@ The host configured in the edit config will override `msg.host`. Leave blank if
The community configured in the edit config will override `msg.community`. Leave blank if you want to use `msg.community` to provide input.
+The username configured in the edit config will override `msg.username`. Leave blank if you want to use `msg.username` to provide input.
+
+The digest security key configured in the edit config will override `msg.authkey`. Leave blank if you want to use `msg.authkey` to provide input.
+
+The encryption security key configured in the edit config will override `msg.privkey`. Leave blank if you want to use `msg.privkey` to provide input.
+
The varbinds configured in the edit config will override `msg.varbinds`. Leave blank if you want to use `msg.varbinds` to provide input.
@@ -89,16 +113,28 @@ The varbinds configured in the edit config will override `msg.varbinds`. Leave b
Simple SNMP table oid fetcher. Triggered by any input.
-`msg.host` may contain the host.
+`msg.host` may contain the host including the port.
-`msg.community` may contain the community.
+`msg.community` may contain the community. (v1 and v2c only)
-`msg.oid` may contain the oid of a single table to search for.
+`msg.username` may contain the username. (v3 only)
+
+`msg.authkey` may contain the digest security key. (v3 only)
+
+`msg.privkey` may contain the encryption security key. (v3 only)
+
+`msg.oid` may contain a comma separated list of oids to search for. (no spaces)
The host configured in the edit config will override `msg.host`. Leave blank if you want to use `msg.host` to provide input.
The community configured in the edit config will override `msg.community`. Leave blank if you want to use `msg.community` to provide input.
+The username configured in the edit config will override `msg.username`. Leave blank if you want to use `msg.username` to provide input.
+
+The digest security key configured in the edit config will override `msg.authkey`. Leave blank if you want to use `msg.authkey` to provide input.
+
+The encryption security key configured in the edit config will override `msg.privkey`. Leave blank if you want to use `msg.privkey` to provide input.
+
The oid configured in the edit config will override `msg.oid`. Leave blank if you
want to use `msg.oid` to provide input.
@@ -109,9 +145,15 @@ Values depends on the oids being requested.
Simple SNMP oid subtree fetcher. Triggered by any input. Reads from OID specified and any below it.
-`msg.host` may contain the host.
+`msg.host` may contain the host including the port.
-`msg.community` may contain the community.
+`msg.community` may contain the community. (v1 and v2c only)
+
+`msg.username` may contain the username. (v3 only)
+
+`msg.authkey` may contain the digest security key. (v3 only)
+
+`msg.privkey` may contain the encryption security key. (v3 only)
`msg.oid` may contain the oid of a single table to search for.
@@ -119,6 +161,12 @@ The host configured in the edit config will override `msg.host`. Leave blank if
The community configured in the edit config will override `msg.community`. Leave blank if you want to use `msg.community` to provide input.
+The username configured in the edit config will override `msg.username`. Leave blank if you want to use `msg.username` to provide input.
+
+The digest security key configured in the edit config will override `msg.authkey`. Leave blank if you want to use `msg.authkey` to provide input.
+
+The encryption security key configured in the edit config will override `msg.privkey`. Leave blank if you want to use `msg.privkey` to provide input.
+
The oid configured in the edit config will override `msg.oid`. Leave blank if you
want to use `msg.oid` to provide input.
@@ -129,9 +177,15 @@ Values depends on the oids being requested.
Simple SNMP oid walker fetcher. Triggered by any input. Reads from OID specified to the end of the table.
-`msg.host` may contain the host.
+`msg.host` may contain the host including the port.
-`msg.community` may contain the community.
+`msg.community` may contain the community. (v1 and v2c only)
+
+`msg.username` may contain the username. (v3 only)
+
+`msg.authkey` may contain the digest security key. (v3 only)
+
+`msg.privkey` may contain the encryption security key. (v3 only)
`msg.oid` may contain the oid of a single table to search for.
@@ -139,6 +193,12 @@ The host configured in the edit config will override `msg.host`. Leave blank if
The community configured in the edit config will override `msg.community`. Leave blank if you want to use `msg.community` to provide input.
+The username configured in the edit config will override `msg.username`. Leave blank if you want to use `msg.username` to provide input.
+
+The digest security key configured in the edit config will override `msg.authkey`. Leave blank if you want to use `msg.authkey` to provide input.
+
+The encryption security key configured in the edit config will override `msg.privkey`. Leave blank if you want to use `msg.privkey` to provide input.
+
The oid configured in the edit config will override `msg.oid`. Leave blank if you
want to use `msg.oid` to provide input.
diff --git a/io/snmp/package.json b/io/snmp/package.json
index c2c118f7..f812391e 100644
--- a/io/snmp/package.json
+++ b/io/snmp/package.json
@@ -1,9 +1,9 @@
{
"name" : "node-red-node-snmp",
- "version" : "0.0.25",
+ "version" : "0.0.26",
"description" : "A Node-RED node that looks for SNMP oids.",
"dependencies" : {
- "net-snmp" : "1.2.4"
+ "net-snmp" : "2.9.6"
},
"repository" : {
"type":"git",
@@ -23,6 +23,7 @@
},
"contributors": [
{ "name": "Mika Karaila" },
- { "name": "Bryan Malyn" }
+ { "name": "Bryan Malyn" },
+ { "name": "Andres" }
]
}
diff --git a/io/snmp/snmp.html b/io/snmp/snmp.html
index 4cd13ef8..0df25340 100644
--- a/io/snmp/snmp.html
+++ b/io/snmp/snmp.html
@@ -3,19 +3,56 @@
-
-
-
-
Timeout
S
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Priv.Prot.
+
+
+
+
+
+
+
+
+
+
+
@@ -31,6 +68,9 @@
Simple SNMP oid or oid list fetcher. Triggered by any input.
msg.host may contain the host.
msg.community may contain the community.
+
msg.username may contain the username.
+
msg.authkey may contain the digest security key.
+
msg.privkey may contain the encryption security key.
msg.oid may contain a comma separated list of oids to request. (no spaces)
When Secure connection is checked, the connection will use TLS.
If not it is still possible to upgrade clear text socket to TLS socket by checking Start TLS.
- If you do no specify your own certificate (path to file) then a pregenerated self-signed certificate is used. Any respectful client refuses to accept such certificate.
+ In most cases when using port 465, check Secure connection. For port 587 or 25 keep it disabled, use Start TLS instead.
+
If you do no specify your own certificate (path to file) then a pregenerated self-signed certificate is used. Any respectful client refuses to accept such certificate.
Authentication
Authentication can be enabled (PLAIN or LOGIN). Add at least one user.
diff --git a/hardware/intel/mraa-gpio-din.js b/hardware/intel/mraa-gpio-din.js
index 5966e448..cfb79612 100644
--- a/hardware/intel/mraa-gpio-din.js
+++ b/hardware/intel/mraa-gpio-din.js
@@ -7,13 +7,16 @@ module.exports = function(RED) {
RED.nodes.createNode(this,n);
this.pin = n.pin;
this.interrupt = n.interrupt;
+ this.mode = n.mode;
+ this.initialMsg = n.initial;
this.x = new m.Gpio(parseInt(this.pin));
this.board = m.getPlatformName();
+ this.defaultTimeout = 100;
var node = this;
- node.x.mode(m.PIN_GPIO);
+ node.x.mode(parseInt(this.mode));
node.x.dir(m.DIR_IN);
- node.x.isr(m.EDGE_BOTH, function() {
- var g = node.x.read();
+
+ var eventHandler = function(g) {
var msg = { payload:g, topic:node.board+"/D"+node.pin };
switch (g) {
case 0: {
@@ -34,8 +37,15 @@ module.exports = function(RED) {
node.status({fill:"grey",shape:"ring",text:"unknown"});
}
}
- });
- switch (node.x.read()) {
+ }
+
+ var isrCallback = function() {
+ eventHandler(node.x.read());
+ }
+
+ node.x.isr(m.EDGE_BOTH, isrCallback);
+ var initialState = node.x.read();
+ switch (initialState) {
case 0: {
node.status({fill:"green",shape:"ring",text:"low"});
break;
@@ -48,8 +58,17 @@ module.exports = function(RED) {
node.status({});
}
}
+
+ if (this.initialMsg) {
+ setTimeout(() => {
+ node.send( { payload: node.x.read(), topic:node.board+"/D"+node.pin } );
+ }, this.defaultTimeout);
+ }
+
this.on('close', function() {
node.x.isr(m.EDGE_BOTH, null);
+ node.x.isrExit();
+ node.x.close();
});
}
RED.nodes.registerType("mraa-gpio-din", gpioDin);
From e133d01e5373b2662a78f13b1eb8db4a23729392 Mon Sep 17 00:00:00 2001
From: Dave Conway-Jones
Date: Tue, 12 Jul 2022 10:14:21 +0100
Subject: [PATCH 23/86] bump mraa node for iot2050 PR
---
hardware/intel/package.json | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/hardware/intel/package.json b/hardware/intel/package.json
index d360b4e5..0d1c7d5b 100644
--- a/hardware/intel/package.json
+++ b/hardware/intel/package.json
@@ -1,7 +1,7 @@
{
"name" : "node-red-node-intel-gpio",
- "version" : "0.0.6",
- "description" : "A Node-RED node to talk to an Intel Galileo or Edison using mraa",
+ "version" : "0.1.0",
+ "description" : "A Node-RED node to talk to an Intel Galileo, Edison or Siemens IOT2050 board using mraa",
"dependencies" : {
},
"repository" : {
@@ -10,7 +10,7 @@
"directory" : "tree/master/hardware/intel"
},
"license": "Apache-2.0",
- "keywords": [ "node-red", "intel", "galileo", "edison" ],
+ "keywords": [ "node-red", "intel", "galileo", "edison", "siemens", "iot2050" ],
"node-red" : {
"nodes" : {
"mraa-gpio-ain": "mraa-gpio-ain.js",
From c32823a85a3d227dbbb943d347e5ed497edeed78 Mon Sep 17 00:00:00 2001
From: Dave Conway-Jones
Date: Thu, 14 Jul 2022 11:28:20 +0100
Subject: [PATCH 24/86] pi gpio close pins timeout
---
hardware/PiGpio/36-rpi-gpio.js | 16 ++++++++++------
hardware/PiGpio/package.json | 2 +-
2 files changed, 11 insertions(+), 7 deletions(-)
diff --git a/hardware/PiGpio/36-rpi-gpio.js b/hardware/PiGpio/36-rpi-gpio.js
index d93a8a40..7ab000fc 100644
--- a/hardware/PiGpio/36-rpi-gpio.js
+++ b/hardware/PiGpio/36-rpi-gpio.js
@@ -108,10 +108,12 @@ module.exports = function(RED) {
delete pinsInUse[node.pin];
if (node.child != null) {
node.finished = done;
- node.child.stdin.write("close "+node.pin);
- node.child.kill('SIGKILL');
+ node.child.stdin.write("close "+node.pin, () => {
+ node.child.kill('SIGKILL');
+ setTimeout(function() { if (done) { done(); } }, 25);
+ });
}
- else { done(); }
+ else { if (done) { done(); } }
});
}
RED.nodes.registerType("rpi-gpio in",GPIOInNode);
@@ -210,10 +212,12 @@ module.exports = function(RED) {
delete pinsInUse[node.pin];
if (node.child != null) {
node.finished = done;
- node.child.stdin.write("close "+node.pin);
- node.child.kill('SIGKILL');
+ node.child.stdin.write("close "+node.pin, () => {
+ node.child.kill('SIGKILL');
+ setTimeout(function() { if (done) { done(); } }, 25);
+ });
}
- else { done(); }
+ else { if (done) { done(); } }
});
}
diff --git a/hardware/PiGpio/package.json b/hardware/PiGpio/package.json
index e445708c..66b71165 100644
--- a/hardware/PiGpio/package.json
+++ b/hardware/PiGpio/package.json
@@ -1,6 +1,6 @@
{
"name": "node-red-node-pi-gpio",
- "version": "2.0.3",
+ "version": "2.0.4",
"description": "The basic Node-RED node for Pi GPIO",
"dependencies" : {
},
From c9f57afe222e361e4ab45d8af99d54cdd56e530a Mon Sep 17 00:00:00 2001
From: Dave Conway-Jones
Date: Thu, 14 Jul 2022 19:00:58 +0100
Subject: [PATCH 25/86] gpio retry failing pin connection
---
hardware/PiGpio/36-rpi-gpio.js | 90 ++++++++++++++++++----------------
hardware/PiGpio/package.json | 2 +-
2 files changed, 50 insertions(+), 42 deletions(-)
diff --git a/hardware/PiGpio/36-rpi-gpio.js b/hardware/PiGpio/36-rpi-gpio.js
index 7ab000fc..ab7a690a 100644
--- a/hardware/PiGpio/36-rpi-gpio.js
+++ b/hardware/PiGpio/36-rpi-gpio.js
@@ -45,46 +45,53 @@ module.exports = function(RED) {
}
}
+ var startPin = function() {
+ node.child = spawn(gpioCommand, ["in",node.pin,node.intype,node.debounce]);
+ node.running = true;
+ node.status({fill:"yellow",shape:"dot",text:"rpi-gpio.status.ok"});
+
+ node.child.stdout.on('data', function (data) {
+ var d = data.toString().trim().split("\n");
+ for (var i = 0; i < d.length; i++) {
+ if (d[i] === '') { return; }
+ if (node.running && node.buttonState !== -1 && !isNaN(Number(d[i])) && node.buttonState !== d[i]) {
+ node.send({ topic:"gpio/"+node.pin, payload:Number(d[i]) });
+ }
+ node.buttonState = d[i];
+ node.status({fill:"green",shape:"dot",text:d[i]});
+ if (RED.settings.verbose) { node.log("out: "+d[i]+" :"); }
+ }
+ });
+
+ node.child.stderr.on('data', function (data) {
+ if (RED.settings.verbose) { node.log("err: "+data+" :"); }
+ });
+
+ node.child.on('close', function (code) {
+ node.running = false;
+ node.child.removeAllListeners();
+ delete node.child;
+ if (RED.settings.verbose) { node.log(RED._("rpi-gpio.status.closed")); }
+ if (!node.finished && code === 1) {
+ setTimeout(function() {startPin()}, 250);
+ }
+ else if (node.finished) {
+ node.status({fill:"grey",shape:"ring",text:"rpi-gpio.status.closed"});
+ node.finished();
+ }
+ else { node.status({fill:"red",shape:"ring",text:"rpi-gpio.status.stopped"}); }
+ });
+
+ node.child.on('error', function (err) {
+ if (err.errno === "ENOENT") { node.error(RED._("rpi-gpio.errors.commandnotfound")); }
+ else if (err.errno === "EACCES") { node.error(RED._("rpi-gpio.errors.commandnotexecutable")); }
+ else { node.error(RED._("rpi-gpio.errors.error",{error:err.errno})) }
+ });
+ }
+
if (allOK === true) {
if (node.pin !== undefined) {
- node.child = spawn(gpioCommand, ["in",node.pin,node.intype,node.debounce]);
- node.running = true;
- node.status({fill:"yellow",shape:"dot",text:"rpi-gpio.status.ok"});
-
- node.child.stdout.on('data', function (data) {
- var d = data.toString().trim().split("\n");
- for (var i = 0; i < d.length; i++) {
- if (d[i] === '') { return; }
- if (node.running && node.buttonState !== -1 && !isNaN(Number(d[i])) && node.buttonState !== d[i]) {
- node.send({ topic:"gpio/"+node.pin, payload:Number(d[i]) });
- }
- node.buttonState = d[i];
- node.status({fill:"green",shape:"dot",text:d[i]});
- if (RED.settings.verbose) { node.log("out: "+d[i]+" :"); }
- }
- });
-
- node.child.stderr.on('data', function (data) {
- if (RED.settings.verbose) { node.log("err: "+data+" :"); }
- });
-
- node.child.on('close', function (code) {
- node.running = false;
- node.child = null;
- if (RED.settings.verbose) { node.log(RED._("rpi-gpio.status.closed")); }
- if (node.finished) {
- node.status({fill:"grey",shape:"ring",text:"rpi-gpio.status.closed"});
- node.finished();
- }
- else { node.status({fill:"red",shape:"ring",text:"rpi-gpio.status.stopped"}); }
- });
-
- node.child.on('error', function (err) {
- if (err.errno === "ENOENT") { node.error(RED._("rpi-gpio.errors.commandnotfound")); }
- else if (err.errno === "EACCES") { node.error(RED._("rpi-gpio.errors.commandnotexecutable")); }
- else { node.error(RED._("rpi-gpio.errors.error",{error:err.errno})) }
- });
-
+ startPin();
}
else {
node.warn(RED._("rpi-gpio.errors.invalidpin")+": "+node.pin);
@@ -109,8 +116,9 @@ module.exports = function(RED) {
if (node.child != null) {
node.finished = done;
node.child.stdin.write("close "+node.pin, () => {
- node.child.kill('SIGKILL');
- setTimeout(function() { if (done) { done(); } }, 25);
+ if (node.child) {
+ node.child.kill('SIGKILL');
+ }
});
}
else { if (done) { done(); } }
@@ -214,7 +222,7 @@ module.exports = function(RED) {
node.finished = done;
node.child.stdin.write("close "+node.pin, () => {
node.child.kill('SIGKILL');
- setTimeout(function() { if (done) { done(); } }, 25);
+ setTimeout(function() { if (done) { done(); } }, 50);
});
}
else { if (done) { done(); } }
diff --git a/hardware/PiGpio/package.json b/hardware/PiGpio/package.json
index 66b71165..b9ee921b 100644
--- a/hardware/PiGpio/package.json
+++ b/hardware/PiGpio/package.json
@@ -1,6 +1,6 @@
{
"name": "node-red-node-pi-gpio",
- "version": "2.0.4",
+ "version": "2.0.5",
"description": "The basic Node-RED node for Pi GPIO",
"dependencies" : {
},
From e7c0459a32fcaacb0b95644d3b0fb3bba2a8dd8f Mon Sep 17 00:00:00 2001
From: Sam Machin
Date: Fri, 15 Jul 2022 14:12:46 +0100
Subject: [PATCH 26/86] Update sensehat.js (#933)
check for sensehat python lib in 2.7 and 3 folders
---
hardware/sensehat/sensehat.js | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/hardware/sensehat/sensehat.js b/hardware/sensehat/sensehat.js
index 67179233..6172c752 100644
--- a/hardware/sensehat/sensehat.js
+++ b/hardware/sensehat/sensehat.js
@@ -7,7 +7,7 @@ module.exports = function(RED) {
var hatCommand = __dirname+'/sensehat';
- if (!fs.existsSync('/usr/lib/python2.7/dist-packages/sense_hat')) {
+ if (!fs.existsSync('/usr/lib/python2.7/dist-packages/sense_hat') && !fs.existsSync('/usr/lib/python3/dist-packages/sense_hat')) {
throw "Error: Can't find Sense HAT python libraries. Run sudo apt-get install sense-hat";
}
From 2b6fbcc5b0d15637cb8cb4979c04f8e778f42296 Mon Sep 17 00:00:00 2001
From: Dave Conway-Jones
Date: Fri, 15 Jul 2022 14:13:51 +0100
Subject: [PATCH 27/86] bump sensehat version for python3 check fix
---
hardware/sensehat/package.json | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/hardware/sensehat/package.json b/hardware/sensehat/package.json
index 23060bbc..20947ada 100644
--- a/hardware/sensehat/package.json
+++ b/hardware/sensehat/package.json
@@ -1,6 +1,6 @@
{
"name" : "node-red-node-pi-sense-hat",
- "version" : "0.1.2",
+ "version" : "0.1.3",
"description" : "A Node-RED node to interact with a Raspberry Pi Sense HAT",
"repository" : {
"type":"git",
From 6830ce4fba3263ef60e4625dd8a569dcc97f6d8f Mon Sep 17 00:00:00 2001
From: Dave Conway-Jones
Date: Tue, 19 Jul 2022 12:59:41 +0100
Subject: [PATCH 28/86] email node - add done capability to retrieving mail
node.
---
social/email/61-email.js | 35 +++++++++++++++++++++++++----------
social/email/package.json | 4 ++--
2 files changed, 27 insertions(+), 12 deletions(-)
diff --git a/social/email/61-email.js b/social/email/61-email.js
index 94052d76..50a5eb06 100644
--- a/social/email/61-email.js
+++ b/social/email/61-email.js
@@ -1,5 +1,7 @@
/* eslint-disable indent */
+const { domainToUnicode } = require("url");
+
/**
* POP3 protocol - RFC1939 - https://www.ietf.org/rfc/rfc1939.txt
*
@@ -224,7 +226,7 @@ module.exports = function(RED) {
}
var node = this;
- this.interval_id = null;
+ node.interval_id = null;
// Process a new email message by building a Node-RED message to be passed onwards
// in the message flow. The parameter called `msg` is the template message we
@@ -253,7 +255,7 @@ module.exports = function(RED) {
// Check the POP3 email mailbox for any new messages. For any that are found,
// retrieve each message, call processNewMessage to process it and then delete
// the messages from the server.
- function checkPOP3(msg) {
+ function checkPOP3(msg,send,done) {
var currentMessage;
var maxMessage;
//node.log("Checking POP3 for new messages");
@@ -270,6 +272,7 @@ module.exports = function(RED) {
if (currentMessage > maxMessage) {
pop3Client.quit();
setInputRepeatTimeout();
+ done();
return;
}
pop3Client.retr(currentMessage);
@@ -294,6 +297,7 @@ module.exports = function(RED) {
pop3Client.on("error", function(err) {
setInputRepeatTimeout();
node.log("error: " + JSON.stringify(err));
+ done();
});
pop3Client.on("connect", function() {
@@ -309,13 +313,13 @@ module.exports = function(RED) {
node.log(util.format("login error: %s %j", status, rawData));
pop3Client.quit();
setInputRepeatTimeout();
+ done();
}
});
pop3Client.on("retr", function(status, msgNumber, data, rawData) {
// node.log(util.format("retr: status=%s, msgNumber=%d, data=%j", status, msgNumber, data));
if (status) {
-
// We have now received a new email message. Create an instance of a mail parser
// and pass in the email message. The parser will signal when it has parsed the message.
simpleParser(data, {}, function(err, parsed) {
@@ -334,6 +338,7 @@ module.exports = function(RED) {
node.log(util.format("retr error: %s %j", status, rawData));
pop3Client.quit();
setInputRepeatTimeout();
+ done();
}
});
@@ -359,7 +364,7 @@ module.exports = function(RED) {
// Check the email sever using the IMAP protocol for new messages.
var s = false;
var ss = false;
- function checkIMAP(msg) {
+ function checkIMAP(msg,send,done) {
//console.log("Checking IMAP for new messages");
// We get back a 'ready' event once we have connected to imap
s = true;
@@ -392,6 +397,7 @@ module.exports = function(RED) {
imap.end();
s = false;
setInputRepeatTimeout();
+ done(err);
return;
}
else {
@@ -407,6 +413,7 @@ module.exports = function(RED) {
imap.end();
s = false;
setInputRepeatTimeout();
+ done(err);
return;
}
else {
@@ -417,6 +424,8 @@ module.exports = function(RED) {
imap.end();
s = false;
setInputRepeatTimeout();
+ msg.payload = 0;
+ done();
return;
}
@@ -454,6 +463,8 @@ module.exports = function(RED) {
imap.end();
s = false;
setInputRepeatTimeout();
+ msg.payload = results.length;
+ done();
};
if (node.disposition === "Delete") {
imap.addFlags(results, "\Deleted", cleanup);
@@ -469,6 +480,7 @@ module.exports = function(RED) {
imap.end();
s = false;
setInputRepeatTimeout();
+ done(err);
});
}
}); // End of imap->search
@@ -478,6 +490,7 @@ module.exports = function(RED) {
node.error(e.toString(),e);
s = ss = false;
imap.end();
+ done(e);
return;
}
}
@@ -486,6 +499,7 @@ module.exports = function(RED) {
node.error(RED._("email.errors.bad_criteria"),msg);
s = ss = false;
imap.end();
+ done();
return;
}
}
@@ -497,11 +511,11 @@ module.exports = function(RED) {
// Perform a check of the email inboxes using either POP3 or IMAP
- function checkEmail(msg) {
+ function checkEmail(msg,send,done) {
if (node.protocol === "POP3") {
- checkPOP3(msg);
+ checkPOP3(msg,send,done);
} else if (node.protocol === "IMAP") {
- if (s === false && ss == false) { checkIMAP(msg); }
+ if (s === false && ss == false) { checkIMAP(msg,send,done); }
}
} // End of checkEmail
@@ -528,11 +542,12 @@ module.exports = function(RED) {
});
}
- this.on("input", function(msg) {
- checkEmail(msg);
+ node.on("input", function(msg, send, done) {
+ send = send || function() { node.send.apply(node,arguments) };
+ checkEmail(msg,send,done);
});
- this.on("close", function() {
+ node.on("close", function() {
if (this.interval_id != null) {
clearTimeout(this.interval_id);
}
diff --git a/social/email/package.json b/social/email/package.json
index da850414..8a7a7e29 100644
--- a/social/email/package.json
+++ b/social/email/package.json
@@ -1,11 +1,11 @@
{
"name": "node-red-node-email",
- "version": "1.16.0",
+ "version": "1.17.0",
"description": "Node-RED nodes to send and receive simple emails.",
"dependencies": {
"imap": "^0.8.19",
"mailparser": "^3.5.0",
- "nodemailer": "^6.7.5",
+ "nodemailer": "^6.7.7",
"smtp-server": "^3.11.0"
},
"bundledDependencies": [
From 67611f6bb692ea6355150c2906d86f38db0530d0 Mon Sep 17 00:00:00 2001
From: Dave Conway-Jones
Date: Fri, 22 Jul 2022 10:18:02 +0100
Subject: [PATCH 29/86] Add cbor object packing node
and test
---
parsers/cbor/70-cbor.html | 44 +++++++++++++
parsers/cbor/70-cbor.js | 38 +++++++++++
parsers/cbor/LICENSE | 14 ++++
parsers/cbor/README.md | 27 ++++++++
parsers/cbor/icons/parser-cbor.png | Bin 0 -> 274 bytes
parsers/cbor/package.json | 28 ++++++++
test/parsers/cbor/70-cbor_spec.js | 101 +++++++++++++++++++++++++++++
7 files changed, 252 insertions(+)
create mode 100644 parsers/cbor/70-cbor.html
create mode 100644 parsers/cbor/70-cbor.js
create mode 100644 parsers/cbor/LICENSE
create mode 100644 parsers/cbor/README.md
create mode 100644 parsers/cbor/icons/parser-cbor.png
create mode 100644 parsers/cbor/package.json
create mode 100644 test/parsers/cbor/70-cbor_spec.js
diff --git a/parsers/cbor/70-cbor.html b/parsers/cbor/70-cbor.html
new file mode 100644
index 00000000..8367e80e
--- /dev/null
+++ b/parsers/cbor/70-cbor.html
@@ -0,0 +1,44 @@
+
+
+
+
+
+
diff --git a/parsers/cbor/70-cbor.js b/parsers/cbor/70-cbor.js
new file mode 100644
index 00000000..abed6dbf
--- /dev/null
+++ b/parsers/cbor/70-cbor.js
@@ -0,0 +1,38 @@
+
+module.exports = function(RED) {
+ "use strict";
+ var cbor = require('cbor-x');
+
+ function CborNode(n) {
+ RED.nodes.createNode(this,n);
+ this.property = n.property||"payload";
+ var node = this;
+ this.on("input", function(msg) {
+ var value = RED.util.getMessageProperty(msg,node.property);
+ if (value !== undefined) {
+ if (Buffer.isBuffer(value)) {
+ var l = value.length;
+ try {
+ value = cbor.decode(value);
+ RED.util.setMessageProperty(msg,node.property,value);
+ node.send(msg);
+ node.status({text:l +" b->o "+ JSON.stringify(value).length});
+ }
+ catch (e) {
+ node.error("Bad decode",msg);
+ node.status({text:"not a cbor buffer"});
+ }
+ }
+ else {
+ var le = JSON.stringify(value).length;
+ value = cbor.encode(value);
+ RED.util.setMessageProperty(msg,node.property,value);
+ node.send(msg);
+ node.status({text:le +" o->b "+ value.length});
+ }
+ }
+ else { node.warn("No payload found to process"); }
+ });
+ }
+ RED.nodes.registerType("cbor",CborNode);
+}
diff --git a/parsers/cbor/LICENSE b/parsers/cbor/LICENSE
new file mode 100644
index 00000000..f5b60114
--- /dev/null
+++ b/parsers/cbor/LICENSE
@@ -0,0 +1,14 @@
+Copyright 2016 JS Foundation and other contributors, https://js.foundation/
+Copyright 2013-2016 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.
diff --git a/parsers/cbor/README.md b/parsers/cbor/README.md
new file mode 100644
index 00000000..d0c7fbf9
--- /dev/null
+++ b/parsers/cbor/README.md
@@ -0,0 +1,27 @@
+node-red-node-cbor
+==================
+
+A Node-RED node to pack and unpack objects to cbor format buffers.
+
+Install
+-------
+
+Run the following command in your Node-RED user directory - typically `~/.node-red`
+
+ npm install node-red-node-cbor
+
+Changes
+-------
+
+Version 1.0.0 - move to cbor-x library (more supported and faster).
+Usage
+-----
+
+Uses the cbor-x npm to pack and unpack msg.payload objects to cbor format buffers.
+
+**Note**: this node does not currently encode raw buffer types.
+It will automatically try to *decode* any buffer received, and may not cause an error.
+
+If the input is NOT a buffer it converts it into a msgpack buffer.
+
+If the input is a msgpack buffer it converts it back to the original type.
diff --git a/parsers/cbor/icons/parser-cbor.png b/parsers/cbor/icons/parser-cbor.png
new file mode 100644
index 0000000000000000000000000000000000000000..02b5ddc0827853bf3ab620a1f75530fdeb164a43
GIT binary patch
literal 274
zcmeAS@N?(olHy`uVBq!ia0vp^B0wz1!3HFCgzU0`6kC$Fy9>jA5L~c#`DCC7XMsm#
zF#`j)FbFd;%$g$s6l5>)^mS!_#KbJX#O@!t;~P+DzNd?0h{y4#lh1NB8wj+dd+{B0
ze);%Ei(P~M)87@@j>oziJ7Rlxc_|j3(&(hXT31tjqj=@
z%fGFh{N)qNI%j^S+!ve=n0^&-Y-77{%=tzQo62Orlqq{{WzTKl>{%Cf=ca?-sb7L_
zYpYKys`tn~jCnpGOu{|*+EU{)zQ3kP{KG*bNPSd+y^`=_8P&;onpeP7|t$O
Q0(2^ar>mdKI;Vst0Qie#$N&HU
literal 0
HcmV?d00001
diff --git a/parsers/cbor/package.json b/parsers/cbor/package.json
new file mode 100644
index 00000000..eb0534c2
--- /dev/null
+++ b/parsers/cbor/package.json
@@ -0,0 +1,28 @@
+{
+ "name" : "node-red-node-cbor",
+ "version" : "1.0.0",
+ "description" : "A Node-RED node to pack and unpack objects to cbor format",
+ "dependencies" : {
+ "cbor-x" : "^1.3.2"
+ },
+ "bundledDependencies": [
+ "cbor-x"
+ ],
+ "repository" : {
+ "type":"git",
+ "url":"https://github.com/node-red/node-red-nodes.git",
+ "directory": "tree/master/parsers/cbor"
+ },
+ "license": "Apache-2.0",
+ "keywords": [ "node-red", "cbor" ],
+ "node-red" : {
+ "nodes" : {
+ "cbor": "70-cbor.js"
+ }
+ },
+ "author": {
+ "name": "Dave Conway-Jones",
+ "email": "dceejay@gmail.com",
+ "url": "http://nodered.org"
+ }
+}
diff --git a/test/parsers/cbor/70-cbor_spec.js b/test/parsers/cbor/70-cbor_spec.js
new file mode 100644
index 00000000..bcebe91c
--- /dev/null
+++ b/test/parsers/cbor/70-cbor_spec.js
@@ -0,0 +1,101 @@
+
+var should = require("should");
+var helper = require("node-red-node-test-helper");
+var testNode = require('../../../parsers/cbor/70-cbor.js');
+
+describe('cbor node', function() {
+ "use strict";
+
+ beforeEach(function(done) {
+ helper.startServer(done);
+ });
+
+ afterEach(function(done) {
+ helper.unload().then(function() {
+ helper.stopServer(done);
+ });
+ });
+
+ it("should be loaded with correct defaults", function(done) {
+ var flow = [{"id":"n1", "type":"cbor", "name":"cbor1", "wires":[[]]}];
+ helper.load(testNode, flow, function() {
+ var n1 = helper.getNode("n1");
+ n1.should.have.property("name", "cbor1");
+ done();
+ });
+ });
+
+ var buf;
+
+ it('should pack an object', function(done) {
+ var flow = [{"id":"n1", "type":"cbor", wires:[["n2"]] },
+ {id:"n2", type:"helper"}];
+ helper.load(testNode, flow, function() {
+ var n1 = helper.getNode("n1");
+ var n2 = helper.getNode("n2");
+ n2.on("input", function(msg) {
+ msg.should.have.a.property("payload");
+ msg.payload.should.be.a.Object;
+ msg.payload.should.have.length(47);
+ buf = msg.payload;
+ done();
+ });
+ n1.emit("input", {payload:{A:1, B:"string", C:true, D:[1,true,"string"], E:{Y:9,Z:"string"}}});
+ });
+ });
+
+ it('should unpack a Buffer', function(done) {
+ var flow = [{"id":"n1", "type":"cbor", wires:[["n2"]] },
+ {id:"n2", type:"helper"} ];
+ helper.load(testNode, flow, function() {
+ var n1 = helper.getNode("n1");
+ var n2 = helper.getNode("n2");
+ n2.on("input", function(msg) {
+ msg.should.have.a.property("payload");
+ msg.payload.should.have.a.property("A",1);
+ msg.payload.should.have.a.property("B",'string');
+ msg.payload.should.have.a.property("C",true);
+ msg.payload.should.have.a.property("D",[1,true,"string"]);
+ msg.payload.should.have.a.property("E");
+ msg.payload.E.should.have.a.property("Y",9);
+ msg.payload.E.should.have.a.property("Z","string");
+ done();
+ });
+ n1.emit("input", {payload:buf});
+ });
+ });
+
+ it('should error if the buffer fails to decode', function(done) {
+ buf[0] = 0x87;
+ var flow = [{"id":"n1", "type":"cbor", wires:[["n2"]] },
+ {id:"n2", type:"helper"} ];
+ helper.load(testNode, flow, function() {
+ var n1 = helper.getNode("n1");
+ var n2 = helper.getNode("n2");
+ n2.on("input", function(msg) {
+ done("should not get here if there is an error.");
+ });
+ setTimeout(function() {
+ done();
+ }, 25);
+ n1.emit("input", {payload:buf});
+ });
+ });
+
+ it('ignore msg with no payload', function(done) {
+ var flow = [{"id":"n1", "type":"cbor", wires:[["n2"]] },
+ {id:"n2", type:"helper"} ];
+ helper.load(testNode, flow, function() {
+ var n1 = helper.getNode("n1");
+ var n2 = helper.getNode("n2");
+ n2.on("input", function(msg) {
+ done("should not get here with no payload.");
+ });
+ setTimeout(function() {
+ done();
+ }, 25);
+ n1.emit("input", {topic:1});
+ });
+ });
+
+});
From 7a5c39ce7b92d864c2da7fe4c914e36ceaf57b68 Mon Sep 17 00:00:00 2001
From: Dave Conway-Jones
Date: Fri, 22 Jul 2022 10:18:18 +0100
Subject: [PATCH 30/86] fix snmp node linting
---
io/snmp/package.json | 4 ++--
io/snmp/snmp.js | 46 +++++++++++++++++++++++---------------------
2 files changed, 26 insertions(+), 24 deletions(-)
diff --git a/io/snmp/package.json b/io/snmp/package.json
index f2023d0f..8bb38f20 100644
--- a/io/snmp/package.json
+++ b/io/snmp/package.json
@@ -1,9 +1,9 @@
{
"name" : "node-red-node-snmp",
- "version" : "1.0.1",
+ "version" : "1.0.2",
"description" : "A Node-RED node that gets and sets SNMP oid values. Supports v1, v2c and v3",
"dependencies" : {
- "net-snmp" : "^3.6.3"
+ "net-snmp" : "^3.8.2"
},
"repository" : {
"type":"git",
diff --git a/io/snmp/snmp.js b/io/snmp/snmp.js
index ca1119db..8c7ca99d 100644
--- a/io/snmp/snmp.js
+++ b/io/snmp/snmp.js
@@ -141,7 +141,7 @@ module.exports = function (RED) {
const IPV6_DOUBLE_COL_PAT = /^\[{0,1}([0-9a-f:]*)::([0-9a-f:]*)(?:\]:(\d+)){0,1}$/g;
const ipv4Matcher = IPV4_PAT.exec(ip);
let hex = "";
- let port = undefined;
+ let port;
let ipOnly = [];
try {
@@ -165,7 +165,7 @@ module.exports = function (RED) {
const IPV6_PAT = new RegExp(ipv6Pattern);
- // IPV6, double colon
+ // IPV6, double colon
const ipv6DoubleColonMatcher = IPV6_DOUBLE_COL_PAT.exec(ip);
if (ipv6DoubleColonMatcher && ipv6DoubleColonMatcher.length) {
let p1 = ipv6DoubleColonMatcher[1];
@@ -392,24 +392,25 @@ module.exports = function (RED) {
node.on("input", function (msg) {
const oids = node.oids || msg.oid;
const { host, sessionid, user, options } = prepareSnmpOptions(node, msg);
+ function feedCb(varbinds) {
+ for (let i = 0; i < varbinds.length; i++) {
+ if (SNMP.isVarbindError(varbinds[i])) {
+ node.error(SNMP.varbindError(varbinds[i]), msg);
+ } else {
+ response.push({ oid: varbinds[i].oid, value: varbinds[i].value });
+ }
+ }
+ }
if (oids) {
msg.oid = oids;
let sess = openSession(sessionid, host, user, options);
sess.on("error", function (err) {
node.error(err, msg);
})
- //move response array & feedCb to inside `node.on("input",` to avoid subsequent
+ //move response array & feedCb to inside `node.on("input",` to avoid subsequent
// calls overwriting results from previous operations (each call gets own result/response)
const response = [];
- function feedCb(varbinds) {
- for (let i = 0; i < varbinds.length; i++) {
- if (SNMP.isVarbindError(varbinds[i])) {
- node.error(SNMP.varbindError(varbinds[i]), msg);
- } else {
- response.push({ oid: varbinds[i].oid, value: varbinds[i].value });
- }
- }
- }
+
sess.subtree(msg.oid, maxRepetitions, feedCb, function (error) {
if (error) {
node.error(error.toString(), msg);
@@ -442,24 +443,25 @@ module.exports = function (RED) {
node.on("input", function (msg) {
const oids = node.oids || msg.oid;
const { host, sessionid, user, options } = prepareSnmpOptions(node, msg);
+ function feedCb(varbinds) {
+ for (let i = 0; i < varbinds.length; i++) {
+ if (SNMP.isVarbindError(varbinds[i])) {
+ node.error(SNMP.varbindError(varbinds[i]), msg);
+ } else {
+ response.push({ oid: varbinds[i].oid, value: varbinds[i].value });
+ }
+ }
+ }
if (oids) {
msg.oid = oids;
let sess = openSession(sessionid, host, user, options);
sess.on("error", function (err) {
node.error(err, msg);
})
- //move response array & feedCb to inside `node.on("input",` to avoid subsequent
+ //move response array & feedCb to inside `node.on("input",` to avoid subsequent
// calls overwriting results from previous operations (each call gets own result/response)
const response = [];
- function feedCb(varbinds) {
- for (let i = 0; i < varbinds.length; i++) {
- if (SNMP.isVarbindError(varbinds[i])) {
- node.error(SNMP.varbindError(varbinds[i]), msg);
- } else {
- response.push({ oid: varbinds[i].oid, value: varbinds[i].value });
- }
- }
- }
+
sess.walk(msg.oid, maxRepetitions, feedCb, function (error) {
if (error) {
node.error(error.toString(), msg);
From a7b9380f2503a173ddb33c31b9fd30c7ae17ffb9 Mon Sep 17 00:00:00 2001
From: Dave Conway-Jones
Date: Fri, 22 Jul 2022 10:18:37 +0100
Subject: [PATCH 31/86] fix mysql node error scope
---
storage/mysql/68-mysql.js | 2 +-
storage/mysql/package.json | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/storage/mysql/68-mysql.js b/storage/mysql/68-mysql.js
index 2f30910d..87dad1b3 100644
--- a/storage/mysql/68-mysql.js
+++ b/storage/mysql/68-mysql.js
@@ -180,7 +180,7 @@ module.exports = function(RED) {
});
}
else {
- node.error(RED._("mysql.errors.notconfigured"));
+ this.error(RED._("mysql.errors.notconfigured"));
}
}
RED.nodes.registerType("mysql",MysqlDBNodeIn);
diff --git a/storage/mysql/package.json b/storage/mysql/package.json
index aa7d93ac..dabe5c85 100644
--- a/storage/mysql/package.json
+++ b/storage/mysql/package.json
@@ -1,6 +1,6 @@
{
"name": "node-red-node-mysql",
- "version": "1.0.2",
+ "version": "1.0.3",
"description": "A Node-RED node to read and write to a MySQL database",
"dependencies": {
"mysql2": "^2.3.3"
From 5bb8b4d968db597156e5df2f7561d677aa8ca2ad Mon Sep 17 00:00:00 2001
From: Dave Conway-Jones
Date: Wed, 27 Jul 2022 14:08:02 +0100
Subject: [PATCH 32/86] add version/engine support metadata
---
parsers/cbor/package.json | 6 +++++-
parsers/markdown/package.json | 8 ++++++--
2 files changed, 11 insertions(+), 3 deletions(-)
diff --git a/parsers/cbor/package.json b/parsers/cbor/package.json
index eb0534c2..ca9cfafd 100644
--- a/parsers/cbor/package.json
+++ b/parsers/cbor/package.json
@@ -1,6 +1,6 @@
{
"name" : "node-red-node-cbor",
- "version" : "1.0.0",
+ "version" : "1.0.1",
"description" : "A Node-RED node to pack and unpack objects to cbor format",
"dependencies" : {
"cbor-x" : "^1.3.2"
@@ -16,6 +16,7 @@
"license": "Apache-2.0",
"keywords": [ "node-red", "cbor" ],
"node-red" : {
+ "version": ">=1.0.0",
"nodes" : {
"cbor": "70-cbor.js"
}
@@ -24,5 +25,8 @@
"name": "Dave Conway-Jones",
"email": "dceejay@gmail.com",
"url": "http://nodered.org"
+ },
+ "engines": {
+ "node": ">=14"
}
}
diff --git a/parsers/markdown/package.json b/parsers/markdown/package.json
index 7dd44f2c..c0320a10 100644
--- a/parsers/markdown/package.json
+++ b/parsers/markdown/package.json
@@ -1,9 +1,9 @@
{
"name": "node-red-node-markdown",
- "version": "0.3.0",
+ "version": "0.4.0",
"description": "A Node-RED node to convert a markdown string to html.",
"dependencies": {
- "markdown-it": "^12.3.2"
+ "markdown-it": "^13.0.1"
},
"repository": {
"type": "git",
@@ -16,6 +16,7 @@
"markdown"
],
"node-red": {
+ "version": ">=1.0.0",
"nodes": {
"markdown": "70-markdown.js"
}
@@ -24,5 +25,8 @@
"name": "Dave Conway-Jones",
"email": "ceejay@vnet.ibm.com",
"url": "http://nodered.org"
+ },
+ "engines": {
+ "node": ">=14"
}
}
From e5e8a33d804b4a70036873be9ed9789e3c70a354 Mon Sep 17 00:00:00 2001
From: Dave Conway-Jones
Date: Fri, 19 Aug 2022 11:40:53 +0100
Subject: [PATCH 33/86] bump notify and timeswitch deps
---
social/notify/package.json | 4 ++--
time/timeswitch/package.json | 4 ++--
2 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/social/notify/package.json b/social/notify/package.json
index 5344fb9c..7b332caa 100644
--- a/social/notify/package.json
+++ b/social/notify/package.json
@@ -1,9 +1,9 @@
{
"name": "node-red-node-notify",
- "version": "0.2.0",
+ "version": "0.3.0",
"description": "A Node-RED node to send local popup Notify alerts",
"dependencies": {
- "node-notifier": "^5.4.5"
+ "node-notifier": "^10.0.1"
},
"repository": {
"type": "git",
diff --git a/time/timeswitch/package.json b/time/timeswitch/package.json
index 0f9c9a51..6c86697c 100644
--- a/time/timeswitch/package.json
+++ b/time/timeswitch/package.json
@@ -1,9 +1,9 @@
{
"name" : "node-red-node-timeswitch",
- "version" : "0.1.0",
+ "version" : "0.2.0",
"description" : "A Node-RED node to provide a simple timeswitch to schedule daily on/off events.",
"dependencies" : {
- "spacetime": "^6.12.5",
+ "spacetime": "^6.16.3",
"suncalc": "^1.8.0"
},
"repository" : {
From d913171f40eb4b87fd5e4964972a66198bdfbb08 Mon Sep 17 00:00:00 2001
From: Dave Conway-Jones
Date: Sat, 20 Aug 2022 18:56:34 +0100
Subject: [PATCH 34/86] Pushbullet - Fix sms missing notifications issue
to close #936
---
social/pushbullet/57-pushbullet.js | 13 +++++++++----
social/pushbullet/package.json | 2 +-
2 files changed, 10 insertions(+), 5 deletions(-)
diff --git a/social/pushbullet/57-pushbullet.js b/social/pushbullet/57-pushbullet.js
index 7e6f0ba1..b2068edb 100644
--- a/social/pushbullet/57-pushbullet.js
+++ b/social/pushbullet/57-pushbullet.js
@@ -221,8 +221,14 @@ module.exports = function(RED) {
msg.payload = incoming.iden;
}
else if (incoming.type === 'sms_changed') {
- msg.topic = "SMS: "+ incoming.notifications[0].title;
- msg.payload = incoming.notifications[0].body;
+ if (incoming.notifications && incoming.notifications.length > 0) {
+ msg.topic = "SMS: "+ incoming.notifications[0].title;
+ msg.payload = incoming.notifications[0].body;
+ }
+ else {
+ msg.topic = "SMS: ";
+ msg.payload = "";
+ }
msg.message = incoming;
}
else {
@@ -244,12 +250,11 @@ module.exports = function(RED) {
function PushbulletOut(n) {
RED.nodes.createNode(this, n);
- var self = this;
-
this.title = n.title;
this.chan = n.chan;
this.pushtype = n.pushtype;
this.pusher = null;
+ var self = this;
var configNode;
diff --git a/social/pushbullet/package.json b/social/pushbullet/package.json
index 6054b93d..a7f2f337 100644
--- a/social/pushbullet/package.json
+++ b/social/pushbullet/package.json
@@ -1,6 +1,6 @@
{
"name" : "node-red-node-pushbullet",
- "version" : "0.0.17",
+ "version" : "0.0.19",
"description" : "A Node-RED node to send alerts via Pushbullet",
"dependencies" : {
"pushbullet": "^2.4.0",
From ecb2849675b305c571c0c92782de28d9ff4e8662 Mon Sep 17 00:00:00 2001
From: Dave Conway-Jones
Date: Mon, 22 Aug 2022 10:27:49 +0100
Subject: [PATCH 35/86] timeswitch, fix display status to local timezone.
to close #944
---
time/timeswitch/package.json | 2 +-
time/timeswitch/timeswitch.js | 11 +++++------
2 files changed, 6 insertions(+), 7 deletions(-)
diff --git a/time/timeswitch/package.json b/time/timeswitch/package.json
index 6c86697c..5bc07d1d 100644
--- a/time/timeswitch/package.json
+++ b/time/timeswitch/package.json
@@ -1,6 +1,6 @@
{
"name" : "node-red-node-timeswitch",
- "version" : "0.2.0",
+ "version" : "0.2.1",
"description" : "A Node-RED node to provide a simple timeswitch to schedule daily on/off events.",
"dependencies" : {
"spacetime": "^6.16.3",
diff --git a/time/timeswitch/timeswitch.js b/time/timeswitch/timeswitch.js
index 87802a8e..28adb4f6 100644
--- a/time/timeswitch/timeswitch.js
+++ b/time/timeswitch/timeswitch.js
@@ -51,6 +51,7 @@ module.exports = function(RED) {
var today = Math.round((nowMillis - midnightMillis) / 60000) % 1440;
var starttime = Number(node.startt);
var endtime = Number(node.endt);
+ var tzOff = (new Date()).getTimezoneOffset();
if ((starttime >= 5000) || (endtime == 5000) || (endtime == 6000)) {
var times = SunCalc.getTimes(now, node.lat, node.lon);
@@ -109,13 +110,11 @@ module.exports = function(RED) {
}
if (proceed >= 2) {
- var duration = newendtime - today;
- if (today > newendtime) { duration += 1440; }
- //node.status({fill:"yellow",shape:"dot",text:"on for " + duration + " mins"});
- node.status({fill:"yellow", shape:"dot", text:"on until " + parseInt(newendtime / 60) + ":" + ("0" + newendtime % 60).substr(-2)});
+ node.status({fill:"yellow", shape:"dot", text:"on until " + parseInt((newendtime -tzOff) / 60) + ":" + ("0" + (newendtime - tzOff) % 60).substr(-2)});
+ }
+ else {
+ node.status({fill:"blue", shape:"dot", text:"off until " + parseInt((starttime - tzOff) / 60) + ":" + ("0" + (starttime - tzOff) % 60).substr(-2)});
}
- //else { node.status({fill:"blue",shape:"dot",text:"off"}); }
- else { node.status({fill:"blue", shape:"dot", text:"off until " + parseInt(starttime / 60) + ":" + ("0" + starttime % 60).substr(-2)}); }
var msg = {};
if (node.mytopic) { msg.topic = node.mytopic; }
From 29e0bed000c172faf0c13b3a1116930b1931d206 Mon Sep 17 00:00:00 2001
From: "J.D. Mallen"
Date: Tue, 23 Aug 2022 09:31:18 -0400
Subject: [PATCH 36/86] Address incorrect timestamps bug in
node-red-node-timeswitch; increase readability (#945)
* Initial fixes before testing and reformatting
* Put sun event offset back in; reformat
* Tabs to spaces
* Fix "Start+X" OFF time; add more comments
* Undo some formatting changes
* Add contributors to package.json
---
time/timeswitch/package.json | 14 +-
time/timeswitch/timeswitch.js | 237 ++++++++++++++++++++++------------
2 files changed, 169 insertions(+), 82 deletions(-)
diff --git a/time/timeswitch/package.json b/time/timeswitch/package.json
index 5bc07d1d..b7b81098 100644
--- a/time/timeswitch/package.json
+++ b/time/timeswitch/package.json
@@ -25,7 +25,19 @@
},
"contributors": [
{
- "name": "@pmacostapdi"
+ "name": "@dceejay"
+ },
+ {
+ "name": "@pmacostapdi"
+ },
+ {
+ "name": "@heikokue"
+ },
+ {
+ "name": "@sammachin"
+ },
+ {
+ "name": "@jdmallen"
}
]
}
diff --git a/time/timeswitch/timeswitch.js b/time/timeswitch/timeswitch.js
index 28adb4f6..3048f378 100644
--- a/time/timeswitch/timeswitch.js
+++ b/time/timeswitch/timeswitch.js
@@ -1,19 +1,18 @@
-
-module.exports = function(RED) {
+module.exports = function (RED) {
"use strict";
var SunCalc = require('suncalc');
const spacetime = require("spacetime")
+ const SUNRISE_KEY = "sunrise";
+ const SUNSET_KEY = "sunset";
function TimeswitchNode(n) {
RED.nodes.createNode(this, n);
this.lat = n.lat;
this.lon = n.lon;
- this.start = n.start || "sunrise";
- this.end = n.end || "sunset";
this.startt = n.starttime;
this.endt = n.endtime;
- this.duskoff = n.duskoff;
- this.dawnoff = n.dawnoff;
+ this.sunriseOffset = n.dawnoff;
+ this.sunsetOffset = n.duskoff;
this.mytopic = n.mytopic;
this.timezone = n.timezone || "UTC";
@@ -24,6 +23,7 @@ module.exports = function(RED) {
this.thu = n.thu;
this.fri = n.fri;
this.sat = n.sat;
+
this.jan = n.jan;
this.feb = n.feb;
this.mar = n.mar;
@@ -38,117 +38,192 @@ module.exports = function(RED) {
this.dec = n.dec;
var node = this;
- var ison = 0;
- var newendtime = 0;
- this.on("input", function(msg2) {
- if (msg2.payload === "reset") { ison = 0; }
+ this.on("input", function () {
+ // current global time
+ const now = spacetime.now();
+ const nowNative = now.toNativeDate();
- var timeOffset = spacetime(Date.now()).goto(this.timezone.toLowerCase()).timezone().current.offset * 60 * 60 * 1000;
- var now = new Date(Date.now() + timeOffset);
- var nowMillis = Date.UTC(now.getUTCFullYear(), now.getUTCMonth(), now.getUTCDate(), now.getUTCHours(), now.getUTCMinutes(), 0);
- var midnightMillis = Date.UTC(now.getUTCFullYear(), now.getUTCMonth(), now.getUTCDate(), 0, 0);
- var today = Math.round((nowMillis - midnightMillis) / 60000) % 1440;
- var starttime = Number(node.startt);
- var endtime = Number(node.endt);
- var tzOff = (new Date()).getTimezoneOffset();
+ // all sun events for the given lat/long
+ const sunEvents = SunCalc.getTimes(nowNative, node.lat, node.lon);
+ let sunriseDateTime = spacetime(sunEvents[SUNRISE_KEY]).nearest("minute");
+ let sunsetDateTime = spacetime(sunEvents[SUNSET_KEY]).nearest("minute");
- if ((starttime >= 5000) || (endtime == 5000) || (endtime == 6000)) {
- var times = SunCalc.getTimes(now, node.lat, node.lon);
- var startMillis = Date.UTC(times[node.start].getUTCFullYear(), times[node.start].getUTCMonth(), times[node.start].getUTCDate(), times[node.start].getUTCHours(), times[node.start].getUTCMinutes());
- var endMillis = Date.UTC(times[node.end].getUTCFullYear(), times[node.end].getUTCMonth(), times[node.end].getUTCDate(), times[node.end].getUTCHours(), times[node.end].getUTCMinutes());
- var dawn = ((startMillis - midnightMillis) / 60000) + Number(node.dawnoff);
- var dusk = ((endMillis - midnightMillis) / 60000) + Number(node.duskoff);
- if (starttime == 5000) { starttime = dawn; }
- if (starttime == 6000) { starttime = dusk; }
- if (endtime == 5000) { endtime = dawn; }
- if (endtime == 6000) { endtime = dusk; }
- if (RED.settings.verbose) { node.log("Dawn " + parseInt(dawn / 60) + ":" + dawn % 60 + " - Dusk " + parseInt(dusk / 60) + ":" + dusk % 60); }
+ // add optional sun event offset, if specified
+ sunriseDateTime = sunriseDateTime.add(Number(node.sunriseOffset), "minutes");
+ sunsetDateTime = sunsetDateTime.add(Number(node.sunsetOffset), "minutes");
+
+ // check if sun event has already occurred today
+ if (now.isAfter(sunriseDateTime)) {
+ // get tomorrow's sunrise, since it'll be different
+ sunriseDateTime = spacetime(SunCalc.getTimes(now.add(1, "day").toNativeDate(), node.lat, node.lon)[SUNRISE_KEY]).nearest("minute");
+ // add optional sun event offset, if specified (again)
+ sunriseDateTime = sunriseDateTime.add(Number(node.sunriseOffset), "minutes");
+ }
+ if (now.isAfter(sunsetDateTime)) {
+ // get tomorrow's sunset, since it'll be different
+ sunsetDateTime = spacetime(SunCalc.getTimes(now.add(1, "day").toNativeDate(), node.lat, node.lon)[SUNSET_KEY]).nearest("minute");
+ // add optional sun event offset, if specified (again)
+ sunsetDateTime = sunsetDateTime.add(Number(node.sunsetOffset), "minutes");
}
- var proceed = 0;
- switch (now.getDay()) {
- case 0 : { if (node.sun) { proceed++; } break; }
- case 1 : { if (node.mon) { proceed++; } break; }
- case 2 : { if (node.tue) { proceed++; } break; }
- case 3 : { if (node.wed) { proceed++; } break; }
- case 4 : { if (node.thu) { proceed++; } break; }
- case 5 : { if (node.fri) { proceed++; } break; }
- case 6 : { if (node.sat) { proceed++; } break; }
+ // log sun events
+ if (RED.settings.verbose) {
+ node.log(`Sunrise ${sunriseDateTime.format("time")} - Sunset ${sunsetDateTime.format("time")} `);
}
- if (proceed) {
- switch (now.getMonth()) {
- case 0 : { if (node.jan) { proceed++; } break; }
- case 1 : { if (node.feb) { proceed++; } break; }
- case 2 : { if (node.mar) { proceed++; } break; }
- case 3 : { if (node.apr) { proceed++; } break; }
- case 4 : { if (node.may) { proceed++; } break; }
- case 5 : { if (node.jun) { proceed++; } break; }
- case 6 : { if (node.jul) { proceed++; } break; }
- case 7 : { if (node.aug) { proceed++; } break; }
- case 8 : { if (node.sep) { proceed++; } break; }
- case 9 : { if (node.oct) { proceed++; } break; }
- case 10: { if (node.nov) { proceed++; } break; }
- case 11: { if (node.dec) { proceed++; } break; }
+ // apply selected timezone to selected times (not to sunrise/sunset-- those are based on lat/long)
+ const currentTimeZone = now.timezone();
+ const selectedTimeZone = spacetime(now.epoch, this.timezone.toLowerCase()).timezone();
+
+ // handler function to convert minute strings (from
+
+
+
+
+
+
diff --git a/hardware/intel/mraa-gpio-led.js b/hardware/intel/mraa-gpio-led.js
index d809c64d..d9a4ce08 100644
--- a/hardware/intel/mraa-gpio-led.js
+++ b/hardware/intel/mraa-gpio-led.js
@@ -3,71 +3,75 @@ module.exports = function(RED) {
function LEDNode(n) {
RED.nodes.createNode(this, n);
this.pin = Number(n.pin);
- this.led0 = new m.Led(0); /*user-led1-green*/
- this.led1 = new m.Led(1); /*user-led1-red*/
- this.led2 = new m.Led(2); /*user-led2-green*/
- this.led3 = new m.Led(3); /*user-led2-red*/
+ this.color = Number(n.color);
+
+ if (this.pin == 0) {
+ this.user1_green = new m.Led(0); /*user-led1-green*/
+ this.user1_red = new m.Led(1); /*user-led1-red*/
+ } if(this.pin == 1) {
+ this.user2_green = new m.Led(2); /*user-led2-green*/
+ this.user2_red = new m.Led(3); /*user-led2-red*/
+ }
+
+ function set_led_green(led_green, led_red) {
+ led_green.setBrightness(1);
+ led_red.setBrightness(0);
+ }
+
+ function set_led_red(led_green, led_red) {
+ led_green.setBrightness(0);
+ led_red.setBrightness(1);
+ }
+
+ function set_led_orange(led_green, led_red) {
+ led_green.setBrightness(1);
+ led_red.setBrightness(1);
+ }
+
+ function turn_off_led(led_green, led_red) {
+ led_green.setBrightness(0);
+ led_red.setBrightness(0);
+ }
+
this.on("input", function(msg) {
+ if (this.pin == 0) {
+ this.led_green = this.user1_green;
+ this.led_red = this.user1_red;
+ }
+ else if (this.pin == 1) {
+ this.led_green = this.user2_green;
+ this.led_red = this.user2_red;
+ }
+
if (msg.payload == "1") {
- switch(this.pin)
- {
- case 0: /*User0 Led Green*/
- this.led0.setBrightness(1);
+ switch(this.color) {
+ case 0:
+ set_led_green(this.led_green, this.led_red);
break;
- case 1: /*User0 Led Red*/
- this.led1.setBrightness(1);
+ case 1:
+ set_led_red(this.led_green, this.led_red);
break;
- case 2: /*User0 Orange*/
- this.led0.setBrightness(1);
- this.led1.setBrightness(1);
- break;
- case 3: /*User1 Led Green*/
- this.led2.setBrightness(1);
- break;
- case 4: /*User1 Led Red*/
- this.led3.setBrightness(1);
- break;
- case 5: /*User1 Orange*/
- this.led2.setBrightness(1);
- this.led3.setBrightness(1);
+ case 2:
+ set_led_orange(this.led_green, this.led_red);
break;
default:
+ console.log("unexpected");
break;
}
}
else {
- switch(this.pin)
- {
- case 0: /*User1 Led Green*/
- this.led0.setBrightness(0);
- break;
- case 1: /*User1 Led Red*/
- this.led1.setBrightness(0);
- break;
- case 2: /*User1 Orange*/
- this.led0.setBrightness(0);
- this.led1.setBrightness(0);
- break;
- case 3: /*User2 Led Green*/
- this.led2.setBrightness(0);
- break;
- case 4: /*User2 Led Red*/
- this.led3.setBrightness(0);
- break;
- case 5: /*User2 Orange*/
- this.led2.setBrightness(0);
- this.led3.setBrightness(0);
- break;
- default:
- break;
- }
+ turn_off_led(this.led_green, this.led_red);
}
});
+
this.on('close', function() {
- this.led0.close();
- this.led1.close();
- this.led2.close();
- this.led3.close();
+ if (this.pin == 0) {
+ this.user1_green.close();
+ this.user1_red.close();
+ } if(this.pin == 1) {
+ this.user2_green.close();
+ this.user2_red.close();
+ }
});
}
RED.nodes.registerType("mraa-gpio-led", LEDNode);
From c15fa79e9535d029d206dfb76474d56bf979504b Mon Sep 17 00:00:00 2001
From: Dave Conway-Jones
Date: Wed, 26 Oct 2022 15:19:57 +0100
Subject: [PATCH 53/86] Bump for PR
---
hardware/intel/package.json | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/hardware/intel/package.json b/hardware/intel/package.json
index dcd692b6..6238514b 100644
--- a/hardware/intel/package.json
+++ b/hardware/intel/package.json
@@ -1,6 +1,6 @@
{
"name" : "node-red-node-intel-gpio",
- "version" : "0.2.1",
+ "version" : "0.3.0",
"description" : "A Node-RED node to talk to an Intel Galileo, Edison or Siemens IOT2050 board using mraa",
"dependencies" : {
},
From 4c9afda6dd67854e0da975f46e56588b9f1e1bd7 Mon Sep 17 00:00:00 2001
From: kaffetorsk <93540369+kaffetorsk@users.noreply.github.com>
Date: Wed, 26 Oct 2022 16:22:48 +0200
Subject: [PATCH 54/86] node-red-daemon append arguments (#939)
* Allow msg.start to append arguments
* Update description
* Update README.md
---
utility/daemon/README.md | 2 +-
utility/daemon/daemon.js | 36 ++++++++++++++++--------
utility/daemon/locales/en-US/daemon.html | 2 +-
3 files changed, 27 insertions(+), 13 deletions(-)
diff --git a/utility/daemon/README.md b/utility/daemon/README.md
index 57577643..95f41c16 100644
--- a/utility/daemon/README.md
+++ b/utility/daemon/README.md
@@ -34,7 +34,7 @@ to restart the command automatically.
Setting `msg.kill` to a signal name (e.g. SIGINT, SIGHUP) will stop the process - but if the restart flag is set it will then auto restart.
-Sending `msg.start` will also re-start the process.
+Sending `msg.start` will also re-start the process. Additional arguments can be specified in `msg.args`.
**Note:** Some applications will automatically buffer lines of output. It is advisable to turn off this behaviour.
For example, if running a Python app, the `-u` parameter will stop the output being buffered.
diff --git a/utility/daemon/daemon.js b/utility/daemon/daemon.js
index bbee3332..928f8143 100644
--- a/utility/daemon/daemon.js
+++ b/utility/daemon/daemon.js
@@ -15,16 +15,21 @@ module.exports = function(RED) {
this.closer = n.closer || "SIGKILL";
this.autorun = true;
if (n.autorun === false) { this.autorun = false; }
- if (this.args.match(/^\[.*\]$/)) {
- try { this.args = JSON.parse(this.args); }
- catch(e) {
- node.warn(RED._("daemon.errors.badparams"))
- }
- }
- else { this.args = this.args.match(/("[^"]*")|[^ ]+/g); }
+ this.args = parseArgs(this.args);
var node = this;
var lastmsg = {};
+ function parseArgs(args) {
+ if (args.match(/^\[.*\]$/)) {
+ try { args = JSON.parse(args); }
+ catch(e) {
+ node.warn(RED._("daemon.errors.badparams"))
+ }
+ }
+ else { args = args.match(/("[^"]*")|[^ ]+/g); }
+ return args;
+ }
+
function inputlistener(msg) {
if (msg != null) {
if (msg.hasOwnProperty("kill") && node.running) {
@@ -32,7 +37,11 @@ module.exports = function(RED) {
node.child.kill(msg.kill.toUpperCase());
}
else if (msg.hasOwnProperty("start") && !node.running) {
- runit();
+ let args = "";
+ if (msg.hasOwnProperty("args") && msg.args.length > 0) {
+ args = parseArgs(msg.args.trim());
+ }
+ runit(args);
}
else {
if (!Buffer.isBuffer(msg.payload)) {
@@ -48,15 +57,20 @@ module.exports = function(RED) {
}
}
- function runit() {
+ function runit(appendArgs) {
var line = "";
if (!node.cmd || (typeof node.cmd !== "string") || (node.cmd.length < 1)) {
node.status({fill:"grey",shape:"ring",text:RED._("daemon.status.nocommand")});
return;
}
+ let args = node.args;
+ if (appendArgs !== undefined && appendArgs.length > 0) {
+ args = args.concat(appendArgs);
+ }
+
try {
- node.child = spawn(node.cmd, node.args);
- node.debug(node.cmd+" "+JSON.stringify(node.args));
+ node.child = spawn(node.cmd, args);
+ node.debug(node.cmd+" "+JSON.stringify(args));
node.status({fill:"green",shape:"dot",text:RED._("daemon.status.running")});
node.running = true;
diff --git a/utility/daemon/locales/en-US/daemon.html b/utility/daemon/locales/en-US/daemon.html
index fd1ec70b..06d750d7 100644
--- a/utility/daemon/locales/en-US/daemon.html
+++ b/utility/daemon/locales/en-US/daemon.html
@@ -5,7 +5,7 @@
Parameters can be space separated, space separated with quotes, or a javascript array. For example `aa bb` or `"cc dd"` or `["aa","bb cc""]`.
If the called program stops (i.e. a return code is produced), this node can attempt to restart the command.
Setting msg.kill to a signal name (e.g. SIGINT, SIGHUP) will stop the process - but if the
- restart flag is set it will then auto restart. Sending msg.start will also re-start the process.
+ restart flag is set it will then auto restart. Sending msg.start will also re-start the process. Additional arguments can be specified in msg.args.
Note: Some applications will automatically buffer lines of output. It is advisable to turn off this behaviour.
For example, if running a Python app, the -u parameter will stop the output being buffered.
From 93614e09ee41895890dc0df077363fb47a47b662 Mon Sep 17 00:00:00 2001
From: Dave Conway-Jones
Date: Wed, 26 Oct 2022 15:23:57 +0100
Subject: [PATCH 55/86] bump daemon for PR to add msg.args
---
utility/daemon/package.json | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/utility/daemon/package.json b/utility/daemon/package.json
index b0e82fd1..1d353087 100644
--- a/utility/daemon/package.json
+++ b/utility/daemon/package.json
@@ -1,6 +1,6 @@
{
"name" : "node-red-node-daemon",
- "version" : "0.4.0",
+ "version" : "0.5.0",
"description" : "A Node-RED node that runs and monitors a long running system command.",
"dependencies" : {
},
From 4c0ecc70bcd7ba9f4c268c5fd7a6d117ef5278c8 Mon Sep 17 00:00:00 2001
From: Dave Conway-Jones
Date: Sat, 29 Oct 2022 16:51:14 +0100
Subject: [PATCH 56/86] add smtp keywords
---
social/email/package.json | 2 ++
1 file changed, 2 insertions(+)
diff --git a/social/email/package.json b/social/email/package.json
index e7e1afe2..e17af937 100644
--- a/social/email/package.json
+++ b/social/email/package.json
@@ -26,6 +26,8 @@
"gmail",
"imap",
"pop",
+ "smtp",
+ "smtp-server",
"mta"
],
"node-red": {
From c3a5716fe76c24e349b59a800f79de39b87998a3 Mon Sep 17 00:00:00 2001
From: Dave Conway-Jones
Date: Tue, 8 Nov 2022 13:52:37 +0000
Subject: [PATCH 57/86] Let email node be able to send blank topic
and let msg.description be " also
to close #959
---
social/email/61-email.js | 6 ++++--
social/email/locales/de/61-email.json | 2 +-
social/email/locales/en-US/61-email.json | 4 ++--
social/email/locales/ja/61-email.json | 2 +-
social/email/package.json | 2 +-
5 files changed, 9 insertions(+), 7 deletions(-)
diff --git a/social/email/61-email.js b/social/email/61-email.js
index 41918cff..fc717d25 100644
--- a/social/email/61-email.js
+++ b/social/email/61-email.js
@@ -98,7 +98,8 @@ module.exports = function(RED) {
sendopts.headers = msg.headers;
sendopts.priority = msg.priority;
}
- sendopts.subject = msg.topic || msg.title || "Message from Node-RED"; // subject line
+ if (msg.hasOwnProperty("topic") && msg.topic === '') { sendopts.subject = ""; }
+ else { sendopts.subject = msg.topic || msg.title || "Message from Node-RED"; } // subject line
if (msg.hasOwnProperty("header") && msg.header.hasOwnProperty("message-id")) {
sendopts.inReplyTo = msg.header["message-id"];
sendopts.subject = "Re: " + sendopts.subject;
@@ -119,7 +120,8 @@ module.exports = function(RED) {
sendopts.attachments[0].contentType = msg.headers["content-type"];
}
// Create some body text..
- sendopts.text = RED._("email.default-message",{filename:fname, description:(msg.description||"")});
+ if (msg.hasOwnProperty("description")) { sendopts.text = msg.description; }
+ else { sendopts.text = RED._("email.default-message",{filename:fname}); }
}
else {
var payload = RED.util.ensureString(msg.payload);
diff --git a/social/email/locales/de/61-email.json b/social/email/locales/de/61-email.json
index 545f1aa2..704dfb9e 100644
--- a/social/email/locales/de/61-email.json
+++ b/social/email/locales/de/61-email.json
@@ -36,7 +36,7 @@
"always": "immer",
"rejectUnauthorised": "Überprüfen sie, ob das serverzertifikat gültig ist"
},
- "default-message": "__description__\n\nDatei von Node-RED ist angehängt: __filename__",
+ "default-message": "\nDatei von Node-RED ist angehängt: __filename__",
"tip": {
"cred": "Hinweis: Berechtigungen von globaler emailkeys.js-Datei kopiert",
"recent": "Tipp: Es wird nur die letzte E-Mail abgerufen",
diff --git a/social/email/locales/en-US/61-email.json b/social/email/locales/en-US/61-email.json
index 67567904..73f25cba 100644
--- a/social/email/locales/en-US/61-email.json
+++ b/social/email/locales/en-US/61-email.json
@@ -42,10 +42,10 @@
"keyFile":"Private key",
"users": "Users",
"auth": "Authenticate users",
- "addButton": "Add",
+ "addButton": "Add",
"expert": "Expert"
},
- "default-message": "__description__\n\nFile from Node-RED is attached: __filename__",
+ "default-message": "\nFile from Node-RED is attached: __filename__",
"tip": {
"cred": "Note: Copied credentials from global emailkeys.js file.",
"recent": "Tip: Only retrieves the single most recent email.",
diff --git a/social/email/locales/ja/61-email.json b/social/email/locales/ja/61-email.json
index c4dbc1c4..82c7bcc7 100644
--- a/social/email/locales/ja/61-email.json
+++ b/social/email/locales/ja/61-email.json
@@ -36,7 +36,7 @@
"always": "常時",
"rejectUnauthorised": "チェックサーバ証明書は有効です"
},
- "default-message": "__description__\n\nNode-REDからファイルが添付されました: __filename__",
+ "default-message": "\nNode-REDからファイルが添付されました: __filename__",
"tip": {
"cred": "注釈: emailkeys.jsファイルから認証情報をコピーしました。",
"recent": "注釈: 最新のメールを1件のみ取得します。",
diff --git a/social/email/package.json b/social/email/package.json
index e17af937..f3c23428 100644
--- a/social/email/package.json
+++ b/social/email/package.json
@@ -1,6 +1,6 @@
{
"name": "node-red-node-email",
- "version": "1.18.1",
+ "version": "1.18.2",
"description": "Node-RED nodes to send and receive simple emails.",
"dependencies": {
"imap": "^0.8.19",
From 074ca44b5f881160c3ac347115b7a52f20453da4 Mon Sep 17 00:00:00 2001
From: Dave Conway-Jones
Date: Wed, 16 Nov 2022 12:02:30 +0000
Subject: [PATCH 58/86] Add specific daemons node stdin error handler
to address issue #960
---
utility/daemon/daemon.js | 10 ++++++++--
utility/daemon/locales/en-US/daemon.json | 3 ++-
utility/daemon/package.json | 2 +-
3 files changed, 11 insertions(+), 4 deletions(-)
diff --git a/utility/daemon/daemon.js b/utility/daemon/daemon.js
index 928f8143..d3ab3817 100644
--- a/utility/daemon/daemon.js
+++ b/utility/daemon/daemon.js
@@ -50,9 +50,9 @@ module.exports = function(RED) {
if (node.cr === true) { msg.payload += "\n"; }
}
node.debug("inp: "+msg.payload);
+ lastmsg = msg;
if (node.child !== null && node.running) { node.child.stdin.write(msg.payload); }
else { node.warn(RED._("daemon.errors.notrunning")); }
- lastmsg = msg;
}
}
}
@@ -65,7 +65,7 @@ module.exports = function(RED) {
}
let args = node.args;
if (appendArgs !== undefined && appendArgs.length > 0) {
- args = args.concat(appendArgs);
+ args = args.concat(appendArgs);
}
try {
@@ -120,6 +120,12 @@ module.exports = function(RED) {
else { node.log('error: ' + err); }
node.status({fill:"red",shape:"ring",text:RED._("daemon.status.error")});
});
+
+ node.child.stdin.on('error', function (err) {
+ if (err.errno === "EPIPE") { node.error(RED._("daemon.errors.pipeclosed"),lastmsg); }
+ else { node.log('error: ' + err); }
+ node.status({fill:"red",shape:"ring",text:RED._("daemon.status.error")});
+ });
}
catch(e) {
if (e.errno === "ENOENT") { node.warn(RED._("daemon.errors.notfound")); }
diff --git a/utility/daemon/locales/en-US/daemon.json b/utility/daemon/locales/en-US/daemon.json
index 20263c3b..52ef4091 100644
--- a/utility/daemon/locales/en-US/daemon.json
+++ b/utility/daemon/locales/en-US/daemon.json
@@ -37,7 +37,8 @@
"notrunning": "Command not running",
"notfound": "Command not found",
"notexecutable": "Command not executable",
- "restarting": "Restarting"
+ "restarting": "Restarting",
+ "pipeclosed": "Process closed"
}
}
}
\ No newline at end of file
diff --git a/utility/daemon/package.json b/utility/daemon/package.json
index 1d353087..f6b7272b 100644
--- a/utility/daemon/package.json
+++ b/utility/daemon/package.json
@@ -1,6 +1,6 @@
{
"name" : "node-red-node-daemon",
- "version" : "0.5.0",
+ "version" : "0.5.1",
"description" : "A Node-RED node that runs and monitors a long running system command.",
"dependencies" : {
},
From 2da42c949591bd2a6eecd58f707c47159a709811 Mon Sep 17 00:00:00 2001
From: Dave Conway-Jones
Date: Mon, 28 Nov 2022 11:50:08 +0000
Subject: [PATCH 59/86] Let sensehat ignore colour sensor warning
to close #958
---
hardware/sensehat/package.json | 2 +-
hardware/sensehat/sensehat.js | 8 +++++++-
2 files changed, 8 insertions(+), 2 deletions(-)
diff --git a/hardware/sensehat/package.json b/hardware/sensehat/package.json
index 20947ada..c9845b99 100644
--- a/hardware/sensehat/package.json
+++ b/hardware/sensehat/package.json
@@ -1,6 +1,6 @@
{
"name" : "node-red-node-pi-sense-hat",
- "version" : "0.1.3",
+ "version" : "0.1.4",
"description" : "A Node-RED node to interact with a Raspberry Pi Sense HAT",
"repository" : {
"type":"git",
diff --git a/hardware/sensehat/sensehat.js b/hardware/sensehat/sensehat.js
index 6172c752..f41d4360 100644
--- a/hardware/sensehat/sensehat.js
+++ b/hardware/sensehat/sensehat.js
@@ -107,7 +107,13 @@ module.exports = function(RED) {
// Any data on stderr means a bad thing has happened.
// Best to kill it and let it reconnect.
if (RED.settings.verbose) { RED.log.error("err: "+data+" :"); }
- hat.kill('SIGKILL');
+ if (data.indexOf("WARNING") === 0) {
+ if (data.indexOf("sensor not present") !== -1) { return; }
+ else { RED.log.warn(data); }
+ }
+ else {
+ hat.kill('SIGKILL');
+ }
});
hat.stderr.on('error', function(err) { });
hat.stdin.on('error', function(err) { });
From 2b50bf38ec7b7aec6dd5b0870abf376677b02928 Mon Sep 17 00:00:00 2001
From: Dave Conway-Jones
Date: Wed, 14 Dec 2022 11:45:33 +0000
Subject: [PATCH 60/86] Fix tail to update status
and retry if file goes away and comes back
---
storage/tail/28-tail.js | 4 ++++
storage/tail/package.json | 2 +-
2 files changed, 5 insertions(+), 1 deletion(-)
diff --git a/storage/tail/28-tail.js b/storage/tail/28-tail.js
index 0f741604..4bdb0fc7 100644
--- a/storage/tail/28-tail.js
+++ b/storage/tail/28-tail.js
@@ -16,6 +16,7 @@ module.exports = function(RED) {
var fileTail = function() {
if (fs.existsSync(node.filename)) {
+ node.status({ });
if (node.filetype === "text") {
node.tail = new Tail(node.filename,{separator:node.split, flushAtEOF:true});
}
@@ -40,6 +41,7 @@ module.exports = function(RED) {
node.tail.on("error", function(err) {
node.status({ fill: "red",shape:"ring", text: "node-red:common.status.error" });
node.error(err.toString());
+ if (err.code ==="ENOENT") { scheduleRestart(); }
});
}
else {
@@ -51,6 +53,8 @@ module.exports = function(RED) {
var scheduleRestart = function() {
node.tout = setTimeout(function() {
node.tout = null;
+ if (node.tail) { node.tail.unwatch(); }
+ delete node.tail;
fileTail();
}, 10000);
};
diff --git a/storage/tail/package.json b/storage/tail/package.json
index d95ade61..a6d542cd 100644
--- a/storage/tail/package.json
+++ b/storage/tail/package.json
@@ -1,6 +1,6 @@
{
"name": "node-red-node-tail",
- "version": "0.3.2",
+ "version": "0.4.0",
"description": "A node to tail files for Node-RED",
"dependencies": {
"tail": "^2.2.4"
From b9053cf962eb877b360f8d1ee919687e2a016135 Mon Sep 17 00:00:00 2001
From: Dave Conway-Jones
Date: Thu, 22 Dec 2022 11:38:00 +0000
Subject: [PATCH 61/86] email - better cleanup of deleted messages ?
---
social/email/61-email.js | 4 ++--
social/email/package.json | 2 +-
2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/social/email/61-email.js b/social/email/61-email.js
index fc717d25..b7ef9f77 100644
--- a/social/email/61-email.js
+++ b/social/email/61-email.js
@@ -469,9 +469,9 @@ module.exports = function(RED) {
done();
};
if (node.disposition === "Delete") {
- imap.addFlags(results, "\Deleted", cleanup);
+ imap.addFlags(results, '\\Deleted', imap.expunge(cleanup) );
} else if (node.disposition === "Read") {
- imap.addFlags(results, "\Seen", cleanup);
+ imap.addFlags(results, '\\Seen', cleanup);
} else {
cleanup();
}
diff --git a/social/email/package.json b/social/email/package.json
index f3c23428..c00d07b2 100644
--- a/social/email/package.json
+++ b/social/email/package.json
@@ -1,6 +1,6 @@
{
"name": "node-red-node-email",
- "version": "1.18.2",
+ "version": "1.18.3",
"description": "Node-RED nodes to send and receive simple emails.",
"dependencies": {
"imap": "^0.8.19",
From bb0a6fd272c44233200440fb04c3146c656aa45d Mon Sep 17 00:00:00 2001
From: Dave Conway-Jones
Date: Thu, 22 Dec 2022 11:39:36 +0000
Subject: [PATCH 62/86] bump email packages
---
social/email/package.json | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/social/email/package.json b/social/email/package.json
index c00d07b2..06524b1a 100644
--- a/social/email/package.json
+++ b/social/email/package.json
@@ -4,7 +4,7 @@
"description": "Node-RED nodes to send and receive simple emails.",
"dependencies": {
"imap": "^0.8.19",
- "mailparser": "^3.5.0",
+ "mailparser": "^3.6.2",
"nodemailer": "^6.8.0",
"smtp-server": "^3.11.0"
},
From b046740e7f87dcbb3ca8ba8e00d84d88f5069a4e Mon Sep 17 00:00:00 2001
From: Dave Conway-Jones
Date: Thu, 22 Dec 2022 11:45:00 +0000
Subject: [PATCH 63/86] Update package.json
---
social/email/package.json | 1 +
1 file changed, 1 insertion(+)
diff --git a/social/email/package.json b/social/email/package.json
index 06524b1a..d1dd34a8 100644
--- a/social/email/package.json
+++ b/social/email/package.json
@@ -31,6 +31,7 @@
"mta"
],
"node-red": {
+ "version": ">=1.0.0",
"nodes": {
"email": "61-email.js"
}
From 9bae313b722147b00480ce2e26ed0aab357b836b Mon Sep 17 00:00:00 2001
From: Dave Conway-Jones
Date: Sat, 24 Dec 2022 14:03:49 +0000
Subject: [PATCH 64/86] revert mailparser to fix node12 (for now)
---
social/email/package.json | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/social/email/package.json b/social/email/package.json
index d1dd34a8..2e362d1a 100644
--- a/social/email/package.json
+++ b/social/email/package.json
@@ -1,10 +1,10 @@
{
"name": "node-red-node-email",
- "version": "1.18.3",
+ "version": "1.18.4",
"description": "Node-RED nodes to send and receive simple emails.",
"dependencies": {
"imap": "^0.8.19",
- "mailparser": "^3.6.2",
+ "mailparser": "~3.5.0",
"nodemailer": "^6.8.0",
"smtp-server": "^3.11.0"
},
From 8553dc30f2d00828c80128e3f42cace2150f9ad0 Mon Sep 17 00:00:00 2001
From: Dave Conway-Jones
Date: Fri, 13 Jan 2023 11:42:06 +0000
Subject: [PATCH 65/86] remove dubious use of rtl direction
to close #970
---
io/snmp/package.json | 2 +-
io/snmp/snmp.html | 36 ++++++++++++++++++------------------
2 files changed, 19 insertions(+), 19 deletions(-)
diff --git a/io/snmp/package.json b/io/snmp/package.json
index eb783a50..3df8a7cf 100644
--- a/io/snmp/package.json
+++ b/io/snmp/package.json
@@ -1,6 +1,6 @@
{
"name" : "node-red-node-snmp",
- "version" : "1.0.5",
+ "version" : "1.0.6",
"description" : "A Node-RED node that gets and sets SNMP oid values. Supports v1, v2c and v3",
"dependencies" : {
"net-snmp" : "^3.8.2"
diff --git a/io/snmp/snmp.html b/io/snmp/snmp.html
index f952e331..3e3c029b 100644
--- a/io/snmp/snmp.html
+++ b/io/snmp/snmp.html
@@ -41,7 +41,7 @@
$(".form-row-snmpv3-auth").toggleClass("hidden", true);
$(".form-row-snmpv3-priv").toggleClass("hidden", true);
break;
- }
+ }
}
});
$("#node-input-version").val(node.version);
@@ -65,7 +65,7 @@
v3
Timeout
- S
+ S
@@ -106,7 +106,7 @@
-
+
@@ -177,10 +177,10 @@
v2c
v3
-
+
Timeout
- S
+ S
@@ -221,7 +221,7 @@
-
+
@@ -353,7 +353,7 @@
-
+
@@ -424,10 +424,10 @@
v2c
v3
-
+
Timeout
- S
+ S
@@ -468,7 +468,7 @@
-
+
@@ -540,10 +540,10 @@
v2c
v3
-
+
Timeout
- S
+ S
@@ -584,7 +584,7 @@
-
+
@@ -597,7 +597,7 @@
From f7f313c197a0510a07459b389291c472841eb193 Mon Sep 17 00:00:00 2001
From: Dave Conway-Jones
Date: Thu, 19 Jan 2023 09:34:28 +0000
Subject: [PATCH 66/86] Fix timeswitch status to show time in timezone set in
the properties
and bump library
---
time/timeswitch/package.json | 4 ++--
time/timeswitch/timeswitch.js | 15 +++++++++------
2 files changed, 11 insertions(+), 8 deletions(-)
diff --git a/time/timeswitch/package.json b/time/timeswitch/package.json
index aa6ff72c..71917d79 100644
--- a/time/timeswitch/package.json
+++ b/time/timeswitch/package.json
@@ -1,9 +1,9 @@
{
"name" : "node-red-node-timeswitch",
- "version" : "0.2.2",
+ "version" : "1.0.0",
"description" : "A Node-RED node to provide a simple timeswitch to schedule daily on/off events.",
"dependencies" : {
- "spacetime": "^6.16.3",
+ "spacetime": "^7.4.0",
"suncalc": "^1.8.0"
},
"repository" : {
diff --git a/time/timeswitch/timeswitch.js b/time/timeswitch/timeswitch.js
index 3048f378..fc5e3c87 100644
--- a/time/timeswitch/timeswitch.js
+++ b/time/timeswitch/timeswitch.js
@@ -23,7 +23,7 @@ module.exports = function (RED) {
this.thu = n.thu;
this.fri = n.fri;
this.sat = n.sat;
-
+
this.jan = n.jan;
this.feb = n.feb;
this.mar = n.mar;
@@ -123,17 +123,20 @@ module.exports = function (RED) {
// handler function for the node payload, called below
let sendPayload = (payload, nextTime) => {
+ // var o = nextTime.goto(selectedTimeZone.name).offset()/60;
+ // if (o > 0) { o = "+" + o; }
+ // else {o = "-" + o; }
if (payload == 1) {
node.status({
fill: "yellow",
shape: "dot",
- text: `on until ${nextTime.format("time")}`
+ text: `on until ${nextTime.goto(selectedTimeZone.name).format("time-24")}`
});
} else {
node.status({
fill: "blue",
shape: "dot",
- text: `off until ${nextTime.format("time")}`
+ text: `off until ${nextTime.goto(selectedTimeZone.name).format("time-24")}`
});
}
var msg = {};
@@ -157,9 +160,9 @@ module.exports = function (RED) {
case 6 : { if (!node.sat) { proceed &= false; } break; }
}
- if (!proceed) {
- sendPayload(0, selectedOnTime);
- return;
+ if (!proceed) {
+ sendPayload(0, selectedOnTime);
+ return;
}
// if this month is not among the selected months, stop here
From 559ce050da8e712ba3cadd2a243152680a49deb2 Mon Sep 17 00:00:00 2001
From: Dave Conway-Jones
Date: Tue, 31 Jan 2023 11:27:31 +0000
Subject: [PATCH 67/86] fix serialport to append chars to buffer correctly
---
io/serialport/25-serial.js | 2 +-
io/serialport/package.json | 6 +++---
2 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/io/serialport/25-serial.js b/io/serialport/25-serial.js
index 6bd45fab..64093ceb 100644
--- a/io/serialport/25-serial.js
+++ b/io/serialport/25-serial.js
@@ -271,7 +271,7 @@ module.exports = function(RED) {
if (addchar !== "") { payload += addchar; }
}
else if (addchar !== "") {
- payload = Buffer.concat([payload,addchar]);
+ payload = Buffer.concat([payload,Buffer.from(addchar)]);
}
return payload;
},
diff --git a/io/serialport/package.json b/io/serialport/package.json
index 22d65481..1ec5dbdf 100644
--- a/io/serialport/package.json
+++ b/io/serialport/package.json
@@ -1,9 +1,9 @@
{
"name" : "node-red-node-serialport",
- "version" : "1.0.1",
+ "version" : "1.0.2",
"description" : "Node-RED nodes to talk to serial ports",
"dependencies" : {
- "serialport" : "^10.3.0"
+ "serialport" : "^10.5.0"
},
"repository" : {
"type":"git",
@@ -21,7 +21,7 @@
"engines" : { "node" : ">=12.0.0" },
"author": {
"name": "Dave Conway-Jones",
- "email": "ceejay@vnet.ibm.com",
+ "email": "dceejay@gmail.com",
"url": "http://nodered.org"
}
}
From a8edd0cb56b7f1a6022eea53dacab5f0e5458028 Mon Sep 17 00:00:00 2001
From: Dave Conway-Jones
Date: Tue, 31 Jan 2023 12:24:33 +0000
Subject: [PATCH 68/86] Add Serialport css to try to highlight blank inputs
---
io/serialport/25-serial.html | 26 +++++++++++++-------------
io/serialport/package.json | 2 +-
2 files changed, 14 insertions(+), 14 deletions(-)
diff --git a/io/serialport/25-serial.html b/io/serialport/25-serial.html
index dfc73f5e..30469ddd 100644
--- a/io/serialport/25-serial.html
+++ b/io/serialport/25-serial.html
@@ -117,22 +117,22 @@