Jump to content

Telemetry Packet: Difference between revisions

From Transight Wiki
No edit summary
Line 137: Line 137:
==Sample Packet==
==Sample Packet==
<pre>
<pre>
HEX "240370e2400e60e3ad81801b0cfaca0be02541c2000000000000000000000000000000009800000000000000000000000000000000000000000000006875e9e5162a05"
HEX "240370e21aeb7abfd5818011047aca0260081b780000000000000000000000000000307890000000000000000000000000000000000000000000000068a7f192162abf"


{
{"imei": 862942074896044, "packet_type": 1, "no_packets": 1, "packet_status": 1, "frame_number": 34, "alert_id": 1, "operator": 1, "signal_strength": 29, "mcc": 404, "mnc": 19, "cell_id": 64, "lac": 56256, "fix_status": 0, "latitude": 0.0, "latitude_dir": 0, "longitude": 0.0, "longitude_dir": 0, "hdop": 0.0, "pdop": 0.0, "speed": 0.0, "altitude": 0.0, "power": 1, "ignition": 1, "immobilizer": 0, "tamper": 0, "supply_volatge": 12.0, "internal_battery_volatge": 3.6, "fuel_sensor_status_1": 0, "fuel_percentage_1": 0.0, "fuel_value_sensor_1": 0, "fuel_sensor_status_2": 0, "fuel_percentage_2": 0.0, "fuel_value_sensor_2": 0, "fuel_sensor_status_3": 0, "fuel_percentage_3": 0.0, "fuel_value_sensor_3": 0, "analog_input1": 0.0, "analog_input2": 0.0, "digital_input1": 0, "digital_input2": 0, "digital_output1": 0, "digital_output2": 0, "temp_sensor_status_1": 0, "temperature_1": 0.0, "temp_sensor_status_2": 0, "temperature_2": 0.0, "temp_sensor_status_3": 0, "temperature_3": 0.0, "humidity": 0, "odometer": 0, "dateTime": 1755836818, "timezone": 22, "dateTime_tz": "2025-08-22 09:56:58", "error_code": 0
{
"imei": 864218069278060, "packet_type": 1, "no_packets": 1, "packet_status":1,"frame_number":54, "alert_id": 3, "operator": 3, "signal_strength": 29, "mcc": 404, "mnc": 95, "cell_id": 298, "lac": 3600,"fix_status": 0, "latitude": 0.0, "latitude_dir": 0, "longitude": 0.0, "longitude_dir": 0,   "hdop": 0.0, "pdop": 0.0,
  "speed": 0.0, "altitude": 0.0, "power": 0, "ignition": 0, "immobilizer": 0, "tamper": 0,
  "supply_volatge": 0.0, "internal_battery_volatge": 3.8,
  "fuel_sensor_status_1": 0, "fuel_percentage_1": 0.0, "fuel_value_sensor_1": 0,
  "fuel_sensor_status_2": 0, "fuel_percentage_2": 0.0, "fuel_value_sensor_2": 0,
  "fuel_sensor_status_3": 0, "fuel_percentage_3": 0.0, "fuel_value_sensor_3": 0,
  "analog_input1": 0.0, "analog_input2": 0.0,
  "digital_input1": 0, "digital_input2": 0,
  "digital_output1": 0, "digital_output2": 0
  "temp_sensor_status_1": 0, "temperature_1": 0.0,
  "temp_sensor_status_2": 0, "temperature_2": 0.0,
  "temp_sensor_status_3": 0, "temperature_3": 0.0,
  "humidity": 0, "odometer": 0,
  "dateTime": 1752558053, "timezone": 22, "dateTime_tz": "2025-07-15 11:10:53",
  "error_code": 0
}
}
</pre>
<html lang="en">
<head>
  <meta charset="UTF-8" />
  <title>Telemetry Packet Parser – Grouped Frames</title>
  <style>
    body { font-family: Arial, sans-serif; margin: 24px; }
    textarea { width: 100%; height: 140px; font-family: monospace; }
    button {
      padding: 10px 20px; border-radius: 50px; 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: 12px; table-layout: fixed; word-wrap: break-word; }
    th, td { border: 1px solid #ccc; padding: 6px; text-align: left; font-size: 13px; }
    th { background-color: #680022; color: white; }
    .error { color: #b00020; margin-top: 8px; font-weight: bold; }
    .section { margin-top: 30px; }
    .json-output { background: #f4f4f4; padding: 12px; font-family: monospace; font-size: 13px; overflow-x: auto; }
    .pkt-title { margin: 18px 0 6px; font-size: 16px; font-weight: bold; color: #333; }
  </style>
</head>
<body>
  <h2>Telemetry Packet Parser</h2>
  <textarea id="hexInput" placeholder="Paste Telemtry Hex Packet Here..."></textarea><br/>
  <button id="parseBtn">Parse Packet</button>
  <div id="errors" class="error"></div>
  <div class="section">
    <h3>Header </h3>
    <table id="headerTable">
      <thead><tr><th>Field</th><th>Value</th></tr></thead>
      <tbody></tbody>
    </table>
  </div>
  <div class="section">
    <h3>Data Packets</h3>
    <div id="dataTables"></div>
  </div>
  <div class="section">
    <h3>JSON Output</h3>
    <pre class="json-output" id="jsonOut"></pre>
  </div>
<script>
function cleanHex(str) {
  return (str || "").toString().trim().replace(/[^0-9a-fA-F]/g, "").toLowerCase();
}
function hexToBits(hex) {
  return hex.match(/.{1,2}/g).map(b => parseInt(b, 16).toString(2).padStart(8, "0")).join("");
}
function bitsToInt(bits) { return bits ? parseInt(bits, 2) : 0; }
function bitsToSignedInt(bits) {
  if (!bits) return 0;
  const v = parseInt(bits, 2);
  const max = 1 << bits.length;
  return v >= max / 2 ? v - max : v;
}
function addRow(tbody, k, v) {
  const tr = document.createElement("tr");
  tr.innerHTML = `<td>${k}</td><td>${v}</td>`;
  tbody.appendChild(tr);
}
/* --- Field Map (bit indices) --- */
const FULL_FIELDS = [
  ["Start Byte", 0, 8], ["Data Length", 8, 20], ["No. of Packets", 20, 25],
  ["IMEI", 25, 75], ["Packet Type", 75, 80], ["Packet Status", 80, 81],
  ["Frame Number", 81, 97], ["Alert ID", 97, 102], ["Operator", 102, 106],
  ["Signal Strength", 106, 111], ["MCC", 111, 121], ["MNC", 121, 131],
  ["Cell ID", 131, 147], ["LAC", 147, 163], ["Fix Status", 163, 164],
  ["Latitude", 164, 193], ["NS Indication", 193, 194], ["Longitude", 194, 223],
  ["EW Indication", 223, 224], ["HDOP", 224, 234], ["PDOP", 234, 244],
  ["Speed", 244, 259], ["Altitude", 259, 274], ["Power Status", 274, 275],
  ["Ignition Status", 275, 276], ["Immobilizer Status", 276, 277],
  ["Tamper", 277, 278], ["Supply Voltage", 278, 288], ["Internal Battery Voltage", 288, 294],
  ["Fuel Sensor Status 1", 294, 295], ["Fuel Percentage 1", 295, 305],
  ["Fuel Sensor Value 1", 305, 321], ["Fuel Sensor Status 2", 321, 322],
  ["Fuel Percentage 2", 322, 332], ["Fuel Sensor Value 2", 332, 348],
  ["Fuel Sensor Status 3", 348, 349], ["Fuel Percentage 3", 349, 359],
  ["Fuel Sensor Value 3", 359, 375], ["Analog Input 1", 375, 385],
  ["Analog Input 2", 385, 395], ["Digital Input 1", 395, 396],
  ["Digital Input 2", 396, 397], ["Digital Output 1", 397, 398],
  ["Digital Output 2", 398, 399], ["Temperature Sensor Status 1", 399, 400],
  ["Temperature 1", 400, 412], ["Temperature Sensor Status 2", 412, 413],
  ["Temperature 2", 413, 425], ["Temperature Sensor Status 3", 425, 426],
  ["Temperature 3", 426, 438], ["Humidity", 438, 445], ["Odometer", 445, 480],
  ["DateTime UTC", 480, 512], ["TimeZone", 512, 520]
];
/* Sub-packet fields (strip first 80 header bits) */
const SUB_FIELDS = FULL_FIELDS
  .filter(([_, s, e]) => s >= 80 && e <= 520)
  .map(([name, s, e]) => [name, s - 80, e - 80]);
/* Packet type label fix */
const PACKET_TYPE_NAME = { 1: "TelemetryPacket" };
/* Render each packet as a 2-column table */
function renderPacketsAsKVTables(dataArray) {
  const container = document.getElementById("dataTables");
  container.innerHTML = "";
  dataArray.forEach((pkt, idx) => {
    const title = document.createElement("div");
    title.className = "pkt-title";
    title.textContent = `Packet #${idx + 1}`;
    container.appendChild(title);


    const table = document.createElement("table");
    const thead = document.createElement("thead");
    thead.innerHTML = `<tr><th>Field</th><th>Value</th></tr>`;
    const tbody = document.createElement("tbody");
    /* Keep the same field order as SUB_FIELDS */
    for (const [name] of SUB_FIELDS) {
      addRow(tbody, name, pkt[name.replace(/\s+/g, '')]);
    }
    table.appendChild(thead);
    table.appendChild(tbody);
    container.appendChild(table);
  });
}
}
</pre>


/* Parse button logic */
document.getElementById("parseBtn").addEventListener("click", () => {
  const hex = cleanHex(document.getElementById("hexInput").value);
  const errors = document.getElementById("errors");
  const headerBody = document.querySelector("#headerTable tbody");
  const dataTables = document.getElementById("dataTables");
  const jsonOut = document.getElementById("jsonOut");
  errors.textContent = "";
  headerBody.innerHTML = "";
  dataTables.innerHTML = "";
  jsonOut.textContent = "";
  if (!hex) { errors.textContent = "No data provided."; return; }
  if (!hex.startsWith("24")) { errors.textContent = "Invalid frame: Start Byte must be 0x24."; return; }
  const bits = hexToBits(hex);
  const dataLenBits = bits.slice(8, 20);
  const countBits = bits.slice(20, 25);
  const dataLenBytes = bitsToInt(dataLenBits);
  const numItems = bitsToInt(countBits);
  const imei = BigInt("0b" + bits.slice(25, 75)).toString();
  const pktTypeVal = bitsToInt(bits.slice(75, 80));
  const pktTypeName = PACKET_TYPE_NAME[pktTypeVal] || pktTypeVal.toString();
  const perItemBytes = numItems > 0 ? dataLenBytes / numItems : 0;
  const perItemBits = perItemBytes * 8;
  const totalBits = bits.length;
  const subStart = 80;
  if (!Number.isInteger(perItemBytes)) { errors.textContent = "Data Length not divisible by packet count."; return; }
  if (totalBits < subStart + perItemBits * numItems) { errors.textContent = "Frame too short for given count."; return; }
  /* Header table (2-column) */
  addRow(headerBody, "Start Byte", "$");
  addRow(headerBody, "Length", dataLenBytes);
  addRow(headerBody, "Data Items", numItems);
  addRow(headerBody, "IMEI", imei);
  addRow(headerBody, "Packet Type", pktTypeName);
  /* Build per-packet objects keyed by compact field name */
  const dataArray = [];
  const KEY_MAP = new Map(FULL_FIELDS.map(([name]) => [name, name.replace(/\s+/g, '')]));
  for (let i = 0; i < numItems; i++) {
    const sbeg = subStart + i * perItemBits;
    const send = sbeg + perItemBits;
    const subBits = bits.slice(sbeg, send);
    const obj = {};
    for (const [name, s, e] of SUB_FIELDS) {
      const b = subBits.slice(s, e);
      let val;
      if (name === "Temperature 1" || name === "Temperature 2" || name === "Temperature 3") {
        val = bitsToSignedInt(b);
      } else if (name === "Supply Voltage" || name === "Internal Battery Voltage") {
        val = bitsToInt(b) / 10;            // e.g., 123 -> 12.3 V
      } else {
        val = bitsToInt(b);
      }
      obj[KEY_MAP.get(name)] = val;
    }
    dataArray.push(obj);
  }
  /* Render each packet as its own key/value table */
  renderPacketsAsKVTables(dataArray);
  /* JSON */
  const out = { StartByte: "$", Length: dataLenBytes, DataItems: numItems, IMEI: imei, PacketType: pktTypeName, Data: dataArray };
  jsonOut.textContent = JSON.stringify(out, null, 2);
});
</script>
</body>
</html>


<html lang="en">
<html lang="en">

Revision as of 07:00, 22 August 2025

Field Size (bits) Bit Range Description Breakdown
Header (10 bytes)
Start byte 8 0–7 Starting character $ (ASCII value 36) $
Data length 12 08–19 2-byte length of the data following the header
Num of data packets 5 20–24 Number of packets (0–32) 0–32
IMEI 50 25–74 Unique device identifier e.g., 887744556677882
packet type 5 75–79 Integer type:
  • 00 - Device Info Packet
  • 01 - Telemetry Packet
  • 02 - OTA Packet
  • 03 - Error Packet
  • 04 - Device Configuration Packet
  • 05 - IP Configuration Packet
Data (= 55 bytes × number of packets)
Packet Status 1 80 Type of packet 0:History, 1:Live
Frame Number 16 81-96 Frame number
AlertID 5 97–101 Alert identifier
Operator 4 102–105 Network operator 00-Airtel, 01-BSNL, 02-VI, 04-JIO
Signal Strength 5 106–110 Signal strength Integer (0–31)
MCC 10 111–120 Mobile country code Integer
MNC 10 121–130 Mobile network code Integer
Cell Id 16 131–146 Cell tower ID Integer
Location Area Code 16 147–162 Location area code Integer
Fix_status 1 163 GPS fix status 0: No fix, 1: Valid Fix
Latitude 29 164–192 Latitude coordinate Divide by 1,000,000 for float value
NS_Indication 1 193 N or S 0: N, 1: S
Longitude 29 194–222 Longitude coordinate Divide by 1,000,000 for float value
EW_Indication 1 223 East/West Indication 0: E, 1: W
HDOP 10 224–233 Horizontal dilution Divide by 10 for float value
PDOP 10 234–243 Position dilution Divide by 10 for float value
Speed 15 244–258 Speed in km/h Divide by 10 for float value
Altitude 15 259–273 Altitude in meters Divide by 10 for float value
Power Status 1 274 Power connection status 0: Power disconnected, 1: Power connected
Ignition Status 1 275 Ignition status 0: OFF, 1: ON
Immobilizer Status 1 276 Immobilizer status 0: OFF, 1: ON
Tamper 1 277 Wire Tamper detection 0: Tamper alert OFF, 1: Tamper alert ON
Supply Voltage 10 278–287 External battery voltage Divide by 10 for float value
Internal Battery Voltage 6 288–293 Internal battery voltage Divide by 10 for float value
FuelSensorstatus 1 1 294 Status of fuel sensor 1 1 if connected, 0 if not connected
Fuel Percentage 1 10 295–304 Fuel level percentage Divide by 10 for float value
Fuel SensorValue 1 16 305–320 Fuel sensor value Divide by 10 if float
FuelSensorstatus 2 1 321 Status of fuel sensor 2 1 if connected, 0 if not connected
Fuel Percentage 2 10 322–331 Fuel level percentage Divide by 10 for float value
Fuel SensorValue 2 16 332–347 Fuel sensor value Divide by 10 if float
FuelSensorstatus 3 1 348 Status of fuel sensor 3 1 if connected, 0 if not connected
Fuel Percentage 3 16 349–358 Fuel sensor value Divide by 10 if float
Fuel SensorValue 3 16 359–374 Fuel level percentage Divide by 10 for float value
Analog Input 1 10 375–384 Analog input Divide by 10 for float value
Analog Input 2 10 385–394 Analog input 1 Divide by 10 for float value
Digital Input 1 1 395 Digital input 1 0 or 1
Digital Input 2 1 396 Digital input 2 0 or 1
Digital Output 1 1 397 Digital output 1 0 or 1
Digital Output 2 1 398 Digital output 2 0 or 1
Temperature sensor status 1 1 399 Status of temperature sensor 1 1 if connected, 0 if not connected
Temperature 1 12 400–411 Temperature in °C Signed, divide by 10
Temperature sensor status 2 1 412 Status of temperature sensor 2 1 if connected, 0 if not connected
Temperature 2 12 413–424 Temperature in °C Signed, divide by 10
Temperature sensor status 3 1 425 Status of temperature sensor 3 1 if connected, 0 if not connected
Temperature 3 12 426–437 Temperature in °C Signed, divide by 10
Humidity 7 438–444 Humidity percentage
Odometer 35 445–479 Odometer value in meters
DateTime UTC 32 480–511 Timestamp UTC time in seconds
TimeZone 8 512–519

Timezone in quarter-hours (e.g., 22 = +5:30). Each unit = 15 mins. Value 22 = 22 × 15 mins = 330 mins = +5:30 Range: -48 to 56, 2's complement ||

Tail
End Character 8 0–7 Starting character * (ASCII value 42) *
CRC 8 8–15 8-bit XOR CRC of data starting from $ to * (excluding $ and *)

Sample Packet

HEX "240370e21aeb7abfd5818011047aca0260081b780000000000000000000000000000307890000000000000000000000000000000000000000000000068a7f192162abf"

{"imei": 862942074896044, "packet_type": 1, "no_packets": 1, "packet_status": 1, "frame_number": 34, "alert_id": 1, "operator": 1, "signal_strength": 29, "mcc": 404, "mnc": 19, "cell_id": 64, "lac": 56256, "fix_status": 0, "latitude": 0.0, "latitude_dir": 0, "longitude": 0.0, "longitude_dir": 0, "hdop": 0.0, "pdop": 0.0, "speed": 0.0, "altitude": 0.0, "power": 1, "ignition": 1, "immobilizer": 0, "tamper": 0, "supply_volatge": 12.0, "internal_battery_volatge": 3.6, "fuel_sensor_status_1": 0, "fuel_percentage_1": 0.0, "fuel_value_sensor_1": 0, "fuel_sensor_status_2": 0, "fuel_percentage_2": 0.0, "fuel_value_sensor_2": 0, "fuel_sensor_status_3": 0, "fuel_percentage_3": 0.0, "fuel_value_sensor_3": 0, "analog_input1": 0.0, "analog_input2": 0.0, "digital_input1": 0, "digital_input2": 0, "digital_output1": 0, "digital_output2": 0, "temp_sensor_status_1": 0, "temperature_1": 0.0, "temp_sensor_status_2": 0, "temperature_2": 0.0, "temp_sensor_status_3": 0, "temperature_3": 0.0, "humidity": 0, "odometer": 0, "dateTime": 1755836818, "timezone": 22, "dateTime_tz": "2025-08-22 09:56:58", "error_code": 0
}


Telemetry Packet Parser – Grouped Frames

Telemetry Packet Parser


Header

FieldValue

Data Packets

JSON Output


  

Telemetry Packet Parser

Telemetry Packet Parser


Parsed Output:

FieldValue