JS `Web HID` `Feature Reports` 与 `Input Reports` 交互

各位观众老爷,欢迎来到今天的Web HID Feature & Input Reports互动脱口秀!今天咱们不讲虚的,直接上干货,保证各位听完之后,能用Web HID玩转各种奇奇怪怪的设备。

啥是Web HID? 你确定不是某种新型饮料?

Web HID (Human Interface Device) 简单来说,就是让你的浏览器可以直接跟各种HID设备对话,而不用安装任何插件或者驱动。想想看,以前想用浏览器控制个游戏手柄,或者读取个奇怪传感器的数值,那简直是噩梦。现在有了Web HID,妈妈再也不用担心我的设备兼容性了!

Feature Reports vs. Input Reports: 报告,情况有点复杂!

Web HID里有两个重要的概念:Feature Reports 和 Input Reports。它们就像是设备跟浏览器之间的两种对话方式。

  • Input Reports (输入报告): 就像设备在“单方面”汇报情况。 设备“主动”向浏览器发送数据,比如鼠标的移动、键盘的按键、手柄的摇杆位置等等。浏览器只能接收,不能主动要求设备发送。

  • Feature Reports (特征报告): 允许浏览器“主动”向设备索取信息,或者设置设备的状态。这就像浏览器在跟设备进行“问答”互动。 浏览器可以读取设备的固件版本、设置LED灯的颜色、甚至控制某些设备的内部参数。

用个例子来比喻:

  • Input Report: 就像一个演讲者(设备)在台上滔滔不绝地演讲,你(浏览器)只能听着,没法打断他。
  • Feature Report: 就像一个记者(浏览器)在采访一个大佬(设备),可以问问题,大佬也可以回答问题。

浏览器: “设备,你给我报个数!” (Feature Report实战)

现在,咱们来用代码演示一下如何使用Feature Reports。假设咱们有一个神奇的设备,它有一个LED灯,我们可以通过Feature Report来控制它的颜色。

首先,我们需要先连接到设备。这部分代码比较通用,我就简单贴一下:

async function connectToDevice() {
  try {
    const devices = await navigator.hid.requestDevice({
      filters: [
        { vendorId: 0x1234, productId: 0x5678 }, // 替换成你设备的Vendor ID和Product ID
      ],
    });

    if (devices.length > 0) {
      device = devices[0];
      await device.open();
      console.log("设备已连接!");
    } else {
      console.log("没有找到设备。");
    }
  } catch (error) {
    console.error("连接设备时出错:", error);
  }
}

注意: 上面的 vendorIdproductId 需要替换成你实际设备的ID。这两个ID是设备的身份证,可以通过一些工具(比如Windows下的Device Manager)来找到。

接下来,咱们来写一个函数,通过Feature Report来设置LED灯的颜色。

async function setLedColor(red, green, blue) {
  if (!device || !device.opened) {
    console.log("设备未连接或未打开。");
    return;
  }

  const reportId = 0x01; // Feature Report的ID,需要根据设备文档来确定
  const data = new Uint8Array([reportId, red, green, blue]); // 构造要发送的数据

  try {
    await device.sendFeatureReport(reportId, data);
    console.log("LED颜色已设置!");
  } catch (error) {
    console.error("发送Feature Report时出错:", error);
  }
}

代码解释:

  1. reportId: 每个Feature Report都有一个ID,用来区分不同的功能。你需要查阅设备的文档,才能知道哪个ID对应哪个功能。
  2. data: 这是一个Uint8Array,包含了要发送给设备的数据。第一个字节通常是reportId,后面的字节是具体的数据,比如这里的红绿蓝颜色值。
  3. device.sendFeatureReport(reportId, data): 这个函数就是用来发送Feature Report的。第一个参数是reportId,第二个参数是数据。

使用方法:

// 调用函数来设置LED颜色
setLedColor(255, 0, 0); // 设置为红色
setLedColor(0, 255, 0); // 设置为绿色
setLedColor(0, 0, 255); // 设置为蓝色

设备:“报告!我很好!” (Input Report实战)

现在,咱们来看看Input Reports。假设咱们的设备是一个游戏手柄,它会不断地向浏览器发送摇杆的位置和按键状态。

async function startReadingInputReports() {
  if (!device || !device.opened) {
    console.log("设备未连接或未打开。");
    return;
  }

  device.addEventListener("inputreport", (event) => {
    const { data, reportId } = event;
    const values = new Uint8Array(data.buffer); // 将DataView转换为Uint8Array,方便读取数据

    // 根据reportId来处理不同的Input Report
    switch (reportId) {
      case 0x02: // 假设reportId为0x02的是游戏手柄的摇杆和按键数据
        const joystickX = values[1]; // 假设X轴摇杆数据在第二个字节
        const joystickY = values[2]; // 假设Y轴摇杆数据在第三个字节
        const button1 = values[3] & 0x01; // 假设第一个按键的状态在第四个字节的最低位
        const button2 = values[3] & 0x02; // 假设第二个按键的状态在第四个字节的第二位

        console.log(
          `摇杆: X=${joystickX}, Y=${joystickY}, 按键1=${button1}, 按键2=${button2}`
        );
        break;
      default:
        console.log(`收到未知的Input Report,ID: ${reportId}`);
    }
  });

  console.log("开始读取Input Reports...");
}

代码解释:

  1. device.addEventListener("inputreport", (event) => { ... });: 这个函数用来监听Input Report事件。当设备发送Input Report时,这个函数就会被调用。
  2. event.data: 这是一个DataView对象,包含了Input Report的数据。
  3. new Uint8Array(data.buffer): 将DataView转换为Uint8Array,方便我们按照字节来读取数据。
  4. reportId: 每个Input Report也有一个ID,用来区分不同的数据类型。
  5. values[1], values[2], values[3]: 这些代码用来读取Input Report中的数据。你需要根据设备的文档来确定每个字节的含义。
  6. values[3] & 0x01, values[3] & 0x02: 这些代码用来读取按键的状态。因为一个字节可以表示多个按键的状态,所以我们需要使用位运算来提取每个按键的状态。

使用方法:

// 调用函数开始读取Input Reports
startReadingInputReports();

Feature Report 和 Input Report 的爱恨情仇: 如何选择?

那么,什么时候该用Feature Report,什么时候该用Input Report呢? 这取决于你的需求。

  • 如果你需要主动控制设备,或者向设备索取信息,那么就用Feature Report。 比如,设置LED灯的颜色、读取设备的固件版本。
  • 如果你只需要接收设备的数据,而不需要主动控制设备,那么就用Input Report。 比如,读取鼠标的移动、键盘的按键、手柄的摇杆位置。

可以参考下面的表格:

特性 Input Report Feature Report
数据流向 设备 -> 浏览器 设备 <-> 浏览器
浏览器主动性 被动接收 主动请求/发送
适用场景 实时数据流 (鼠标, 键盘, 手柄) 配置/控制设备 (LED, 固件版本)
传输方向 单向 双向
浏览器控制能力
延迟 通常较低 可能较高 (取决于设备响应速度)

一些需要注意的坑:小心掉进去!

  • 设备文档是王道! Web HID最大的坑就是缺乏统一的标准。不同的设备厂商可能会使用不同的Report ID和数据格式。所以,一定要仔细阅读设备的文档,才能正确地使用Web HID。
  • 权限问题。 Web HID需要用户授权才能访问设备。所以,在使用Web HID之前,一定要先请求用户的授权。
  • 数据格式转换。 Web HID传输的数据都是二进制数据,你需要根据设备的文档来将这些数据转换成有意义的值。
  • 兼容性。 虽然Web HID已经得到了广泛的支持,但是仍然有一些浏览器不支持Web HID。所以,在使用Web HID之前,最好先检查一下浏览器的兼容性。

进阶技巧:让你的Web HID应用更上一层楼!

  • 使用Web Serial API和Web Bluetooth API。 Web Serial API可以让你通过串口与设备通信,Web Bluetooth API可以让你通过蓝牙与设备通信。这些API可以让你连接到更多类型的设备。
  • 使用WebAssembly。 WebAssembly可以让你在浏览器中运行高性能的代码。如果你需要处理大量的数据,或者需要进行复杂的计算,那么可以考虑使用WebAssembly。
  • 使用JavaScript框架。 有很多JavaScript框架可以帮助你更方便地开发Web HID应用,比如React、Vue、Angular。

总结:Web HID,未来可期!

Web HID是一个非常有潜力的技术,它可以让你的浏览器直接与各种设备互动,从而创造出更加丰富多彩的应用。虽然Web HID还存在一些挑战,比如缺乏统一的标准,但是随着Web HID的不断发展,相信这些问题都会得到解决。

希望今天的脱口秀能让大家对Web HID的Feature Reports和Input Reports有了更深入的了解。 记住,实践是检验真理的唯一标准! 赶紧拿起你的设备,开始你的Web HID之旅吧! 如果遇到什么问题,欢迎随时提问,我会尽力解答。 感谢各位的收看,咱们下期再见!

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注