Open b1rigu opened 7 months ago
I fixed the large attendance data issue by adding a check when packet is fully sent. Just change the whole function to this
readWithBuffer(reqData, cb = null) {
return new Promise(async (resolve, reject) => {
this.replyId++;
const buf = createTCPHeader(COMMANDS.CMD_DATA_WRRQ, this.sessionId, this.replyId, reqData)
let reply = null;
try {
reply = await this.requestData(buf)
//console.log(reply.toString('hex'));
} catch (err) {
reject(err)
}
const header = decodeTCPHeader(reply.subarray(0, 16))
switch (header.commandId) {
case COMMANDS.CMD_DATA: {
resolve({ data: reply.subarray(16), mode: 8 })
break;
}
case COMMANDS.CMD_ACK_OK:
case COMMANDS.CMD_PREPARE_DATA: {
// this case show that data is prepared => send command to get these data
// reply variable includes information about the size of following data
const recvData = reply.subarray(16)
const size = recvData.readUIntLE(1, 4)
// We need to split the data to many chunks to receive , because it's to large
// After receiving all chunk data , we concat it to TotalBuffer variable , that 's the data we want
let remain = size % MAX_CHUNK
let numberChunks = Math.round(size - remain) / MAX_CHUNK
let totalPackets = numberChunks + (remain > 0 ? 1 : 0)
let replyData = Buffer.from([])
let totalBuffer = Buffer.from([])
let realTotalBuffer = Buffer.from([])
let isDataOnGoing = false
const timeout = 10000
let timer = setTimeout(() => {
internalCallback(replyData, new Error('TIMEOUT WHEN RECEIVING PACKET'))
}, timeout)
const internalCallback = (replyData, err = null) => {
// this.socket && this.socket.removeListener('data', handleOnData)
timer && clearTimeout(timer)
resolve({ data: replyData, err })
}
const handleOnData = (reply) => {
if (checkNotEventTCP(reply)) return;
clearTimeout(timer)
timer = setTimeout(() => {
internalCallback(replyData,
new Error(`TIME OUT !! ${totalPackets} PACKETS REMAIN !`))
}, timeout)
totalBuffer = Buffer.concat([totalBuffer, reply])
const packetLength = totalBuffer.readUIntLE(4, 2)
if (totalBuffer.length >= 8 + packetLength) {
realTotalBuffer = Buffer.concat([realTotalBuffer, totalBuffer.subarray(16, 8 + packetLength)])
totalBuffer = totalBuffer.subarray(8 + packetLength)
if ((totalPackets > 1 && realTotalBuffer.length === MAX_CHUNK + 8)
|| (totalPackets === 1 && realTotalBuffer.length === remain + 8)) {
replyData = Buffer.concat([replyData, realTotalBuffer.subarray(8)])
totalBuffer = Buffer.from([])
realTotalBuffer = Buffer.from([])
totalPackets -= 1
isDataOnGoing = false;
cb && cb(replyData.length, size)
if (totalPackets <= 0) {
internalCallback(replyData)
}
}
}
}
this.socket.once('close', () => {
internalCallback(replyData, new Error('Socket is disconnected unexpectedly'))
})
this.socket.on('data', handleOnData)
for (let i = 0; i <= numberChunks; i++) {
if (i === numberChunks) {
this.sendChunkRequest(numberChunks * MAX_CHUNK, remain)
} else {
this.sendChunkRequest(i * MAX_CHUNK, MAX_CHUNK)
}
isDataOnGoing = true;
while (isDataOnGoing) {
await new Promise(r => setTimeout(r, 100))
}
}
break;
}
default: {
reject(new Error('ERROR_IN_UNHANDLE_CMD ' + exportErrorMessage(header.commandId)))
}
}
})
}
Sometimes it gets all data, and sometimes it doesn't with an error like this: "TIME OUT !! 14 PACKETS REMAIN". This is random and the amount of packets remaining is random ranging from 1 to n. I have tried a package in python and it consistently gets all the data. So I don't there is an internal device issue. Device is: zk face702 info: {userCounts: 80, logCounts: 27538, logCapacity: 120000} trying to get attendance data by getAttendances()