diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 526464a6..9c8cea7f 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -11,7 +11,7 @@ Put an `x` in the boxes that apply --> - [ ] Bugfix (non-breaking change which fixes an issue) -- [ ] New feature (non-breaking change which adds functionality) +- [x] New feature (non-breaking change which adds functionality) +Adds authentication option to the Email node (node-red-node-email) to use OAuth and XOAuth2 +********** This version: IMAP ONLY ********** + ## Checklist -- [ ] I have read the [contribution guidelines](https://github.com/node-red/node-red-nodes/blob/master/CONTRIBUTING.md) -- [ ] For non-bugfix PRs, I have discussed this change on the forum/slack team. -- [ ] I have run `grunt` to verify the unit tests pass -- [ ] I have added suitable unit tests to cover the new/changed functionality +- [x] I have read the [contribution guidelines](https://github.com/node-red/node-red-nodes/blob/master/CONTRIBUTING.md) +- [x] For non-bugfix PRs, I have discussed this change on the forum/slack team. +- [x] I have run `grunt` to verify the unit tests pass +- [x] I have added suitable unit tests to cover the new/changed functionality diff --git a/.gitignore b/.gitignore index 729dabf3..7d7e9f83 100644 --- a/.gitignore +++ b/.gitignore @@ -8,3 +8,4 @@ setenv.sh package-lock.json social/xmpp/92-xmpp.old *.tgz +.DS_Store diff --git a/function/random/package.json b/function/random/package.json index 13ac148e..ba190135 100644 --- a/function/random/package.json +++ b/function/random/package.json @@ -1,6 +1,6 @@ { "name" : "node-red-node-random", - "version" : "0.4.0", + "version" : "0.4.1", "description" : "A Node-RED node that when triggered generates a random number between two values.", "dependencies" : { }, diff --git a/function/random/random.js b/function/random/random.js index 681cfefe..1b9f0c50 100644 --- a/function/random/random.js +++ b/function/random/random.js @@ -18,9 +18,8 @@ module.exports = function(RED) { if (node.low) { // if the the node has a value use it tmp.low = Number(node.low); } else if ('from' in msg) { // else see if a 'from' is in the msg - if (Number(msg.from)) { // if it is, and is a number, use it - tmp.low = Number(msg.from); - } else { // otherwise setup NaN error + tmp.low = Number(msg.from); + if (isNaN(msg.from)) { // if it isn't a number setup NaN error tmp.low = NaN; tmp.low_e = " From: " + msg.from; // setup to show bad incoming msg.from } @@ -31,9 +30,8 @@ module.exports = function(RED) { if (node.high) { // if the the node has a value use it tmp.high = Number(node.high); } else if ('to' in msg) { // else see if a 'to' is in the msg - if (Number(msg.to)) { // if it is, and is a number, use it - tmp.high = Number(msg.to); - } else { // otherwise setup NaN error + tmp.high = Number(msg.to); + if (isNaN(msg.to)) { // if it isn't a number setup NaN error tmp.high = NaN tmp.high_e = " To: " + msg.to // setup to show bad incoming msg.to } diff --git a/hardware/PiGpio/36-rpi-gpio.js b/hardware/PiGpio/36-rpi-gpio.js index d93a8a40..ae234c49 100644 --- a/hardware/PiGpio/36-rpi-gpio.js +++ b/hardware/PiGpio/36-rpi-gpio.js @@ -45,46 +45,59 @@ 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.code === "ENOENT") { node.error(RED._("rpi-gpio.errors.commandnotfound")+err.path,err); } + else if (err.code === "EACCES") { node.error(RED._("rpi-gpio.errors.commandnotexecutable")+err.path,err); } + else { node.error(RED._("rpi-gpio.errors.error",{error:err.code}),err) } + }); + + node.child.stdin.on('error', function (err) { + if (!node.finished) { + node.error(RED._("rpi-gpio.errors.error",{error:err.code}),err); + } + }); + } + 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); @@ -108,10 +121,13 @@ 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, () => { + if (node.child) { + node.child.kill('SIGKILL'); + } + }); } - else { done(); } + else { if (done) { done(); } } }); } RED.nodes.registerType("rpi-gpio in",GPIOInNode); @@ -188,11 +204,16 @@ module.exports = function(RED) { }); 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")+': ' + err.errno); } + if (err.code === "ENOENT") { node.error(RED._("rpi-gpio.errors.commandnotfound")+err.path,err); } + else if (err.code === "EACCES") { node.error(RED._("rpi-gpio.errors.commandnotexecutable")+err.path,err); } + else { node.error(RED._("rpi-gpio.errors.error",{error:err.code}),err) } }); + node.child.stdin.on('error', function (err) { + if (!node.finished) { + node.error(RED._("rpi-gpio.errors.error",{error:err.code}),err); + } + }); } else { node.warn(RED._("rpi-gpio.errors.invalidpin")+": "+node.pin); @@ -210,10 +231,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(); } }, 50); + }); } - else { done(); } + else { if (done) { done(); } } }); } diff --git a/hardware/PiGpio/locales/de/36-rpi-gpio.json b/hardware/PiGpio/locales/de/36-rpi-gpio.json index 9024f880..8f8c621e 100644 --- a/hardware/PiGpio/locales/de/36-rpi-gpio.json +++ b/hardware/PiGpio/locales/de/36-rpi-gpio.json @@ -66,8 +66,8 @@ "invalidinput": "Ungültige Eingabe", "needtobeexecutable": "__command__ muss ausführbar sein", "mustbeexecutable": "nrgpio muss ausführbar sein", - "commandnotfound": "nrgpio-Befehl nicht gefunden", - "commandnotexecutable": "nrgpio-Befehl nicht ausführbar", + "commandnotfound": "nrgpio-Befehl nicht gefunden ", + "commandnotexecutable": "nrgpio-Befehl nicht ausführbar ", "error": "Fehler: __error__", "pythoncommandnotfound": "nrgpio-Python-Befehl nicht aktiv" } diff --git a/hardware/PiGpio/locales/en-US/36-rpi-gpio.json b/hardware/PiGpio/locales/en-US/36-rpi-gpio.json index 8931f170..fdc1bcec 100644 --- a/hardware/PiGpio/locales/en-US/36-rpi-gpio.json +++ b/hardware/PiGpio/locales/en-US/36-rpi-gpio.json @@ -66,8 +66,8 @@ "invalidinput": "Invalid input", "needtobeexecutable": "__command__ needs to be executable", "mustbeexecutable": "nrgpio must to be executable", - "commandnotfound": "nrgpio command not found", - "commandnotexecutable": "nrgpio command not executable", + "commandnotfound": "nrgpio command not found ", + "commandnotexecutable": "nrgpio command not executable ", "error": "error: __error__", "pythoncommandnotfound": "nrgpio python command not running" } diff --git a/hardware/PiGpio/locales/ja/36-rpi-gpio.json b/hardware/PiGpio/locales/ja/36-rpi-gpio.json index 619eb3ef..644980a8 100644 --- a/hardware/PiGpio/locales/ja/36-rpi-gpio.json +++ b/hardware/PiGpio/locales/ja/36-rpi-gpio.json @@ -66,8 +66,8 @@ "invalidinput": "入力が不正です", "needtobeexecutable": "__command__ は実行可能である必要があります", "mustbeexecutable": "nrgpio は実行可能である必要があります", - "commandnotfound": "nrgpio コマンドが見つかりません", - "commandnotexecutable": "nrgpio コマンドが実行可能ではありません", + "commandnotfound": "nrgpio コマンドが見つかりません ", + "commandnotexecutable": "nrgpio コマンドが実行可能ではありません ", "error": "エラー: __error__", "pythoncommandnotfound": "nrgpio python コマンドが実行されていません" } diff --git a/hardware/PiGpio/locales/ko/36-rpi-gpio.json b/hardware/PiGpio/locales/ko/36-rpi-gpio.json index 323ae882..a5161ac9 100644 --- a/hardware/PiGpio/locales/ko/36-rpi-gpio.json +++ b/hardware/PiGpio/locales/ko/36-rpi-gpio.json @@ -65,8 +65,8 @@ "invalidinput": "입력이 올바르지 않습니다", "needtobeexecutable": "__command__ 은 실행가능상태일 필요가 있습니다 ", "mustbeexecutable": "nrgpio 은 실행가능상태일 필요가 있습니다 ", - "commandnotfound": "nrgpio 커맨드를 찾을수 없습니다", - "commandnotexecutable": "nrgpio 커맨드가 실행가능상태가 아닙니다", + "commandnotfound": "nrgpio 커맨드를 찾을수 없습니다 ", + "commandnotexecutable": "nrgpio 커맨드가 실행가능상태가 아닙니다 ", "error": "에러: __error__", "pythoncommandnotfound": "nrgpio python 커맨드가 실행되지 않았습니다" } diff --git a/hardware/PiGpio/package.json b/hardware/PiGpio/package.json index e445708c..7581e563 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.6", "description": "The basic Node-RED node for Pi GPIO", "dependencies" : { }, diff --git a/hardware/intel/mraa-gpio-ain.html b/hardware/intel/mraa-gpio-ain.html index 93d5a5ae..57b19627 100644 --- a/hardware/intel/mraa-gpio-ain.html +++ b/hardware/intel/mraa-gpio-ain.html @@ -1,7 +1,7 @@ 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); diff --git a/hardware/intel/mraa-gpio-dout.html b/hardware/intel/mraa-gpio-dout.html index ed0289ac..b9808617 100644 --- a/hardware/intel/mraa-gpio-dout.html +++ b/hardware/intel/mraa-gpio-dout.html @@ -1,7 +1,7 @@ diff --git a/hardware/intel/mraa-gpio-dout.js b/hardware/intel/mraa-gpio-dout.js index 020db558..6bb833d3 100644 --- a/hardware/intel/mraa-gpio-dout.js +++ b/hardware/intel/mraa-gpio-dout.js @@ -29,6 +29,7 @@ module.exports = function(RED) { }); this.on('close', function() { + node.p.close(); }); } RED.nodes.registerType("mraa-gpio-dout", gpioDout); diff --git a/hardware/intel/mraa-gpio-led.html b/hardware/intel/mraa-gpio-led.html new file mode 100644 index 00000000..985774fa --- /dev/null +++ b/hardware/intel/mraa-gpio-led.html @@ -0,0 +1,85 @@ + + + + + + diff --git a/hardware/intel/mraa-gpio-led.js b/hardware/intel/mraa-gpio-led.js new file mode 100644 index 00000000..d9a4ce08 --- /dev/null +++ b/hardware/intel/mraa-gpio-led.js @@ -0,0 +1,86 @@ +module.exports = function(RED) { + var m = require('mraa'); + function LEDNode(n) { + RED.nodes.createNode(this, n); + this.pin = Number(n.pin); + 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.color) { + case 0: + set_led_green(this.led_green, this.led_red); + break; + case 1: + set_led_red(this.led_green, this.led_red); + break; + case 2: + set_led_orange(this.led_green, this.led_red); + break; + default: + console.log("unexpected"); + break; + } + } + else { + turn_off_led(this.led_green, this.led_red); + } + }); + + this.on('close', function() { + 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); + + RED.httpAdmin.get('/mraa-gpio/:id', RED.auth.needsPermission('mraa-gpio.read'), function(req,res) { + res.json(m.getPlatformType()); + }); + + RED.httpAdmin.get('/mraa-version/:id', RED.auth.needsPermission('mraa-version.read'), function(req,res) { + res.json(m.getVersion()); + }); +} diff --git a/hardware/intel/mraa-gpio-pwm.html b/hardware/intel/mraa-gpio-pwm.html index 2dfb95e6..c1d078bc 100644 --- a/hardware/intel/mraa-gpio-pwm.html +++ b/hardware/intel/mraa-gpio-pwm.html @@ -1,7 +1,7 @@ diff --git a/hardware/intel/mraa-gpio-pwm.js b/hardware/intel/mraa-gpio-pwm.js index 22b02cb4..6a2469f2 100644 --- a/hardware/intel/mraa-gpio-pwm.js +++ b/hardware/intel/mraa-gpio-pwm.js @@ -21,6 +21,7 @@ module.exports = function(RED) { this.on('close', function() { node.p.enable(false); + node.p.close(); }); } RED.nodes.registerType("mraa-gpio-pwm", gpioPWM); diff --git a/hardware/intel/package.json b/hardware/intel/package.json index d360b4e5..6238514b 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.3.0", + "description" : "A Node-RED node to talk to an Intel Galileo, Edison or Siemens IOT2050 board using mraa", "dependencies" : { }, "repository" : { @@ -10,18 +10,27 @@ "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", "mraa-gpio-din": "mraa-gpio-din.js", "mraa-gpio-dout": "mraa-gpio-dout.js", - "mraa-gpio-pwm": "mraa-gpio-pwm.js" + "mraa-gpio-pwm": "mraa-gpio-pwm.js", + "mraa-gpio-led": "mraa-gpio-led.js" } }, "author": { "name": "Dave Conway-Jones", "email": "ceejay@vnet.ibm.com", "url": "http://nodered.org" - } + }, + "contributors": [ + { + "name": "@fr0st61te" + }, + { + "name": "@jan-kiszka" + } + ] } diff --git a/hardware/mcp3008/.DS_Store b/hardware/mcp3008/.DS_Store deleted file mode 100644 index 5008ddfc..00000000 Binary files a/hardware/mcp3008/.DS_Store and /dev/null differ diff --git a/hardware/sensehat/package.json b/hardware/sensehat/package.json index 23060bbc..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.2", + "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 67179233..f41d4360 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"; } @@ -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) { }); diff --git a/hardware/unicorn/package.json b/hardware/unicorn/package.json index 78af1a10..43ff515a 100644 --- a/hardware/unicorn/package.json +++ b/hardware/unicorn/package.json @@ -1,9 +1,9 @@ { "name" : "node-red-node-pi-unicorn-hat", - "version" : "0.1.1", + "version" : "0.1.2", "description" : "A Node-RED node to output to a Raspberry Pi Unicorn HAT from Pimorini.", "dependencies" : { - "pngjs": "2.2.*" + "pngjs": "2.3.1" }, "repository" : { "type":"git", diff --git a/hardware/wemo/README.md b/hardware/wemo/README.md index d5a6dbd7..03995a84 100644 --- a/hardware/wemo/README.md +++ b/hardware/wemo/README.md @@ -16,7 +16,7 @@ Run the following command in your Node-RED user directory - typically `~/.node-r The output node switches a socket, a light or group of lights on or off -This should be backward compatible with the pervious version of this node but will benefit +This should be backward compatible with the previous version of this node but will benefit from opening the config dialog and selecting the node you want. The node accepts the following `msg.payload` as input diff --git a/hardware/wemo/package.json b/hardware/wemo/package.json index 339b6ced..8dc74a6d 100644 --- a/hardware/wemo/package.json +++ b/hardware/wemo/package.json @@ -28,14 +28,14 @@ ], "license": "Apache-2.0", "dependencies": { - "node-ssdp": "~3.2.5", - "request": "~2.74.0", + "node-ssdp": "~3.3.0", + "request": "~2.88.2", "xml2js": "~0.4.13", - "util": "~0.10.3", + "util": "~0.12.4", "url": "~0.11.0", - "ip": "~1.0.1", - "body-parser": "~1.14.1", - "q": "~1.4.1" + "ip": "~1.1.5", + "body-parser": "~1.20.0", + "q": "~1.5.1" }, "node-red": { "nodes": { diff --git a/io/ping/88-ping.js b/io/ping/88-ping.js index c7119ba1..505f9380 100644 --- a/io/ping/88-ping.js +++ b/io/ping/88-ping.js @@ -4,7 +4,7 @@ module.exports = function(RED) { var spawn = require("child_process").spawn; var plat = require("os").platform(); - function doPing(node, host, arrayMode) { + function doPing(node, host, msg, arrayMode) { const defTimeout = 5000; var ex, ex6, hostOptions, commandLineOptions; if (typeof host === "string") { @@ -20,7 +20,8 @@ module.exports = function(RED) { hostOptions.timeout = hostOptions.timeout < 1000 ? 1000 : hostOptions.timeout; hostOptions.timeout = hostOptions.timeout > 30000 ? 30000 : hostOptions.timeout; var timeoutS = Math.round(hostOptions.timeout / 1000); //whole numbers only - var msg = { payload:false, topic:hostOptions.host }; + msg.payload = false; + msg.topic = hostOptions.host; //only include the extra msg object if operating in advance/array mode. if (arrayMode) { msg.ping = hostOptions @@ -221,7 +222,7 @@ module.exports = function(RED) { let pingables = generatePingList(node.host); for (let index = 0; index < pingables.length; index++) { const element = pingables[index]; - if (element) { doPing(node, element, false); } + if (element) { doPing(node, element, {}, false); } } }, node.timer); } @@ -234,12 +235,12 @@ module.exports = function(RED) { let pingables = generatePingList(payload) for (let index = 0; index < pingables.length; index++) { const element = pingables[index]; - if (element) { doPing(node, element, false); } + if (element) { doPing(node, element, RED.util.cloneMessage(msg), false); } } } else if (Array.isArray(payload) ) { for (let index = 0; index < payload.length; index++) { const element = payload[index]; - if (element) { doPing(node, element, true); } + if (element) { doPing(node, element, RED.util.cloneMessage(msg), true); } } } }); diff --git a/io/ping/package.json b/io/ping/package.json index 8f5e22be..c56918ad 100644 --- a/io/ping/package.json +++ b/io/ping/package.json @@ -1,6 +1,6 @@ { "name" : "node-red-node-ping", - "version" : "0.3.1", + "version" : "0.3.3", "description" : "A Node-RED node to ping a remote server, for use as a keep-alive check.", "dependencies" : { }, 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 @@
Simple snmp Set node. Trigger by any input
msg.host
may contain the host.
msg.community
may contain the community.
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 varbinds as an array of json objects containing multiple oids, types and values.
-
[ - { - "oid": "1.3.6.1.2.1.1.5.0", - "type": "OctetString", - "value": "host1" - }, - { "oid": ... } -]+
[
+ {
+ "oid": "1.3.6.1.2.1.1.5.0",
+ "type": "OctetString",
+ "value": "host1"
+ },
+ { "oid": ... }
+]
Any numeric inputs must be numbers, not strings, e.g. 1 not "1".
OIDs must be numeric. iso. is the same a 1.
@@ -114,12 +261,27 @@ color: "YellowGreen", defaults: { host: { value: "127.0.0.1" }, - community: { value: "public" }, version: { value: "1", required: true }, - varbinds: { value: "" }, timeout: { value: 5 }, + community: { value: "public" }, + auth: { value: "noAuthNoPriv", required: true }, + authprot: { value: "MD5", required: true }, + privprot: { value: "DES", required: true }, + oids: { value: "" }, + varbinds: { value: "", validate:function(v) { + try { + return !v || !!JSON.parse(v); + } catch(e) { + return false; + } + }}, name: { value: "" } }, + credentials: { + username: { type: "text" }, + authkey: { type: "password" }, + privkey: { type: "password" } + }, inputs: 1, outputs: 0, icon: "snmp.png", @@ -128,6 +290,9 @@ }, labelStyle: function () { return this.name ? "node_label_italic" : ""; + }, + oneditprepare: function () { + node_snmp_common.oneditprepare(this); } }); @@ -137,19 +302,58 @@Simple SNMP oid table fetcher. Triggered by any input.
msg.host
may contain the host.
msg.community
may contain the community.
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 table to request.
OID must be numeric. iso. is the same a 1.
The node will output msg.payload
and msg.oid
.
Simple SNMP oid subtree fetcher. Triggered by any input. Reads all OIDS at and below the current base OID.
msg.host
may contain the host.
msg.community
may contain the community.
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 table to request.
OID must be numeric. iso. is the same a 1.
The node will output msg.payload
and msg.oid
.
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 00000000..02b5ddc0
Binary files /dev/null and b/parsers/cbor/icons/parser-cbor.png differ
diff --git a/parsers/cbor/package.json b/parsers/cbor/package.json
new file mode 100644
index 00000000..ca9cfafd
--- /dev/null
+++ b/parsers/cbor/package.json
@@ -0,0 +1,32 @@
+{
+ "name" : "node-red-node-cbor",
+ "version" : "1.0.1",
+ "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" : {
+ "version": ">=1.0.0",
+ "nodes" : {
+ "cbor": "70-cbor.js"
+ }
+ },
+ "author": {
+ "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"
}
}
diff --git a/social/email/61-email.html b/social/email/61-email.html
index b6885ccc..d67fb52b 100644
--- a/social/email/61-email.html
+++ b/social/email/61-email.html
@@ -40,15 +40,32 @@
You may optionally set msg.from
in the payload which will override the userid
default value.
If you are accessing Gmail you may need to either enable an application password, - or enable less secure access via your Google account settings.
+If you are accessing Gmail you may need to either enable an application password.
+When connecting to a SMTP server, two authentication types are available: Basic and XOAuth2.
+msg
property to extract the access tokenSASL XOAuth2 tokens are created by combining the username and token, encoding it in base64, and passing it to the mail server in the following format:
+base64("user=" + userName + "^Aauth=Bearer " + accessToken + "^A^A")+
If the checkbox is unticked, flow creators can format the token themselves before passing it to the node.
The payload can be html format. You may supply a separate plaintext version using msg.plaintext
.
If you don't and msg.payload
contains html, it will also be used for the plaintext.
@@ -26,43 +35,78 @@
diff --git a/social/email/locales/en-US/61-email.json b/social/email/locales/en-US/61-email.json
index 9d876117..d825cb44 100644
--- a/social/email/locales/en-US/61-email.json
+++ b/social/email/locales/en-US/61-email.json
@@ -31,12 +31,24 @@
"unflagged": "Unflagged",
"unseen": "Unseen",
"autotls": "Start TLS?",
+ "authtype": "Auth type",
+ "saslformat": "Format to SASL",
+ "token": "Token",
"never": "never",
"required": "if required",
"always": "always",
- "rejectUnauthorised": "Check server certificate is valid"
+ "rejectUnauthorised": "Check server certificate is valid",
+ "enableSecure": "Secure connection",
+ "enableStarttls": "Start TLS",
+ "starttlsUpgrade": "Upgrade cleartext connection with STARTTLS",
+ "certFile": "Certificate",
+ "keyFile":"Private key",
+ "users": "Users",
+ "auth": "Authenticate users",
+ "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.",
@@ -60,6 +72,7 @@
"errors": {
"nouserid": "No e-mail userid set",
"nopassword": "No e-mail password set",
+ "notoken": "No token property set",
"nocredentials": "No Email credentials found. See info panel.",
"nosmtptransport": "No SMTP transport. See info panel.",
"nopayload": "No payload to send",
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 62046064..2d98b4c6 100644
--- a/social/email/package.json
+++ b/social/email/package.json
@@ -1,15 +1,17 @@
{
"name": "node-red-node-email",
- "version": "1.15.1",
+ "version": "2.0.0",
"description": "Node-RED nodes to send and receive simple emails.",
"dependencies": {
"imap": "^0.8.19",
- "mailparser": "^3.4.0",
- "nodemailer": "^6.7.3",
- "smtp-server": "^3.10.0"
+ "node-pop3": "^0.8.0",
+ "mailparser": "^3.6.4",
+ "nodemailer": "^6.9.1",
+ "smtp-server": "^3.11.0"
},
"bundledDependencies": [
"imap",
+ "node-pop3",
"mailparser",
"nodemailer",
"smtp-server"
@@ -26,9 +28,12 @@
"gmail",
"imap",
"pop",
+ "smtp",
+ "smtp-server",
"mta"
],
"node-red": {
+ "version": ">=1.0.0",
"nodes": {
"email": "61-email.js"
}
diff --git a/social/email/poplib.js b/social/email/poplib.js
deleted file mode 100644
index 9fcaa80f..00000000
--- a/social/email/poplib.js
+++ /dev/null
@@ -1,859 +0,0 @@
-/*
-
- Node.js POP3 client library
-
- Copyright (C) 2011-2013 by Ditesh Shashikant Gathani
The output emits a msg.payload
of 1 or 0 every minute depending on
whether the current time is during the selected on time or off time.
If you just need the transitions from 0->1 or 1->0 then follow this node with an RBE node.
+If you just need the transitions from 0->1 or 1->0 then follow this node with a filter (RBE) node.
You may also optionally specify a msg.topic
if required.