使用NodeJS和serialport库读取USB RFID读卡器卡号问题咨询
问题根因
- Readline解析器无输出:该RFID读卡器的串口输出未用换行符作为数据帧分隔符,Readline默认按
\n/\r\n切割数据流,因此无法触发回调。 - 原始
data事件输出零散数据:serialport的data事件会实时返回当前收到的字节分片,不会等待完整的读卡数据帧传输完成,因此拿到的是不完整的分段数据。
解决方案
你已经找到了数据帧的前后缀规则,只需先把所有收到的串口数据攒成完整的hex缓存,再按规则匹配完整数据帧、提取中间卡号段即可,参考实现代码如下:
const SerialPort = require('serialport'); const port = new SerialPort('/dev/cu.usbserial-0001', { baudRate: 9600 }); // 全局hex缓存,用于拼接分片数据 let hexBuffer = ''; // 已梳理的固定前后缀(去掉空格拼接为连续hex) const FRAME_PREFIX = '00181818189898e098'; const FRAME_SUFFIX = '18f8'; // 卡号段长度:10字节对应20位hex字符 const CARD_HEX_LENGTH = 20; port.on('data', (data) => { // 新收到的数据转hex拼入缓存 hexBuffer += data.toString('hex'); // 循环匹配缓存中所有符合规则的完整帧 while (hexBuffer.includes(FRAME_PREFIX) && hexBuffer.includes(FRAME_SUFFIX)) { // 定位前缀起始位置 const prefixIndex = hexBuffer.indexOf(FRAME_PREFIX); // 前缀结束位置即为卡号段起始位置 const cardStart = prefixIndex + FRAME_PREFIX.length; // 定位后缀起始位置(必须在卡号段之后) const suffixIndex = hexBuffer.indexOf(FRAME_SUFFIX, cardStart); // 确认帧结构完整 if (suffixIndex !== -1 && (suffixIndex - cardStart) === CARD_HEX_LENGTH) { // 提取卡号hex,转大写后拼接MT_前缀即为数据库兼容格式 const cardHex = hexBuffer.slice(cardStart, suffixIndex).toUpperCase(); const cardId = `MT_${cardHex}`; console.log('读取到卡号:', cardId); // 从缓存中删除已处理的内容,避免重复匹配 hexBuffer = hexBuffer.slice(suffixIndex + FRAME_SUFFIX.length); } else { // 帧不完整,等待更多数据输入后再匹配 break; } } }); port.on('error', (err) => { console.error('串口错误:', err.message); });
可选调整项
- 如果匹配不到完整帧,可以临时打印
hexBuffer内容,确认前后缀规则是否有偏差,比如前后缀的字节长度是否和梳理的一致 - 若输出的卡号和卡片印刷号不匹配,可调整提取的卡号段长度,若需要匹配印刷的十进制卡号,可以将提取到的hex转十进制后取对应位数即可
内容的提问来源于stack exchange,提问作者mrclbls
相关产品推荐
相关产品推荐

