Start · Sprachen · JavaScript · Referenz · Serial

Serial

Schnittstelle

Das <code>Serial</code>-Interface der Web Serial API stellt Methoden und Events bereit, mit denen eine Webseite serielle Ports finden, anfordern und verbinden kann.

seit JavaScript Chromium 89+ (Chrome, Edge, Opera, nur Desktop); n Kategorie: webapi

Signatur

interface Serial extends EventTarget

Beschreibung

Das Serial-Interface ist der Einstiegspunkt der Web Serial API. Man greift darüber auf navigator.serial (im Fenster) bzw. self.navigator.serial (in Dedicated Workern) zu. Damit können Webanwendungen mit Geräten über serielle Schnittstellen sprechen, z. B. mit Mikrocontrollern (Arduino, ESP32), 3D-Druckern, Messgeräten, GPS-Empfängern oder USB-zu-Seriell-Adaptern. Auch Bluetooth-RFCOMM-Geräte werden in neueren Chromium-Versionen unterstützt.

Die wichtigsten Mitglieder sind:

  • requestPort(options) – öffnet einen Browser-Dialog, in dem der Nutzer einen Port auswählt. Liefert ein Promise<SerialPort>. Muss durch eine Nutzeraktion (z. B. Klick) ausgelöst werden.
  • getPorts() – liefert ein Promise<SerialPort[]> mit allen Ports, für die die Seite bereits eine Berechtigung hat (ohne Dialog).
  • Event connect – wird ausgelöst, wenn ein zuvor freigegebener Port angeschlossen wird (auch als onconnect).
  • Event disconnect – wird ausgelöst, wenn ein Port entfernt wird (auch als ondisconnect).

Nach der Auswahl wird der Port über SerialPort.open({ baudRate }) geöffnet; die Kommunikation erfolgt dann mit Streams (port.readable als ReadableStream, port.writable als WritableStream). Typischer Ablauf: beim Laden per getPorts() bekannte Geräte wiederverbinden, sonst per Button requestPort() aufrufen.

Parameter

Name Typ Default Beschreibung
$options object {} Nur für requestPort(): Optionsobjekt.
$options.filters Array<{usbVendorId?: number, usbProductId?: number, bluetoothServiceClassId?: number|string}> Schränkt die im Dialog angezeigten Geräte ein, z. B. auf eine USB-Vendor-ID (0x2341 für Arduino).
$options.allowedBluetoothServiceClassIds Array<number|string> Liste zusätzlicher Bluetooth-Service-Class-IDs (RFCOMM), die auswählbar sein sollen.

Rückgabewert

Typ
Serial
Beschreibung
navigator.serial ist eine Serial-Instanz. requestPort() liefert Promise<SerialPort>, getPorts() liefert Promise<SerialPort[]>.

Beispiele

Unterstützung prüfen und Port per Klick anfordern

const button = document.querySelector('#connect');

button.addEventListener('click', async () => {
  if (!('serial' in navigator)) {
    console.log('Web Serial API wird nicht unterstützt.');
    return;
  }
  try {
    // Nur Arduino-Geräte anzeigen (USB-Vendor-ID 0x2341)
    const port = await navigator.serial.requestPort({
      filters: [{ usbVendorId: 0x2341 }]
    });
    await port.open({ baudRate: 9600 });
    console.log('Verbunden:', port.getInfo());
  } catch (err) {
    // NotFoundError, wenn der Nutzer den Dialog abbricht
    console.log('Keine Verbindung:', err.name);
  }
});
Verbunden: { usbVendorId: 9025, usbProductId: 67 }

Bereits freigegebene Ports beim Laden wiederverwenden

const reconnect = async () => {
  const ports = await navigator.serial.getPorts();
  console.log(`${ports.length} freigegebene(r) Port(s)`);
  if (ports.length === 0) return null;

  const port = ports[0];
  await port.open({ baudRate: 115200 });
  return port;
};

reconnect().then((port) => {
  if (port) console.log('Automatisch wiederverbunden');
});
1 freigegebene(r) Port(s) Automatisch wiederverbunden

Daten lesen und schreiben über Streams

const talk = async (port) => {
  // Befehl senden
  const encoder = new TextEncoder();
  const writer = port.writable.getWriter();
  await writer.write(encoder.encode('STATUS\n'));
  writer.releaseLock();

  // Antwort lesen
  const decoder = new TextDecoderStream();
  const closed = port.readable.pipeTo(decoder.writable);
  const reader = decoder.readable.getReader();
  const { value } = await reader.read();
  console.log('Antwort:', value);

  await reader.cancel();
  await closed.catch(() => {});
  await port.close();
};
Antwort: OK temp=21.5

connect- und disconnect-Events

const onConnect = (event) => {
  console.log('Angeschlossen:', event.target.getInfo());
};

navigator.serial.addEventListener('connect', onConnect);

// Alternativ über die on-Property
navigator.serial.ondisconnect = (event) => {
  console.log('Getrennt:', event.target.getInfo());
};

// Später wieder abmelden
// navigator.serial.removeEventListener('connect', onConnect);
Getrennt: { usbVendorId: 9025, usbProductId: 67 }

// Wichtig · Fallstricke

  • Browser-Kompatibilität: Nur in Chromium-basierten Desktop-Browsern (Chrome/Edge/Opera ab Version 89). Firefox und Safari unterstützen die API nicht; auf Android nur eingeschränkt bzw. gar nicht. Immer mit 'serial' in navigator prüfen.
  • Sicherer Kontext: Nur über HTTPS bzw. localhost verfügbar. In iframes muss die Permissions Policy serial erlaubt sein (allow="serial").
  • Nutzeraktion erforderlich: requestPort() wirft einen SecurityError, wenn es nicht in einem Klick- oder Tastatur-Handler aufgerufen wird. Bricht der Nutzer ab, wird mit NotFoundError abgelehnt – immer try/catch verwenden.
  • Events: connect/disconnect feuern nur für Ports, für die bereits eine Berechtigung besteht. Das event.target ist der betroffene SerialPort.
  • Ports schließen: port.close() schlägt fehl, solange Reader oder Writer gesperrt sind – zuerst reader.cancel() bzw. writer.releaseLock() aufrufen.
  • Berechtigungen können per SerialPort.forget() (Chrome 103+) wieder entzogen werden.
  • Sicherheit: Serielle Geräte können physische Aktionen auslösen (Motoren, Firmware-Flashen). Eingaben aus der Seite niemals ungeprüft an Geräte weiterreichen.