Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Expecting 14 bytes, reader.read() not consistently reading 14 bytes. #124

Closed
kevindekemele opened this issue Feb 25, 2021 · 3 comments
Closed

Comments

@kevindekemele
Copy link

kevindekemele commented Feb 25, 2021

I have an arduino sending 14 bytes numerical data.
I manage to connect to the arduino, and to read. But, not everytime I get 14 bytes, sometimes less sometimes more.
This piece of code send a "0" every 50 ms. Then the arduino will send 14 bytes. I then print the array length, which should be 14:

      async read() {
          setInterval( async ()=>{ let array = [];
           await this.writer.write(this.encoder.encode("0"));
            try {
                const { value} = await this.reader.read();
                console.log(value.length);
                return this.decoder.decode(value.length);
            }
            catch (err) {
                const errorMessage = `error reading data: ${err}`;
                console.error(errorMessage);
                return errorMessage;
            }},50)
          
        }

Obsering the console.log:

image

Reveals that about 90 % of the time, 14 bytes are received. How do I ensure consistend reads?

Thanks in advance.

@kevindekemele kevindekemele changed the title Expecting 14 bytes, reader.read() not consistently reader 14 bytes. Expecting 14 bytes, reader.read() not consistently reading 14 bytes. Feb 25, 2021
@reillyeon
Copy link
Collaborator

From the lengths reported it appears that the device is always sending 14 bytes but that sometimes the data is chunked into different sized pieces. For example, 9 + 19 = 28 which is 14 * 2.

This is expected behavior. The Promise returned by the read() function is resolved with all the data that has been received so far by the port. If no data is available yet then it will resolve when some arrives. Calling it on an interval as you do means that if the two devices are perfectly in sync and 14 bytes are sent every 50ms you will get 14 bytes from every call to read(), but the devices are likely to get out of sync and so read() is called early and gets less then 14 bytes and then called late and gets more because the data available includes the next message in addition to the bytes which were missed the first time.

Using setInterval() to call read() like this is unnecessary because it is an asynchronous function. Rather than calling read() periodically your application can be reading all the time and the asynchronous function will "wake up" whenever there is new data. Note that if you do this you will find that read() returns even smaller chunks, since your Javascript code can pull data from the port much faster than the device sends it. You will need to combine multiple chunks into a single 14 byte message if that is what the rest of your application expects. One way to accomplish this is with a TransformStream. In this example I show how to build a transformer which breaks ASCII messages on newlines. Breaking binary messages on a 14-byte boundary can be done similarly.

CC @ricea, it looks like whatwg/streams#1003 already tracks adding an alternative to read() where the developer can indicate the number of bytes they want the reader to wait for before resolving the Promise. As pointed out there, this can also be polyfilled efficiently using a BYOB reader.

@marciot
Copy link

marciot commented Feb 26, 2021

@kevindekemele: In addition to the suggestions already given, you might want to take a look at the SequentialSerial class I posted in #125. I ran into similar problems as you and I wrote a wrapper to deal with the situation. My code isn't particularly efficient, but I think it may do what you want.

@reillyeon
Copy link
Collaborator

Closing this issue. The answers above should resolve the reporter's issue and there has been no response.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants