Jump to content

OTA PACKET PARSER: Difference between revisions

From Transight Wiki
No edit summary
Blanked the page
Tag: Blanking
 
(6 intermediate revisions by the same user not shown)
Line 1: Line 1:
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>OTA Packet Parser</title>
  <style>
    body { font-family: Arial, sans-serif; padding: 20px; }
    textarea { width: 100%; height: 100px; font-family: monospace; margin-bottom: 10px; }
    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; }
    th { background-color: #680022; color: white; }
  </style>
</head>
<body>


<h2>OTA Packet Parser</h2>
<textarea id="hexInput" placeholder="Paste OTA packet hex here..."></textarea><br>
<button id="parseBtn">Parse OTA Packet</button>
<h3>Parsed Output:</h3>
<table id="resultTable">
  <thead><tr><th>Field</th><th>Value</th></tr></thead>
  <tbody></tbody>
</table>
<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) {
  let value = parseInt(bits, 2);
  const max = Math.pow(2, bits.length);
  return value >= max / 2 ? value - max : value;
}
function bitsToAscii(bits) {
  let ascii = '';
  for (let i = 0; i < bits.length; i += 8) {
    ascii += String.fromCharCode(parseInt(bits.slice(i, i + 8), 2));
  }
  return ascii;
}
function parseIMEIFromHex(hex, bitStart, bitEnd) {
  const byteStart = bitStart / 8;
  const byteEnd = bitEnd / 8;
  const imeiHex = hex.slice(byteStart * 2, byteEnd * 2); // 2 hex chars per byte
  let imei = '';
  for (let i = 0; i < imeiHex.length; i += 2) {
    const byte = imeiHex.slice(i, i + 2);
    const firstDigit = (parseInt(byte, 16) & 0xF0) >> 4;
    const secondDigit = parseInt(byte, 16) & 0x0F;
    imei += firstDigit.toString() + secondDigit.toString();
  }
  return imei.replace(/^0+/, '');
}
function parseOTAPacket() {
  const hex = document.getElementById("hexInput").value.trim().toLowerCase();
  const resultBody = document.querySelector("#resultTable tbody");
  resultBody.innerHTML = "";
  if (!hex.startsWith("24")) {
    alert("Packet must start with hex '24'");
    return;
  }
  const bits = hexToBits(hex);
  const getBits = (start, end) => bits.slice(start, end);
  const output = (label, value) => {
    const row = document.createElement("tr");
    row.innerHTML = `<td>${label}</td><td>${value}</td>`;
    resultBody.appendChild(row);
  };
  // ✅ Corrected IMEI bit range: 24–74
  const imei = parseIMEIFromHex(hex, 24, 74);
  output("IMEI", imei);
  output("Packet Type", bitsToInt(getBits(75, 80)));
  output("OTA Source", bitsToInt(getBits(80, 85)));
  output("Error Status", bitsToInt(getBits(85, 93)));
  const cellBits = getBits(93, 144);
  const isWithCountryCode = cellBits[0] === '1';
  const cellNo = parseInt(cellBits.slice(1), 2);
  output("Cell Number", isWithCountryCode ? `+${cellNo}` : cellNo);
  const dt = bitsToInt(getBits(144, 176));
  output("UTC Timestamp", new Date(dt * 1000).toISOString());
  const timezoneRaw = bitsToSignedInt(getBits(176, 184));
  const offsetMinutes = timezoneRaw * 15;
  const h = Math.floor(Math.abs(offsetMinutes) / 60);
  const m = Math.abs(offsetMinutes % 60);
  const tzSign = offsetMinutes >= 0 ? "+" : "-";
  output("Timezone", `${offsetMinutes} mins = UTC${tzSign}${h}:${m.toString().padStart(2, '0')}`);
  const localTime = new Date((dt + offsetMinutes * 60) * 1000)
    .toISOString().replace("T", " ").replace(".000Z", "");
  output("DateTime (Local)", localTime);
  const cmdLength = bitsToInt(getBits(184, 192));
  output("Command Length", cmdLength);
  const cmdBits = getBits(192, 192 + cmdLength * 8);
  output("Command", bitsToAscii(cmdBits));
  const respLenStart = 192 + cmdLength * 8;
  const responseLength = bitsToInt(getBits(respLenStart, respLenStart + 8));
  output("Response Length", responseLength);
  const respBits = getBits(respLenStart + 8, respLenStart + 8 + responseLength * 8);
  output("Response", bitsToAscii(respBits));
}
// ✅ Attach parse function to button click
document.getElementById("parseBtn").addEventListener("click", parseOTAPacket);
</script>
</body>
</html>

Latest revision as of 10:44, 21 July 2025