Start · Sprachen · JavaScript · Referenz · HIDDevice.sendReport()

HIDDevice.sendReport()

Methode

Sendet einen Ausgabereport (Output Report) mit optionaler Report-ID an ein geöffnetes HID-Gerät und liefert ein Promise zurück.

seit JavaScript WebHID: Chrome/Edge 89+, Opera 75+ (nicht in Firef Kategorie: webapi

Signatur

HIDDevice.prototype.sendReport(reportId, data)

Beschreibung

Mit sendReport() schickt man Daten an ein HID-Gerät (Human Interface Device), zum Beispiel um LEDs an einer Tastatur oder einem Gamepad zu schalten, einen Rumble-Motor zu starten oder Steuerbefehle an Spezialhardware wie Stream-Decks, Barcode-Scanner oder Messgeräte zu senden. Die Methode gehört zur WebHID-API und schreibt in einen Output Report, wie er im Report-Deskriptor des Geräts definiert ist.

Das Gerät muss vorher mit navigator.hid.requestDevice() ausgewählt und mit device.open() geöffnet worden sein. Der erste Parameter ist die Report-ID. Nutzt das Gerät keine Report-IDs, übergibt man 0. Der zweite Parameter enthält die eigentlichen Nutzdaten ohne das Byte für die Report-ID, das der Browser selbst voranstellt.

Welche Report-IDs und Längen gültig sind, steht in device.collections[].outputReports. Das Promise wird erfüllt, sobald der Report übertragen wurde. Bei ungültigen Daten, einem geschlossenen Gerät oder einem Übertragungsfehler wird es mit einer DOMException abgelehnt. Antworten des Geräts kommen nicht als Rückgabewert zurück, sondern asynchron über das Ereignis inputreport.

Parameter

Name Typ Default Beschreibung
$reportId Pflicht number 8-Bit-Report-ID des Ausgabereports. Für Geräte ohne Report-IDs 0 übergeben.
$data Pflicht BufferSource (ArrayBuffer | TypedArray | DataView) Nutzdaten des Reports ohne das Präfix mit der Report-ID. Die Länge sollte der im Report-Deskriptor definierten Größe entsprechen.

Rückgabewert

Typ
Promise<undefined>
Beschreibung
Ein Promise, das mit undefined erfüllt wird, sobald der Report gesendet wurde. Schlägt das Senden fehl, wird es mit einer DOMException abgelehnt, z. B. InvalidStateError bei nicht geöffnetem Gerät oder NotAllowedError/NotSupportedError bei gesperrten oder abgelehnten Reports.

Beispiele

Gerät auswählen, öffnen und Report senden

// Muss durch eine Nutzeraktion ausgelöst werden (z. B. Klick)
document.querySelector('#connect').addEventListener('click', async () => {
  const [device] = await navigator.hid.requestDevice({
    filters: [{ vendorId: 0x0fd9 }] // Beispiel: Elgato
  });
  if (!device) return;

  if (!device.opened) await device.open();

  // Report-ID 0x02, Nutzdaten ohne ID-Byte
  const data = new Uint8Array([0x0b, 0x00, 0x00, 0x00]);
  await device.sendReport(0x02, data);
  console.log(`Report an ${device.productName} gesendet`);
});
Report an Stream Deck gesendet

Gerät ohne Report-IDs: LED einschalten mit Fehlerbehandlung

const setLed = async (device, on) => {
  try {
    // reportId 0, weil das Gerät keine Report-IDs verwendet
    await device.sendReport(0, new Uint8Array([on ? 0x01 : 0x00]));
    console.log(`LED ${on ? 'an' : 'aus'}`);
  } catch (err) {
    console.error(`Senden fehlgeschlagen: ${err.name} – ${err.message}`);
  }
};

const [device] = await navigator.hid.getDevices();
if (device) {
  await device.open();
  await setLed(device, true);
}
LED an

Befehl senden und Antwort über inputreport empfangen

const sendCommand = (device, reportId, bytes, timeout = 1000) =>
  new Promise((resolve, reject) => {
    const timer = setTimeout(() => {
      device.removeEventListener('inputreport', onReport);
      reject(new Error('Zeitüberschreitung'));
    }, timeout);

    const onReport = (event) => {
      clearTimeout(timer);
      device.removeEventListener('inputreport', onReport);
      resolve(new Uint8Array(event.data.buffer));
    };

    device.addEventListener('inputreport', onReport);
    device.sendReport(reportId, Uint8Array.from(bytes)).catch(reject);
  });

const [device] = await navigator.hid.getDevices();
await device.open();
const answer = await sendCommand(device, 0x01, [0x10, 0x00]);
console.log('Antwort:', answer);
Antwort: Uint8Array(63) [16, 1, ...]

Verfügbare Output-Reports prüfen

const [device] = await navigator.hid.getDevices();
for (const collection of device.collections) {
  for (const report of collection.outputReports ?? []) {
    console.log('Output-Report-ID:', report.reportId);
  }
}
Output-Report-ID: 2

// Wichtig · Fallstricke

  • Browser-Kompatibilität: WebHID gibt es nur in Chromium-Browsern auf dem Desktop (Chrome, Edge, Opera). Firefox und Safari unterstützen es nicht. Vor der Nutzung mit 'hid' in navigator prüfen.
  • Sicherer Kontext: Die API funktioniert nur über HTTPS (oder localhost). requestDevice() braucht eine Nutzeraktion. In iframes muss die Permissions-Policy hid erlaubt sein.
  • Gerät öffnen: Ohne vorheriges await device.open() wird das Promise mit InvalidStateError abgelehnt.
  • Report-ID nicht doppelt senden: Das ID-Byte gehört nicht in data. Wer es trotzdem voranstellt, verschiebt alle Nutzdaten um ein Byte. Das ist ein häufiger Fehler beim Portieren von node-hid- oder hidapi-Code.
  • Gesperrte Geräte: Aus Sicherheitsgründen blockiert der Browser bestimmte Top-Level-Collections, etwa Tastaturen, Mäuse und FIDO-Sicherheitsschlüssel. Manche Geräte sind außerdem auf einer Sperrliste. Reports an solche Geräte werden abgelehnt.
  • Feature- vs. Output-Reports: Viele Geräte erwarten Konfigurationsdaten als Feature Report. Dafür ist sendFeatureReport() gedacht, nicht sendReport().
  • Reihenfolge: Mehrere Reports kurz hintereinander besser nacheinander mit await senden, damit die Reihenfolge feststeht und das Gerät nicht überlastet wird.