UNPKG

vite-uni-dev-tool

Version:

vite-uni-dev-tool, debug, uni-app, 一处编写,到处调试

551 lines (496 loc) 12.6 kB
import { ref } from 'vue'; import { onLoad, onUnload } from '@dcloudio/uni-app'; import { getReadWriteStandard, getSakHex, getSakType, parseAtqa, transformArrayBuffer, } from './utils'; export default function useNFCMpWeiXin( listener: (data: NFC.Result) => void, options: { timeout?: number; checkConnectedDelay?: number } = { timeout: 0, checkConnectedDelay: 500, }, ) { /** 是否支持 nfc */ const isSupportNFC = ref<boolean | undefined>(false); /** 是否监听中 */ const isListening = ref<boolean>(false); /** * 是否已连接 * 需要手动维护,调用connect()后连接 调用close()后断开 ,实际nfc 断开之后是无法监听到的, isConnected 已经被废弃掉了 */ const isConnected = ref<boolean>(false); /** nfc 数据 */ const data = ref<NFC.Result>({ id: new ArrayBuffer(0), techs: [], byteArray: [], hexArray: [], hexNumberArray: [], hexString: '', }); /** nfc 适配器 */ let nfcAdapter: NFC.Adapter; /** nfc 实例 */ let nfcInstance: NFC.Instance | undefined; /** ndef 写入方式比较特殊,需要特殊处理 */ let isNdef = ref(false); /** * 初始化 nfc adapter * * @return {*} */ async function initNfcAdapter() { await checkHCEState(); if (!isSupportNFC.value) return; nfcAdapter = wx.getNFCAdapter(); nfcAdapter.onDiscovered(innerListener); } function getAtqa(nfcInstance: NFC.Instance): Promise<NFC.Atqa> { return new Promise((resolve, reject) => { if (!nfcInstance.getAtqa) { reject({ errMsg: '不支持获取 atqa' }); } nfcInstance?.getAtqa?.({ success: (res) => { resolve(res); }, fail: (err) => { reject(err); }, }); }); } function getMaxTransceiveLength( nfcInstance: NFC.Instance, ): Promise<NFC.MaxTransceiveLength> { return new Promise((resolve, reject) => { if (!nfcInstance.getMaxTransceiveLength) { reject({ errMsg: '不支持获取 maxTransceiveLength' }); } nfcInstance?.getMaxTransceiveLength?.({ success: (res) => { resolve(res); }, fail: (err) => { reject(err); }, }); }); } function getSak(nfcInstance: NFC.Instance): Promise<NFC.Sak> { return new Promise((resolve, reject) => { if (!nfcInstance.getMaxTransceiveLength) { reject({ errMsg: '不支持获取 sak' }); } nfcInstance?.getSak?.({ success: (res) => { resolve(res); }, fail: (err) => { reject(err); }, }); }); } /** * 检查HCE状态 * * @return {*} */ function checkHCEState() { // uni.showToast({ title: '初始化 NFC' }); return new Promise((resolve, reject) => { wx.getHCEState({ success: (res: any) => { isSupportNFC.value = true; resolve(res); }, fail: (err: any) => { isSupportNFC.value = false; reject(err); }, }); }); } /** * 启用HCE * * @return {*} */ function startHCE() { if (!isSupportNFC.value) { uni.showToast({ title: '设备不支持 NFC', icon: 'none', }); return; } // 前置校验 if (!nfcAdapter) { uni.showToast({ title: '请先初始化 NFC 适配器', icon: 'none' }); return false; } if (isListening.value) { uni.showToast({ title: 'NFC 监听已开启,无需重复操作', icon: 'none' }); return true; } nfcAdapter.startDiscovery(); isListening.value = true; uni.showToast({ title: '开始监听NFC', icon: 'none', }); } /** * 停用HCE * * @return {*} */ function stopHCE() { // 前置校验 if (!isSupportNFC.value) { uni.showToast({ title: '设备不支持 NFC', icon: 'none', }); return; } // 前置校验 if (!nfcAdapter) { uni.showToast({ title: '请先初始化 NFC 适配器', icon: 'none' }); return false; } if (!isListening.value) { uni.showToast({ title: 'NFC 监听已关闭,无需重复操作', icon: 'none' }); return true; } nfcAdapter.stopDiscovery(); isListening.value = false; uni.showToast({ title: '停止监听NFC', icon: 'none', }); } /** * 读取监听 * * @param {*} res */ async function innerListener(res: NFC.Data) { const transform = transformArrayBuffer(res?.id); /** * 获取标签类型 * 默认取第一个 */ const type = res.techs[0]; switch (type) { case 'NFC-A': nfcInstance = nfcAdapter.getNfcA(); break; case 'NFC-B': nfcInstance = nfcAdapter.getNfcB(); break; case 'NFC-F': nfcInstance = nfcAdapter.getNfcF(); break; case 'NFC-V': nfcInstance = nfcAdapter.getNfcV(); break; case 'MIFARE Classic': nfcInstance = nfcAdapter.getMifareClassic(); break; case 'MIFARE Ultralight': nfcInstance = nfcAdapter.getMifareUltralight(); break; case 'Ndef': isNdef.value = true; nfcInstance = nfcAdapter.getNdef(); break; case 'ISO-DEP': nfcInstance = nfcAdapter.getIsoDep(); break; default: nfcInstance = undefined; break; } if (res.techs.includes('NFC-A')) { const nfcA = nfcAdapter.getNfcA(); try { const atqa = await getAtqa(nfcA); const atqaInfo = parseAtqa(atqa.atqa); data.value.atqa = atqa.atqa; data.value.uidType = atqaInfo?.uidType; data.value.storageSize = atqaInfo?.storageSize; data.value.manufacturer = atqaInfo?.manufacturer; data.value.cardFeatures = atqaInfo?.cardFeatures; data.value.reserved = atqaInfo?.reserved; } catch (error) {} try { const sak = await getSak(nfcA); const sakType = getSakType(sak.sak); const sakHex = getSakHex(sak.sak); data.value.sak = sak.sak; data.value.sakType = sakType; data.value.sakHex = sakHex; } catch (error) {} } if (nfcInstance) { const maxTransceive = await getMaxTransceiveLength(nfcInstance); data.value.maxTransceiveLength = maxTransceive.length; data.value.readWriteStandard = getReadWriteStandard(res.techs); if (options?.timeout && options.timeout > 0) { nfcInstance?.setTimeout?.({ timeout: options.timeout, }); } data.value = { ...data.value, ...res, ...transform, }; isConnected.value = true; listener?.(data.value); // 可将改行去除 uni?.__dev_tool_nfc_collection__?.(data.value); } } /** * 移除监听读取消息 * * @return {*} */ function offHCEMessage() { if (!isSupportNFC.value) { uni.showToast({ title: '设备不支持 NFC,无需移除监听', icon: 'none' }); return { errMsg: 'success' }; } isConnected.value = false; nfcAdapter.offDiscovered(innerListener); uni.showToast({ title: 'NFC 监听已移除', icon: 'none' }); return { errMsg: 'success' }; } /** * 连接 nfc * * @return {*} */ function connect() { return new Promise((resolve, reject) => { if (!isSupportNFC.value) { uni.showToast({ title: '设备不支持 NFC', icon: 'none' }); reject({ errMsg: '设备不支持 NFC', }); return; } if (!isListening.value) { uni.showToast({ title: '请先开启前台调度监听', icon: 'none' }); reject({ errMsg: '请先开启前台调度监听', }); return; } if (!nfcInstance) { uni.showToast({ title: '请先靠近 NFC 标签', icon: 'none' }); reject({ errMsg: '请先靠近 NFC 标签', }); return; } nfcInstance?.connect?.({ success: (res) => { console.log('res: ', res); resolve(res); isConnected.value = true; uni.showToast({ title: 'NFC 连接成功', icon: 'none', }); }, fail: (err) => { if (err.errMsg === 'connect:fail:Tech already connected') { resolve(err); isConnected.value = true; } else { reject(err); isConnected.value = false; uni.showToast({ title: 'NFC 连接失败', icon: 'none', }); } }, }); }); } /** * 断开 nfc * * @return {*} */ function close() { return new Promise((resolve, reject) => { if (!isSupportNFC.value) { reject({ errMsg: '不支持NFC', }); return; } if (!nfcInstance) { reject({ errMsg: '未读取到NFC卡', }); return; } nfcInstance?.close?.({ success: (res) => { isConnected.value = false; nfcInstance = undefined; resolve(res); uni.showToast({ title: 'NFC 连接已关闭', icon: 'none' }); }, fail: (err) => { reject(err); uni.showToast({ title: 'NFC 连接关闭失败', icon: 'none' }); }, }); }); } async function transceive(data: ArrayBuffer) { return new Promise((resolve, reject) => { if (!isSupportNFC.value) { reject({ errMsg: '不支持NFC', }); return; } if (!nfcInstance) { reject({ errMsg: '未读取到NFC卡', }); return; } nfcInstance?.transceive?.({ data, success: (res) => { resolve(res); }, fail: (err) => { reject(err); }, }); }); } async function writeNdefMessage(data: NFC.NdefData) { return new Promise((resolve, reject) => { if (!isSupportNFC.value) { reject({ errMsg: '不支持NFC', }); return; } if (!nfcInstance) { reject({ errMsg: '未读取到NFC卡', }); return; } nfcInstance?.writeNdefMessage?.({ ...data, success: (res) => { resolve(res); }, fail: (err) => { reject(err); }, }); }); } /** * 写入数据 * * 支持以以下类型 * ISO-DEP * MIFARE Classic * MIFARE Ultralight * NFC-A * NFC-B * NFC-F * NFC-V * * @param {*} data * @return {*} */ async function write(data: ArrayBuffer) { try { // 连接 nfc await connect(); uni.showToast({ title: '开始写入数据, 请勿断开连接', icon: 'none', }); // 写入数据 await transceive(data); uni.showToast({ title: '写入成功', icon: 'none', }); // 断开 nfc // await close(); } catch (error) { throw error; } } /** * 写入数据 * 支持以以下类型 * Ndef * * @param {NFC.NdefData} data */ async function writeNdf(data: NFC.NdefData) { try { // 连接 nfc await connect(); uni.showToast({ title: '开始写入数据, 请勿断开连接', icon: 'none', }); // 写入数据 await writeNdefMessage(data); uni.showToast({ title: '写入成功', icon: 'none', }); // 断开 nfc await close(); } catch (error) { throw error; } } onLoad(() => { initNfcAdapter(); }); onUnload(() => { stopHCE(); offHCEMessage(); }); return { data, isNdef, isSupportNFC, isListening, isConnected, nfcInstance, startHCE, stopHCE, connect, close, write, writeNdf, }; }