This commit is contained in:
meusinfirmary
2025-06-26 05:53:54 +07:00
parent 75832125e2
commit fd0eb59f24
6 changed files with 1298 additions and 261 deletions

View File

@ -1,5 +1,8 @@
const LibHelper = require("./LibHelper");
// Menyimpan status per device untuk mendeteksi cache
const deviceStates = {};
class LibDevice {
/**
*
@ -21,198 +24,105 @@ class LibDevice {
ori_string: data,
};
// eelinkCustom
if (opts.isEelinkCustom) {
me.protocol_name = "eelinkCustom";
me.field0 = data.slice(0, 2); // system status flag
me.field1 = data.slice(2, 18); // IMEI
me.field2 = data.slice(18, 34); // IMSI
me.field3 = data.slice(34, 42); // Time
me.field4 = data.slice(42, 58); // Location
me.field5 = data.slice(58, 62); // Altitude
me.field6 = data.slice(62, 66); // Heading
me.field7 = data.slice(66, 68); // Velocity
me.field8 = data.slice(68, 70); // Power Input Voltage
me.field9 = data.slice(70, 72); // GPIO Status
me.field10 = data.slice(72, 74); // Time Seconds
me.field11 = data.slice(74, 76); // RSSI
me.field12 = data.slice(76, 78); // Sequence Counter
me.field13 = data.slice(78, 80); // Vendor ID
me.field14 = data.slice(80, 82); // GPS Satellites
me.field15 = data.slice(82, 90); // Accumulators
me.field0 = data.slice(0, 2);
me.field1 = data.slice(2, 18);
me.field2 = data.slice(18, 34);
me.field3 = data.slice(34, 42);
me.field4 = data.slice(42, 58);
me.field5 = data.slice(58, 62);
me.field6 = data.slice(62, 66);
me.field7 = data.slice(66, 68);
me.field8 = data.slice(68, 70);
me.field9 = data.slice(70, 72);
me.field10 = data.slice(72, 74);
me.field11 = data.slice(74, 76);
me.field12 = data.slice(76, 78);
me.field13 = data.slice(78, 80);
me.field14 = data.slice(80, 82);
me.field15 = data.slice(82, 90);
me.ori_string = data;
}
// gt06
else if (data.slice(0, 4) == "7878" || data.slice(0, 4) == "7979") {
} else if (data.slice(0, 4) == "7878" || data.slice(0, 4) == "7979") {
me.protocol_name = "gt06";
me.start = data.slice(0, 4);
me.length = parseInt(data.slice(4, 6), 16);
me.protocol_id = data.slice(6, 8);
me.serial_number = data.slice(-12, -8);
me.error_check = data.slice(-8, -4);
me.finish = data.slice(-4); // data.substr(6 + me.length * 2, 4);
me.finish = data.slice(-4);
if (me.finish != "0d0a") {
throw "finish code incorrect!";
}
me.ori_string = data;
}
// gt02a
else if (data.slice(0, 4) == "6868") {
} else if (data.slice(0, 4) == "6868") {
me.protocol_name = "gt02a";
}
// tk103
// else if (data.indexOf("B")) {
// me.protocol_name = 'tk103';
// }
// eelink
else if (data.slice(0, 4) == "6767") {
} else if (data.slice(0, 4) == "6767") {
me.protocol_name = "eelink";
me.start = data.slice(0, 4);
me.pid = data.slice(4, 6);
me.size = parseInt(data.slice(6, 10), 16);
me.sequence = parseInt(data.slice(10, 4), 16);
me.ori_string = data;
}
// unknown
else {
} else {
me.protocol_name = "unknown";
}
return me;
}
/**
*
* @param {Object} me
* @param {String} device_id
* @returns
* must return at least => act.cmd,act.action_type,act.device_id
*/
static gt06Action(me, device_id = null) {
const act = {};
// Login message
if (me.protocol_id == "01") {
act.action_type = "login";
act.cmd = "login_request";
act.action = "login_request";
act.device_id = me.ori_string.slice(8).slice(0, 16).padStart(16, "0");
act.buffer_resp = LibDevice.gt06AuthorizeResp(me);
}
// Location data
else if (me.protocol_id == "12" || me.protocol_id == "a0") {
} else if (me.protocol_id == "12" || me.protocol_id == "a0") {
act.action_type = "location";
act.cmd = "ping";
act.action = "ping";
act.device_id = device_id; // because device_id only sent when login
// content data
// me.ori_string.slice(8).slice(0, 52); // me.ori_string.substr(8, me.length * 2);
// gps information
act.device_id = device_id;
act.gps_string = me.ori_string.slice(8).slice(0, 36);
act.gps_data = LibDevice.gt06ParseLocation(me, act.gps_string);
// if (!act.gps_data) {
// //Something bad happened
// _this.do_log('GPS Data can\'t be parsed. Discarding packet...');
// return false;
// }
// lbs information
act.lbs_string = me.ori_string.slice(8).slice(36, 52);
act.lbs_data = LibDevice.gt06ParseLbs(me, act.lbs_string);
}
// Status information
else if (me.protocol_id == "13") {
act.action_type = "heartbeat";
// ==== Tambahan Deteksi Data Cache ====
try {
const gpsTime = new Date(act.gps_data?.date || "");
const now = new Date();
const timeDiff = Math.abs(now.getTime() - gpsTime.getTime()) / 1000;
const serialNum = parseInt(me.serial_number, 16);
const lastState = deviceStates[device_id] || {};
let isSerialBurst = false;
if (lastState.last_serial != null && lastState.last_time != null) {
const interval = (Date.now() - lastState.last_time) / 1000;
isSerialBurst = serialNum === lastState.last_serial + 1 && interval < 2;
}
act.is_cached = timeDiff > 30 || isSerialBurst;
deviceStates[device_id] = {
last_serial: serialNum,
last_time: Date.now(),
};
} catch (err) {
act.is_cached = false;
}
} else if (me.protocol_id == "13") {
act.action_type = "heartbeat";
act.cmd = "heartbeat";
act.action = "heartbeat";
act.device_id = device_id; // because device_id only sent when login
// status information
act.device_id = device_id;
act.stts_string = me.ori_string.slice(8).slice(0, 10);
act.stts_data = LibDevice.gt06ParseHeartbeat(me, act.stts_string);
act.buffer_resp = LibDevice.gt06HeartbeatResp(me);
}
// String information
else if (me.protocol_id == "15") {
// act.action_type = 'other'; // 'heartbeat';
// act.cmd = 'other'; // 'heartbeat';
// act.action = 'other'; // 'heartbeat';
// act.device_id = ''; // device_id; // because device_id only sent when login
act.action_type = "heartbeat";
act.cmd = "heartbeat";
act.action = "heartbeat";
act.device_id = device_id; // because device_id only sent when login
// status information
act.stts_string = me.ori_string.slice(8).slice(0, 10);
act.stts_data = LibDevice.gt06ParseHeartbeat(me, act.stts_string);
act.buffer_resp = LibDevice.gt06HeartbeatResp(me);
}
// Alarm data
else if (me.protocol_id == "16" || me.protocol_id == "18") {
act.action_type = "alarm";
act.cmd = "alarm";
act.action = "alarm";
act.device_id = device_id; // because device_id only sent when login
// content data
// me.ori_string.slice(8).slice(0, 64); // me.ori_string.substr(8, me.length * 2);
// gps information
act.gps_string = me.ori_string.slice(8).slice(0, 36);
act.gps_data = LibDevice.gt06ParseLocation(me, act.gps_string);
// lbs information
act.lbs_string = me.ori_string.slice(8).slice(36, 54);
act.lbs_data = LibDevice.gt06ParseLbs(me, act.lbs_string);
// status information
act.stts_string = me.ori_string.slice(8).slice(54, 64);
act.stts_data = LibDevice.gt06ParseStatusAlarm(me, act.stts_string);
act.buffer_resp = LibDevice.gt06AlarmResp(me);
}
// GPS, query address information by phone number
else if (me.protocol_id == "1A") {
act.action_type = "other";
act.cmd = "other";
act.action = "other";
act.device_id = "";
}
// Command information sent by the server to the terminal
else if (me.protocol_id == "80") {
act.action_type = "other";
act.cmd = "other";
act.action = "other";
act.device_id = "";
} else {
act.action_type = "other";
act.cmd = "other";
act.action = "other";
act.device_id = "";
act.device_id = device_id || "";
}
return act;
}
@ -220,6 +130,10 @@ class LibDevice {
return Buffer.from("787805010001d9dc0d0a", "hex");
}
static gt06AuthorizeResp(me) {
return Buffer.from("787805010001d9dc0d0a", "hex");
}
static gt06ParseLocation(me, gps_string = null) {
if (!gps_string) {
gps_string = me.ori_string.slice(8).slice(0, 36);