Signatur
Beschreibung
Die Methode writeValueWithoutResponse() sendet die Bytes aus einem ArrayBuffer, einem TypedArray oder einer DataView an eine Charakteristik eines verbundenen Bluetooth-Low-Energy-Geräts. Dabei wird der GATT-Vorgang Write Without Response verwendet: Das Peripheriegerät schickt keine Bestätigung auf Protokollebene zurück.
Weil keine Bestätigung nötig ist, hat dieser Vorgang weniger Overhead und eine geringere Latenz als writeValueWithResponse(). Deshalb eignet er sich für häufige, zeitkritische Daten, bei denen ein einzelnes verlorenes Paket nicht schlimm ist, zum Beispiel Steuerbefehle für Spielzeugroboter, LED-Farbwerte, Streaming-Daten oder UART-artige Protokolle wie den Nordic UART Service.
Das zurückgegebene Promise wird erfüllt, sobald der Browser die Daten an den Bluetooth-Stack übergeben hat. Das heißt nicht, dass das Gerät die Daten erhalten oder verarbeitet hat. Die Charakteristik muss die Eigenschaft writeWithoutResponse unterstützen, was du vorher über characteristic.properties.writeWithoutResponse prüfen kannst.
Diese Methode ersetzt zusammen mit writeValueWithResponse() die veraltete Methode writeValue(), bei der der Browser die Schreibart selbst gewählt hat.
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $value Pflicht | ArrayBuffer | TypedArray | DataView | Die zu sendenden Bytes. Die Daten werden beim Aufruf kopiert, spätere Änderungen am Puffer haben also keine Auswirkung. Die maximale Länge hängt von der ausgehandelten ATT-MTU ab (meist 20 Byte Nutzdaten bei MTU 23, maximal 512 Byte). |
Rückgabewert
Promise, das ohne Wert erfüllt wird, sobald der Schreibvorgang an den Bluetooth-Stack übergeben wurde. Es wird mit einer DOMException abgelehnt, z. B. NotSupportedError (Schreibart nicht unterstützt), NetworkError (Gerät nicht verbunden), InvalidModificationError (Wert länger als 512 Byte), SecurityError (gesperrte Charakteristik) oder NotAllowedError.Beispiele
LED-Farbe an ein BLE-Leuchtmittel senden
// Muss durch eine Nutzeraktion (z. B. Klick) ausgelöst werden
const SERVICE_UUID = '0000ffe5-0000-1000-8000-00805f9b34fb';
const CHAR_UUID = '0000ffe9-0000-1000-8000-00805f9b34fb';
document.querySelector('#connect').addEventListener('click', async () => {
const device = await navigator.bluetooth.requestDevice({
filters: [{ services: [SERVICE_UUID] }]
});
const server = await device.gatt.connect();
const service = await server.getPrimaryService(SERVICE_UUID);
const characteristic = await service.getCharacteristic(CHAR_UUID);
if (!characteristic.properties.writeWithoutResponse) {
console.warn('Charakteristik unterstützt kein Write Without Response');
return;
}
// Rot = 255, Grün = 80, Blau = 0
const payload = new Uint8Array([0x56, 255, 80, 0, 0x00, 0xf0, 0xaa]);
await characteristic.writeValueWithoutResponse(payload);
console.log('Farbe gesendet');
});
Text über den Nordic UART Service in MTU-großen Stücken senden
const NUS_SERVICE = '6e400001-b5a3-f393-e0a9-e50e24dcca9e';
const NUS_RX = '6e400002-b5a3-f393-e0a9-e50e24dcca9e';
const sendText = async (characteristic, text, chunkSize = 20) => {
const bytes = new TextEncoder().encode(text);
for (let offset = 0; offset < bytes.length; offset += chunkSize) {
const chunk = bytes.subarray(offset, offset + chunkSize);
await characteristic.writeValueWithoutResponse(chunk);
}
console.log(`${bytes.length} Bytes gesendet`);
};
document.querySelector('#send').addEventListener('click', async () => {
const device = await navigator.bluetooth.requestDevice({
filters: [{ services: [NUS_SERVICE] }]
});
const server = await device.gatt.connect();
const service = await server.getPrimaryService(NUS_SERVICE);
const rx = await service.getCharacteristic(NUS_RX);
await sendText(rx, 'Hallo Mikrocontroller!\n');
});
Fehlerbehandlung mit Rückfall auf Write With Response
const writeFast = async (characteristic, data) => {
try {
if (characteristic.properties.writeWithoutResponse) {
await characteristic.writeValueWithoutResponse(data);
} else {
// Rückfall: bestätigter Schreibvorgang
await characteristic.writeValueWithResponse(data);
}
} catch (error) {
if (error.name === 'NetworkError') {
console.error('Gerät ist nicht mehr verbunden');
} else {
console.error(`Schreiben fehlgeschlagen: ${error.name}`);
}
}
};
// Beispiel: 16-Bit-Motordrehzahl als Little Endian senden
const view = new DataView(new ArrayBuffer(2));
view.setUint16(0, 1500, true);
// await writeFast(characteristic, view);
// Wichtig · Fallstricke
- Keine Zustellgarantie: Wenn das Promise erfüllt wird, heißt das nur, dass die Daten lokal in die Warteschlange gestellt wurden. Für kritische Befehle, etwa Konfiguration oder Firmware-Metadaten, solltest du
writeValueWithResponse()verwenden. - Überlastung: Rufst du die Methode in einer engen Schleife ohne
awaitauf, können Puffer überlaufen und Pakete stillschweigend verloren gehen. Warte daher jeden Aufruf mitawaitab und begrenze die Senderate. - Paketgröße: Daten, die größer als ATT-MTU − 3 Byte sind, werden bei diesem Vorgang nicht automatisch aufgeteilt. Viele Geräte schneiden sie ab oder verwerfen sie. Teile die Daten deshalb selbst in Stücke auf, meist 20 Byte groß.
- Kompatibilität: Die Web Bluetooth API ist experimentell. Sie funktioniert nur in Chromium-Browsern (Chrome, Edge, Opera, Chrome für Android), nicht in Firefox oder Safari und auch nicht unter iOS. Unter Linux muss sie teilweise über ein Flag aktiviert werden.
- Sicherheit: Die API ist nur in sicheren Kontexten (HTTPS) verfügbar.
requestDevice()braucht eine Nutzeraktion. In iframes kann die API über die Permissions Policybluetoothgesperrt sein. Bestimmte UUIDs stehen auf einer Sperrliste und lösen einenSecurityErroraus. - Die ältere Methode
writeValue()ist veraltet. Verwende für neuen Code gezielt eine der beiden neuen Varianten.