2

Accordding to my last question SerialPort 'close' event never fire. I was unabled to detected if the COM is disconnected so I have created my own way to detect it.

I have created timestamp, and checked it with interval() every 1 sec to see if it is connected. when it's detect the COM is unplugged I have try to re-establish the connection or re-instance port with SerialPort like you'll see inside the code below.

When it's try to reconnect I've get Error: Access denied.

There is a way to refresh or clean the cache? , because I think the server still hold the connection when isn't closed propely.

I've also tried port.close() and it's throw me out: Error: Port is not open.

var comPort = '\\\\.\\COM7',
    lastDataTime,
    lastresult,
    count = 0,
    lastDataTime,
    comStatus,
    error;
var port = new SerialPort(comPort, function (err) {
    if (err) {
        comStatus = false;
        return console.log('Error: ', err.message);
    }
});
const parser = port.pipe(new Readline());
port.on('open', function () {
    console.log('~Port is open.');

    parser.on('data', function (data) {
        comStatus = true;
        lastDataTime = Date.now();
        if (++count == 10) {
            count = 0;
            lastresult = data;
        }
    });
});

setInterval(function () {
    if (Date.now() - lastDataTime > 1000 || !comStatus) {
        comStatus = false;
        port.close();
        port = new SerialPort(comPort, function (err) {
            if (err) {
                error = 'Error: ' + err.message;
                return console.log(error);
            }
        });
    }
}, 1000);


app.get('/', function (req, res) {
    res.send((comStatus) ? lastresult : 'Disconnected - ' + error);
    console.log(lastresult);
})

Thanks!

Itzik.B
  • 1,023
  • 2
  • 15
  • 35

2 Answers2

2

As you can see in /node_modules/serialport/lib/serialport.js: close-event may not be emitted (unlike disconnect).

You can add console.log locally like below to simple debug.

P.S. I tested it on Win7x32. Close-event is emitted.

SerialPort.prototype._disconnected = function(err) {
  this.paused = true;
  this.emit('disconnect', err);

  // add: console.log('1', this.closing);

  if (this.closing) {
    return;
  }

  // add: console.log('2', this.fd);

  if (this.fd === null) {
    return;
  }

  this.closing = true;
  if (process.platform !== 'win32') {
    this.readable = false;
    this.serialPoller.close();
  }

  // add: console.log('3');

  SerialPortBinding.close(this.fd, function(err) {
    // add: console.log('4', this._events.close.toString());

    this.closing = false;
    if (err) {
      debug('Disconnect close completed with error: ', err);
    }
    this.fd = null;
    this.emit('close'); // it's your target
  }.bind(this));
};

Reconnect example

var SerialPort = require('serialport');
var port = new SerialPort('COM1', {autoOpen: false, baudRate: 9600});

function open () {
    port.open(functon (err) {
        if (!err)
           return;

        console.log('Port is not open: ' + err.message);
        setTimeout(open, 10000); // next attempt to open after 10s
    });
}

port.on('open', function() {
    function send() {
        if (!port.isOpen()) // v5.x require
            return console.log('Port closed. Data is not sent.');

        port.write(123, function (err) {
            if (err)
                console.log('Error on write: ' +  err.message)

            port.drain(() => console.log('DONE'));
        });
    }

    setInterval(send, 1000);
});

port.on('close', function () {
    console.log('CLOSE');
    open(); // reopen 
});

port.on('data', (data) => console.log('Data: ' + data));
port.on('error', (err) => console.error('Error: ', err.message));

open(); // open manually
Aikon Mogwai
  • 4,954
  • 2
  • 18
  • 31
  • Thanks that helped!, after the event fire i've tried reconnect the `COM` but after i reconnect it the data stop flowing. do you know how to reconnect after disconnect? – Itzik.B Sep 19 '17 at 22:41
1

According to the serialport.io,

The resume() method causes an explicitly paused, Readable stream to resume emitting 'data' events, switching the stream into flowing mode.

Simply, when port is closes, serialport library emits a close event

serialport.on('close', function(error){
  if(error.disconnected === true){
    console.log("disconnected");
 }
} 

, which will allow us whether port is disconnected or not.

That means the disconnected port is not available to re-establish the connection again, so you have to use serialport.resume() method to re-enable the connection.

serialport.on('close', function(err){
  console.log("Port closed.");
  if(err.disconnected === true){
    console.log("Disconnected!");
    serialport.resume(function(e){
      reconnectDevice(); // Serial Port Initialization Function. It's your method to declare serial port.
      console.log("Error on resuming port:", e);
    });
  }
});

After that, it will automatically switch COM ports and you won't get error as 'Port Access denied.'.

zemunkh
  • 662
  • 7
  • 13