nodejs чтение парсера последовательного порта - PullRequest
0 голосов
/ 20 июня 2020

Я пытаюсь прочитать данные чип-карты с помощью устройства чтения карт, подключенного к последовательному USB-порту моего RPi.

Хотя я могу читать и писать, у меня возникают проблемы с настройкой парсеров, обещаний и т. Д. c ...

Основная проблема в том, что при чтении asyn c я не могу использовать стандартный синтаксический анализатор, так как ридер общается в двоичных данных (я использую буфер). Полученные данные НЕ обозначаются стандартным символом.

Протокол:

Я отправляю:

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>

и с каждым разом все становится хуже time:

========== 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) { 

Но я просто не понимаю, как это обойти.

1 Ответ

0 голосов
/ 22 июня 2020

Если вы не используете порт (переменную 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(...);

Возможно, есть способ получше, но он тоже должен работать.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...