Start · Sprachen · JavaScript · Referenz · SerialPort.readable

SerialPort.readable

Eigenschaft

Gibt einen <code>ReadableStream</code> zurück, über den Daten vom angeschlossenen seriellen Gerät empfangen werden, oder <code>null</code>, wenn der Port nicht geöffnet ist.

seit JavaScript Web Serial API: Chrome/Edge 89+, Opera 75+ (nicht Kategorie: webapi

Signatur

get SerialPort.readable

Beschreibung

Die schreibgeschützte Eigenschaft readable der SerialPort-Schnittstelle liefert einen ReadableStream mit Rohbytes (Uint8Array-Blöcken), die das angeschlossene Gerät sendet, etwa ein Mikrocontroller, ein GPS-Empfänger oder ein Barcode-Scanner.

Solange der Port nicht mit port.open() geöffnet wurde, ist der Wert null. Nach dem Öffnen liest man üblicherweise mit port.readable.getReader() in einer Schleife, bis done den Wert true hat oder der Leser mit reader.cancel() abgebrochen wird. Wenn Sie Text erwarten, können Sie den Stream mit pipeThrough(new TextDecoderStream()) in Zeichenketten umwandeln.

Wichtig: Tritt ein nicht fataler Fehler auf, etwa ein Pufferüberlauf, ein Framing- oder Paritätsfehler, wirft der Leser eine Ausnahme und der Stream wird unbrauchbar. port.readable liefert danach einen neuen Stream. Robuster Code packt die Leseschleife deshalb in eine äußere Schleife while (port.readable). Bei einem fatalen Fehler, zum Beispiel wenn das Gerät abgesteckt wird, wird readable zu null.

Vor port.close() muss die Sperre des Streams freigegeben werden (reader.releaseLock()). Sonst wird das Promise von close() abgelehnt.

Rückgabewert

Typ
ReadableStream<Uint8Array> | null
Beschreibung
Ein ReadableStream, der Uint8Array-Blöcke liefert. Der Wert ist null, wenn der Port geschlossen ist oder ein fataler Fehler aufgetreten ist.

Beispiele

Port öffnen und Rohdaten lesen

// Muss durch eine Benutzeraktion ausgelöst werden (z. B. Klick)
const button = document.querySelector('#connect');

button.addEventListener('click', async () => {
  const port = await navigator.serial.requestPort();
  console.log(port.readable); // null – noch nicht geöffnet

  await port.open({ baudRate: 9600 });
  const reader = port.readable.getReader();

  try {
    while (true) {
      const { value, done } = await reader.read();
      if (done) break; // reader.cancel() wurde aufgerufen
      console.log('Empfangen:', value); // Uint8Array
    }
  } finally {
    reader.releaseLock();
  }
});
null Empfangen: Uint8Array(12) [72, 101, 108, 108, 111, ...]

Text zeilenweise dekodieren (z. B. Arduino Serial.println)

const readLines = async (port, onLine) => {
  const decoder = new TextDecoderStream();
  const closed = port.readable.pipeTo(decoder.writable);
  const reader = decoder.readable.getReader();
  let buffer = '';

  try {
    while (true) {
      const { value, done } = await reader.read();
      if (done) break;
      buffer += value;
      const lines = buffer.split('\n');
      buffer = lines.pop(); // unvollständige Zeile aufheben
      lines.forEach((line) => onLine(line.trim()));
    }
  } finally {
    reader.releaseLock();
  }
  await closed.catch(() => {});
};

// Aufruf nach port.open():
// await readLines(port, (line) => console.log('Zeile:', line));
Zeile: Temperatur=22.5 Zeile: Temperatur=22.6

Robust lesen mit Fehlerbehandlung und sauberem Schließen

let keepReading = true;
let reader;

const readUntilClosed = async (port) => {
  // Nach nicht fatalen Fehlern liefert port.readable einen neuen Stream
  while (port.readable && keepReading) {
    reader = port.readable.getReader();
    try {
      while (true) {
        const { value, done } = await reader.read();
        if (done) break;
        console.log(`${value.byteLength} Bytes erhalten`);
      }
    } catch (error) {
      console.warn('Lesefehler (z. B. Paritätsfehler):', error.name);
    } finally {
      reader.releaseLock();
    }
  }
  await port.close();
  console.log('Port geschlossen');
};

const stop = async () => {
  keepReading = false;
  await reader?.cancel(); // beendet read() mit done: true
};
8 Bytes erhalten Port geschlossen

// Wichtig · Fallstricke

  • Browser-Unterstützung: Die Web Serial API gibt es nur in Chromium-basierten Desktop-Browsern (Chrome, Edge, Opera). Firefox und Safari unterstützen sie nicht, und auf Android gilt sie als experimentell. Prüfen Sie das vorher mit 'serial' in navigator.
  • Sicherer Kontext: Die API funktioniert nur über HTTPS oder localhost. requestPort() muss durch eine Benutzeraktion ausgelöst werden. Die Permissions-Policy serial kann die API in iframes sperren.
  • Sperre: Es kann immer nur ein Leser aktiv sein. Solange der Stream gesperrt ist, schlagen ein zweites getReader() und auch port.close() fehl. Deshalb immer releaseLock() im finally-Block aufrufen.
  • Blockgrenzen: Die Bytes kommen in beliebig großen Blöcken an. Eine Nachricht vom Gerät kann auf mehrere read()-Aufrufe verteilt sein. Sammeln Sie die Daten in einem Puffer und zerlegen Sie sie selbst (etwa an Zeilenumbrüchen).
  • null-Prüfung: Wird das Gerät getrennt, wird readable zu null. Reagieren Sie zusätzlich auf das disconnect-Ereignis.
  • Die Puffergröße lässt sich über die Option bufferSize von open() festlegen (Standard: 255 Bytes). Ist sie zu klein und werden die Daten zu langsam gelesen, kommt es zu einem BufferOverrunError.