2 min read

Web Serial API

The Web Serial API provides a way for websites to read from and write to a serial device. These devices are connected via a serial port, or emulate a serial port over USB or Bluetooth.

1. The Concept

It bridges the web and the physical world by allowing communication with microcontrollers (like Arduino, ESP32), 3D printers, and other industrial hardware that uses serial communication (UART).

2. The Connection Flow

  1. Request Port: Ask the user to select a serial port.
  2. Open: Open the connection with specific parameters (baud rate).
  3. Read/Write: Use the Streams API (ReadableStream, WritableStream) to transfer data.

3. Requesting a Port

Like other hardware APIs, this requires a user gesture.

const button = document.getElementById('connect-serial');

button.addEventListener('click', async () => {
  try {
    // Request a port (filters are optional)
    const port = await navigator.serial.requestPort({
        filters: [{ usbVendorId: 0x2341 }] // Example: Arduino
    });

    console.log('Port selected');
    await connectToPort(port);
  } catch (error) {
    console.error('Serial Error:', error);
  }
});

4. Connecting and Communicating

Opening a port requires a baud rate. Reading and writing use standard Web Streams.

async function connectToPort(port) {
  // Open the port
  await port.open({ baudRate: 9600 });
  console.log('Port opened at 9600 baud');

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

  // Write data
  await writer.write("Hello Serial!");

  // Setup Reader
  const textDecoder = new TextDecoderStream();
  const readableStreamClosed = port.readable.pipeTo(textDecoder.writable);
  const reader = textDecoder.readable.getReader();

  // Read loop
  while (true) {
    const { value, done } = await reader.read();
    if (done) {
      // Allow the serial port to be closed later.
      reader.releaseLock();
      break;
    }
    if (value) {
      console.log('Received:', value);
    }
  }
}

5. Security and Privacy

  • HTTPS: Only works on secure contexts.
  • User Gesture: requestPort must be triggered by a user interaction.
  • Permission: The user must explicitly select the port.

6. Events

You can detect when ports are connected or disconnected.

navigator.serial.addEventListener('connect', (e) => {
  console.log('Port connected', e.target);
});

navigator.serial.addEventListener('disconnect', (e) => {
  console.log('Port disconnected', e.target);
});

programming/javascript/vanilla/javascript programming/javascript/vanilla/promises-async-await programming/javascript/vanilla/webusb-api