【问题标题】:nodejs reading serialport parsernodejs读取串口解析器
【发布时间】:2020-06-20 09:31:40
【问题描述】:

我正在尝试使用连接到我的 RPi 的 USB 串行端口的读卡器读取芯片卡数据。

虽然我可以读写,但我在设置解析器、promise 等时遇到了麻烦...

主要问题是读取异步我不能使用标准解析器,因为阅读器以二进制数据进行通信(我使用缓冲区)。接收到的数据不以标准字符结尾。

协议是:

我发送:

STX (0x02)
LenMsb (Most significant byte of package length)
LenLsb (Least sig. byte of package length)
Param1
Param2
Data (if needed)
ETX (0x03)
BCC (checksum)

我收到了 ACK (0x06) 或 NAK (0x15)

如果我收到 ACK,我会发送 ENQ (0x05)

读者以上述格式的打包响应。

所以基本上我需要开始读取包,检查长度,等待 ETX,检查校验和,然后才处理它。

任何人都可以帮忙设置这个。我把全局缓冲区弄得一团糟,等等。

这就是我做这一切的呼吁。

function sp288do(port, cmd){
    return new Promise(function(resolve, reject) { 
        // I send the prepared command
        port.write(cmdPrep(cmd), function () {
            console.log('Send CMD')
            port.on('data', function(data) { 
                // log what I read 
                console.log ('<<------', data);
                
                if (data[0] == NAK) { //not awk
                    console.log("Rcvd NAK");
                    data = null;
                    reject(NAK)
                    return;
                }

                if(data[0] == ACK) { //awk
                    console.log ("Rcvd ACK");
                    // data = null;
                    data = null;
                    console.log('Send ENQ')
                    port.write(Buffer.from([ENQ]), function () {
                        buffer = [];
                    })
                    return;
                }   
/*** 
if I get here, it means I have to wait for the whole data packet.
The total package length will be in buffer[2], plus STR, lMSB, lLSB .... EOT, BCC
So, if it tells me 2 bytes of data in buffer[2], I have to wait for 2 + 5 = 7 bytes.
***/                

                var expected = 0;
                for (i=0; i<data.length; i++) {
                    buffer[buffer.length] = data[i];
                    
                    if(buffer.length > 3 && expected == 0) {
                        expected = buffer[2] + 5;
                    }
                        
                    if (expected > 0 && buffer.length >= expected)
                        return(resolve(buffer));
                    
                }           

            })
        });      
    });
}

我调用函数:

sp288do(sp288, cmd).then(res => {
            console.log("Result:" , res);
            console.log ("=====================================================");
})      

发生的情况是,我第一次调用该函数时,一切正常:

========== Requesting Presence ====================
SENDING COMMAND
Send CMD
<<------ <Buffer 06>
Rcvd ACK
Send ENQ
<<------ <Buffer 02>
<<------ <Buffer 00 03>
<<------ <Buffer 31 30 4e>
<<------ <Buffer 03 4d>
Result: [
   2,  0, 3, 49,
  48, 78, 3, 77
]
=====================================================

但是如果我再调用一次,就好像两次读取串口一样:


========== Requesting Presence ====================
SENDING COMMAND
Send CMD
<<------ <Buffer 06>
Rcvd ACK
Send ENQ
<<------ <Buffer 06>
Rcvd ACK
Send ENQ
<<------ <Buffer 02>
<<------ <Buffer 02>
<<------ <Buffer 00 03 31>
<<------ <Buffer 00 03 31>
Result: [ 2, 2, 0, 3, 49, 0 ]
=====================================================
<<------ <Buffer 30 4e 03 4d>
<<------ <Buffer 30 4e 03 4d>

而且每次都会变得最糟糕:

========== Requesting Presence ====================
SENDING COMMAND
Send CMD
<<------ <Buffer 06>
Rcvd ACK
Send ENQ
<<------ <Buffer 06>
Rcvd ACK
Send ENQ
<<------ <Buffer 06>
Rcvd ACK
Send ENQ
<<------ <Buffer 02 00>
<<------ <Buffer 02 00>
<<------ <Buffer 02 00>
<<------ <Buffer 03 31 30>
<<------ <Buffer 03 31 30>
<<------ <Buffer 03 31 30>
Result: [
  2, 0, 2, 0, 2,
  0, 3, 3, 3
]
=====================================================
<<------ <Buffer 4e 03 4d>
<<------ <Buffer 4e 03 4d>
<<------ <Buffer 4e 03 4d>

我了解到,每次调用该函数时,我都会“安装”另一个侦听器:

port.on('data', function(data) { 

但我根本无法理解如何绕过它。

【问题讨论】:

  • 您需要向我们展示您尝试过的代码。指定问题出在哪里,您希望它做什么以及它实际做什么。
  • 抱歉,我发布了不完整的问题。现在我已经用完整的代码等编辑了问题......

标签: node.js raspberry-pi serial-port


【解决方案1】:

如果您没有在代码中的其他任何地方使用端口(sp288 变量),那么这样做可能会解决您的问题。

function SP288(options) {
    // this is only example, i don't know how you created the sp288 variable
    var port = this.port = require('sp288').connect(options);

    port.on('data', this.ondata);
};

SP288.prototype.cmd = function(cmd) {

    var self = this;
    return new Promise(function(resolve, reject){
        // you may need to queue the command if the previous one hasn't finished yet
        // since you would overwrite the ondata function
        self.queue.push({ cmd, resolve, reject });
        if (!self.processing)
            self._process();
    });
};

SP288.prorotype._process = function() {
    var self = this;

    if (self.processing)
         return;
    
    if (self.queue.length) {

        self.processing = true;

        var item = self.queue.shift(); // take the first command in the queue

        self.ondata = function(data) {
        
            // do your things with data
        
            item.resolve(); // or item.reject();
            self.processing = false;
            self.ondata = function(){}; // if there bwere some more data this will prevent resolve/reject being called twice
            self._process(); // process next command if there's one in the queue
        };
        self.port.write(cmdPrep(item.cmd));
    }
};

像这样使用它:

var sp288 = new SP288(options);

sp288.cmd(...)
.then(...)
.catch(...);

可能还有更好的方法,但这也应该有效。

【讨论】:

    猜你喜欢
    • 2011-08-27
    • 2023-03-20
    • 2018-04-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-06-28
    相关资源
    最近更新 更多