USB读卡器读取时报TypeError [ERR_INVALID_ARG_TYPE]错误求助
USB读卡器读取数据报错:TypeError [ERR_INVALID_ARG_TYPE]
读卡器已成功连接,但执行读取功能时抛出错误:
TypeError [ERR_INVALID_ARG_TYPE]: The "size" argument must be of type number. Received an instance of Buffer
问题代码片段
const express = require('express'); const usb = require('usb'); const cors = require('cors'); const app = express(); const port = 3001; app.use(cors()); app.use(express.json()); // 列出所有可用USB设备的函数 function listUSBDevices() { const devices = usb.getDeviceList(); // 返回USB设备列表 return devices.map((device, index) => ({ id: index + 1, descriptor: device.deviceDescriptor, manufacturer: device.deviceDescriptor.iManufacturer, product: device.deviceDescriptor.iProduct, })); } // 连接指定USB设备的函数 function connectToUSBDevice(targetVendorId, targetProductId) { const devices = usb.getDeviceList(); const targetDevice = devices.find((device) => { return ( device.deviceDescriptor.idVendor === targetVendorId && device.deviceDescriptor.idProduct === targetProductId ); }); return targetDevice; } // 从USB设备读取数据的函数 function readDataFromUSBDevice(vendorId, productId, blockNum, callback) { const targetDevice = connectToUSBDevice(vendorId, productId); if (!targetDevice) { callback('USB device not found.'); return; } try { targetDevice.open(); const interface = targetDevice.interfaces[0]; const endpoint = interface.endpoints[0]; const bufferSize = 64; // 设置缓冲区大小(单位:字节) const buffer = Buffer.alloc(bufferSize); // 创建用于存储读取数据的缓冲区 // 发送读取命令(请根据设备协议修改此部分) buffer[0] = 0x04; buffer[1] = 0x21; buffer[2] = 0x02; buffer[3] = blockNum; // 替换为目标块编号 // 根据协议对缓冲区进行其他必要修改 endpoint.transfer(buffer, (error, actualLength) => { if (error) { console.error('Error sending command to USB device:', error); targetDevice.close(); callback('Error reading from USB device.'); } else { // 处理接收的数据并传递给回调函数 const data = buffer.slice(0, actualLength).toString('utf8'); targetDevice.close(); callback(null, data); } }); } catch (error) { console.error('Error reading from USB device:', error); callback('Error reading from USB device.'); } } // 处理根URL请求 app.get('/', (req, res) => { res.send('Hello, this is your server response!'); }); app.get('/listUSBDevices', (req, res) => { const usbDevices = listUSBDevices(); res.json(usbDevices); }); // 添加读取数据的新路由 app.post('/communicateWithDevice', (req, res) => { const { vendorId, productId, action, data, blockNum } = req.body; if (action === 'read') { readDataFromUSBDevice(vendorId, productId, blockNum, (error, result) => { if (error) { res.json({ message: error }); } else { res.json({ message: result }); } }); } else if (action === 'write') { const result = writeToUSBDevice(targetDevice, data); res.json({ message: result }); } else if (action === 'connectToDevice') { // 修正动作名称 const targetDevice = connectToUSBDevice(vendorId, productId); const result = targetDevice ? 'Connected to USB device successfully.' : 'USB device not found.'; res.json({ message: result }); } else { res.json({ message: 'Invalid action specified.' }); } }); app.listen(port, () => { console.log(`Server is running on port ${port}`); });
错误原因
node-usb库中,端点的transfer方法参数根据端点类型不同而不同:
- OUT端点(用于向设备发送数据):第一个参数是要发送的Buffer
- IN端点(用于从设备读取数据):第一个参数是读取的字节数(数字)
你的代码直接使用了interface.endpoints[0],如果该端点是IN类型,传入Buffer就会触发类型错误。此外,读取读卡器数据通常需要先通过OUT端点发送读取命令,再通过IN端点接收返回数据。
解决方案
- 区分IN/OUT端点,分别用于读取和发送命令
- 先发送读取命令,再读取设备返回的数据
- 修复端点调用逻辑,添加接口权限管理
修正后的核心代码
// 从USB设备读取数据的函数 function readDataFromUSBDevice(vendorId, productId, blockNum, callback) { const targetDevice = connectToUSBDevice(vendorId, productId); if (!targetDevice) { callback('USB device not found.'); return; } try { targetDevice.open(); const interface = targetDevice.interfaces[0]; // 处理内核驱动,申请接口权限 if (interface.isKernelDriverActive()) { interface.detachKernelDriver(); } interface.claim(); // 分别找到OUT(发命令)和IN(读数据)端点 const outEndpoint = interface.endpoints.find(ep => ep.direction === 'out'); const inEndpoint = interface.endpoints.find(ep => ep.direction === 'in'); if (!outEndpoint || !inEndpoint) { callback('Required endpoints not found.'); targetDevice.close(); return; } // 构造读取命令缓冲区 const cmdBuffer = Buffer.alloc(64); cmdBuffer[0] = 0x04; cmdBuffer[1] = 0x21; cmdBuffer[2] = 0x02; cmdBuffer[3] = blockNum; // 第一步:发送读取命令到设备 outEndpoint.transfer(cmdBuffer, (cmdError) => { if (cmdError) { console.error('Error sending command:', cmdError); interface.release(); targetDevice.close(); callback('Failed to send read command.'); return; } // 第二步:从IN端点读取设备返回的数据 const readSize = 64; inEndpoint.transfer(readSize, (readError, data) => { // 释放资源 interface.release(); targetDevice.close(); if (readError) { console.error('Error reading data:', readError); callback('Failed to read data from device.'); return; } // 处理并返回数据 const result = data.toString('utf8'); callback(null, result); }); }); } catch (error) { console.error('Error during USB operation:', error); targetDevice?.close(); callback('Error reading from USB device.'); } }
额外注意:
- 命令格式需严格遵循你的读卡器通信协议,上述命令仅为示例
- 操作完成后必须释放接口权限并关闭设备,避免资源泄漏
内容的提问来源于stack exchange,提问作者Radhika Padiya
相关产品推荐
相关产品推荐

