WebHID API:如何解析 inputReport 事件中的数据?

问题描述

我正在尝试使用 WebHID API 从我的数字转换器(X 倾斜、Y 倾斜、提示压力、提示开关、橡皮擦、笔、Puck 等)获取传感器输入。这是我到目前为止所得到的:

index.js:

page_log = text => {
  let p = document.createElement("p");
  p.textContent = text;
  log.appendChild(p);
};

let device;

if (!("hid" in navigator)) {
  page_log("WebHID is not available yet.");
}

navigator.hid.getDevices().then(devices => {
  if (devices.length == 0) {
    page_log(`No HID devices selected. Press the "request device" button.`);
    return;
  }
  if (devices.length > 1) {
    page_log(`You have multiple devices.`);
  }
  device = devices[0];
  page_log(`User prevIoUsly selected "${device.productName}" HID device.`);
  page_log(`Now press "open device" button to receive input reports.`);
});

requestDeviceButton.onclick = async event => {
  document.body.style.display = "none";
  try {
    const filters = [
      {
        vendorId: 0x056a,// wacom Co.,Ltd
        productId: 0x00b1 //PTZ-630 [Intuos3 (6x8)]
      },{
        vendorId: 0x056a,Ltd
        productId: 0x00b2 //PTZ-930 [Intuos3 (9x12)]
      },Ltd
        productId: 0x00b3 //PTZ-1230 [Intuos3 (12x12)]
      },Ltd
        productId: 0x00b4 //PTZ-1231W [Intuos3 (12x19)]
      },];

    [device] = await navigator.hid.requestDevice({ filters });
    if (!device) return;

    page_log(`User selected "${device.productName}" HID device.`);
    page_log(`Now press "open device" button to receive input reports.`);
  } finally {
    document.body.style.display = "";
  }
};


openButton.onclick = async event => {
  if (!device) return;

  await device.open().catch(console.error);
  page_log(`Waiting for user to press button...`);

  device.addEventListener("inputreport",event => {
    const { data,device,reportId } = event;

    let buffArray = new Uint8Array(data.buffer);
    console.log(buffArray);
    // console.log(device);
  
  });
};

控制台输出

index.js:72 Uint8Array(9) [224,49,125,58,74,35,195,85]
index.js:72 Uint8Array(9) [224,109,64,194,94]
index.js:72 Uint8Array(9) [224,94,43,102]
index.js:72 Uint8Array(9) [224,82,22,193,113]
index.js:72 Uint8Array(9) [224,52,1,123]
index.js:72 Uint8Array(9) [224,26,57,228,192,128]
index.js:72 Uint8Array(9) [224,48,253,190,141]
index.js:72 Uint8Array(9) [224,223,137,65,148]
index.js:72 Uint8Array(9) [224,203,90,66,159]
index.js:72 Uint8Array(9) [224,186,36,167]
index.js:72 Uint8Array(9) [224,177,56,242,67,174]
index.js:72 Uint8Array(9) [224,166,208,196,178]

如何找出每个数字对应的传感器?

我尝试阅读 WebHID specHID Usage Tables,但到目前为止我一直无法找到破译输出所需的信息。


更新:

我在安装 wacom 官方驱动程序后在 Windows 中进行了测试,我从 InputReport 中获得了更多数据。

输出:(带有 wacom 驱动程序的 Windows)

index.js:73 reportId: 15
index.js:76 Uint8Array(10) [2,224,55,229,45,30,176,195]
index.js:73 reportId: 15
index.js:76 Uint8Array(21) [2,163,99,31,189,15,2,98,69,190]
index.js:73 reportId: 7
index.js:76 Uint8Array(37) [32,29,238,97,50,3,34,8,16,87,126,112,212,254,249,232,28,184,136,0]
index.js:73 reportId: 7
index.js:76 Uint8Array(37) [32,241,89,197,255,250,76,162,144,123,0]
index.js:73 reportId: 15
index.js:76 Uint8Array(10) [2,178,185]
index.js:73 reportId: 15
index.js:76 Uint8Array(32) [2,54,215,32,183,139,44,226,179,62,187,33,178]
index.js:73 reportId: 7
index.js:76 Uint8Array(37) [32,27,51,14,156,171,88,237,96,6,53,236,20,239,147,175]

注意:这次我已经记录了 reportId,因为我现在得到了 2 个不同的。

我还注意到 HIDDevice.collections 对象中的不同数据:

devtools screenshot windows

这次我在我的 outputReports 中得到了一些东西。

输出:(Linux 比较)

index.js:73 reportId: 2
index.js:74 Uint8Array(9) [224,174,38,177]
index.js:73 reportId: 2
index.js:74 Uint8Array(9) [224,21,39,204,180]
index.js:73 reportId: 2
index.js:74 Uint8Array(9) [224,165,40,77,183]
index.js:73 reportId: 2
index.js:74 Uint8Array(9) [224,19,206,182]
index.js:73 reportId: 2
index.js:74 Uint8Array(9) [224,134,18,41,80,181]
index.js:73 reportId: 2
index.js:74 Uint8Array(9) [224,9,17,191,210,184]
index.js:73 reportId: 2
index.js:74 Uint8Array(9) [224,225,150,86,186]
index.js:73 reportId: 2
index.js:74 Uint8Array(9) [224,83,153,190]
index.js:73 reportId: 2
index.js:74 Uint8Array(9) [224,110,195]
index.js:73 reportId: 2
index.js:74 Uint8Array(9) [224,214,199]
index.js:73 reportId: 2
index.js:74 Uint8Array(9) [160,142,216,202]

还有我在 linux 上得到的 HIDDevice.collections

enter image description here

所以我仍然不明白如何使用 featureReportsInputReportsOutputReports 映射数据。所以我发现我从 Windows 上的 wacom 驱动程序中获得的 HID 数据多于 linux。


更新 2:

我一直在查看 Windows 输出上的 HIDDevice.collection 对象,并将其与 Report Descriptors 进行比较,我通过使用 usbhid-dump 运行 hidrd-convert(以使它们易于阅读)在 Linux 上。这是我目前发现的。

  • 看起来我只需要查看带有相应 inputReportsreportID 元素,因为我只是尝试读取发送到主机的传感器数据。>

  • 我查看 items 数组以了解报告发送的数据。

    • 我查看 items 中项目的索引号以了解从 DataView(我的 data 变量)中提取数据的顺序。
    • 我查看 reportCountreportSize 以了解 DataView 中该项目的数据形状。
    • 我查看每个项目的“使用情况”以了解数据的用途。
      • 不幸的是,WebHID 似乎没有在每个项目的基础上公开“使用情况”(就像我在 usbhid-dump 中展示的“Report Descriptors”)。相反,它仅在每个集合的基础上公开它。
      • 可以通过 usagePagecollection 十六进制值查找“使用页面”,在 HID Usage Tables 中查找“使用”(如果可用),然后对给定的 usage 十六进制值执行相同的操作。

示例:

    if (reportId !== 7) return;
    console.log('reportId: ' + reportId);
    let zero_through_six = data.getUint8(0);


    let report_data = [
      (zero_through_six & 128) == 128,//0 (1-bit)
      (zero_through_six & 64) == 64,//1 (1-bit)
      (zero_through_six & 32) == 32,//2 (1-bit)
      (zero_through_six & 16) == 16,//3 (1-bit)
      (zero_through_six & 8) == 8,//4 (1-bit)
      (zero_through_six & 4) == 4,//5 (1-bit)
      zero_through_six & 3,//6 (2-bits)
      data.getUint16(1),//7
      data.getUint16(3),//8
      data.getUint16(5),//9
      data.getUint16(7),//10
      data.getUint32(9),//11
      data.getBigUint64(13),//12
      data.getUint32(21),//13
      data.getUint16(23),//14
      data.getUint16(25),//15
      data.getUint16(27),//16
      data.getUint16(29),//17
      data.getUint16(31),//18
      data.getUint16(33),//19
    ];

    console.log(report_data);

  });

这是我在 Windows 版本上拆分我进入的数据和数组时所做的事情。第一个 items[1-6] 是 1 位,items[7] 2 位,items[7-10] 16-位等等。

同样,由于 WebHID 不会在每个项目的基础上公开“使用情况”,因此每个项目映射到的传感器/按钮仍然未知。至少除了简单的单独测试之外,这在如此复杂的设备上很难做到。

更新 3:

事实证明,我的用例并不真正需要 WebHID API(从我的数字化仪获取传感器输入)。看起来 PointerEventMouseEvent 属性满足了我的需求。 (真的,应该先看看那个(;一_一)) 至少,我学到了一些如何使用WebHID API。

解决方法

我想 https://web.dev/devices-introduction/ 会很有用,因为它解释了如何选择合适的 API 来与您选择的硬件设备进行通信。

很高兴你想通了!