Jump to content

Device Info Packet: Difference between revisions

From Transight Wiki
No edit summary
No edit summary
Line 175: Line 175:
"packet_type": 0, "no_packets": 1, "dateTime": 1752664936, "timezone": 22, "dateTime_tz": "2025-07-16 16:52:16", "iccid": "89919509129637929835", "vid": "TRAN", "cmfv_name": "TSD4G", "cmfv_version": " 3. 0. 4", "cmfv_build": " 0", "mcua_name": "TSD4R", "mcua_version": " 3. 0. 3", "mcua_build": " 0", "mcub_name": "TSDRB", "mcub_version": " 3. 0. 1", "mcub_build": " 0", "vn": "XXXXXXXXXX", "hwinfo_build": "PCB-0261-AA", "error_code": 0, "raw_data": }
"packet_type": 0, "no_packets": 1, "dateTime": 1752664936, "timezone": 22, "dateTime_tz": "2025-07-16 16:52:16", "iccid": "89919509129637929835", "vid": "TRAN", "cmfv_name": "TSD4G", "cmfv_version": " 3. 0. 4", "cmfv_build": " 0", "mcua_name": "TSD4R", "mcua_version": " 3. 0. 3", "mcua_build": " 0", "mcub_name": "TSDRB", "mcub_version": " 3. 0. 1", "mcub_build": " 0", "vn": "XXXXXXXXXX", "hwinfo_build": "PCB-0261-AA", "error_code": 0, "raw_data": }
</pre>                                                                                               
</pre>                                                                                               


<html lang="en">
<html lang="en">
Line 181: Line 182:
   <title>Device Info Packet Parser</title>
   <title>Device Info Packet Parser</title>
   <style>
   <style>
     body { font-family: Arial, sans-serif; }
     body { font-family: Arial, sans-serif; padding: 20px; }
     textarea {
     textarea { width: 100%; height: 100px; font-family: monospace; }
      width: 100%; height: 100px; font-family: monospace;
    }
     button {
     button {
       padding: 10px 20px;
       padding: 10px 20px;
       border-radius: 20px;
       border-radius: 20px;
      margin-top: 10px;
       font-weight: bold;
       font-weight: bold;
       background-color: #680022;
       background-color: #680022;
Line 198: Line 196:
       background-color: #4c0019;
       background-color: #4c0019;
     }
     }
     table {
     table { width: 100%; border-collapse: collapse; }
      width: 100%;
     th, td { border: 1px solid #ccc; padding: 8px; text-align: left; }
      border-collapse: collapse;
     th { background-color: #680022; color: white; }
      margin-top: 20px;
    }
     th, td {
      border: 1px solid #ccc;
      padding: 8px;
      text-align: left;
    }
     th {
      background-color: #680022;
      color: white;
    }
   </style>
   </style>
</head>
</head>
Line 217: Line 204:


<h2>Device Info Packet Parser</h2>
<h2>Device Info Packet Parser</h2>
<textarea id="hexInput" placeholder="Paste Device Info Packet here..."></textarea><br>
<textarea id="packetInput" placeholder="Paste your hex packet here..."></textarea><br>
<button onclick="parseDeviceInfo()">Parse Packet</button>
<button onclick="parsePacket()">Parse Packet</button>


<h3>Parsed Output:</h3>
<h3>Parsed Output:</h3>
Line 228: Line 215:
<script>
<script>
function hexToBits(hex) {
function hexToBits(hex) {
   return hex.match(/.{1,2}/g).map(b => parseInt(b, 16).toString(2).padStart(8, '0')).join('');
   return hex.match(/.{1,2}/g).map(byte =>
    parseInt(byte, 16).toString(2).padStart(8, '0')).join('');
}
}
function bitsToInt(bits) {
function bitsToInt(bits) {
   return parseInt(bits, 2);
   return parseInt(bits, 2);
}
}
function bitsToSignedInt(bits) {
function bitsToSignedInt(bits) {
   const val = parseInt(bits, 2);
   let value = parseInt(bits, 2);
   return val >= 2 ** (bits.length - 1) ? val - 2 ** bits.length : val;
   const max = Math.pow(2, bits.length);
  return value >= max / 2 ? value - max : value;
}
}
function bitsToAscii(bits) {
function bitsToAscii(bits) {
   return bits.match(/.{1,8}/g).map(b => String.fromCharCode(parseInt(b, 2))).join('').replace(/\0/g, '');
   return bits.match(/.{8}/g).map(b => String.fromCharCode(parseInt(b, 2))).join('').trim();
}
}
function bigIntFromBits(bits) {
 
   return BigInt('0b' + bits).toString();
function parseImeiFromHex(hex, byteStart, byteEnd) {
  const bcd = hex.slice(byteStart * 2, byteEnd * 2);
   return bcd.replace(/f/gi, '').split('').join('');
}
}


function parseDeviceInfo() {
function parsePacket() {
   const hex = document.getElementById("hexInput").value.trim().toLowerCase();
   const hex = document.getElementById('packetInput').value.trim().toLowerCase();
   const resultBody = document.querySelector("#resultTable tbody");
   const resultBody = document.querySelector("#resultTable tbody");
   resultBody.innerHTML = "";
   resultBody.innerHTML = "";


   if (!hex || !hex.startsWith("24")) {
   if (!hex || !hex.startsWith("24")) {
     alert("Invalid packet! Must start with 24 (hex for $)");
     alert("Invalid packet");
     return;
     return;
   }
   }
Line 261: Line 255:
   };
   };


   const fields = [
  // Corrected IMEI parsing from BCD
    ["Start Character", 0, 8],
   const imei = parseImeiFromHex(hex, 7, 15);
    ["Length", 8, 19],
  output("IMEI", imei);
    ["No of Packets", 19, 24],
 
    ["IMEI", 24, 75],
  const packetType = bitsToInt(bits.slice(75, 80));
    ["Packet Type", 75, 80],
  output("Packet Type", packetType);
    ["Time", 80, 112],
 
    ["Time Zone", 112, 120],
  const tsBits = bits.slice(80, 112);
     ["ICCID", 120, 280],
  const timezoneBits = bits.slice(112, 120);
  const ts = bitsToInt(tsBits);
  const timezoneRaw = bitsToSignedInt(timezoneBits);
  const offsetMin = timezoneRaw * 15;
  const sign = offsetMin >= 0 ? "+" : "-";
  const h = Math.floor(Math.abs(offsetMin) / 60);
  const m = Math.abs(offsetMin % 60);
  const localDate = new Date((ts + offsetMin * 60) * 1000);
  const localStr = localDate.toISOString().replace("T", " ").replace(".000Z", "");
 
  output("DateTime (Epoch)", ts);
  output("TimeZone", `${offsetMin} mins = UTC${sign}${h}:${m.toString().padStart(2, '0')}`);
  output("DateTime (Local Time)", localStr);
 
  // ASCII Fields
  const asciiFields = [
     ["ICCID", 120, 279],
     ["VID", 280, 311],
     ["VID", 280, 311],
     ["CELLULAR_MODULE_FV NAME", 312, 352],
     ["CMFV Name", 312, 351],
     ["CELLULAR_MODULE_FV VERSION", 352, 432],
     ["CMFV Version", 352, 431],
     ["CELLULAR_MODULE_FV BUILD NO", 432, 472],
     ["CMFV Build", 432, 471],
     ["MCU_APP_MODULE_FV NAME", 472, 512],
     ["MCUA Name", 472, 511],
     ["MCU_APP_MODULE_FV VERSION", 512, 592],
     ["MCUA Version", 512, 591],
     ["MCU_APP_MODULE_FV BUILD NO", 592, 632],
     ["MCUA Build", 592, 631],
     ["MCU_BTL_MODULE_FV NAME", 632, 672],
     ["MCUB Name", 632, 671],
     ["MCU_BTL_MODULE_FV VERSION", 672, 752],
     ["MCUB Version", 672, 751],
     ["MCU_BTL_MODULE_FV BUILD NO", 752, 792],
     ["MCUB Build", 752, 791],
     ["VN", 792, 871],
     ["VN", 792, 871],
     ["HWINFO", 872, 956],
     ["HWINFO", 872, 959]
    ["End Character", 0, 8],
    ["CRC", 8, 15]
   ];
   ];


   for (const [label, start, end] of fields) {
   for (const [label, start, end] of asciiFields) {
     const val = bits.slice(start, end);
     const value = bitsToAscii(bits.slice(start, end + 1));
    switch (label) {
    output(label, value);
      case "IMEI":
        output(label, bigIntFromBits(val));
        break;
      case "Time":
        const timestamp = bitsToInt(val);
        output(label, new Date(timestamp * 1000).toISOString());
        break;
      case "Time Zone":
        const tz = bitsToSignedInt(val);
        const mins = tz * 15;
        const sign = mins >= 0 ? "+" : "-";
        const h = Math.floor(Math.abs(mins) / 60);
        const m = Math.abs(mins % 60);
        output("Time Zone", `${mins} mins (UTC${sign}${h}:${m.toString().padStart(2, '0')})`);
        break;
      case "ICCID":
      case "VID":
      case "CELLULAR_MODULE_FV NAME":
      case "CELLULAR_MODULE_FV VERSION":
      case "CELLULAR_MODULE_FV BUILD NO":
      case "MCU_APP_MODULE_FV NAME":
      case "MCU_APP_MODULE_FV VERSION":
      case "MCU_APP_MODULE_FV BUILD NO":
      case "MCU_BTL_MODULE_FV NAME":
      case "MCU_BTL_MODULE_FV VERSION":
      case "MCU_BTL_MODULE_FV BUILD NO":
      case "VN":
      case "HWINFO":
        output(label, bitsToAscii(val).trim());
        break;
      case "Start Character":
      case "End Character":
        output(label, String.fromCharCode(bitsToInt(val)));
        break;
      case "CRC":
        output(label, bitsToInt(val).toString(16).toUpperCase().padStart(2, '0'));
        break;
      default:
        output(label, bitsToInt(val));
    }
   }
   }
  output("Error Code", 0);
  output("Raw Data", hex);
}
}
</script>
</script>
</body>
</html>
<!DOCTYPE html
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Device Info Packet Parser</title>
  <style>
    body { font-family: Arial, sans-serif; padding: 20px; }
    textarea { width: 100%; height: 100px; font-family: monospace; }
    button {
      padding: 10px 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>
  <h2>Device Info Packet Parser</h2>
  <textarea id="packetInput" placeholder="Paste your hex packet here..."></textarea><br>
  <button onclick="parsePacket()">Parse Packet</button>
  <div id="output"></div>
  <script>
    function parsePacket() {
      const hex = document.getElementById('packetInput').value.trim();
      if (!hex) return;
      const bits = hex.match(/.{1,2}/g).map(h => parseInt(h, 16).toString(2).padStart(8, '0')).join('');
      const getBits = (start, end) => bits.slice(start, end + 1);
      const getAscii = (start, end) => getBits(start, end).match(/.{8}/g).map(b => String.fromCharCode(parseInt(b, 2))).join('').trim();
      const getInt = (start, end) => parseInt(getBits(start, end), 2);
      const getTimestamp = (start, end, tzBits) => {
        const ts = getInt(start, end);
        const tzRaw = parseInt(getBits(tzBits, tzBits + 7), 2);
        const timezone = tzRaw > 127 ? tzRaw - 256 : tzRaw;
        const date = new Date((ts + timezone * 900) * 1000);
        return { ts, timezone, local: date.toISOString().replace('T', ' ').slice(0, 19) };
      };
      const parsed = {
        "IMEI": parseInt(getBits(24, 74), 2),
        "Packet Type": getInt(75, 79),
        "No. of Packets": getInt(19, 23),
        ...(() => {
          const ts = getTimestamp(80, 111, 112);
          return {
            "DateTime (UTC seconds)": ts.ts,
            "Timezone": ts.timezone,
            "DateTime (Local)": ts.local
          };
        })(),
        "ICCID": getAscii(120, 279),
        "VID": getAscii(280, 311),
        "CELLULAR_MODULE_FV NAME": getAscii(312, 351),
        "CELLULAR_MODULE_FV VERSION": getAscii(352, 431),
        "CELLULAR_MODULE_FV BUILD NO": getAscii(432, 471),
        "MCU_APP_MODULE_FV NAME": getAscii(472, 511),
        "MCU_APP_MODULE_FV VERSION": getAscii(512, 591),
        "MCU_APP_MODULE_FV BUILD NO": getAscii(592, 631),
        "MCU_BTL_MODULE_FV NAME": getAscii(632, 671),
        "MCU_BTL_MODULE_FV VERSION": getAscii(672, 751),
        "MCU_BTL_MODULE_FV BUILD NO": getAscii(752, 791),
        "VN": getAscii(792, 871),
        "HWINFO": getAscii(872, 959),
        "Error Code": 0,
        "Raw Packet": hex
      };
      const outputDiv = document.getElementById('output');
      outputDiv.innerHTML = `
        <table>
          <thead>
            <tr><th>Field</th><th>Value</th></tr>
          </thead>
          <tbody>
            ${Object.entries(parsed).map(([k, v]) =>
              `<tr><td>${k}</td><td>${v}</td></tr>`).join('')}
          </tbody>
        </table>
      `;
    }
  </script>
</body>
</body>
</html>
</html>

Revision as of 07:06, 17 July 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
Number of data packets 5 20–24 Number of packets (0–32) 0–32
IMEI 50 25–74 Unique device identifier
Packet type 5 75–79 Type of packet 00 - Device Info
Data
Time 32 UTC Timestamp UTC time in seconds
Time Zone 8 Timezone in quarter-hours (e.g., 22 = +5:30), quarter-hour increment means each unit represents 15 minutes. The value 22 represents 22 quarter hours. Ranges from -48 to 56, negative timezone to 2's complement representation eg: 22 (+5:30) → 22×15=330 minutes → 330÷60=5.5 hours → 5 hours and 30 minutes
ICCID 160 20 Bytes, Character string 8991000903297069053F
VID 32 4 Bytes, Character string TRAN
CELLULAR_MODULE_FV NAME 40 5 Bytes, Character string TSPJT
CELLULAR_MODULE_FV VERSION 80 10 Bytes, Character string XX.YY.ZZZZ
CELLULAR_MODULE_FV BUILD NO 40 5 Bytes, Character string YYDDD
MCU_APP_MODULE_FV NAME 40 5 Bytes, Character string TSPJT
MCU_APP_MODULE_FV VERSION 80 10 Bytes, Character string XX.YY.ZZZZ
MCU_APP_MODULE_FV BUILD NO 40 5 Bytes, Character string YYDDD
MCU_BTL_MODULE_FV NAME 40 5 Bytes, Character string TSPJT
MCU_BTL_MODULE_FV VERSION 80 10 Bytes, Character string XX.YY.ZZZZ
MCU_BTL_MODULE_FV BUILD NO 40 5 Bytes, Character string YYDDD
VN 80 10 Bytes, Character string KL07CP8490
HWINFO 88 11 Bytes, Character string PCB-0220-AB
Tail(2 Bytes)
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 : "2406e0e21aeb7abfd58068778b681638393931393530393132393633373932393833355452414e545344344720332e20302e202020342020202030545344345220332e20302e202020332020202030545344524220332e20302e202020312020202030585858585858585858585043422d303236312d41412ab9"
{"imei": 862942074896044, 
"packet_type": 0, "no_packets": 1, "dateTime": 1752664936, "timezone": 22, "dateTime_tz": "2025-07-16 16:52:16", "iccid": "89919509129637929835", "vid": "TRAN", "cmfv_name": "TSD4G", "cmfv_version": " 3. 0. 4", "cmfv_build": " 0", "mcua_name": "TSD4R", "mcua_version": " 3. 0. 3", "mcua_build": " 0", "mcub_name": "TSDRB", "mcub_version": " 3. 0. 1", "mcub_build": " 0", "vn": "XXXXXXXXXX", "hwinfo_build": "PCB-0261-AA", "error_code": 0, "raw_data": }


Device Info Packet Parser

Device Info Packet Parser


Parsed Output:

FieldValue