diff --git a/io/serialport/25-serial.html b/io/serialport/25-serial.html
index 30469ddd..96472f2c 100644
--- a/io/serialport/25-serial.html
+++ b/io/serialport/25-serial.html
@@ -230,7 +230,7 @@
RED.nodes.registerType('serial-port',{
category: 'config',
defaults: {
- //name: {value:""},
+ name: {value:""},
serialport: {value:"",required:true},
serialbaud: {value:"57600",required:true,validate:RED.validators.number()},
databits: {value:8,required:true},
@@ -252,7 +252,7 @@
this.databits = this.databits || 8;
this.parity = this.parity || this._("serial.label.none");
this.stopbits = this.stopbits || 1;
- return this.serialport+":"+this.serialbaud+"-"+this.databits+this.parity.charAt(0).toUpperCase()+this.stopbits;
+ return this.name||(this.serialport+":"+this.serialbaud+"-"+this.databits+this.parity.charAt(0).toUpperCase()+this.stopbits);
},
oneditprepare: function() {
var previous = null;
@@ -361,3 +361,37 @@
}
});
+
+
+
+
\ No newline at end of file
diff --git a/io/serialport/25-serial.js b/io/serialport/25-serial.js
index 64093ceb..ceb10dd9 100644
--- a/io/serialport/25-serial.js
+++ b/io/serialport/25-serial.js
@@ -27,42 +27,102 @@ module.exports = function(RED) {
this.out = n.out || "char";
this.waitfor = n.waitfor || "";
this.responsetimeout = n.responsetimeout || 10000;
- }
- RED.nodes.registerType("serial-port",SerialPortNode);
+
+ this.newPort = (serialPort) => {
+ serialPool.close(this.serialport,() => {});
+ this.serialport = serialPort.port;
+ this.serialbaud = parseInt(serialPort.serialbaud) || this.serialbaud;
+ this.databits = parseInt(serialPort.databits) || this.databits;
+ this.parity = serialPort.parity || this.parity;
+ this.stopbits = parseInt(serialPort.stopbits) || this.stopbits;
+ this.dtr = serialPort.dtr || this.dtr;
+ this.rts = serialPort.rts || this.rts;
+ this.cts = serialPort.cts || this.cts;
+ this.dsr = serialPort.dsr || this.dsr;
+ this.bin = serialPort.bin || this.bin;
+ this.out = serialPort.out || this.out;
+ this.waitfor = serialPort.waitfor || this.waitfor;
+ this.responsetimeout = n.responsetimeout || 10000;
+ return serialPool.get(this);
+ }
+ };
+ RED.nodes.registerType("serial-port",SerialPortNode);
// receives msgs and sends them to the serial port
function SerialOutNode(n) {
RED.nodes.createNode(this,n);
+ this.serialConfig = RED.nodes.getNode(n.serial);
+
+ if (!this.serialConfig) {
+ this.error(RED._("serial.errors.missing-conf"), {});
+ return;
+ }
+
this.serial = n.serial;
- this.serialConfig = RED.nodes.getNode(this.serial);
+ var node = this;
+ node.port = serialPool.get(this.serialConfig);
+ var serialConfig = this.serialConfig;
- if (this.serialConfig) {
- var node = this;
- node.port = serialPool.get(this.serialConfig);
+ this.serialConfig.on('newport', function(newPort) {
+ node.port = serialPool.get(serialConfig);
+ });
- node.on("input",function(msg) {
- if (msg.hasOwnProperty("baudrate")) {
- var baud = parseInt(msg.baudrate);
- if (isNaN(baud)) {
- node.error(RED._("serial.errors.badbaudrate"),msg);
- } else {
- node.port.update({baudRate: baud},function(err,res) {
- if (err) {
- var errmsg = err.toString().replace("Serialport","Serialport "+node.port.serial.path);
- node.error(errmsg,msg);
- }
- });
- }
+ node.on("input",function(msg) {
+ if (msg.hasOwnProperty("baudrate")) {
+ var baud = parseInt(msg.baudrate);
+ if (isNaN(baud)) {
+ node.error(RED._("serial.errors.badbaudrate"),msg);
+ } else {
+ node.port.update({baudRate: baud},function(err,res) {
+ if (err) {
+ var errmsg = err.toString().replace("Serialport","Serialport "+node.port.serial.path);
+ node.error(errmsg,msg);
+ }
+ });
}
- if (!msg.hasOwnProperty("payload")) { return; } // do nothing unless we have a payload
- var payload = node.port.encodePayload(msg.payload);
- node.port.write(payload,function(err,res) {
- if (err) {
- var errmsg = err.toString().replace("Serialport","Serialport "+node.port.serial.path);
- node.error(errmsg,msg);
- }
- });
+ }
+ if (!msg.hasOwnProperty("payload")) { return; } // do nothing unless we have a payload
+ var payload = node.port.encodePayload(msg.payload);
+ node.port.write(payload,function(err,res) {
+ if (err) {
+ var errmsg = err.toString().replace("Serialport","Serialport "+node.port.serial.path);
+ node.error(errmsg,msg);
+ }
+ });
+ });
+ node.port.on('ready', function() {
+ node.status({fill:"green",shape:"dot",text:"node-red:common.status.connected"});
+ });
+ node.port.on('closed', function() {
+ node.status({fill:"red",shape:"ring",text:"node-red:common.status.not-connected"});
+ });
+ }
+ RED.nodes.registerType("serial out",SerialOutNode);
+
+ // receives data from the serial port and emits msgs
+ function SerialInNode(n) {
+ RED.nodes.createNode(this,n);
+ this.serialConfig = RED.nodes.getNode(n.serial);
+
+ if (!this.serialConfig) {
+ this.error(RED._("serial.errors.missing-conf"), {});
+ return;
+ }
+
+ this.serial = n.serial;
+ var node = this;
+
+ this.serialConfig.on('newport', function(newPort) {
+ setCallback(node, node.serialConfig);
+ });
+
+ function setCallback(node) {
+ node.status({fill:"grey",shape:"dot",text:"node-red:common.status.not-connected"});
+ node.port = serialPool.get(node.serialConfig);
+
+ node.port.on('data', function(msgout) {
+ node.send(msgout);
});
node.port.on('ready', function() {
node.status({fill:"green",shape:"dot",text:"node-red:common.status.connected"});
@@ -70,56 +130,8 @@ module.exports = function(RED) {
node.port.on('closed', function() {
node.status({fill:"red",shape:"ring",text:"node-red:common.status.not-connected"});
});
- }
- else {
- this.error(RED._("serial.errors.missing-conf"), {});
- }
-
- this.on("close", function(done) {
- if (this.serialConfig) {
- serialPool.close(this.serialConfig.serialport,done);
- }
- else {
- done();
- }
- });
- }
- RED.nodes.registerType("serial out",SerialOutNode);
-
-
- // receives data from the serial port and emits msgs
- function SerialInNode(n) {
- RED.nodes.createNode(this,n);
- this.serial = n.serial;
- this.serialConfig = RED.nodes.getNode(this.serial);
-
- if (this.serialConfig) {
- var node = this;
- node.status({fill:"grey",shape:"dot",text:"node-red:common.status.not-connected"});
- node.port = serialPool.get(this.serialConfig);
-
- this.port.on('data', function(msgout) {
- node.send(msgout);
- });
- this.port.on('ready', function() {
- node.status({fill:"green",shape:"dot",text:"node-red:common.status.connected"});
- });
- this.port.on('closed', function() {
- node.status({fill:"red",shape:"ring",text:"node-red:common.status.not-connected"});
- });
- }
- else {
- this.error(RED._("serial.errors.missing-conf"), {});
- }
-
- this.on("close", function(done) {
- if (this.serialConfig) {
- serialPool.close(this.serialConfig.serialport,done);
- }
- else {
- done();
- }
- });
+ };
+ setCallback(node)
}
RED.nodes.registerType("serial in",SerialInNode);
@@ -200,6 +212,32 @@ module.exports = function(RED) {
}
RED.nodes.registerType("serial request", SerialRequestNode);
+
+ // Port Select Node
+ function PortSelectNode(n) {
+ RED.nodes.createNode(this,n);
+ this.serialConfig = RED.nodes.getNode(n.serial);
+
+ if (!this.serialConfig) {
+ this.error(RED._("serial.errors.missing-conf"), {});
+ return;
+ }
+
+ this.serial = n.serial;
+ var node = this;
+ node.port = serialPool.get(this.serialConfig);
+ node.on("input",function(msg) {
+ if (msg.payload.hasOwnProperty("port")) {
+ node.serialConfig.newPort(msg.payload);
+ node.serialConfig.emit('newport',msg.payload);
+ node.send(msg);
+ } else {
+ node.send({payload: {port: node.serialConfig.serialport}});
+ }
+ });
+ }
+ RED.nodes.registerType("port select", PortSelectNode);
+
var serialPool = (function() {
var connections = {};
return {
diff --git a/io/serialport/README.md b/io/serialport/README.md
index a5965222..b82cdb41 100644
--- a/io/serialport/README.md
+++ b/io/serialport/README.md
@@ -55,3 +55,18 @@ This node behaves as a tightly coupled combination of serial in and serial out n
Send the request message in `msg.payload` as you would do with a serial out node. The message will be forwarded to the serial port following a strict FIFO (First In, First Out) queue, waiting for a single response before transmitting the next request. Once a response is received (with the same logic of a serial in node), or after a timeout occurs, a message is produced on the output, with msg.payload containing the received response (or missing in case if timeout), msg.status containing relevant info, and all other fields preserved.
For consistency with the serial in node, msg.port is also set to the name of the port selected.
+
+### Port Select
+
+Provides the capability to change the serial ports on the run time programatically.
+
+When you start the node-red, the flow(program) picks up the pre-programmed serial ports and open them. But when a device re-connects after disconnecting for any reason, it may be possible the port number change, and the end user of the flow can't change the port. With this `port selection node`, it's possible to let the user change the port while running the program by sending a message like this.
+```json
+{
+ "port": "/dev/tty.usbmodem1234561",
+ "serialbaud": 115200,
+ "databits": 8,
+ "parity": "none",
+ "stopbits": 1
+}
+```