ACR1255U-J1蓝牙NFC阅读器无法识别Mifare Ultralight卡
问题:ACR1255U-J1蓝牙NFC阅读器无法识别Mifare Ultralight卡
多日尝试使用ACR1255U-J1蓝牙NFC阅读器读取Mifare Ultralight卡,以实现手机打开指定URL的功能,但始终失败。无论阅读器上方是否放置NFC卡,输出日志完全一致。
日志示例
放置NFC卡时的日志:
Running "NFCReaderApp" with {"rootTag":141,"initialProps":{},"fabric":true} NFCReader.js:54 Connected device: ACR1255U-J1-035094 NFCReader.js:150 Comando enviado: ff 00 00 00 00 NFCReader.js:150 Comando enviado: ff 00 00 02 01 NFCReader.js:150 Comando enviado: ff 00 00 03 01 NFCReader.js:82 Reader Initialized NFCReader.js:100 Raw data: 05 00 07 52 00 00 00 00 01 53 07 0a
未放置NFC卡时的日志:
Running "NFCReaderApp" with {"rootTag":141,"initialProps":{},"fabric":true} NFCReader.js:54 Connected device: ACR1255U-J1-035094 NFCReader.js:150 Comando enviado: ff 00 00 00 00 NFCReader.js:150 Comando enviado: ff 00 00 02 01 NFCReader.js:150 Comando enviado: ff 00 00 03 01 NFCReader.js:82 Reader Initialized NFCReader.js:100 Raw data: 05 00 07 52 00 00 00 00 01 53 07 0a
已排查情况
- 更换多张Mifare Ultralight卡,输出结果无变化
- 阅读器连接ACS官方BLETest.apk可正常工作
- 卡片在手机NFC阅读器上能正常识别
代码实现
import base64 from 'base-64'; import { BleManager } from 'react-native-ble-plx'; class NFCReaderApp { constructor(onCardStatusChange) { this.bleManager = new BleManager(); this.SERVICE_UUID = "3c4afff0-4783-3de5-a983-d348718ef133"; this.WRITE_CHARACTERISTIC = "3c4afff1-4783-3de5-a983-d348718ef133"; this.NOTIFY_CHARACTERISTIC = "3c4afff2-4783-3de5-a983-d348718ef133"; this.scanning = false; this.onDeviceFound = null; this.onError = null; this.lastCardStatus = false; this.onCardStatusChange = onCardStatusChange; } async checkBluetoothState() { try { const state = await this.bleManager.state(); return state === 'PoweredOn'; } catch (error) { console.error('Error checking Bluetooth:', error); return false; } } startScanning() { if (this.scanning) return; this.scanning = true; this.bleManager.startDeviceScan(null, null, (error, device) => { if (error) { this.scanning = false; if (this.onError) this.onError('Scanning error: ' + error); return; } if (device?.name?.includes('ACR1255U')) { this.stopScanning(); this.connectToDevice(device); } }); } stopScanning() { if (this.scanning) { this.bleManager.stopDeviceScan(); this.scanning = false; } } async connectToDevice(device) { try { console.log('Connecting to device:', device.name); const connectedDevice = await device.connect(); await connectedDevice.discoverAllServicesAndCharacteristics(); if (this.onDeviceFound) { this.onDeviceFound(device); } await this.initializeReader(connectedDevice); await this.setupCardDetection(connectedDevice); } catch (error) { console.error('Connection error:', error); if (this.onError) this.onError('Connection error: ' + error); } } async initializeReader(device) { try { const initCommands = [ [0xFF, 0x00, 0x00, 0x00, 0x00], // Reset [0xFF, 0x00, 0x00, 0x02, 0x01], // Auto polling on [0xFF, 0x00, 0x00, 0x03, 0x01] // Set operation mode ]; for (const cmd of initCommands) { await this.sendCommand(device, cmd); await new Promise(resolve => setTimeout(resolve, 300)); } console.log('Reader Initialized'); } catch (error) { console.error('Error initializing reader:', error); } } async setupCardDetection(device) { return device.monitorCharacteristicForService( this.SERVICE_UUID, this.NOTIFY_CHARACTERISTIC, (error, characteristic) => { if (error) { console.error('Error monitoring characteristic:', error); return; } if (characteristic?.value) { const rawData = this.base64ToArray(characteristic.value); console.log('Raw data:', this.bytesToHex(rawData)); this.analyzeResponse(rawData); } } ); } analyzeResponse(data) { if (!data || data.length === 0) return; switch(data[0]) { case 0x61: // Card status response const cardPresent = this.validateCardPresence(data); if (cardPresent !== this.lastCardStatus) { this.lastCardStatus = cardPresent; console.log(cardPresent ? '✅ CARD DETECTED' : '❌ NO CARD'); if (this.onCardStatusChange) { this.onCardStatusChange(cardPresent); } } break; case 0x4E: // No card if (this.lastCardStatus) { this.lastCardStatus = false; console.log('❌ NO CARD'); if (this.onCardStatusChange) { this.onCardStatusChange(false); } } break; } } validateCardPresence(data) { // Specific validation for Mifare Ultralight if (data.length < 3) return false; // Check if there are valid card data return data[1] !== 0x00 || data[2] !== 0x00; } async sendCommand(device, command) { try { const encodedCommand = this.arrayToBase64(command); await device.writeCharacteristicWithResponseForService( this.SERVICE_UUID, this.WRITE_CHARACTERISTIC, encodedCommand ); console.log('Comando enviado:', this.bytesToHex(command)); } catch (error) { console.error('Error sending command:', error); } } bytesToHex(bytes) { return Array.from(bytes) .map(byte => byte.toString(16).padStart(2, '0')) .join(' '); } arrayToBase64(array) { return base64.encode(String.fromCharCode(...array)); } base64ToArray(str) { return new Uint8Array(base64.decode(str).split('').map(c => c.charCodeAt(0))); } cleanup() { this.stopScanning(); this.bleManager.destroy(); } } export default NFCReaderApp;
可能的原因及解决方案
1. 初始化命令不符合阅读器规范
当前发送的自动轮询命令[0xFF, 0x00, 0x00, 0x02, 0x01]可能无效。根据ACS官方文档,开启持续自动轮询的正确命令应为FF 00 00 02 02,01仅触发单次轮询,无法持续检测卡片状态变化。同时,操作模式命令[0xFF, 0x00, 0x00, 0x03, 0x01]需确认是否兼容Mifare Ultralight所属的ISO 14443 Type A协议。
修正方案:
更新初始化命令数组,参考官方文档调整参数:
const initCommands = [ [0xFF, 0x00, 0x00, 0x00, 0x00], // 重置阅读器 [0xFF, 0x00, 0x00, 0x02, 0x02], // 开启持续自动轮询 [0xFF, 0x00, 0x00, 0x03, 0x00] // 设置为ISO 14443 Type A兼容模式 ];
2. 响应解析逻辑未匹配阅读器返回格式
日志中返回的原始数据开头为0x05,但你的analyzeResponse方法仅处理0x61(卡片状态)和0x4E(无卡)两种响应,导致无论有无卡片都无法触发状态变更。
修正方案:
先打印所有响应的首字节,对照官方文档确认含义,扩展解析逻辑:
analyzeResponse(data) { if (!data || data.length === 0) return; console.log('响应首字节:', data[0].toString(16)); switch(data[0]) { case 0x61: // 卡片状态响应 const cardPresent = this.validateCardPresence(data); if (cardPresent !== this.lastCardStatus) { this.lastCardStatus = cardPresent; console.log(cardPresent ? '✅ CARD DETECTED' : '❌ NO CARD'); this.onCardStatusChange?.(cardPresent); } break; case 0x4E: // 无卡 if (this.lastCardStatus) { this.lastCardStatus = false; console.log('❌ NO CARD'); this.onCardStatusChange?.(false); } break; case 0x05: // 阅读器状态通知(需参考文档确认具体含义) // 添加对应处理逻辑,比如检查后续字节判断卡片状态 break; default: console.log('未识别的响应码:', data[0].toString(16)); } }
3. BLE特征UUID可能不准确
虽然能连接设备,但需再次确认SERVICE_UUID、WRITE_CHARACTERISTIC和NOTIFY_CHARACTERISTIC是否与ACR1255U-J1的官方BLE服务UUID完全一致。部分设备可能使用不同的UUID变体,可通过BLE调试工具(如nRF Connect)扫描设备获取准确值。
内容的提问来源于stack exchange,提问作者Adriel García
相关产品推荐
相关产品推荐

