【问题标题】:Unplugging serial device causes error 'bad file descriptor'; reinitialising the serial port ends up receiving inconsistent data拔出串行设备会导致错误“错误文件描述符”;重新初始化串口最终会收到不一致的数据
【发布时间】:2021-01-12 14:23:06
【问题描述】:

以下 node.js 脚本扫描自定义 FTDI 设备的所有端口,一旦找到该设备,它会检查其序列号和温度。 console.log 显示:

Serial number: 1003
Temperature: 28

如果我拔下设备,我会收到以下错误:Port closed: bad file descriptor。当我重新插入设备时,我得到了一些未定义的行为。有时我得到正确的序列号但温度不正确:

Serial number: 1003
Temperature: 0

有时我会收到来自设备的回复unknown command(代码未显示在下面的 sn-p 中)。但是,如果我在 Visual Studio Code 中调试脚本,在 ftdiPort = new serialPort(path, {baudRate: 115200}); 处设置断点并在重新连接设备后等待 4 秒以上继续,我会得到正确的数据。

代码:

'use strict';
const serialPort = require('serialport');
let ftdiPort;

searchFtdiPort();

//Check all ports every 1 second if device is connected
function searchFtdiPort() {
    let checkPorts = setInterval(function() {
        serialPort.list().then(ports => {
            for(let i = 0; i < ports.length; i++) {
                if(ports[i].manufacturer == 'FTDI') {
                    openFtdiPort(ports[i].path);
                    clearInterval(checkPorts);
                    break;
                }
            }
        });
    }, 1000);
}

//When device is connected, open port and ask for serial number and temperature
function openFtdiPort(path) {
    ftdiPort = new serialPort(path, {baudRate: 115200});
    let Readline = require('@serialport/parser-readline');
    let parser = ftdiPort.pipe(new Readline({delimiter: '\n'}));
    ftdiPort.on('open', function() {
        getSerial(path);
        getTemperature(path);
    });
    ftdiPort.on('error', function(error) {
        console.log('Port error: ', error.message);
    });
    ftdiPort.on('close', function(info) {
        console.log('Port closed: ', info.message);
        searchFtdiPort();
    });
    parser.on('data', function(data) {
        parseFtdiData(data);
    });
}

function parseFtdiData(data) {
    let key = res[0];
    let value = res[1];
    switch(key) {
        case 'serial':
            console.log('Serial number:', value);
            break;
        case 'fmcw_temp':
            console.log('Temperature:', value);
            break;
        default:
            console.log('Key not specified.');
            break;
    }
}

function getSerial(path) {
    let serialCmd = 'get_serial\n';
    ftdiPort.write(serialCmd, function(error) {
        if(error) {
            console.log('Writing on port failed: ', error.message);
            return;
        }
        console.log('Write', serialCmd, 'on', path);
    });
}
function getTemperature(path) {
    let serialCmd = 'fmcw_temp\n';
    ftdiPort.write(serialCmd, function(error) {
        if(error) {
            console.log('Writing on port failed: ', error.message);
            return;
        }
        console.log('Write', serialCmd, 'on', path);
    });
}

Linux 上的调试信息(例如,我在这里得到的是 unknown command 而不是 temperature=0):

user@linux-ayq9:~/Desktop/Service> DEBUG=* node test.js 
  serialport/bindings loading LinuxBinding +0ms
  serialport/stream .list +0ms
  serialport/stream opening path: /dev/ttyUSB0 +51ms
  serialport/binding-abstract open +0ms
  serialport/stream _read queueing _read for after open +1ms
  serialport/bindings/poller Creating poller +0ms
  serialport/stream opened path: /dev/ttyUSB0 +0ms
  serialport/stream _write 11 bytes of data +1ms
  serialport/binding-abstract write 11 bytes +2ms
  serialport/stream _read reading { start: 0, toRead: 65536 } +0ms
  serialport/binding-abstract read +1ms
  serialport/bindings/unixWrite Starting write 11 bytes offset 0 bytesToWrite 11 +0ms
  serialport/bindings/unixRead Starting read +0ms
  serialport/bindings/unixWrite write returned: wrote 11 bytes +0ms
  serialport/bindings/unixWrite Finished writing 11 bytes +1ms
  serialport/stream binding.write write finished +2ms
  serialport/stream _write 10 bytes of data +0ms
  serialport/binding-abstract write 10 bytes +1ms
Write get_serial
 on /dev/ttyUSB0
  serialport/bindings/unixWrite Starting write 10 bytes offset 0 bytesToWrite 10 +0ms
  serialport/bindings/unixRead read error { [Error: EAGAIN: resource temporarily unavailable, read] errno: -11, code: 'EAGAIN', syscall: 'read' } +1ms
  serialport/bindings/unixRead waiting for readable because of code: EAGAIN +0ms
  serialport/bindings/poller Polling for "readable" +3ms
  serialport/bindings/unixWrite write returned: wrote 10 bytes +1ms
  serialport/bindings/unixWrite Finished writing 10 bytes +0ms
  serialport/stream binding.write write finished +1ms
Write fmcw_temp
 on /dev/ttyUSB0
  serialport/bindings/poller received "readable" +16ms
  serialport/bindings/unixRead Starting read +16ms
  serialport/bindings/unixRead Finished read 48 bytes +0ms
  serialport/stream binding.read finished { bytesRead: 48 } +15ms
Serial number: 1003
Temperature: 28
  serialport/stream _read reading { start: 48, toRead: 65488 } +0ms
  serialport/binding-abstract read +16ms
  serialport/bindings/unixRead Starting read +0ms
  serialport/bindings/unixRead read error { [Error: EAGAIN: resource temporarily unavailable, read] errno: -11, code: 'EAGAIN', syscall: 'read' } +1ms
  serialport/bindings/unixRead waiting for readable because of code: EAGAIN +0ms
  serialport/bindings/poller Polling for "readable" +1ms
  serialport/bindings/poller error [Error: bad file descriptor] +3s
  serialport/stream binding.read error [Error: bad file descriptor] +3s
  serialport/stream disconnected [Error: bad file descriptor] +0ms
  serialport/stream #close +1ms
  serialport/binding-abstract close +3s
  serialport/stream _read queueing _read for after open +0ms
  serialport/bindings/poller Stopping poller +2ms
  serialport/bindings/poller Destroying poller +1ms
  serialport/stream binding.close finished +1ms
Port closed:  bad file descriptor
  serialport/stream .list +1s
  serialport/stream .list +1s
  serialport/stream .list +1s
  serialport/stream opening path: /dev/ttyUSB0 +44ms
  serialport/binding-abstract open +3s
  serialport/stream _read queueing _read for after open +0ms
  serialport/bindings/poller Creating poller +3s
  serialport/stream opened path: /dev/ttyUSB0 +2ms
  serialport/stream _write 11 bytes of data +0ms
  serialport/binding-abstract write 11 bytes +2ms
  serialport/stream _read reading { start: 0, toRead: 65536 } +0ms
  serialport/binding-abstract read +0ms
  serialport/bindings/unixWrite Starting write 11 bytes offset 0 bytesToWrite 11 +6s
  serialport/bindings/unixRead Starting read +6s
  serialport/bindings/unixWrite write returned: wrote 11 bytes +0ms
  serialport/bindings/unixWrite Finished writing 11 bytes +0ms
  serialport/stream binding.write write finished +0ms
  serialport/stream _write 10 bytes of data +0ms
  serialport/binding-abstract write 10 bytes +0ms
Write get_serial
 on /dev/ttyUSB0
  serialport/bindings/unixWrite Starting write 10 bytes offset 0 bytesToWrite 10 +0ms
  serialport/bindings/unixRead read error { [Error: EAGAIN: resource temporarily unavailable, read] errno: -11, code: 'EAGAIN', syscall: 'read' } +0ms
  serialport/bindings/unixRead waiting for readable because of code: EAGAIN +1ms
  serialport/bindings/poller Polling for "readable" +2ms
  serialport/bindings/unixWrite write returned: wrote 10 bytes +1ms
  serialport/bindings/unixWrite Finished writing 10 bytes +0ms
  serialport/stream binding.write write finished +1ms
Write fmcw_temp
 on /dev/ttyUSB0
  serialport/bindings/poller received "readable" +21ms
  serialport/bindings/unixRead Starting read +21ms
  serialport/bindings/unixRead Finished read 71 bytes +0ms
  serialport/stream binding.read finished { bytesRead: 71 } +22ms
Unknown command: get_serial
Unknown command: fmcw_temp
  serialport/stream _read reading { start: 71, toRead: 65465 } +0ms
  serialport/binding-abstract read +23ms
  serialport/bindings/unixRead Starting read +1ms
  serialport/bindings/unixRead read error { [Error: EAGAIN: resource temporarily unavailable, read] errno: -11, code: 'EAGAIN', syscall: 'read' } +0ms
  serialport/bindings/unixRead waiting for readable because of code: EAGAIN +0ms
  serialport/bindings/poller Polling for "readable" +1ms

因此,在连接丢失后重新初始化端口似乎无法正常工作。我不知道这是否是 node.js 串行端口的一般问题,或者我是否错误地使用了该包。也许这与我的 Linux 发行版有关(顺便说一下,它是 openSuse 15.1)。 如果有人可以在这里帮助我,我会很高兴。谢谢。

【问题讨论】:

    标签: node.js linux serial-port ftdi


    【解决方案1】:

    如前所述,如果您在重新连接设备后等待 4 秒以上继续操作,您将获得正确的数据,这意味着缓冲区没有被清除或之前的操作仍在进行中。

    看来嵌入式设备可能正忙于处理先前的命令或某些中间缓冲区没有被清除。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-09-27
      • 2011-12-18
      • 2016-08-26
      • 2022-11-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多