//build:20240715 //通过这个组件来读取卡,包括M1卡,psam卡之类的 //依赖组件: dxDriver,dxMap,dxLogger,dxDriver,dxCommon,dxEventBus import { nfcClass } from './libvbar-p-dxnfc.so' import dxCommon from './dxCommon.js' import bus from './dxEventBus.js' import dxMap from './dxMap.js' const nfcObj = new nfcClass(); const map = dxMap.get("default") const nfc = {} /** * NFC 初始化 * @param {number} useEid 非必填,是否使用云证 0不使用 1使用 */ nfc.init = function (useEid = 0) { let pointer = nfcObj.init(useEid) if (pointer === undefined || pointer === null) { throw new Error("nfc.init: init failed") } dxCommon.handleId("nfc", 'nfcid', pointer) } /** * NFC 普通卡注册回调 */ nfc.cbRegister = function (callback) { let pointer = dxCommon.handleId("nfc", 'nfcid') return nfcObj.cbRegister(pointer, "nfc_cb", 1, callback) } /** * NFC PSAM卡注册回调 */ nfc.psamCbRegister = function (callback) { let pointer = dxCommon.handleId("nfc", 'nfcid') return nfcObj.nfcPsamCheckVgcardCallback(pointer, callback) } /** * NFC 取消初始化 */ nfc.deinit = function () { let pointer = dxCommon.handleId("nfc", 'nfcid') let ret = nfcObj.cbUnregister(pointer, "nfc_cb") if (ret === false) { throw new Error("nfc.cbUnregister: cbUnregister failed") } return nfcObj.deinit(pointer) } /** * NFC 卡信息创建 * @param {number} cardType 卡芯片类型(原厂定义) * @param {ArrayBuffer} cardId 卡号 * @param {number} type 卡类型(我们自己定义的) * @returns cardInfo(pointer) */ nfc.cardInfoCreate = function (cardType, cardId, type) { if (!cardType) { throw new Error("cardInfoCreate:cardType should not be null or empty") } if (!cardId) { throw new Error("cardInfoCreate:cardId should not be null or empty") } if (!type) { throw new Error("cardInfoCreate:type should not be null or empty") } return nfcObj.cardInfoCreate(cardType, cardId, type); } /** * NFC 卡信息销毁 * @param {pointer} cardInfo 卡信息 * @returns */ nfc.cardInfoDestory = function (cardInfo) { if (!cardInfo) { throw new Error("cardInfoDestory:cardInfo should not be null or empty") } return nfcObj.cardInfoDestory(cardInfo); } /** * NFC 卡信息复制 * @param {pointer} cardInfo 卡信息 * @returns cardInfo(pointer) */ nfc.cardInfoCopy = function (cardInfo) { if (cardInfo == null) { throw new Error("cardInfoCopy:cardInfo should not be null or empty") } return nfcObj.cardInfoCopy(cardInfo); } /** * NFC 判断是否有卡 * @returns bool */ nfc.isCardIn = function () { let pointer = dxCommon.handleId("nfc", 'nfcid') return nfcObj.isCardIn(pointer); } /** * NFC 读M1卡扇区 * @param {number} taskFlg 任务标志: * 0x00->AUTO 告知扫码器该指令可单独执行,无指令间的依赖关系。 * 0x01->START 告知扫码器开始对卡操作或对卡操作尚未结束,且指令间可能存在依赖关系。 * 0x02->FINISH 告知扫码器本条指令是操作卡的最后一条指令,将卡片操作环境恢复到默态。 * @param {number} secNum 扇区号 * @param {number} logicBlkNum 块号(在扇区内的逻辑号0~3) * @param {number} blkNums 块数 * @param {array} key 密钥, 长度6bytes * @param {number} keyType 密钥类型: A:0x60 B:0x61 * @returns Array 读取结果 undefined:失败 */ nfc.m1cardReadSector = function (taskFlg, secNum, logicBlkNum, blkNums, key, keyType) { let pointer = dxCommon.handleId("nfc", 'nfcid') _validate('m1cardReadSector', taskFlg, secNum, logicBlkNum, blkNums, key, keyType, ' ') return nfcObj.m1cardReadSector(pointer, taskFlg, secNum, logicBlkNum, blkNums, key, keyType); } /** * NFC 读M1卡扇区 * @param {number} taskFlg 任务标志: * 0x00->AUTO 告知扫码器该指令可单独执行,无指令间的依赖关系。 * 0x01->START 告知扫码器开始对卡操作或对卡操作尚未结束,且指令间可能存在依赖关系。 * 0x02->FINISH 告知扫码器本条指令是操作卡的最后一条指令,将卡片操作环境恢复到默态。 * @param {number} secNum 扇区号 * @param {number} logicBlkNum 块号(在扇区内的逻辑号0~3) * @param {number} blkNums 块数 * @param {array} key 密钥, 长度6bytes * @param {number} keyType 密钥类型: A:0x60 B:0x61 * @param {array} data 写入数据 * @returns int 写入长度 -1:错误 */ nfc.m1cardWriteSector = function (taskFlg, secNum, logicBlkNum, blkNums, key, keyType, data) { let pointer = dxCommon.handleId("nfc", 'nfcid') _validate('m1cardWriteSector', taskFlg, secNum, logicBlkNum, blkNums, key, keyType, data) return nfcObj.m1cardWriteSector(pointer, taskFlg, secNum, logicBlkNum, blkNums, key, keyType, data); } /** * * @param {number} taskFlg 任务标志: * 0x00->AUTO 告知扫码器该指令可单独执行,无指令间的依赖关系。 * 0x01->START 告知扫码器开始对卡操作或对卡操作尚未结束,且指令间可能存在依赖关系。 * 0x02->FINISH 告知扫码器本条指令是操作卡的最后一条指令,将卡片操作环境恢复到默态。 * @param {number} blkNums 块号 * @param {array} key 密钥, 长度6bytes * @param {number} keyType 密钥类型: A:0x60 B:0x61 * @returns Array 读取结果 undefined:失败 */ nfc.m1cardReadBlk = function (taskFlg, blkNum, key, keyType) { let pointer = dxCommon.handleId("nfc", 'nfcid') _validate('m1cardReadBlk', taskFlg, 1, 0, blkNum, key, keyType, ' ') return nfcObj.m1cardReadBlk(pointer, taskFlg, blkNum, key, keyType); } /** * * @param {number} taskFlg 任务标志: * 0x00->AUTO 告知扫码器该指令可单独执行,无指令间的依赖关系。 * 0x01->START 告知扫码器开始对卡操作或对卡操作尚未结束,且指令间可能存在依赖关系。 * 0x02->FINISH 告知扫码器本条指令是操作卡的最后一条指令,将卡片操作环境恢复到默态。 * @param {number} blkNums 块号 * @param {array} key 密钥, 长度6bytes * @param {number} keyType 密钥类型: A:0x60 B:0x61 * @param {array} data 写入数据 * @returns int 写入长度 -1:错误 */ nfc.m1cardWriteBlk = function (taskFlg, blkNum, key, keyType, data) { let pointer = dxCommon.handleId("nfc", 'nfcid') _validate('m1cardWriteBlk', taskFlg, 1, 0, blkNum, key, keyType, data) return nfcObj.m1cardWriteBlk(pointer, taskFlg, blkNum, key, keyType, data); } /** * ATS检测 */ nfc.nfc_iso14443_type_a_get_ats = function () { let pointer = dxCommon.handleId("nfc", 'nfcid') return nfcObj.nfc_iso14443_type_a_get_ats(pointer) } /** * * @param {number} taskFlg 任务标志: * 0x00->AUTO 告知扫码器该指令可单独执行,无指令间的依赖关系。 * 0x01->START 告知扫码器开始对卡操作或对卡操作尚未结束,且指令间可能存在依赖关系。 * 0x02->FINISH 告知扫码器本条指令是操作卡的最后一条指令,将卡片操作环境恢复到默态。 * @param {ArrayBuffer} buffer 要发送的数据 * @param {number} bufferLen 要发送的数据长度 * @returns buffer */ nfc.iso14443Apdu = function (taskFlg, buffer, bufferLen) { let pointer = dxCommon.handleId("nfc", "nfcid") return nfcObj.iso14443Apdu(pointer, taskFlg, buffer, bufferLen); } /** * PSAM卡断电 */ nfc.nfcPsamPowerDown = function () { let pointer = dxCommon.handleId("nfc", "nfcid") return nfcObj.nfcPsamPowerDown(pointer); } /** * NFC 改变状态 */ nfc.nfcPsamChangeBaud = function () { let pointer = dxCommon.handleId("nfc", "nfcid") return nfcObj.nfcPsamChangeBaud(pointer); } /** * PSAM卡重置 */ nfc.nfcPsamCardReset = function (force) { let pointer = dxCommon.handleId("nfc", "nfcid") return nfcObj.nfcPsamCardReset(pointer, force); } /** * 发送PSAM APDU指令 */ nfc.nfcPsamCardApdu = function (buffer) { let pointer = dxCommon.handleId("nfc", "nfcid") return nfcObj.nfcPsamCardApdu(pointer, buffer); } /** * EID 更新云证配置 * @param {object} eidConfig 云证配置 * @param {string} eidConfig.appid 平台分配给应用的appid * @param {number} eidConfig.read_len; // 单次读卡长度,默认0x80 * @param {number} eidConfig.declevel; // 是否读取照片,1为不读取,2为读取 * @param {number} eidConfig.loglevel; //日志级别,支持0,1,2 * @param {number} eidConfig.model; // 是否直接查出信息 0是 1否 (即0是原路返回,返回身份信息,1是转发,返回reqid) * @param {number} eidConfig.type; // 卡片类型:0 身份证 1电子证照 * @param {number} eidConfig.pic_type; // 照片解码数据类型 0 wlt 1 jpg * @param {number} eidConfig.envCode; // 环境识别码 * @param {string} eidConfig.sn[128]; // 设备序列号 * @param {string} eidConfig.device_model[128]; // 设备型号 * @param {number} eidConfig.info_type; // 信息返回类型,0 身份信息结构体 ,1原始数据 char */ nfc.eidUpdateConfig = function (eidConfig) { if (eidConfig == null) { throw new Error("eidUpdateConfig:eidConfig should not be null or empty") } return nfcObj.eidUpdateConfig(eidConfig); } /** * 读NTAG版本号 * @param {number} hdl nfc句柄 * @returns {ArrayBuffer} buffer */ nfc.nfcNtagReadVersion = function () { let pointer = dxCommon.handleId("nfc", 'nfcid') return nfcObj.nfcNtagReadVersion(pointer); } /** * 读NTAG页内容 固定读取4页共16字节 * @param {number} hdl nfc句柄 * @param {number} pageNum 起始页地址: * 每次读取四个页 * 如果地址(Addr)是04h,则返回页04h、05h、06h、07h内容 * @returns {ArrayBuffer} buffer */ nfc.nfcNtagReadPage = function (pageNum) { let pointer = dxCommon.handleId("nfc", 'nfcid') if (pageNum == null) { throw new Error("nfcNtagReadPage:pageNum should not be null or empty") } return nfcObj.nfcNtagReadPage(pointer, pageNum); } /** * 读NTAG多页内容 读取数据的buffer,最小为 页数*4;要读取的数据长度 页数*4 * @param {number} hdl nfc句柄 * @param {number} start_addr 起始页地址 * @param {number} end_addr 结束页地址 * @returns {ArrayBuffer} buffer */ nfc.nfcNtagFastReadPage = function (start_page, end_page) { let pointer = dxCommon.handleId("nfc", 'nfcid') if (start_page == null) { throw new Error("nfcNtagFastReadPage:start_page should not be null or empty") } if (end_page == null) { throw new Error("nfcNtagFastReadPage:end_page should not be null or empty") } return nfcObj.nfcNtagFastReadPage(pointer, start_page, end_page); } /** * 写NTAG页内容 * @param {number} hdl nfc句柄 * @param {number} pageNum 写入的页号 :有效Addr参数 * 对于NTAG213,页地址02h至2Ch * 对于NTAG215,页地址02h至86h * 对于NTAG216,页地址02h至E6h * @param {ArrayBuffer} pageData 写入页的内容:四字节 * @returns {boolean} ture/false */ nfc.nfcNtagWritePage = function (pageNum, pageData) { let pointer = dxCommon.handleId("nfc", 'nfcid') if (pageNum == null) { throw new Error("nfcNtagWritePage:pageNum should not be null or empty") } if (!pageData) { throw new Error("nfcNtagWritePage:pageData should not be null or empty") } return nfcObj.nfcNtagWritePage(pointer, pageNum, pageData); } /** * 判断nfc消息队列是否为空 * @returns bool */ nfc.msgIsEmpty = function () { let pointer = dxCommon.handleId("nfc", 'nfcid') return nfcObj.msgIsEmpty(pointer) } /** * 从nfc消息队列中读取数据 * @returns json消息对象 */ nfc.msgReceive = function () { let pointer = dxCommon.handleId("nfc", 'nfcid') let msg = nfcObj.msgReceive(pointer) return JSON.parse(msg); } function _validate(fun, taskFlg, secNum, logicBlkNum, blkNums, key, keyType, data) { if (![0x00, 0x01, 0x02].includes(taskFlg)) { throw new Error(fun, ":taskFlg error") } if (!(secNum >= 0)) { throw new Error(fun, ":secNum error") } if (logicBlkNum == null || logicBlkNum == undefined || logicBlkNum < 0 || logicBlkNum > 3) { throw new Error(fun, ":logicBlkNum error") } if (blkNums == null || blkNums == undefined || blkNums < 0 || blkNums > 59) { throw new Error(fun, ":blkNums error") } if (key == null || key === undefined || key.length < 0) { throw new Error(fun, ":key error") } if (![0x60, 0x61].includes(keyType)) { throw new Error(fun, ":keyType error") } if (data === null || data === undefined) { throw new Error(fun, ":data error") } } nfc.RECEIVE_MSG = '__nfc__MsgReceive' /** * 简化NFC组件的使用,无需轮询去获取网络状态,网络的状态会通过eventcenter发送出去 * run 只会执行一次,执行之后网络基本配置不能修改 * 如果需要实时获取刷卡数据,可以订阅 eventCenter的事件,事件的topic是nfc.CARD,事件的内容是类似 * {id:'卡id',card_type:卡芯片类型,id_len:卡号长度,type:卡类型,timestamp:'刷卡时间戳',monotonic_timestamp:'相对开机的时间'} * @param {*} options * @param {boolean} options.m1 非必填,普通卡回调开关 * @param {boolean} options.psam 非必填,psam卡回调开关 */ nfc.run = function (options) { if (options === undefined || options.length === 0) { throw new Error("dxnfc.run:'options' parameter should not be null or empty") } let init = map.get("__nfc__run_init") if (!init) {//确保只初始化一次 map.put("__nfc__run_init", options) bus.newWorker("__nfc", '/app/code/dxmodules/nfcWorker.js') } } /** * 如果nfc单独一个线程,可以直接使用run函数,会自动启动一个线程, * 如果想加入到其他已有的线程,可以使用以下封装的函数 */ nfc.worker = { //在while循环前 beforeLoop: function (options) { nfc.init(options.useEid) // PSAM和普通卡回调 if (options.m1) { nfc.cbRegister() } if (options.psam) { nfc.psamCbRegister() } }, //在while循环里 loop: function () { if (!nfc.msgIsEmpty()) { let res = nfc.msgReceive(); bus.fire(nfc.RECEIVE_MSG, res) } } } export default nfc;