Start · Sprachen · JavaScript · Referenz · HIDDevice: inputreport

HIDDevice: inputreport

Ereignis

Wird am <code>HIDDevice</code> ausgelöst, wenn das geöffnete HID-Gerät einen neuen Eingabebericht (Input Report) an die Seite sendet.

seit JavaScript WebHID API – Chrome/Edge 89+, Opera 75+; nicht in Kategorie: webapi

Signatur

hidDevice.addEventListener("inputreport", handler)

Beschreibung

Das Ereignis inputreport ist der zentrale Weg, um Daten von einem HID-Gerät (Human Interface Device) über die WebHID API zu empfangen, z. B. von Gamepads, Makro-Tastaturen, Stream-Decks, Barcode-Scannern oder eigenen Mikrocontroller-Geräten. Jedes Mal, wenn das Gerät einen Input Report schickt, erhält der Handler ein HIDInputReportEvent.

Das Ereignisobjekt enthält drei wichtige Eigenschaften: device (das auslösende HIDDevice), reportId (die ID des Berichts, 0 wenn das Gerät keine Report-IDs nutzt) und data, ein DataView mit den Nutzdaten ohne das Report-ID-Byte. Wie die Bytes zu deuten sind, legt der Report-Deskriptor des Geräts fest; über device.collections lässt sich die Struktur einsehen.

Registrieren lässt sich der Handler per addEventListener("inputreport", handler) oder über die Eigenschaft hidDevice.oninputreport = handler. Voraussetzung ist, dass das Gerät zuvor mit navigator.hid.requestDevice() ausgewählt und mit device.open() geöffnet wurde – vorher werden keine Berichte zugestellt.

Parameter

Name Typ Default Beschreibung
$type Pflicht string Der Ereignisname "inputreport".
$handler Pflicht (event: HIDInputReportEvent) => void Callback, der pro empfangenem Bericht aufgerufen wird. event.data ist ein DataView, event.reportId eine Zahl, event.device das HIDDevice.
$options boolean | AddEventListenerOptions false Übliche Listener-Optionen wie once oder signal (zum Entfernen per AbortController).

Rückgabewert

Typ
void
Beschreibung
addEventListener gibt nichts zurück. Der Handler erhält ein HIDInputReportEvent.

Beispiele

Gerät auswählen, öffnen und Berichte empfangen

const connectButton = document.querySelector('#connect');

connectButton.addEventListener('click', async () => {
  // Muss durch eine Nutzeraktion ausgelöst werden
  const [device] = await navigator.hid.requestDevice({
    filters: [{ vendorId: 0x057e }] // Beispiel: Nintendo
  });
  if (!device) return;

  await device.open();

  device.addEventListener('inputreport', (event) => {
    const { data, reportId, device } = event;
    const bytes = new Uint8Array(data.buffer, data.byteOffset, data.byteLength);
    console.log(`${device.productName} – Report ${reportId}:`, bytes);
  });
});
Joy-Con (L) – Report 63: Uint8Array(11) [0, 0, 8, 0, 128, 0, 128, 0, 128, 0, 128]

Tastenstatus aus dem DataView auslesen

const handleReport = ({ data, reportId }) => {
  if (reportId !== 1) return; // nur Report 1 enthält Tasten

  const buttons = data.getUint8(0);     // Bitmaske
  const x = data.getInt16(1, true);     // Little Endian
  const y = data.getInt16(3, true);

  const pressed = [...Array(8).keys()].filter((bit) => buttons & (1 << bit));
  console.log({ pressed, x, y });
};

const [device] = await navigator.hid.getDevices();
if (device) {
  if (!device.opened) await device.open();
  device.oninputreport = handleReport;
}
{ pressed: [0, 2], x: -120, y: 35 }

Listener wieder entfernen und Gerät schließen

const controller = new AbortController();

const [device] = await navigator.hid.getDevices();
await device.open();

device.addEventListener('inputreport', (e) => {
  console.log('Bytes:', e.data.byteLength);
}, { signal: controller.signal });

// Nach 10 Sekunden aufräumen
setTimeout(async () => {
  controller.abort();          // entfernt den Listener
  device.oninputreport = null; // falls zusätzlich gesetzt
  await device.close();
  console.log('Verbindung beendet');
}, 10_000);
Bytes: 8 Bytes: 8 … Verbindung beendet

// Wichtig · Fallstricke

  • Browser-Unterstützung: Nur Chromium-Browser auf dem Desktop (Chrome, Edge, Opera). Firefox und Safari unterstützen WebHID nicht, daher vorher if ('hid' in navigator) prüfen.
  • Sicherer Kontext: Funktioniert nur über HTTPS (oder localhost). requestDevice() braucht eine Nutzeraktion, und in iframes muss die Permissions Policy hid erlaubt sein.
  • Kein Ereignis ohne open(): Ein nur ausgewähltes, nicht geöffnetes Gerät sendet keine Berichte.
  • Report-ID nicht in data: Das erste Byte ist bereits entfernt. Wer Offsets aus Datenblättern übernimmt, muss sie oft um 1 verschieben.
  • DataView korrekt nutzen: Bei new Uint8Array(data.buffer) immer byteOffset und byteLength angeben. Für Mehrbyte-Werte auf die Byte-Reihenfolge achten (HID nutzt meist Little Endian).
  • Blockierte Geräte: Tastaturen, Mäuse und FIDO-Sicherheitsschlüssel sind durch eine Sperrliste geschützt. Ihre Berichte kommen nicht an.
  • Leistung: Manche Geräte senden Hunderte Berichte pro Sekunde. Im Handler wenig Arbeit erledigen und DOM-Änderungen z. B. per requestAnimationFrame bündeln.