You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java中如何识别输入来自哪台条码扫描器?

区分两台条码扫描器的输入来源

首先明确:条码扫描器常见两种工作模式,模拟键盘(Keyboard Wedge)和USB HID设备。如果是键盘模式,系统会把扫描内容当成普通键盘输入,无法通过usb4java区分来源,需要先将扫描器切换到HID模式(通常用扫描器自带的设置条码完成)。如果已经是HID模式,可按以下步骤用usb4java实现设备区分:

核心步骤

1. 唯一标识设备

同型号的扫描器vendorId和productId会相同,必须用busNumber + deviceAddress作为唯一标识,这两个值你已经在现有代码中获取到了。

2. 打开目标设备并获取句柄

在遍历设备时,匹配到目标扫描器(比如根据vendorId、productId,再结合bus/address)后,打开设备:

DeviceHandle handle = new DeviceHandle();
int openResult = LibUsb.open(device, handle);
if (openResult != LibUsb.SUCCESS) {
    throw new LibUsbException("Failed to open device", openResult);
}

3. 配置设备并声明接口

HID设备需要配置后才能通信,先设置配置,再找到对应的HID接口并声明:

// 设置设备配置(通常配置值为1,可从DeviceDescriptor获取bNumConfigurations确认)
int configResult = LibUsb.setConfiguration(handle, 1);
if (configResult != LibUsb.SUCCESS) {
    throw new LibUsbException("Failed to set configuration", configResult);
}

// 获取配置描述符
ConfigurationDescriptor configDescriptor = new ConfigurationDescriptor();
int configDescResult = LibUsb.getConfigDescriptor(device, 0, configDescriptor);
if (configDescResult != LibUsb.SUCCESS) {
    throw new LibUsbException("Failed to get config descriptor", configDescResult);
}

// 遍历接口,找到HID类接口(bInterfaceClass为0x03)
Interface iface = configDescriptor.interface()[0];
for (InterfaceDescriptor ifaceDesc : iface.altsetting()) {
    if (ifaceDesc.bInterfaceClass() == LibUsb.CLASS_HID) {
        // 声明接口
        int claimResult = LibUsb.claimInterface(handle, ifaceDesc.bInterfaceNumber());
        if (claimResult != LibUsb.SUCCESS) {
            throw new LibUsbException("Failed to claim interface", claimResult);
        }
        break;
    }
}

4. 读取设备输入数据

找到HID接口的中断端点(通常是IN端点,bEndpointAddress的最高位为1),然后同步或异步读取数据:

// 找到IN端点
EndpointDescriptor inEndpoint = null;
for (EndpointDescriptor epDesc : ifaceDesc.endpoint()) {
    if ((epDesc.bEndpointAddress() & LibUsb.ENDPOINT_IN) != 0) {
        inEndpoint = epDesc;
        break;
    }
}

// 同步读取数据(缓冲区大小根据扫描器的报告长度设置,通常64字节)
byte[] buffer = new byte[64];
IntBuffer transferred = IntBuffer.allocate(1);
int readResult = LibUsb.interruptTransfer(handle, inEndpoint.bEndpointAddress(), 
    ByteBuffer.wrap(buffer), transferred, 5000); // 5秒超时
if (readResult == LibUsb.SUCCESS) {
    // 处理扫描到的数据,buffer里就是扫描器发送的内容
    String barcode = new String(buffer, 0, transferred.get(0)).trim();
    System.out.printf("来自设备(Bus %d, Device %d)的条码: %s%n", busNumber, address, barcode);
}

5. 资源释放

使用完设备后,要释放接口、关闭设备:

LibUsb.releaseInterface(handle, ifaceDesc.bInterfaceNumber());
LibUsb.close(handle);
LibUsb.freeDeviceList(list, true);

关键注意事项

  • 如果扫描器是键盘模式,必须先切换到HID模式:参考扫描器的用户手册,扫描对应的设置条码即可切换。
  • 权限问题:在Linux/macOS下可能需要设置udev规则,避免权限不足;Windows下通常需要驱动支持。
  • 异步读取:如果需要同时监听两台设备,建议使用usb4java的异步传输API(LibUsb.asyncTransfer),避免阻塞主线程。

内容的提问来源于stack exchange,提问作者Ahmed

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.30 21:42:42