简体   繁体   English

Node.js | 如何通过串口向设备发送和接收一个字节?

[英]Node.js | How to send and receive one byte to a device through serial port?

I am trying to write Node.js script that uses the serialport npm package to read and write data to COM5 serial port, which is connected to a device using RS-232 cable.我正在尝试编写 Node.js 脚本,该脚本使用serialport package 读取和写入数据到COM5串口,该串口使用 RS-23 连接到设备。 This device is automatically transmitting the data it has.该设备正在自动传输其拥有的数据。

To retrieve the data stored inside the device, I need to send, first, one byte 0x80 ( uInt8 ) to the device and expect to receive 81 as a hex number from the device.要检索存储在设备内的数据,我需要首先向设备发送一个字节 0x80 ( uInt8 ),并期望从设备接收 81 作为十六进制数。 Second, I need to send another byte 0x81 ( uInt8 ) and then expect to receive all stored data (around 130000 bytes) as lines.其次,我需要发送另一个字节 0x81 ( uInt8 ),然后期望以行的形式接收所有存储的数据(大约 130000 字节)。

There is no way how to retrieve the whole stored data only by two bytes, one after another.没有办法如何仅通过两个字节,一个接一个地检索整个存储的数据。 Communication with the device can only be done by bytes.与设备的通信只能通过字节来完成。

I tried the following code:我尝试了以下代码:

import SerialPort from 'serialport';

const sp = new SerialPort.SerialPort({path: "COM5", baudRate: 115200});

const buff = Buffer.allocUnsafe(1);
buff.writeUInt8(0x80, 0);

sp.write(buff, function (err){
    if (err){
        return console.log("Error on write: ", err.message);
    }
    console.log("Port.write: ", buff);
});

sp.on('readable', function () {
    var arr = new Uint8Array(sp._pool);
    console.log('Data:', arr);
});

When running my script (using node myScript.mjs ), I see the following:运行我的脚本(使用node myScript.mjs )时,我看到以下内容:

PortWrite:  <Buffer 80>
Data: Uint8Array(65536) [
    0,  30, 167, 106, 127,   2,  0,  0,  32,  31, 170, 106,
  127,   2,   0,   0,   0, 128,  0,  0,   0,   0,   0,   0,
   16,  84,  18,  76, 196,   0,  0,  0, 100,  84,  18,  76,
  196,   0,   0,   0, 184,  84, 18, 76, 196,   0,   0,   0,
  160,  84,  18,  76, 196,   0,  0,  0, 244,  84,  18,  76,
  196,   0,   0,   0,  72,  85, 18, 76, 196,   0,   0,   0,
  240, 120,  18,  76, 196,   0,  0,  0,  68, 121,  18,  76,
  196,   0,   0,   0, 152, 121, 18, 76, 196,   0,   0,   0,
  240, 120,  18,  76,
  ... 65436 more items
]

The program doesn't exit until I hit Ctrl+c .在我按下Ctrl+c之前程序不会退出。 I am not sure what ps._pool does but it seems the output is not correct but looks like giving something at random.我不确定ps._pool做了什么,但似乎 output 不正确,但看起来像是随机给出的东西。

I am new to Node.js.我是 Node.js 的新手。 I am also not sure how to add an argument TimeOut of 10 seconds in the sp object.我也不确定如何在sp object 中添加 10 秒的参数TimeOut

I tried to use Matlab, for testing, and I could retrieve the data successfully.我尝试使用Matlab进行测试,我可以成功检索到数据。

I tried Python too but didn't work for me - PySerial package is reading serial data before writing?我也试过 Python 但对我不起作用 - PySerial package 在写入之前读取串行数据? . .

I believe you are listening for your data incorrectly.我相信您正在错误地收听您的数据。 SerialPort is a form of a stream called aduplex which are both readable and writable. SerialPort 是 stream 的一种形式,称为双工,可读写。 To listen for new data on a stream it is common practice to listen for the data event .要在 stream 上侦听新数据,通常的做法是侦听data事件

Also worth noting in Javascript when variables start with an underscore, such as _pool it usually means its a private variable which isn't generally suppose to use.在 Javascript 中还值得注意的是,当变量以下划线开头时,例如_pool它通常意味着它是一个通常不应该使用的私有变量。 See this SO question for more info有关更多信息,请参阅此SO 问题

Simply rewriting sp.on('readable', function () { part to be只需重写sp.on('readable', function () { part to be

sp.on('data', function(buffer) {
    console.log(buffer);
});

Should make you start seeing the data your expecting.应该让您开始看到您期望的数据。


To test this I wrote up the scenario you outlined but only wrote 10,000 bytes after 0x81 to test.为了测试这一点,我写了你概述的场景,但在 0x81 之后只写了 10,000 个字节来测试。

Please don't take this as great way to work with streams in JS.请不要将此视为在 JS 中处理流的好方法。 This was my attempt at doing it "lightweight" and there's probably better ways to write this这是我尝试做“轻量级”的尝试,可能有更好的方法来写这个

const {SerialPort} = require('serialport');

const sp = new SerialPort({path: "COM2", baudRate: 115200});

function Deferred(data) {
    this.data = data;
    this.resolve = null;
    this.reject = null;
    this.reset = () => {
        this.promise = new Promise(function(resolve, reject) {
            this.resolve = resolve;
            this.reject = reject;
        }.bind(this));
    }

    this.reset();
}

async function run() {
    let readBuffer = Buffer.alloc(0);
    let nextReadDeferred = new Deferred();

    sp.on('data', function(newData) {
        readBuffer = Buffer.concat([readBuffer, newData], newData.length + readBuffer.length)
        console.log('Got new data: ' + newData.length + ' buffer length is ' + readBuffer.length);
        nextReadDeferred.resolve(readBuffer);
        nextReadDeferred.reset();
    });

    console.log('Start 0x80')
    sp.write(Buffer.from([0x80]), e => { if(e) throw e; });
    await nextReadDeferred.promise;
    if(0x81 === readBuffer[0]) {
        // clear the buffer in prep of getting our data
        readBuffer = Buffer.alloc(0);
        console.log('Send 0x81 to start data flow')
        sp.write(Buffer.from([0x81]), e => { if(e) throw e; });

        console.log('Starting to receive data. Not sure how to know when were done?');
        // Dont know what to do here, I dont think the serial port closes. Maybe we are supposed to just expect a duration
        // of no data transfer? I dont know a whole lot about COM communication
    } else {
        console.warn('Expected 0x81 but got', readBuffer)
    }
}

run();

Output: Output:

$ node index.js
Start 0x80
Got new data: 1 buffer length is 1
Send 0x81 to start data flow
Starting to receive data. Not sure how to know when were done?
Got new data: 1024 buffer length is 1024
Got new data: 4096 buffer length is 5120
Got new data: 1024 buffer length is 6144
Got new data: 3856 buffer length is 10000

To test this I used eterlogic for a virtual com port backed with a TCP server and the following Node code to be my "device"为了测试这一点,我将eterlogic用于虚拟 com 端口,该端口支持 TCP 服务器和以下节点代码作为我的“设备”

const s = require('net').Socket();
s.connect(5555, '127.0.0.1');

s.on('data', function(d){
    console.log('Got', d);
    if(d.equals(Buffer.from([0x80]))) {
        s.write(Buffer.from([0x81]));
    } else if(d.equals(Buffer.from([0x81]))) {
        s.write(Buffer.alloc(10000, 1));
    }
});

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM