Signatur
Beschreibung
Die schreibgeschützte Eigenschaft writable der Schnittstelle SerialPort liefert einen WritableStream, der Uint8Array-Blöcke (bzw. andere BufferSource-Werte) annimmt und diese an das serielle Gerät weitergibt, z. B. an einen Mikrocontroller, einen 3D-Drucker oder ein Messgerät.
Der Stream existiert erst, wenn der Port mit port.open() geöffnet wurde. Vorher und nach dem Schließen gibt die Eigenschaft null zurück. Zum Schreiben holt man sich mit getWriter() einen WritableStreamDefaultWriter. Dieser sperrt den Stream, bis er mit releaseLock() wieder freigegeben wird.
Wer Text senden möchte, schaltet am besten einen TextEncoderStream davor und verbindet ihn mit pipeTo(). Tritt ein fataler Fehler auf, etwa weil das Gerät abgezogen wurde, wird der Stream fehlerhaft. Ein späterer Zugriff auf writable kann dann einen neuen Stream liefern, sofern der Port noch offen ist.
Rückgabewert
WritableStream für ausgehende Bytes, solange der Port geöffnet ist, sonst null.Beispiele
Bytes an ein Gerät senden
// Muss durch eine Benutzeraktion (z. B. Klick) ausgelöst werden
const button = document.querySelector('#verbinden');
button.addEventListener('click', async () => {
const port = await navigator.serial.requestPort();
await port.open({ baudRate: 9600 });
const writer = port.writable.getWriter();
const daten = new Uint8Array([0x48, 0x69, 0x0a]); // "Hi\n"
await writer.write(daten);
// Sperre freigeben, damit der Port geschlossen werden kann
writer.releaseLock();
await port.close();
console.log('Gesendet:', daten.length, 'Bytes');
});
Text per TextEncoderStream senden (z. B. G-Code)
const sendeBefehle = async (port, befehle) => {
const encoder = new TextEncoderStream();
const pipeFertig = encoder.readable.pipeTo(port.writable);
const writer = encoder.writable.getWriter();
for (const befehl of befehle) {
await writer.write(`${befehl}\n`);
}
await writer.close(); // beendet auch die Pipe
await pipeFertig; // wartet, bis alles übertragen ist
};
// Nutzung mit einem bereits geöffneten Port:
// await sendeBefehle(port, ['G28', 'G1 X10 Y10']);
Status prüfen und sauber schließen
const trennen = async (port) => {
if (port.writable === null) {
console.log('Port ist nicht geöffnet');
return;
}
const writer = port.writable.getWriter();
try {
await writer.write(new Uint8Array([0x04])); // EOT senden
} catch (err) {
console.error('Schreibfehler:', err);
} finally {
writer.releaseLock();
}
await port.close();
console.log('Nach close():', port.writable);
};
// 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. Vor der Nutzung mit
'serial' in navigatorprüfen. - Nur in sicheren Kontexten: Die API funktioniert nur über HTTPS oder auf
localhost.requestPort()muss durch eine Benutzeraktion ausgelöst werden. Mit der Permissions-Policyseriallässt sich die API sperren, etwa in iframes. - Sperre beachten: Solange ein Writer aktiv ist oder eine Pipe läuft, ist der Stream gesperrt.
port.close()schlägt dann mit einem Fehler fehl. Deshalb vorher immerreleaseLock()aufrufen oder den Writer bzw. die Pipe schließen. - Nur Binärdaten:
writer.write('text')funktioniert nicht direkt. Text muss zuerst mitTextEncoderoderTextEncoderStreamin Bytes umgewandelt werden. - Puffer: Die Größe des Ausgabepuffers legt die Option
bufferSizebeiopen()fest. Ein erfüllteswrite()-Promise bedeutet nicht unbedingt, dass das Gerät die Daten schon empfangen hat. - Ist der Port nicht geöffnet, ist der Wert
null. Ein Aufruf vonport.writable.getWriter()wirft dann einenTypeError.