[英]Node.js | How to send and receive one byte to a device through serial port?
我正在尝试编写 Node.js 脚本,该脚本使用serialport
package 读取和写入数据到COM5
串口,该串口使用 RS-23 连接到设备。 该设备正在自动传输其拥有的数据。
要检索存储在设备内的数据,我需要首先向设备发送一个字节 0x80 ( uInt8
),并期望从设备接收 81 作为十六进制数。 其次,我需要发送另一个字节 0x81 ( uInt8
),然后期望以行的形式接收所有存储的数据(大约 130000 字节)。
没有办法如何仅通过两个字节,一个接一个地检索整个存储的数据。 与设备的通信只能通过字节来完成。
我尝试了以下代码:
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);
});
运行我的脚本(使用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
]
在我按下Ctrl+c
之前程序不会退出。 我不确定ps._pool
做了什么,但似乎 output 不正确,但看起来像是随机给出的东西。
我是 Node.js 的新手。 我也不确定如何在sp
object 中添加 10 秒的参数TimeOut
。
我尝试使用Matlab进行测试,我可以成功检索到数据。
我也试过 Python 但对我不起作用 - PySerial package 在写入之前读取串行数据? .
我相信您正在错误地收听您的数据。 SerialPort 是 stream 的一种形式,称为双工,可读写。 要在 stream 上侦听新数据,通常的做法是侦听data
事件。
在 Javascript 中还值得注意的是,当变量以下划线开头时,例如_pool
它通常意味着它是一个通常不应该使用的私有变量。 有关更多信息,请参阅此SO 问题
只需重写sp.on('readable', function () {
part to be
sp.on('data', function(buffer) {
console.log(buffer);
});
应该让您开始看到您期望的数据。
为了测试这一点,我写了你概述的场景,但在 0x81 之后只写了 10,000 个字节来测试。
请不要将此视为在 JS 中处理流的好方法。 这是我尝试做“轻量级”的尝试,可能有更好的方法来写这个
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:
$ 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
为了测试这一点,我将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.