通过 WebUSB 打开现金抽屉 JavaScript

Open Cash Drawer via WebUSB JavaScript

我有一个 c# 应用程序,它可以打开装有 Windows 驱动程序的现金抽屉。非常简单,因为驱动程序使 USB 设备显示为串行端口:

 SerialPort rsPort = new SerialPort(textBox1.Text);
 byte[] openCmd = new byte[5];
 openCmd[0] = 27;
 openCmd[1] = 112;
 openCmd[2] = 0;
 openCmd[3] = 60;
 openCmd[4] = 255;
 rsPort.Open();
 Thread.Sleep(100);
 rsPort.Write(openCmd, 0, 5);
 Thread.Sleep(100);
 rsPort.Close();

我现在正尝试通过 WebUSB 打开同一个 USB 现金抽屉。我已经使用 ZaDig 安装了通用 USB 驱动器并且 Chrome 可以看到 USB 设备;可以打开设备;但是,我很难发送正确的命令。

这是配置的图片:

这是我当前的代码:

<!DOCTYPE html>
<html>
<body>

<h2>JavaScript WebUSB</h2>

<button id="myBtn">Try it</button>

<script>
document.getElementById("myBtn").addEventListener("click", talkToDrawer);

async function talkToDrawer() {
  try {
    let device = await navigator.usb.requestDevice({ filters: [{ vendorId: 1659 }] });
    console.log(device);
    await device.open(); // Begin a session.
    await device.selectConfiguration(1); // Select configuration #1 for the device.
    await device.claimInterface(0); // Request exclusive control over interface #2.
    result = await device.controlTransferOut({
        requestType: 'standard', // tried all combinations: standard / class / vendor
        recipient: 'endpoint', // tried all combinations: device / interface / endpoint / other
        request: 0x27,
        value: 0,
        index: 1
     });
     result = await device.controlTransferOut({
        requestType: 'standard', // tried all combinations: standard / class / vendor
        recipient: 'endpoint', // tried all combinations: device / interface / endpoint / other
        request: 0x112,
        value: 0,
        index: 1
     });
     result = await device.controlTransferOut({
        requestType: 'standard', // tried all combinations: standard / class / vendor
        recipient: 'endpoint', // tried all combinations: device / interface / endpoint / other
        request: 0x0,
        value: 0,
        index: 1
     });
     result = await device.controlTransferOut({
        requestType: 'standard', // tried all combinations: standard / class / vendor
        recipient: 'endpoint', // tried all combinations: device / interface / endpoint / other
        request: 0x60,
        value: 0,
        index: 1
     });
         result = await device.controlTransferOut({
        requestType: 'standard', // tried all combinations: standard / class / vendor
        recipient: 'endpoint', // tried all combinations: device / interface / endpoint / other
        request: 0x255,
        value: 0,
        index: 1
     });

  } catch (error) {
    console.log(error);
  }
}


</script>

</body>
</html> 

在不了解更多设备信息的情况下,我在代码中看到了两个错误,

  1. 在 C# 示例中,命令是 [27, 112, 0, 60, 255],值以十进制形式给出,而在 Javascript 示例中,值以十六进制常量形式给出。在 Javascript 中构造命令缓冲区的适当代码是,
const cmd = new Uint8Array([27, 112, 0, 60, 255]);
  1. 而不是使用 controlTransferOut() 发送数据,使用 transferOut() 和 select 端点编号 3 最有可能是正确的。Prolific USB 转串口转换器芯片实现了一个类似于标准 USB 串行协议 class,它使用一对批量输入和输出端点作为串行数据流,
result = await device.transferOut(3, cmd);

剩下的悬而未决的问题是在发送此命令之前是否需要执行任何控制传输。控制传输用于配置设备,对于 USB 转串口芯片,这通常涉及设置波特率或将 DCE 位设置为高电平。在对如何与 USB 设备通信进行逆向工程时,我建议使用 Wireshark 查看来自工作驱动程序的 USB 流量。

请注意,如果您使用的是串行设备,则应使用 Serial API。在 chrome://flags/#enable-experimental-web-platform-features 标志后面的 Chrome 中有一个实验性实现。此 API 专为专门针对串行设备的应用程序而设计,避免了必须重新实现 USB 转串行芯片的驱动程序。