Chrome.serial.onReceive event divides bytes in responce from device

I'm building an app for Google Chrome that gets some bytes from device via COM (usb) port.

The code:

// connects the device
function connect(port_name, timeout) {
    chrome.serial.connect(port_name, {
        bitrate: 115200,
        bufferSize: 32768,
        dataBits: "eight",
        stopBits: "one",
        parityBit: "no",
        sendTimeout: timeout,
        receiveTimeout: timeout
    }, function(connectionInfo) {
        if (typeof (connectionInfo) !== 'undefined') {
            if (typeof (connectionInfo.connectionId) !== 'undefined' && connectionInfo.connectionId < 1) {
                console.log('Connection error #1');
            } else {
                sessionStorage.setItem('connection', connectionInfo.connectionId);
            }
        }
    })
}
// sends bytes to device
function send_bytes(bytes) {
    var bytes_to_send = new Uint8Array(bytes);
    var connection = Number(sessionStorage.getItem('connection'));
    chrome.serial.send(connection, (bytes_to_send).buffer, function(sent_data) {});
}
// recieves the data
chrome.serial.onReceive.addListener(function(data_recieved) {
    var arr = new Uint8Array(data_recieved.data);
    var final_hex = [];
    for (byte in arr) {
        final_hex.push(arr[byte].toString(16));
    }
    console.log('====== HEX ======');
    console.log(final_hex);
});

If I run next code in console several times:

connect('COM5',15000); // we connected!
send_bytes([0x05, 0xAD, 0x1E, 0x00, 0x00, 0x00, 0xB6]); // bytes away! ( runs N times)

Usually I receive correct HEX sequence:

["6", "2", "16", "ad", "0", "0", "0", "0", "0", "0", "10", "a", "6", "10", "20", "58", "2", "0", "0", "b5", "c0", "ea", "6a", "0", "c", "34"]

But sometimes I receive bytes separately, in two .onReceive callbacks:

 ["6", "2", "16", "ad", "0", "0", "0", "0", "0", "0", "10", "a", "6", "10", "20"]
 ["58", "2", "0", "0", "b5", "c0", "ea", "6a", "0", "c", "34"]

At first look, this happens because Chrome thinks that device completed sending data, and next part of data comes like new answer from device. I did not find any options for "time to wait for the next byte while receiving responce from device" in API documentation.

How to prevent byte sequence from separating by chrome.serial.onReceive?

Upvotes: 1

Views: 1156

Answers (1)

woxxom
woxxom

Reputation: 73746

Postpone processing if the incoming array is less than minimum response length, save the chunk and process it in the next event.

var MIN_RESPONSE_LENGTH = 26;
var incoming = new Uint8Array();

chrome.serial.onReceive.addListener(function(info) {
    appendBuffer(info.data);
    if (incoming.length < MIN_RESPONSE_LENGTH) {
        setTimeout(function() {
            console.log('Timeout waiting for the data, got only:', incoming);
        }, 1000);
        return;
    }
    // process
    console.log(incoming);
    ................
    // reset
    incoming = new Uint8Array();
});

function appendBuffer(arraybuffer) {
    var tmp = new Uint8Array(incoming.length + arraybuffer.byteLength);
    tmp.set(incoming, 0);
    tmp.set(new Uint8Array(arraybuffer), incoming.length);
    incoming = tmp;
}

Upvotes: 2

Related Questions