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

使用LibUsbDotNet读取通用USB RFID读卡器,如何获取卡面RFID编号?

解决USB RFID读卡器字节数组转卡片编号的问题

既然你已经发现读卡器是通过模拟HID键盘输入来输出编号的,那我们直接解析LibUsbDotNet拿到的字节数组(也就是HID键盘报告)就行,不用绕键盘记录器的路子了。

核心思路:解析HID键盘报告格式

USB键盘的标准HID报告通常是8字节的结构:

  • 第0字节:修饰键位掩码(比如Shift、Ctrl这些,一般读卡器用不到)
  • 第1字节:保留位(固定为0)
  • 第2-7字节:按键扫描码(最多同时发送6个按键,没按键的位置是0)

读卡器会把卡片编号的每个字符,依次转换成对应的键盘扫描码发送出来,我们只需要把这些扫描码映射回字符,拼接起来就是卡片表面的编号。

具体实现步骤

  1. 建立扫描码到字符的映射表
    针对数字和常见的RFID编号字符(比如0-9),先定义标准美式键盘的扫描码映射(不同地区键盘布局可能略有差异,可根据实际调整):

    private static Dictionary<byte, char> KeyScanCodeMap = new Dictionary<byte, char>
    {
        {0x0B, '0'},
        {0x02, '1'},
        {0x03, '2'},
        {0x04, '3'},
        {0x05, '4'},
        {0x06, '5'},
        {0x07, '6'},
        {0x08, '7'},
        {0x09, '8'},
        {0x0A, '9'},
        {0x28, '\r'} // 部分读卡器最后会发送回车,后续需要过滤
    };
    
  2. 解析LibUsb读取到的字节数组
    假设你用LibUsbDotNet读取到的字节数组是byte[] readBuffer,我们遍历有效扫描码位并转换为字符:

    public string ConvertRfidBytesToCardNumber(byte[] readBuffer)
    {
        StringBuilder cardNumber = new StringBuilder();
        
        // 跳过前2字节(修饰键+保留位),遍历第2到第7字节的扫描码
        for (int i = 2; i < readBuffer.Length; i++)
        {
            byte scanCode = readBuffer[i];
            if (scanCode == 0)
                continue; // 跳过空按键位置
            
            if (KeyScanCodeMap.TryGetValue(scanCode, out char c))
            {
                if (c != '\r') // 过滤回车符,只保留编号内容
                    cardNumber.Append(c);
            }
        }
        
        return cardNumber.ToString();
    }
    
  3. 集成到原有读取逻辑
    在你原来用LibUsbDotNet读取数据的代码中,把拿到的readBuffer传入上面的方法,就能直接得到和键盘记录器一致的卡片编号了。

额外注意事项

  • 如果你的读卡器支持字母编号,需要补充对应扫描码映射,若涉及大写字母还需结合第0字节的修饰键位判断是否需要转大写。
  • 部分读卡器的HID报告长度可能略有不同,若解析失败可先打印readBuffer的所有字节值,调整遍历的起始位置和范围。
  • 少数读卡器会发送按键按下+抬起的两次报告,这时候需要过滤掉重复的扫描码,只保留首次出现的有效按键。

内容的提问来源于stack exchange,提问作者OJ Raqueño

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 09:00:04