Search code examples
node.jsarduinoserial-portnode-serialport

Why isn't node SerialPort Readline parser working?


I've got an Arduino sending very basic messages:

Serial.print('R');
Serial.println(1);

or

Serial.print('R');
Serial.println(2);

I'm trying to read each line using node.js and the SerialPort module but I get inconsistent results:

Data: <Buffer 52 31 0d 0a> R1

Data: <Buffer 52 32 0d 0a> R2

Data: <Buffer 52 31 0d 0a> R1

Data: <Buffer 52 32 0d 0a> R2

Data: <Buffer 52 31 0d 0a> R1

Data: <Buffer 52 32 0d 0a> R2

Data: <Buffer 52 31 0d 0a> R1

Data: <Buffer 52 32 0d 0a> R2

Data: <Buffer 52> R
Data: <Buffer 31 0d 0a> 1

Data: <Buffer 52 32 0d 0a> R2

And here's how I've tried to parse:

this.port = new SerialPort(portName, {
            baudRate: baudRate,
            autoOpen:false,
            flowControl: false,
            parser: new Readline("\r\n")
        });

        this.port.open(function (err) {
            if (err) {
                return console.log('Error opening port: ', err.message);
            }

            console.log("port open!");

        });

        this.port.on('error', function(err) {
            console.log('Error: ', err.message);
        })

        this.port.on('open', function() {
            console.log("open event called");
        });

        this.port.on('data', function (data) {
            console.log('Data:', data,data.toString('utf8'));
        });

In short: I'm expecting R1, R2 messages coming in consistently, not split up like this:

Data: <Buffer 52> R
Data: <Buffer 31 0d 0a> 1

I'm passing ("\r\n" / 0x0d 0x0a) to Readline. What am I missing ? How can I get consistent new line parsing using SerialPort in node ?


Solution

  • I think that the solution to your problem requires to bind an event on the parser object, while you're currently listening it on the port object. Data that arrives trough the port is not always terminated by 0x0d 0x0a (*). Those two byte are a string terminator signal for the ReadLine parser only.

    Thus, maybe you should write this listener in your code instead:

    // I'm not actually sure where parser lives, I'm not
    // in the condition of trying by myself...
    this.port.parser.on('data', function (data) {
      console.log('Data:', data,data.toString('utf8'));
    });
    

    Unfortunately, I don't have any suggestion to make the syntax more elegant, and for my standard this solution is more elegant than create a function that redirects bindings for you. It depends on your application though, and at the moment I don't have enough information to suggest a possible better solution.

    (*) In the first (wrong) comment that I immediately deleted, I asked why you put both byte as termination to the line 0x0d 0x0a (\r\n), and not simply 0x0a (\n) but the Serial.println method actually writes both bytes by default.