Search code examples
webstreamserial-portusbserialweb-serial-api

How to read bytes response from web serial api writer


I'm trying to work with Web Serial API. I want to write bytes to device and read bytes response from it.

I can write bytes as well as string to device - here everything working as expected. I can read bytes and string from device - here I have problems. Examples are showing that you can create a while(true) loop and the stream will return { value, done } flags. But I didn't find what actually done flag means. When I'm connecting to device and start this loop, it never ends.

    while (this.port.readable) {
      try {
        while (true) {
          const { value, done } = await this.reader.read();
          if (value) {
            getChunk(value);
          }
          if (done) {
            break;
          }
        }
      } catch (error) {
        console.error("Serial port reading error: " + error);
      } finally {
        this.reader.releaseLock();
      }
    }

I did find some suggestions with pipeTo function but it only operates in examples on string responses, in addition it don't work in my case:

const textEncoder = new TextEncoderStream();
const writableStreamClosed = textEncoder.readable.pipeTo(this.port.writable);
const writer = textEncoder.writable.getWriter();

await writer.write("help");
Uncaught (in promise) TypeError: Failed to execute 'pipeTo' on 'ReadableStream': Cannot pipe to a locked stream

So to sum up. How can I write bytes to device via serial API and receive back response from it.

Thanks in advance.


Solution

  • Ok, I did write my own function that reads given number of bytes. Maybe this will help someone.

    public async readBytes(numberOfBytes: number): Promise<Uint8Array> {
        let bytes: Uint8Array = new Uint8Array(numberOfBytes);
        let readBytes: number = 0;
        let finished: boolean = false;
    
        try {
          while (true) {
            const { value, done } = await this.reader.read();
            if (value) {
              let chunk: Uint8Array = value;
    
              if (readBytes === 0 && chunk[0] === SerialService.FAIL) {
                return bytes;
              }
    
              for (let i = 0; i < chunk.length; i++) {
                bytes[i] = chunk[i];
                readBytes++;
    
                if (readBytes >= numberOfBytes) {
                  finished = true;
                }
              }
            }
            if (done || finished) {
              break;
            }
          }
        } catch (error) {
          console.error("Serial port reading error: " + error);
        }
    
        return bytes;
      }