'use strict'; const koffi = require('koffi'); const { Service } = require('ee-core'); const Services = require("ee-core/services"); const CoreWindow = require("ee-core/electron/window"); const path = require("path"); const Ps = require("ee-core/ps"); const {ChildJob, ChildPoolJob} = require("ee-core/jobs"); const {times} = require("lodash/util"); var iconv = require('iconv-lite'); const aa = () => { } const CHANNEL_LIST = { service: 'controller.icrf.service', communication: 'controller.icrf.communication', card: 'controller.icrf.card' } //向前端线程发送消息 const sendMainContents =(channel,textJson) =>{ const win = CoreWindow.getMainWindow(); win.webContents.send(channel, textJson); } const ff = { 1:'初始化通信端口失败.', 2:'关闭通信端口失败.', 3:'串口被占用.', 4:'不支持的串口波特率.', 5:'未扫描到设备.', 6:'设备未连接.', 7:'无效的句柄.', 8:'通讯发生错误.', 9:'通讯数据格式错误.', 10:'参数错误.', 11:'数据长度错误.', 12:'地址越界.', 13:'缓冲区溢出.', 14:'操作超时.', 15:'写(卡片)错误.', 16:'读(卡片)错误.', 17:'BCC 校验和错误.', 18:'不支持的卡座编号.', 19:'卡片类型错误.', 20:'卡座有卡未上电.', 21:'未检测到卡片.', 22:'非法卡.', 23:'装载密码出错.', 24:'获取读卡器密码错误.', 25:'操作失败,读写器返回未知错误.', 26:'请求失败.', 27:'防冲突失败.', 28:'选卡失败.', 29:'认证错误.', 30:'非值存储区域.', 31:'值溢出错误.', 32:'Restore 错误.', 33:'Transfer 错误.', 34:'增值错误.', 35:'减值错误.', 36:'Mifare 值操作失败.', 37:'磁条卡数据错误.', 38:'CPU 卡复位出错.', 39:'CPU 卡 APDU 失败.', 40:'命令不支持.', 41:'系统操作出错.', 42:'密码错误.', 43:'加载动态库失败.', 44:'获取身份证图片信息失败.', 45:'指定的标签数据区不存在或标签不支持指定长度的 EPC.', 46:'灭活标签失败.', 47:'锁定标签数据区失败.', 48:'指定的标签数据区被锁定并且/或者是永久锁定,而且锁定状态为不可写或不可读.', 49:'标签没有收到足够的能量来读写操作.', 50:'NXP 特有错误.', 129:'标签处于只读状态.', 130:'命令不支持或标签不是任何有效状态 (即检查ndef 失败或以前未被调用).', 131:'标签已经是 ndef 格式化状态.', 132:'不支持的 NDEF 版本.', 133:'标记未按照 ndef 规范配置.', 134:'标签不支持 NDEF 格式.', 135:'标签处于初始化状态 (即没有 ndef 或空ndef.', 136:'标签未 ndef 格式化.', } const getFunErrMsg = (it) => { let absNum = Math.abs(it); let msg = ff[absNum]; return msg?msg:'未知错误' } const strCoverZero =(str = "")=>{ if (str.length <32){ str = str +'0'; return strCoverZero(str) } return str } /** * 将字符串转换成16进制字符 * @param {string} str 要转换的字符串 * @returns {string} 转换后的16进制字符 */ function strToHexCharCode(str="") { let buffer = iconv.encode(str,"utf-8"); let hexString = buffer.toString('hex'); // 确保结果为 32 字节(64 个字符) if (hexString.length > 32) { // 截断超出的部分 hexString = hexString.slice(0, 32); } else if (hexString.length < 32) { // 补零到 64 个字符 hexString = hexString.padStart(32, '0'); } return hexString; } function hexCharCodeToStr(buffer) { // 截取有效数据的 Buffer let hex = iconv.decode(buffer, 'utf-8'); let trimmedHex = hex.replace(/^0+/, ''); const buffer2 = Buffer.from(trimmedHex, 'hex'); return iconv.decode(buffer2, 'utf-8'); } /** * ICRF服务(service层为单例) * @class */ class Icrf extends Service { handle = null; timer = null; constructor(ctx) { super(ctx); const dllPath = path.join(Ps.getExtraResourcesDir(),'dll','hc_icrf64.dll'); this.hcicrf =koffi.load(dllPath); } connectDevice(initFunction, ...args) { const hcInit = initFunction(...args); let msg = hcInit > 0 ? '读写器连接成功' : getFunErrMsg(hcInit); if (hcInit > 0) { this.handle = hcInit; this.beep(); } sendMainContents(CHANNEL_LIST.service, { status: hcInit }); sendMainContents(CHANNEL_LIST.communication, { msg, handle: hcInit }); return hcInit; } connectFun(initFun,msgSuc,...args){ const code = initFun(...args); let msg = code === 0? msgSuc:getFunErrMsg(code); return {code ,msg} } /** * 连接串口读写器 * @param {params.number} port 端口号, 取值 0 ~ 19, 对应端口 COM1 ~ COM20 * @param {params.number} baud 波特率, 取值 9600 ~ 115200 * @returns {number} 读写器句柄 */ connectSerialPort(port,baud) { const hc_init = this.hcicrf.func('int __stdcall hc_init(short port, uint32_t baud)'); return this.connectDevice(hc_init, port, baud); }; connectUsb(number){ const hc_init_usb = this.hcicrf.func('int __stdcall hc_init_usb(int number)'); return this.connectDevice(hc_init_usb, number); } connectExit(){ const func = this.hcicrf.func('int hc_exit(short iced)'); let connectFun = this.connectFun(func,'读写器断开连接成功',this.handle); sendMainContents(CHANNEL_LIST.service, { status: connectFun.code }); return connectFun; } getErrMsg(it){ const err = this.hcicrf.func( 'int16 getErrMsg(int16 st, int32 lg, char* errMsg)'); let errMsgBuffer = Buffer.alloc(1024) err(it,1,errMsgBuffer); return errMsgBuffer.toString('utf-8'); } beep(time = 30){ const dv = this.hcicrf.func('int16 dv_beep(short iced,int time)'); dv(this.handle,time); } doJobByPool(){ if (!this.timer){ this.timer = setInterval(()=>{ const data = this.connectRfCard(); sendMainContents(CHANNEL_LIST.card,data); },2000) } } unJobByPool(){ if (this.timer){ clearInterval(this.timer); this.timer = null; } } connectRfCard(){ const func = this.hcicrf.func('int rf_card(short iced, uint8 _Mode, uint32* _Snr)'); const mode = 0x01; // 示例模式值 let snrBuffer = Buffer.alloc(4); // 分配一个 4 字节的缓冲区,用于存储 SNR let connectFun = this.connectFun(func,'寻卡成功',this.handle,mode,snrBuffer); return {...connectFun,snr:snrBuffer.readUInt32LE(0)} } connectRfAuthenticationKey(addr){ // 定义 func 函数 const func = this.hcicrf.func('int16 rf_authentication_key(short iced, uint8 _Mode, uint8 _BlockNr, uint8* _Key)'); const key = Buffer.from([0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF]); // 示例 6 字节密码 return this.connectFun(func,'校验密码成功',this.handle,0x00,addr,key); } connectRfRead(addr){ const func = this.hcicrf.func('int16 rf_read_hex(short iced, uint8 _Adr, char* _Data)'); let dataBuffer = Buffer.alloc(32); let conn = this.connectFun(func,'读数据成功',this.handle,addr,dataBuffer); let data ; if (conn.code === 0){ data = hexCharCodeToStr(dataBuffer); } return {...conn,data} } connectRfWrite(data,addr){ let dataBuffer = strToHexCharCode(data); console.log(dataBuffer,addr) const func = this.hcicrf.func('int16 rf_write_hex(short iced, uint8 _Adr, char* _Data)'); return this.connectFun(func,'写数据成功',this.handle,addr,dataBuffer); } connectRfHalt(){ const func = this.hcicrf.func('int rf_halt(short iced)'); return this.connectFun(func,'终止卡成功',this.handle); } } Icrf.toString = () => '[class IcrfService]'; module.exports = Icrf;