diff --git a/io/serialport/25-serial.js b/io/serialport/25-serial.js index 66703c76..0a7803bf 100644 --- a/io/serialport/25-serial.js +++ b/io/serialport/25-serial.js @@ -25,10 +25,10 @@ module.exports = function(RED) { this.dsr = n.dsr || "none"; this.bin = n.bin || "false"; this.out = n.out || "char"; - this.enable = n.enable || true; + this.enabled = n.enabled || true; this.waitfor = n.waitfor || ""; this.responsetimeout = n.responsetimeout || 10000; - + this.changePort = (serialPort) => { serialPool.close(this.serialport,() => {}); this.serialport = serialPort.serialport || this.serialport; @@ -95,6 +95,9 @@ module.exports = function(RED) { node.port.on('closed', function() { node.status({fill:"red",shape:"ring",text:"node-red:common.status.not-connected"}); }); + node.port.on('stopped', function() { + node.status({fill:"grey",shape:"ring",text:"serial.status.stopped"}); + }); } RED.nodes.registerType("serial out",SerialOutNode); @@ -117,7 +120,7 @@ module.exports = function(RED) { this.on("close", function(done) { serialPool.close(this.serialConfig.serialport,done); - }); + }); function setCallback(node) { node.status({fill:"grey",shape:"dot",text:"node-red:common.status.not-connected"}); @@ -132,13 +135,16 @@ module.exports = function(RED) { node.port.on('closed', function() { node.status({fill:"red",shape:"ring",text:"node-red:common.status.not-connected"}); }); + node.port.on('stopped', function() { + node.status({fill:"grey",shape:"ring",text:"serial.status.stopped"}); + }); }; setCallback(node) } RED.nodes.registerType("serial in",SerialInNode); - /******* REQUEST *********/ + // request data and waits for reply function SerialRequestNode(n) { RED.nodes.createNode(this,n); this.serial = n.serial; @@ -197,13 +203,15 @@ module.exports = function(RED) { node.status({ fill: "red", shape: "ring", text: "serial.status.timeout" }); node.send(msgout); }); - 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" }); }); + node.port.on('stopped', function() { + node.status({fill:"grey",shape:"ring",text:"serial.status.stopped"}); + }); }; setCallback(node); } @@ -223,11 +231,11 @@ module.exports = function(RED) { RED.nodes.registerType("serial request", SerialRequestNode); - // Serial Control Node - function PortSelectNode(n) { + // control node to stop, start, reconfigure ports + function SerialControlNode(n) { const configProps = [ "serialport", "serialbaud", "databits", "parity", "stopbits", - "dtr", "rts", "cts", "dsr", "bin", "out" + "dtr", "rts", "cts", "dsr" ] RED.nodes.createNode(this,n); this.serialConfig = RED.nodes.getNode(n.serial); @@ -239,32 +247,43 @@ module.exports = function(RED) { this.serial = n.serial; var node = this; - node.port = serialPool.get(this.serialConfig); + node.port = serialPool.get(node.serialConfig); + node.port.on('stopped', function() { + node.status({fill:"grey",shape:"ring",text:"serial.status.stopped"}); + }); + node.port.on('ready', function() { + node.status({fill:"green",shape:"dot",text:node.serialConfig.serialbaud+","+node.serialConfig.databits+","+(node.serialConfig.parity.toUpperCase().substr(0,1))+","+node.serialConfig.stopbits}); + }); node.on("input",function(msg) { - if (configProps.some((p) =>{return msg.payload.hasOwnProperty(p)})) { - msg.payload.enable = msg.payload.hasOwnProperty('enable') ? msg.payload.enable : true; + if (msg.hasOwnProperty("flush") && msg.flush === true) { node.port.serial.flush(); } + if (configProps.some((p) => { return msg.payload.hasOwnProperty(p) })) { + msg.payload.enabled = msg.payload.hasOwnProperty('enabled') ? msg.payload.enabled : true; node.serialConfig.changePort(msg.payload); } - if (msg.payload.hasOwnProperty("enable")) { - // if any of config parameters or enable property is passed, do this control - node.serialConfig.enable = msg.payload.enable; - if (msg.payload.enable === true) { + var stat = {fill:"green",shape:"dot",text:node.serialConfig.serialbaud+","+node.serialConfig.databits+","+(node.serialConfig.parity.toUpperCase().substr(0,1))+","+node.serialConfig.stopbits} + if (msg.payload.hasOwnProperty("enabled")) { + node.serialConfig.enabled = msg.payload.enabled; + if (msg.payload.enabled === true || msg.payload.enabled === "true") { node.serialConfig.emit('start'); - } else { + } + else { serialPool.close(node.serialConfig.serialport,() => { RED.log.info("[serialconfig:"+node.serialConfig.id+"] " + RED._("serial.stopped",{port:node.serialConfig.serialport})); }); + stat.fill = "grey"; + stat.shape = "ring"; } } let currentConfig = {}; configProps.map((p) => { currentConfig[p] = node.serialConfig[p]; }); - currentConfig.enable = node.serialConfig.enable; - node.send({payload: currentConfig}); + currentConfig.enabled = node.serialConfig.enabled; + node.status(stat); + node.send({payload:currentConfig}); }); } - RED.nodes.registerType("serial control", PortSelectNode); + RED.nodes.registerType("serial control", SerialControlNode); var serialPool = (function() { var connections = {}; @@ -442,6 +461,9 @@ module.exports = function(RED) { setupSerial(); }, serialReconnectTime); } + else { + obj._emitter.emit('stopped'); + } }); obj.serial.on('open',function() { olderr = ""; diff --git a/io/serialport/README.md b/io/serialport/README.md index 423eb7b1..4b9557b7 100644 --- a/io/serialport/README.md +++ b/io/serialport/README.md @@ -18,7 +18,7 @@ you to install the full set of tools in order to compile the underlying package. ## Usage -Provides three nodes - one to receive messages, and one to send, and a request node which can send then wait for a response. +Provides four nodes - one to receive messages, and one to send, a request node which can send then wait for a response, and a control node that allows dynamic control of the ports in use. ### Input @@ -56,49 +56,47 @@ Send the request message in `msg.payload` as you would do with a serial out node For consistency with the serial in node, msg.port is also set to the name of the port selected. -### Serial Control -When the node-red starts, the flow(program) picks up the pre-programmed serial port, open it, and start the communication. But there are some cases the port needs to switch to a different port, stop, and start again. For example, in order to upload a new binary for Arduino, the serial port needs to be stopped relased from the nodered, and start it again after uploading. Or when the FTDI device re-connects after disconnected for any reason, it may be possible the port number change, and the end user of the flow can't change the port. +### Control +When the node-red starts, the flow(program) picks up the pre-programmed serial port, open it, and starts the communication. But there are some cases the port needs to switch to a different port, stop, and start again. For example, in order to upload a new binary for Arduino, the serial port needs to be stopped relased from the nodered, and start it again after uploading. Or when the FTDI device re-connects after disconnecting for any reason, it may be possible that the port number changes, and the end user of the flow can't change the port. -This `Serial Control` node provides the serial port control capability to -1. change the serial port and its configuration on the run time programatically. -2. stop the communication and releasing the serial port so, for example the Arduino can upload the new binary without shutting down the nodered. -3. start the communication after stopped with this `Serial Control` node for above reason or the like. +This node provides the ability to: + + 1. change the serial port and its configuration on the run time programatically. + 2. stop the communication and release the serial port. + 3. reopen the port and restart the communications. + +In order to control the communication, send a **msg.payload** to the control node. -
In order to control the communication, just send these JSON messages to the control node.
-{ - "serialport": "/dev/tty.usbmodem1234561", + "serialport": "/dev/ttyUSB0", "serialbaud": 115200, "databits": 8, "parity": "none", - "stopbits": 1 - "enable": true - } -+ "stopbits": 1, + "enabled": true + } + changes the serial port and the configuration on the fly. -
The following optional parameters will change the configuration only if they are present.
-Any combination of them can be passed to change/control the serial communication
-