Signatur
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 einPromise<SerialPort>. Muss durch eine Nutzeraktion (z. B. Klick) ausgelöst werden.getPorts()– liefert einPromise<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 alsonconnect). - Event
disconnect– wird ausgelöst, wenn ein Port entfernt wird (auch alsondisconnect).
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
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);
}
});
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');
});
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();
};
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);
// 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 navigatorprüfen. - Sicherer Kontext: Nur über HTTPS bzw.
localhostverfügbar. In iframes muss die Permissions Policyserialerlaubt sein (allow="serial"). - Nutzeraktion erforderlich:
requestPort()wirft einenSecurityError, wenn es nicht in einem Klick- oder Tastatur-Handler aufgerufen wird. Bricht der Nutzer ab, wird mitNotFoundErrorabgelehnt – immertry/catchverwenden. - Events:
connect/disconnectfeuern nur für Ports, für die bereits eine Berechtigung besteht. Dasevent.targetist der betroffeneSerialPort. - Ports schließen:
port.close()schlägt fehl, solange Reader oder Writer gesperrt sind – zuerstreader.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.