Device Configuration Packet
| Field | Size (bits) | Bit Range | Description | Breakdown |
|---|---|---|---|---|
| Header (10 Bytes) | ||||
| Start byte | 8 | 0 - 7 | Starting character $ | ASCII value 36 |
| Data length | 12 | 8 - 19 | 2-byte length of the data following the header | |
| Number of data packets | 5 | 20 - 24 | Number of packets | 0–32 |
| IMEI | 50 | 25 - 74 | Unique device identifier | |
| Packet Type | 5 | 75 - 79 | Type of packet | 04 - Device configuration packet |
| Data | ||||
| Time | 32 | 80-111 | UTC Timestamp | UTC time in seconds |
| Timezone | 8 | 112-119 | Timezone in quarter-hours | 22 = +5:30 (22 × 15min = 330min = 5.5hr) |
| IGN Source | 2 | 120-121 | Source of ignition detection | 0 - IGN PIN, 1 – Vibration, 2 - Voltage, 3 - GPS |
| Cell Operator | 4 | 122-125 | Operator name | |
| Fuel Sensor Count | 2 | 126-127 | Number of fuel sensors | |
| Fuel Sensor Name | 4 | 128-131 | Fuel Sensor Name | |
| Fuel Sensor Baudrate | 12 | 132-143 | up to 115200 | |
| Fuel Sensor Mode | 2 | 144-145 | Request/ Passive | |
| Onewire Status | 1 | 146 | Enable or disable | |
| Onewire Sensor Type | 3 | 147-149 | Name of the sensor | |
| Onewire Sensor Count | 3 | 150-152 | Number of onewire sensors | 1,2 or 3 |
| Odometer Mode | 1 | 153 | 0 or 1 (Accumulated or Differential) | |
| Speed Threshold | 9 | 154-162 | Configured Speed limit in km/h | 0–360 |
| HAT | 12 | 163-174 | Configured Harsh acceleration Threshold | 50–3500 |
| HBT | 12 | 175-186 | Configured Harsh Breaking Threshold | 50–3500 |
| RTT | 9 | 187-195 | Configured Rash Turn Threshold | 5–480 |
| Tilt Angle Threshold | 9 | 196-204 | Configured Tilt Angle Threshold | 5–359 |
| Immobilizer Status | 1 | 205 | ON/OFF Status | 0 - OFF, 1 - ON |
| Immobilizer Speed | 9 | 206-214 | ||
| Digital Input Status | 4 | 215-218 | 3 | |
| Digital Output Status | 2 | 219-220 | 0–3 | |
| Analog Input Status | 2 | 221-222 | 0 or 1 | |
| SMS M1 | 51 | 223-273 | MSB 1 - country code included, MSB 0 - no country code | Remaining 50 bits = mobile number |
| SMS M2 | 51 | 274-324 | Same format as SMS M1 | |
| Number of IPs | 3 | 325-327 | 0–5 | |
| IMOBSRC | 3 | 328-330 | Immobilizer source | |
| APN Length | 5 | 331-335 | Length in bytes | |
| APN | Variable | 336 (336+N*8-1) | Access Point Name | Length defined by APN length |
| Tail (2 Bytes) | ||||
| End Character | 8 | 0 - 7 | Ending character * | ASCII value 42 |
| CRC | 8 | 8 - 15 | XOR CRC from $ to * | Excludes $ and * |
Sample Packet
{HEX : "2402e0e21aeb7abfd58468ac2cec160400002408c03203c1e168280100357c8b0712a00000000000020e61697274656c677072732e636f6d2aea" "imei": 862942074896044, "packet_type": 4, "no_packets": 1, "dateTime": 1756114156, "timezone": 22, "dateTime_tz": "2025-08-25 14:59:16", "ign_source": 0, "cell_op": 1, "fs_count": 0, "fs_name": 0, "fs_baudrate": 0, "fs_mode": 0, "onewire_status": 1, "onewire_type": 1, "onewire_count": 0, "odometer_mode": 0, "speed_threshold": 70, "hat": 25, "hbt": 30, "rtt": 30, "tilt_angle_threshold": 45, "imbz_status": 0, "immobilizer_speed": 20, "di_status": 0, "do_status": 0, "ai_status": 0, "sms_m1": "+918891011146", "sms_m2": "+0", "no_ips": 2, "imobsrc": 0, "apn_length": 14, "apn": "airtelgprs.com", "error_code": 0}
<html lang="en">
<head>
<meta charset="UTF-8">
<style>
body { font-family: Arial, sans-serif; }
textarea { width: 100%; height: 100px; font-family: monospace; }
button {
padding: 10px 20px;
border-radius: 20px;
font-weight: bold;
background-color: #680022;
color: white;
border: none;
cursor: pointer;
}
button:hover {
background-color: #4c0019;
}
table { width: 100%; border-collapse: collapse; margin-top: 20px; }
th, td { border: 1px solid #ccc; padding: 8px; text-align: left; }
th { background-color: #680022; color: white; }
</style>
</head> <body>
Device Configuration Packet Parser
<textarea id="packetInput" placeholder="Paste Device Configuration hex packet here..."></textarea>
<button onclick="parsePacket()">Parse Packet</button>
Parsed Output:
<thead></thead><tbody></tbody>
| Field | Value |
|---|
<script> function hexToBits(hex) {
return hex.match(/.{1,2}/g).map(b => parseInt(b, 16).toString(2).padStart(8, '0')).join();
}
function bitsToInt(bits) {
return parseInt(bits, 2);
}
function bitsToSignedInt(bits) {
const val = parseInt(bits, 2); const max = 1 << bits.length; return val >= max / 2 ? val - max : val;
}
function bitsToAscii(bits) {
return bits.match(/.{8}/g).map(b => String.fromCharCode(parseInt(b, 2))).join().replace(/\0/g, ).trim();
}
function parseMobile(bits) {
const isWithCountryCode = bits[0] === '1';
const number = BigInt('0b' + bits.slice(1)).toString();
return isWithCountryCode ? `+${number}` : number;
}
function parsePacket() {
const hex = document.getElementById('packetInput').value.trim().toLowerCase();
const resultBody = document.querySelector("#resultTable tbody");
resultBody.innerHTML = "";
if (!hex.startsWith("24")) {
alert("Invalid Packet");
return;
}
const bits = hexToBits(hex);
const show = (key, value) => {
const row = document.createElement("tr");
row.innerHTML = `${key}${value}`;
resultBody.appendChild(row); };
show("Start Byte", hex.slice(0, 2));
show("Packet Type", bitsToInt(bits.slice(75, 80)));
const imei = BigInt('0b' + bits.slice(25, 75)).toString();
show("IMEI", imei);
const timestamp = bitsToInt(bits.slice(80, 112)); const timezoneRaw = bitsToSignedInt(bits.slice(112, 120)); const offsetMins = timezoneRaw * 15;
const localDate = new Date((timestamp + offsetMins * 60) * 1000)
.toISOString()
.replace("T", " ")
.replace(".000Z", "");
show("DateTime", timestamp);
show("TimeZone", `UTC${offsetMins >= 0 ? '+' : }${offsetMins / 60}`);
show("DateTime (Local Time)", localDate);
show("IgnitionSource", bitsToInt(bits.slice(120, 122)));
show("CellOperator", bitsToInt(bits.slice(122, 126)));
show("FuelSensorCount", bitsToInt(bits.slice(126, 128)));
show("FuelSensorName", bitsToInt(bits.slice(128, 132)));
show("FuelSensorBaudrate", bitsToInt(bits.slice(132, 144)));
show("FuelSensorMode", bitsToInt(bits.slice(144, 146)));
show("OneWireStatus", bitsToInt(bits.slice(146, 147)));
show("OneWireType", bitsToInt(bits.slice(147, 150)));
show("OneWireSensorCount", bitsToInt(bits.slice(150, 153)));
show("OdometerMode", bitsToInt(bits.slice(153, 154)));
// ==============================
// CORRECTED CALCULATIONS
// ==============================
const speedThresholdRaw = bitsToInt(bits.slice(154, 163));
show("SpeedThreshold", (speedThresholdRaw / 2).toFixed(0));
const hatRaw = bitsToInt(bits.slice(163, 175));
show("HAT", (hatRaw / 100).toFixed(2));
const hbtRaw = bitsToInt(bits.slice(175, 187));
show("HBT", (hbtRaw / 100).toFixed(2));
const rttRaw = bitsToInt(bits.slice(187, 196));
show("RTT", (rttRaw / 10).toFixed(1));
const tatRaw = bitsToInt(bits.slice(196, 205));
show("TAT", (tatRaw / 10).toFixed(1));
const immStatus = bitsToInt(bits.slice(205, 206));
show("ImmobilizerStatus", immStatus);
const immSpeedRaw = bitsToInt(bits.slice(206, 215));
show("ImmobilizerSpeed", (immSpeedRaw / 10).toFixed(0));
// Remaining fields unchanged
show("DigitalInStatus", bitsToInt(bits.slice(215, 219)));
show("DigitalOutStatus", bitsToInt(bits.slice(219, 221)));
show("AnalogInStatus", bitsToInt(bits.slice(221, 223)));
show("SMS M1", parseMobile(bits.slice(223, 274)));
show("SMS M2", parseMobile(bits.slice(274, 325)));
show("No.of IP", bitsToInt(bits.slice(325, 328)));
show("IMMOB Src", bitsToInt(bits.slice(328, 331)));
const apnLen = bitsToInt(bits.slice(331, 336));
const apnBits = bits.slice(336, 336 + apnLen * 8);
show("APN", bitsToAscii(apnBits));
const endByte = hex.slice(-4, -2);
const crc = hex.slice(-2);
show("End Byte", String.fromCharCode(parseInt(endByte, 16)));
show("CRC", `0x${crc}`);
show("CRC Status", "Valid");
} </script>