Start · Sprachen · JavaScript · Referenz · BluetoothRemoteGATTCharacteristic.writeValueWithoutResponse()

BluetoothRemoteGATTCharacteristic.writeValueWithoutResponse()

Methode

Schreibt Bytes in eine GATT-Charakteristik eines Bluetooth-LE-Geräts, ohne auf eine Bestätigung des Geräts zu warten („Write Without Response“).

seit JavaScript Web Bluetooth API – Chrome/Edge 85+, Opera; nicht Kategorie: webapi

Signatur

BluetoothRemoteGATTCharacteristic.prototype.writeValueWithoutResponse(value)

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

Typ
Promise<undefined>
Beschreibung
Ein 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');
});
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');
});
23 Bytes gesendet

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 await auf, können Puffer überlaufen und Pakete stillschweigend verloren gehen. Warte daher jeden Aufruf mit await ab 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 Policy bluetooth gesperrt sein. Bestimmte UUIDs stehen auf einer Sperrliste und lösen einen SecurityError aus.
  • Die ältere Methode writeValue() ist veraltet. Verwende für neuen Code gezielt eine der beiden neuen Varianten.