import { formatNullCharacter, stringToArrayBuffer, arrayBufferToString, ab2hex, byteLength, generateUUID } from './util.js' // 标签写入的类型 export const WRITE_TYPE_ENUM = { T: 'T', U: 'U' }; export const WRITE_TYPE_TEXT_ENUM = { T: '文本', U: '网址', }; export const NFC_STATUS_ENUM = { INIT: 'INIT', // 初始化NFC INIT_OK: 'INIT_OK', // 初始化NFC成功 INIT_ERROR: 'INIT_ERROR', // 初始化NFC失败 READ_START: 'READ_START', // 读取开始 READING: 'READING', // 正在读取 READ_SUCCESS: 'READ_SUCCESS', // 读取成功 READ_FAIL: 'READ_FAIL', // 读取失败 WRITE_START: 'WRITE_START', // 写入开始 WRITING: 'WRITING', // 正在写入 WRITE_SUCCESS: 'WRITE_SUCCESS', // 写入成功 WRITE_FAIL: 'WRITE_FAIL', // 写入失败 DEVICE_NO_NFC: 'DEVICE_NO_NFC', // 设备不支持NFC DEVICE_NFC_NOT_ENABLE: 'DEVICE_NFC_NOT_ENABLE', // 设备未开启NFC TIMEOUT_ERROR: 'TIMEOUT_ERROR', // 超时提示 TOAST: 'TOAST', // toast提示 }; const ERR_CODE_ENUM = { 13000: '本设备不支持NFC', 13001: '系统NFC开关未打开', 13010: '未知错误', 13019: '用户未授权', 13021: '已经开始NFC扫描', 13018: '尝试在未开始NFC扫描时停止NFC扫描', 13022: '标签已经连接', 13023: '尝试在未连接标签时断开连接', 13013: '未扫描到NFC标签', 13014: '无效的标签技术', 13015: '从标签上获取对应技术失败', 13024: '当前标签技术不支持该功能', 13017: '相关读写操作失败', 13016: '连接失败', } class NFCTool { static NFCAdapter = null; // NFC适配器对象 static NFCType = null; // NFC标签 nfcState = false; // nfc开启状态 isConnect = false; // 开启连接 noNFC = false; // 是否有NFC功能 callBack = null; readFuc = null; writeFuc = null; timeOut = 60 * 1000; maxLength = 120; // 写入NFC的相关数据 readyWrite = false; // 开启写 writeTimer = null; writeParams = { id: '', // 将要写入ID text: '', // 写入的字符 type: '', // 写入的类型 }; nfcTagId = ''; // nfc唯一标识 // 读取NFC的相关数据 readyRead = false; // 开启读 readTimer = null; readParams = { id: '', // 读取ID text: '', // 读取的字符 type: '', // 读取的类型 }; constructor(NFCToolCallBack, data) { this.callBack = NFCToolCallBack; this.timeOut = data?.timeOutNum ? Number(data?.timeOutNum) : 60 * 1000; // this.startDiscovery(); } /** * 开始监听 */ startDiscovery(data) { console.log(data, uni.getSystemInfoSync().platform) if (uni.getSystemInfoSync().platform !== "android") { return } let _this = this; _this.readyWrite = data?.readyWrite ? data?.readyWrite : false; _this.callBack({ status: NFC_STATUS_ENUM.INIT, tip: '初始化NFC' }) // try { if (!_this.nfcState) { let adapter = wx.getNFCAdapter(); console.log(adapter) if (adapter == null) { _this.callBack({ status: NFC_STATUS_ENUM.DEVICE_NO_NFC, tip: '设备不支持NFC或未开启NFC' }) _this.noNFC = true; return; } _this.NFCAdapter = adapter; _this.nfcState = true; _this.NFCAdapter.startDiscovery({ success(res) { _this.callBack({ status: NFC_STATUS_ENUM.INIT_OK, tip: 'NFC读取功能已开启', }); // 绑定监听 NFC Tag 读取 _this.readFuc = _this.readDiscoverHandler.bind(_this); _this.NFCAdapter.onDiscovered(_this.readFuc); if (_this.readyWrite) { // 绑定监听 NFC Tag 写入 _this.writeTimer = setTimeout(() => { if (_this.readyWrite && !_this.isConnect) { _this.callBack({ status: NFC_STATUS_ENUM.TIMEOUT_ERROR, tip: 'NFC读取超时,请重试...' }) _this.readyRead = false; _this.stopDiscovery(); } clearTimeout(_this.writeTimer); }, _this.timeOut); _this.writeFuc = _this.writeDiscoverHandler.bind(_this); _this.NFCAdapter.onDiscovered(_this.writeFuc); } // } }, fail(err) { let errCodeTips = err?.errCode ? ERR_CODE_ENUM[Number(err?.errCode)] : ''; _this.callBack({ status: NFC_STATUS_ENUM.INIT_ERROR, tip: '请检查NFC功能是否正常', data: errCodeTips }); _this.noNFC = true; } }) } // } catch (e) { // _this.callBack({ // status: NFC_STATUS_ENUM.INIT_ERROR, // tip: '请检查NFC功能是否正常' // }) // _this.noNFC = true; // } } /** * 读取NFC标签 */ readData() { let _this = this; if (_this.nfcState) { if (_this.noNFC) { _this.callBack({ status: NFC_STATUS_ENUM.READ_FAIL, tip: '请检查设备是否支持并开启 NFC 功能!', data: '' }) return; } _this.readTimer = setTimeout(() => { if (_this.readyRead) { _this.callBack({ status: NFC_STATUS_ENUM.TIMEOUT_ERROR, tip: 'NFC读取超时,请重试...' }) _this.readyRead = false; } clearTimeout(_this.readTimer); }, _this.timeOut); _this.callBack({ status: NFC_STATUS_ENUM.READ_START, tip: '请将设备靠近NFC识别区' }) // 更改读状态 _this.readyRead = true; } } /** * 监听 NFC Tag 读取 * @param id ArrayBuffer * @param techs Array tech 数组,用于匹配NFC卡片具体可以使用什么标准(NfcA等实例)处理 * @param messages */ async readDiscoverHandler({ id, techs, messages }) { let _this = this; try { if (_this.readyRead && _this.nfcState) { _this.callBack({ status: NFC_STATUS_ENUM.READING, tip: '识别NFC标签中' }) let adapter = _this.NFCAdapter; await _this.readTag(id); if (techs.includes(adapter.tech.nfcA)) { let nfcA = adapter.getNfcA(); _this.NFCType = nfcA; if (messages) { let cordsArray = messages[0].records; cordsArray.forEach(item => { _this.readParams = { id: arrayBufferToString(item.id), // 读取ID text: arrayBufferToString(item.payload), // 读取的字符 type: arrayBufferToString(item.type), // 读取的类型 } _this.callBack({ status: NFC_STATUS_ENUM.READ_SUCCESS, tip: '读取成功', data: { ..._this.readParams, nfcTagId: _this.nfcTagId, } }) }) } else { _this.callBack({ status: NFC_STATUS_ENUM.READ_SUCCESS, tip: '读取成功', data: { ..._this.readParams, nfcTagId: _this.nfcTagId, } }) } _this.readyRead = false; } } } catch (e) { _this.callBack({ status: NFC_STATUS_ENUM.READ_FAIL, tip: '读取失败' }) } } /** * 写入NFC标签 * @param {Object} data 写入的数据 */ writeTag(data) { let _this = this; if (_this.nfcState) { if (data) { _this.callBack({ status: NFC_STATUS_ENUM.WRITE_START, tip: '请将设备靠近NFC识别区' }) _this.writeParams = { id: data.id, text: data.positionName, // 写入的字符 type: WRITE_TYPE_ENUM.T, // 写入的类型 }; if (byteLength(JSON.stringify(_this.writeParams)) > _this.maxLength) { _this.callBack({ status: NFC_STATUS_ENUM.WRITE_FAIL, tip: '数据超过NFC容量大小,请重试' }); _this.stopDiscovery(); return; } if (_this.isConnect) { _this.writeNdefMessage() } else { // TODO 报错 NFC断开连接 } } else { _this.callBack({ status: NFC_STATUS_ENUM.WRITE_FAIL, tip: '写入数据不可为空,请重试' }) } } } /** * 监听 NFC Tag 写入 * @param id ArrayBuffer * @param techs Array tech 数组,用于匹配NFC卡片具体可以使用什么标准(NfcA等实例)处理 * @param messages */ async writeDiscoverHandler({ id, techs, messages }) { let _this = this; if (_this.nfcState) { _this.callBack({ status: NFC_STATUS_ENUM.READING, tip: '识别NFC标签中' }) let adapter = _this.NFCAdapter; await _this.readTag(id); let nDef = adapter.getNdef(); _this.NFCType = nDef; if (_this.isConnect) { _this.onCloseConnect(); } _this.onConnect(); } } /** * 读取 NFC 标签 返回的 id * @param {Object} id */ readTag(id) { let aid = parseInt(ab2hex(id), 16); // 使用 new Uint8Array处理返回一个数组 const data = new Uint8Array(id); let tagId = "" data.forEach(e => { // 因为我们的卡号是16位制的,所以这里选择转换成16位数字 let item = e.toString(16) if (item.length == 1) { item = '0' + item } // 因为我们需要的是大写,所以要转 item = item.toUpperCase() tagId = item + tagId }) // 最终结果 /* 这里获取的tagId就是我们读取出的UID码了 */ this.nfcTagId = tagId; } /** * 设备连接操作 写入操作 */ onConnect() { let _this = this; if (!_this.isConnect) { _this.NFCType.connect({ success: function(cRes) { _this.isConnect = true; _this.callBack({ status: NFC_STATUS_ENUM.WRITING, tip: '已连接,请勿移开设备', data: { isConnect: true, } }) // _this.writeNdefMessage() }, fail: function(err) { let errCodeTips = err?.errCode ? ERR_CODE_ENUM[Number(err?.errCode)] : ''; _this.callBack({ status: NFC_STATUS_ENUM.WRITE_FAIL, tip: '设备连接错误', data: { nfcTagId: _this.nfcTagId, errCodeTips } }); _this.stopDiscovery(); } }); } } /** * NFC写入操作 */ writeNdefMessage() { let _this = this; // let idBuffer = stringToArrayBuffer(''); // 写入的字符 let idBuffer = stringToArrayBuffer((_this.writeParams.id).toString()); // 写入的字符 let textBuffer = stringToArrayBuffer(_this.writeParams.text); // 写入的字符 let typeBuffer = stringToArrayBuffer(_this.writeParams.type); // 写入的类型 const records = [{ id: idBuffer, payload: textBuffer, type: typeBuffer, tnf: 2 }]; _this.NFCType.writeNdefMessage({ records: records, success: function(tRes) { _this.callBack({ status: NFC_STATUS_ENUM.WRITE_SUCCESS, tip: '写入成功', data: { ..._this.writeParams, nfcTagId: _this.nfcTagId, isConnect: false } }) }, fail: function(err) { let errCodeTips = err?.errCode ? ERR_CODE_ENUM[Number(err?.errCode)] : ''; _this.callBack({ status: NFC_STATUS_ENUM.WRITE_FAIL, tip: '数据写入失败', data: { nfcTagId: _this.nfcTagId, errCodeTips, isConnect: false } }) }, complete: res => { _this.writeParams = { id: '', text: '', // 写入的字符 type: '', // 写入的类型 }; _this.readyWrite = false; _this.onCloseConnect(); _this.stopDiscovery(); } }) } onCloseConnect() { let _this = this; _this.isConnect = false; if (_this.NFCType) { _this.NFCType.close({ success: function(cRes) {}, fail: function(err) { let errCodeTips = err?.errCode ? ERR_CODE_ENUM[Number(err?.errCode)] : ''; }, complete: res => {} }); } } /** * 设置超时时间 */ onSetTimeout() { } /** * @param {Object} data格式化NFC数据 */ formatNFC(data) { // 这里可以添加数据格式化的逻辑 return 'Formatted data: ' + data; } changeNFCState() { let _this = this; _this.nfcState = !_this.nfcState; } /** * 停止监听贴卡 */ stopDiscovery() { let _this = this; if (_this.NFCType) { _this.isConnect && _this.onCloseConnect(); _this.NFCType = null; } if (_this.NFCAdapter) { _this.NFCAdapter.offDiscovered(_this.readFuc); _this.NFCAdapter.offDiscovered(_this.writeFuc); _this.NFCAdapter.stopDiscovery(); _this.NFCAdapter = null; _this.nfcState = false; } if (_this.readTimer) { clearTimeout(_this.readTimer); } if (_this.writeTimer) { clearTimeout(_this.writeTimer); } } } export default NFCTool;