更新 IDCardData 结构体字段类型为 uint8,并重构解码函数以支持 UCS-2/UTF-16LE 解码
This commit is contained in:
@@ -5,35 +5,49 @@ const iconv = require("iconv-lite");
|
||||
|
||||
// 定义结构体
|
||||
const IDCardData = koffi.struct("IDCardData", {
|
||||
Name: koffi.array("char", 32),
|
||||
Sex: koffi.array("char", 6),
|
||||
Nation: koffi.array("char", 20),
|
||||
Born: koffi.array("char", 18),
|
||||
Address: koffi.array("char", 72),
|
||||
IDCardNo: koffi.array("char", 38),
|
||||
GrantDept: koffi.array("char", 32),
|
||||
UserLifeBegin: koffi.array("char", 18),
|
||||
UserLifeEnd: koffi.array("char", 18),
|
||||
reserved: koffi.array("char", 38),
|
||||
PhotoFileName: koffi.array("char", 255),
|
||||
Name: koffi.array("uint8", 32),
|
||||
Sex: koffi.array("uint8", 6),
|
||||
Nation: koffi.array("uint8", 20),
|
||||
Born: koffi.array("uint8", 18),
|
||||
Address: koffi.array("uint8", 72),
|
||||
IDCardNo: koffi.array("uint8", 38),
|
||||
GrantDept: koffi.array("uint8", 32),
|
||||
UserLifeBegin: koffi.array("uint8", 18),
|
||||
UserLifeEnd: koffi.array("uint8", 18),
|
||||
reserved: koffi.array("uint8", 38),
|
||||
PhotoFileName: koffi.array("uint8", 255),
|
||||
});
|
||||
|
||||
let lib = null;
|
||||
let running = false;
|
||||
|
||||
// 解码 GBK 字符串
|
||||
function decodeGBK(buffer) {
|
||||
// 找到第一个 null 字节 (0x00) 的位置
|
||||
// 解码字符串 (尝试 UCS-2/UTF-16LE)
|
||||
function decodeString(buffer) {
|
||||
// 这里的 buffer 是 uint8 数组,先转为 Buffer
|
||||
const buf = Buffer.from(buffer);
|
||||
|
||||
// 很多读卡器 DLL 返回的是 UCS-2 (UTF-16LE)
|
||||
// 也有可能是 GBK。我们可以通过检查字节特征来判断,或者优先尝试 UCS-2
|
||||
// UCS-2 的特征是每两个字节一个字符,对于 ASCII 字符,高字节通常是 0x00
|
||||
|
||||
// 尝试作为 UTF-16LE 解码
|
||||
// 找到双 null 结尾 (0x00 0x00)
|
||||
let nullIndex = -1;
|
||||
for (let i = 0; i < buffer.length; i++) {
|
||||
if (buffer[i] === 0) {
|
||||
for (let i = 0; i < buf.length - 1; i += 2) {
|
||||
if (buf[i] === 0 && buf[i + 1] === 0) {
|
||||
nullIndex = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
// 如果找到了 null,截取前面的部分;否则使用整个 buffer
|
||||
const validBuffer = nullIndex !== -1 ? buffer.slice(0, nullIndex) : buffer;
|
||||
return iconv.decode(validBuffer, "gbk").trim();
|
||||
const validBuf16 = nullIndex !== -1 ? buf.slice(0, nullIndex) : buf;
|
||||
const str16 = iconv.decode(validBuf16, "utf16le").trim();
|
||||
|
||||
// 如果解码出来的字符串看起来是乱码(包含很多 )或者为空但 buffer 不为空,可能需要尝试 GBK
|
||||
// 但通常 Syn_IDCardRead.dll 返回的是 UCS-2
|
||||
// 让我们先打印一下原始 hex 以便调试
|
||||
// parentPort.postMessage({ type: 'log', payload: `Hex: ${buf.slice(0, 10).toString('hex')}` });
|
||||
|
||||
return str16;
|
||||
}
|
||||
|
||||
// 加载 DLL
|
||||
@@ -188,16 +202,16 @@ async function startListen() {
|
||||
|
||||
if (ret === 0 && data) {
|
||||
const payload = {
|
||||
name: decodeGBK(Buffer.from(data.Name)),
|
||||
sex: decodeGBK(Buffer.from(data.Sex)),
|
||||
nation: decodeGBK(Buffer.from(data.Nation)),
|
||||
born: decodeGBK(Buffer.from(data.Born)),
|
||||
address: decodeGBK(Buffer.from(data.Address)),
|
||||
id_card_no: decodeGBK(Buffer.from(data.IDCardNo)),
|
||||
grant_dept: decodeGBK(Buffer.from(data.GrantDept)),
|
||||
life_begin: decodeGBK(Buffer.from(data.UserLifeBegin)),
|
||||
life_end: decodeGBK(Buffer.from(data.UserLifeEnd)),
|
||||
photo_path: decodeGBK(Buffer.from(data.PhotoFileName)),
|
||||
name: decodeString(data.Name),
|
||||
sex: decodeString(data.Sex),
|
||||
nation: decodeString(data.Nation),
|
||||
born: decodeString(data.Born),
|
||||
address: decodeString(data.Address),
|
||||
id_card_no: decodeString(data.IDCardNo),
|
||||
grant_dept: decodeString(data.GrantDept),
|
||||
life_begin: decodeString(data.UserLifeBegin),
|
||||
life_end: decodeString(data.UserLifeEnd),
|
||||
photo_path: decodeString(data.PhotoFileName),
|
||||
};
|
||||
|
||||
parentPort.postMessage({
|
||||
|
||||
Reference in New Issue
Block a user