Signatur
Beschreibung
Die schreibgeschützte Eigenschaft navigator.serial gibt ein Serial-Objekt zurück. Darüber können Webanwendungen mit seriellen Geräten kommunizieren, etwa mit Mikrocontrollern (Arduino, ESP32), 3D-Druckern, Messgeräten, Barcode-Scannern oder USB-Seriell-Adaptern. Dabei wird eine echte serielle Schnittstelle (RS-232) oder eine per USB/Bluetooth nachgebildete verwendet.
Das Serial-Objekt stellt vor allem zwei Methoden bereit: requestPort() öffnet einen Auswahldialog des Browsers, in dem der Nutzer ein Gerät freigibt. getPorts() liefert die Ports, die die Seite schon früher freigegeben bekommen hat. Zusätzlich meldet es mit den Events connect und disconnect, wenn ein freigegebenes Gerät angeschlossen oder abgezogen wird.
Die eigentliche Kommunikation läuft über SerialPort-Objekte. Nach port.open({ baudRate }) stehen port.readable und port.writable als ReadableStream bzw. WritableStream bereit. Die API funktioniert nur in einem sicheren Kontext (HTTPS oder localhost). requestPort() erfordert außerdem eine Nutzeraktion, zum Beispiel einen Klick.
Rückgabewert
Serial-Objekt des aktuellen Dokuments. Es ist ein EventTarget mit den Methoden requestPort() und getPorts(). In Browsern ohne Unterstützung existiert die Eigenschaft nicht und liefert undefined.Beispiele
Unterstützung prüfen
if ('serial' in navigator) {
console.log('Web Serial API verfügbar');
} else {
console.log('Web Serial API wird nicht unterstützt');
}
Port auswählen und Daten von einem Arduino lesen
// <button id="connect">Verbinden</button>
document.querySelector('#connect').addEventListener('click', async () => {
try {
// Nur Geräte mit Arduino-Hersteller-ID anzeigen
const port = await navigator.serial.requestPort({
filters: [{ usbVendorId: 0x2341 }]
});
await port.open({ baudRate: 9600 });
const decoder = new TextDecoderStream();
port.readable.pipeTo(decoder.writable);
const reader = decoder.readable.getReader();
while (true) {
const { value, done } = await reader.read();
if (done) break;
console.log('Empfangen:', value);
}
reader.releaseLock();
} catch (err) {
console.error('Verbindung fehlgeschlagen:', err.name, err.message);
}
});
Freigegebene Ports wiederverwenden und Befehl senden
const sendCommand = async (text) => {
const [port] = await navigator.serial.getPorts();
if (!port) {
console.log('Kein freigegebener Port – bitte zuerst verbinden.');
return;
}
await port.open({ baudRate: 115200 });
const writer = port.writable.getWriter();
await writer.write(new TextEncoder().encode(text + '\n'));
writer.releaseLock();
await port.close();
console.log('Gesendet:', text);
};
sendCommand('LED ON');
Auf An- und Abstecken reagieren
navigator.serial.addEventListener('connect', (event) => {
const { usbVendorId, usbProductId } = event.target.getInfo();
console.log('Gerät verbunden:', usbVendorId, usbProductId);
});
navigator.serial.addEventListener('disconnect', (event) => {
console.log('Gerät getrennt:', event.target.getInfo());
});
// Wichtig · Fallstricke
- Browser-Kompatibilität: Wird nur von Chromium-basierten Desktop-Browsern unterstützt (Chrome, Edge und Opera ab Version 89). Firefox und Safari unterstützen die API nicht. Auf Android ist die Unterstützung eingeschränkt. Prüfe die Unterstützung immer vorher mit
'serial' in navigator. - Sicherer Kontext: Die API steht nur über HTTPS oder auf
localhostzur Verfügung. In Iframes muss die Permissions-Policyserialsie erlauben. - Nutzeraktion nötig:
requestPort()ohne vorherigen Klick oder Tastendruck wirft einenSecurityError. Bricht der Nutzer den Dialog ab, folgt einNotFoundError. - Port ist belegt: Nutzt ein anderes Programm oder ein anderer Tab den Port bereits, schlägt
open()mitNetworkErrorbzw.InvalidStateErrorfehl. - Sauber schließen: Vor
port.close()musst du alle Reader und Writer freigeben (releaseLock()bzw.reader.cancel()). Sonst wird der Port nicht geschlossen. - Baudrate: Sie muss mit der des Geräts übereinstimmen, sonst kommen unlesbare Daten an.
- Sicherheit: Behandle Daten vom Gerät als nicht vertrauenswürdig und füge sie nie ungeprüft per
innerHTMLin die Seite ein.