nodejs-serialport => ПОВТОРНО установить соединение с портом после закрытия

В соответствии с моим последним вопросом событие закрытия SerialPort никогда не срабатывает. Мне не удалось обнаружить, если COM отключен, поэтому я создал свой собственный способ его обнаружения.

Я создал временную метку и проверял ее с помощью interval() каждую 1 секунду, чтобы убедиться, что она подключена. когда он обнаруживает, что COM отключен, я пытаюсь восстановить соединение или переустановить порт с SerialPort, как вы увидите в коде ниже.

При попытке повторного подключения получаю Error: Access denied.

Есть способ обновить или почистить кеш? , потому что я думаю, что сервер все еще удерживает соединение, когда оно не закрыто должным образом.

Я также пробовал port.close(), и это выкинуло меня: 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);
})

Спасибо!


person itzikb    schedule 19.09.2017    source источник


Ответы (2)


Как вы можете видеть в /node_modules/serialport/lib/serialport.js: close-событие может не генерироваться (в отличие от disconnect).

Вы можете добавить console.log локально, как показано ниже, для простой отладки.

P.S. Я проверил это на Win7x32. Close-выдается событие.

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));
};

Пример повторного подключения

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
person Aikon Mogwai    schedule 19.09.2017
comment
Спасибо, что помогло! После пожара события я попытался переподключить COM, но после повторного подключения данные перестают передаваться. Вы знаете, как переподключиться после отключения? - person itzikb; 20.09.2017

По данным serialport.io,

Метод возобновления () заставляет явно приостановленный поток Readable возобновить отправку событий «данных», переключая поток в непрерывный режим.

Просто, когда порт закрывается, библиотека последовательного порта генерирует событие закрытия.

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

, что позволит нам, отключен ли порт или нет.

Это означает, что отключенный порт недоступен для повторного установления соединения, поэтому вам необходимо использовать метод serialport.resume() для повторного включения соединения.

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);
    });
  }
});

После этого он автоматически переключит COM-порты, и вы не получите сообщение об ошибке «Отказано в доступе к порту».

person zemunkh    schedule 12.09.2019