15815213711
2025-04-24 16c179b122eb8c69d31b0fab66c5e29b9c332b8d
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
 
'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;