Start · Sprachen · JavaScript · Referenz · HIDDevice.collections

HIDDevice.collections

Eigenschaft

Schreibgeschützte Eigenschaft, die ein Array von <code>HIDCollectionInfo</code>-Objekten mit den Berichtsformaten (Report-Deskriptor) eines HID-Geräts liefert.

seit JavaScript Chrome/Edge 89+ (Desktop), kein Firefox/Safari Kategorie: webapi

Signatur

HIDDevice.collections

Beschreibung

Die Eigenschaft collections eines HIDDevice-Objekts gibt die aufbereitete Struktur des HID-Report-Deskriptors zurück. Jedes Element ist ein HIDCollectionInfo-Objekt. Es beschreibt eine logische Gruppe (Collection) von Funktionen des Geräts, zum Beispiel „Gamepad“, „Tastatur“ oder einen herstellerspezifischen Kanal.

Ein HIDCollectionInfo-Objekt hat folgende Felder:

  • usagePage und usage: numerische Kennungen nach der HID-Usage-Tables-Spezifikation (z. B. 0x01/0x05 = Generic Desktop/Gamepad, ab 0xFF00 herstellerspezifisch).
  • type: Art der Collection (0 = Physical, 1 = Application, 2 = Logical, 3 = Report, 4 = Named Array, 5 = Usage Switch, 6 = Usage Modifier).
  • children: verschachtelte Unter-Collections, ebenfalls vom Typ HIDCollectionInfo.
  • inputReports, outputReports, featureReports: Arrays von HIDReportInfo, jeweils mit reportId und items (HIDReportItem mit Angaben wie reportSize, reportCount, logicalMinimum, logicalMaximum, usages).

Die Eigenschaft braucht man vor allem, um vor dem Senden oder Empfangen zu prüfen, welche Report-IDs und Datenformate ein Gerät unterstützt. Nur so lassen sich sendReport(), sendFeatureReport() oder das inputreport-Ereignis korrekt einsetzen, ohne Byte-Layouts fest im Code zu hinterlegen. Die Informationen stehen sofort nach navigator.hid.requestDevice() bzw. getDevices() bereit. Das Gerät muss dafür nicht mit open() geöffnet sein.

Rückgabewert

Typ
HIDCollectionInfo[]
Beschreibung
Ein schreibgeschütztes Array der Collections auf oberster Ebene. Jede kann über children weitere Collections sowie Input-, Output- und Feature-Reports enthalten.

Beispiele

Collections eines ausgewählten Geräts ausgeben

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

  for (const c of device.collections) {
    console.log(
      `Usage-Page 0x${c.usagePage.toString(16)}, Usage 0x${c.usage.toString(16)}, Typ ${c.type}`
    );
    console.log('Input-Reports:', c.inputReports.map(r => r.reportId));
    console.log('Output-Reports:', c.outputReports.map(r => r.reportId));
    console.log('Feature-Reports:', c.featureReports.map(r => r.reportId));
  }
});
Usage-Page 0x1, Usage 0x5, Typ 1 Input-Reports: [1] Output-Reports: [5] Feature-Reports: []

Prüfen, ob ein bestimmter Output-Report unterstützt wird

const unterstuetztOutputReport = (device, reportId) =>
  device.collections.some(c =>
    c.outputReports.some(r => r.reportId === reportId)
  );

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

if (device && unterstuetztOutputReport(device, 0x05)) {
  if (!device.opened) await device.open();
  // z. B. LED-Farbe setzen (gerätespezifisches Format)
  await device.sendReport(0x05, new Uint8Array([0xff, 0x00, 0x00]));
  console.log('Report 0x05 gesendet');
} else {
  console.log('Report 0x05 wird nicht unterstützt');
}
Report 0x05 gesendet

Verschachtelte Collections rekursiv durchlaufen

const collectionTypen = ['Physical', 'Application', 'Logical', 'Report',
  'Named Array', 'Usage Switch', 'Usage Modifier'];

const ausgeben = (collections, tiefe = 0) => {
  for (const c of collections) {
    const einzug = '  '.repeat(tiefe);
    console.log(`${einzug}${collectionTypen[c.type]} (Page 0x${c.usagePage.toString(16)}, Usage 0x${c.usage.toString(16)})`);
    for (const report of c.inputReports) {
      const bits = report.items.reduce((s, i) => s + i.reportSize * i.reportCount, 0);
      console.log(`${einzug}  Input-Report ${report.reportId}: ${bits / 8} Byte`);
    }
    ausgeben(c.children, tiefe + 1);
  }
};

const [device] = await navigator.hid.getDevices();
if (device) ausgeben(device.collections);
Application (Page 0x1, Usage 0x5) Input-Report 1: 8 Byte Physical (Page 0x1, Usage 0x1)

// Wichtig · Fallstricke

  • Browser-Unterstützung: Die WebHID-API gibt es nur in Chromium-Browsern auf dem Desktop (Chrome, Edge, Opera ab Version 89). Firefox und Safari unterstützen sie nicht. Prüfen Sie die Verfügbarkeit mit 'hid' in navigator.
  • Die API funktioniert nur in einem sicheren Kontext (HTTPS oder localhost). Sie kann per Permissions-Policy hid gesperrt sein, etwa in iframes. requestDevice() braucht zusätzlich eine Nutzeraktion.
  • Ist die Report-ID 0, verwendet das Gerät keine Report-IDs. In diesem Fall wird bei sendReport() die 0 übergeben, und die Nutzdaten enthalten kein ID-Byte.
  • Collections, die das Betriebssystem als geschützt einstuft, werden aus Sicherheitsgründen ausgeblendet, zum Beispiel Tastaturen, Mäuse oder FIDO-Sicherheitsschlüssel. collections kann daher weniger Einträge enthalten als der tatsächliche Deskriptor oder sogar leer sein.
  • Die Werte beschreiben nur das Format der Reports. Wie die Bytes zu deuten sind, ist bei herstellerspezifischen Usage-Pages (ab 0xFF00) oft nur in der Dokumentation des Herstellers beschrieben.