123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501 |
- 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;
|