UNPKG

zklib-js-zkteko

Version:

Improved JavaScript library for working with ZKTeco biometric attendance devices

253 lines (206 loc) 7.18 kB
const { USHRT_MAX , COMMANDS } = require('./constants') const { log } = require('./helpers/errorLog') const parseTimeToDate = (time)=>{ const second = time % 60; time = (time - second) / 60; const minute = time % 60; time = (time - minute) / 60; const hour = time % 24; time = (time - hour) / 24; const day = time % 31 + 1; time = (time - (day - 1)) / 31; const month = time % 12; time = (time - month) / 12; const year = time + 2000; return new Date(year, month, day, hour, minute, second); } const parseHexToTime = (hex)=>{ const time = { year: hex.readUIntLE(0,1), month:hex.readUIntLE(1,1), date: hex.readUIntLE(2,1), hour: hex.readUIntLE(3,1), minute: hex.readUIntLE(4,1), second: hex.readUIntLE(5,1) } return new Date(2000+ time.year, time.month - 1 , time.date, time.hour, time.minute, time.second) } const createChkSum = (buf)=>{ let chksum = 0; for (let i = 0; i < buf.length; i += 2) { if (i == buf.length - 1) { chksum += buf[i]; } else { chksum += buf.readUInt16LE(i); } chksum %= USHRT_MAX; } chksum = USHRT_MAX - chksum - 1; return chksum; } module.exports.createUDPHeader = (command , sessionId, replyId, data)=>{ const dataBuffer = Buffer.from(data); const buf = Buffer.alloc(8 + dataBuffer.length); buf.writeUInt16LE(command, 0); buf.writeUInt16LE(0, 2); buf.writeUInt16LE(sessionId, 4); buf.writeUInt16LE(replyId, 6); dataBuffer.copy(buf, 8); const chksum2 = createChkSum(buf); buf.writeUInt16LE(chksum2, 2); replyId = (replyId + 1) % USHRT_MAX; buf.writeUInt16LE(replyId, 6); return buf } module.exports.createTCPHeader = (command , sessionId, replyId, data)=>{ const dataBuffer = Buffer.from(data); const buf = Buffer.alloc(8 + dataBuffer.length); buf.writeUInt16LE(command, 0); buf.writeUInt16LE(0, 2); buf.writeUInt16LE(sessionId, 4); buf.writeUInt16LE(replyId, 6); dataBuffer.copy(buf, 8); const chksum2 = createChkSum(buf); buf.writeUInt16LE(chksum2, 2); replyId = (replyId + 1) % USHRT_MAX; buf.writeUInt16LE(replyId, 6); const prefixBuf = Buffer.from([0x50, 0x50, 0x82, 0x7d, 0x13, 0x00, 0x00, 0x00]) prefixBuf.writeUInt16LE(buf.length, 4) return Buffer.concat([prefixBuf, buf]); } const removeTcpHeader = (buf)=>{ if (buf.length < 8) { return buf; } if (buf.compare(Buffer.from([0x50, 0x50, 0x82, 0x7d]), 0, 4, 0, 4) !== 0) { return buf; } return buf.slice(8); } module.exports.removeTcpHeader = removeTcpHeader module.exports.decodeUserData28 = (userData)=>{ const user = { uid: userData.readUIntLE(0, 2), role: userData.readUIntLE(2, 1), name: userData .slice(8,8+8) .toString('ascii') .split('\0') .shift(), userId: userData.readUIntLE(24,4) }; return user; } module.exports.decodeUserData72 = (userData)=>{ const user = { uid: userData.readUIntLE(0, 2), role: userData.readUIntLE(2, 1), password: userData .subarray(3, 3+8) .toString('ascii') .split('\0') .shift(), name: userData .slice(11) .toString('ascii') .split('\0') .shift(), cardno: userData.readUIntLE(35,4), userId: userData .slice(48, 48+9) .toString('ascii') .split('\0') .shift(), }; return user; } module.exports.decodeRecordData40 = (recordData)=>{ const record = { userSn: recordData.readUIntLE(0, 2), deviceUserId: recordData .slice(2, 2+9) .toString('ascii') .split('\0') .shift(), recordTime: parseTimeToDate(recordData.readUInt32LE(27)).toString(), } return record } module.exports.decodeRecordData16 = (recordData)=>{ const record = { deviceUserId: recordData.readUIntLE(0, 2), recordTime: parseTimeToDate(recordData.readUInt32LE(4)) } return record } module.exports.decodeRecordRealTimeLog18 = (recordData)=>{ const userId = recordData.readUIntLE(8,1) const attTime = parseHexToTime(recordData.subarray(12,18)) return {userId , attTime} } module.exports.decodeRecordRealTimeLog52 =(recordData)=>{ const payload = removeTcpHeader(recordData) const recvData = payload.subarray(8) const userId = recvData.slice(0 , 9) .toString('ascii') .split('\0') .shift() const attTime = parseHexToTime(recvData.subarray(26,26+6)) return { userId, attTime} } module.exports.decodeUDPHeader = (header)=> { const commandId = header.readUIntLE(0,2) const checkSum = header.readUIntLE(2,2) const sessionId = header.readUIntLE(4,2) const replyId = header.readUIntLE(6,2) return { commandId , checkSum , sessionId , replyId } } module.exports.decodeTCPHeader = (header) => { const recvData = header.subarray(8) const payloadSize = header.readUIntLE(4,2) const commandId = recvData.readUIntLE(0,2) const checkSum = recvData.readUIntLE(2,2) const sessionId = recvData.readUIntLE(4,2) const replyId = recvData.readUIntLE(6,2) return { commandId , checkSum , sessionId , replyId , payloadSize } } module.exports.exportErrorMessage = (commandValue)=>{ const keys = Object.keys(COMMANDS) for(let i =0 ; i< keys.length; i++){ if (COMMANDS[keys[i]] === commandValue){ return keys[i].toString() } } return 'AN UNKNOWN ERROR' } module.exports.checkNotEventTCP = (data)=> { try{ data = removeTcpHeader(data) const commandId = data.readUIntLE(0,2) const event = data.readUIntLE(4,2) return event === COMMANDS.EF_ATTLOG && commandId === COMMANDS.CMD_REG_EVENT }catch(err){ log(`[228] : ${err.toString()} ,${data.toString('hex')} `) return false } } module.exports.checkNotEventUDP = (data)=>{ const commandId = this.decodeUDPHeader(data.subarray(0,8)).commandId return commandId === COMMANDS.CMD_REG_EVENT } module.exports.decodeRecordData49 = (recordData) => { const record = { userSn: recordData.readUIntLE(0, 2), // Ejemplo: 2 bytes para el ID de usuario deviceUserId: recordData .slice(2, 2 + 9) .toString('ascii') .split('\0') .shift(), // 9 bytes para el ID de dispositivo recordTime: parseTimeToDate(recordData.readUInt32LE(27)).toString(), // 4 bytes para el timestamp // Agrega más campos según la estructura de tus 49 bytes extraField1: recordData.readUInt8(31), // Ejemplo de un campo adicional de 1 byte extraField2: recordData.readUInt32LE(32), // Ejemplo de otro campo de 4 bytes // Continúa con más campos según sea necesario }; return record; };