Using Web Serial with ReactJS

2.2k views Asked by At

I am having a random set of data bits that I need to write to a serial port using a React app. When implementing using vanilla javascript the script is able to write to the esp module using serialport but when implementing the same in reactjs it doesn't work. Do I need to use a server (With Django in backend) or socket protocol instead of directly accessing serial from React.

2

There are 2 answers

0
Yourself On

If you are using React, https://gist.github.com/joshpensky/426d758c5779ac641d1d09f9f5894153 gist exists. Just copy and paste it into a new file, wrap your app in the SerialProvider component, then use useSerial wherever you want to use serial.

0
Kevin Dick On

You can do this with Chromium browsers (Chrome, Chromium, Edge) at this point using the web serial API. You do not need a backend, but you can call values from a backend in case you have different serial devices (I use this for scales and they are all different).

There are a few libraries that can help you implement this, but you can also do so natively from the API. Here are some resources:

You must, at this point, enable experimental web platform features in chrome://flags/, but this will eventually become part of the browser implementation.

You can test with https://googlechromelabs.github.io/serial-terminal/

You can see device logs at about://device-log

The API requires a user interaction. Basically, when you call the port a window pops up that lists available ports. The user chooses the port (e.g., 'USB Serial Connector' for certain RS-232 to USB adapters). Once connected, the serial device should stream, push or pull depending on its settings.

There are a few libraries that make this easier if you don't want to write your own. In Angular, I use browser-serial and change the values of the 'serialOptions' object with backend data from an API.

Example (the 'serial' object is from the library):

async connectToScale(user: User) {
    if (!user.scale) {
      return;
    }
    console.log("Connecting to scale: ", user.scale);

    this.serial.serialOptions = {
      baudRate: user.scale.baud_rate,
      dataBits: user.scale.data_bit,
      stopBits: user.scale.stop_bit,
      bufferSize: user.scale.buffer_size,
      flowControl: "none",
    };

    const regex = new RegExp(user.scale.regex);

    await this.serial.connect();

    this.serial.readLoop((output: string, _done: boolean) => {
      const result = regex.exec(output);
      if (!result) {
        console.warn("Could not parse the scale output - regex issue:\n", output);
        return true;
      }
      console.log("Result from parsing raw scale output:\n", result);

let weight: number;
      weight = parseInt(result[0]);

      const scaleWeight: ScaleWeight = { scale: weight };
      console.log("Pushing to scaleValue:", scaleWeight);
      this.scaleValue.next(scaleWeight);
      return true;
    });
  }