Jump to content

OTA (Over-The-Air) Packet

From Transight Wiki
Revision as of 09:20, 21 July 2025 by Editor (talk | contribs)
Field Size (bits) Bit Range Description Breakdown
Header
Start byte 8 0–7 Starting character $ (ASCII value 36) $
Data length 12 8–18 2-byte length of the data following the header
Num of data packets 5 19–23 Number of packets (0–32) 0 - 32
IMEI 50 24–74 Unique device identifier Integer type: e.g., 887744556677882
Packet Type 5 75–79 Type of packet

00 - Device info
01 - Alert packet
02 - OTA pkt
03 - Error Packet
04 - Device configuration packet
05 - IP configuration packet

Data
OTA Source 5 Source of OTA

00 - OTA_SRC_SERIAL
01 - OTA_SRC_SMS
02 - OTA_SRC_IP_TRANSIGHT
03 - OTA_SRC_IP_CUSTOMER

Error status 8 Non-zero value indicates an error 0 = No Error, Non-zero = Error
Cell Number 51 First bit (MSB) indicates presence of country code. Remaining 50 bits = mobile number

Example: 400D6276ACF52 (+919784312658)

Date & Time 32 UTC Timestamp UTC time in seconds
Timezone 8 Timezone in quarter-hours (e.g., 22 = +5:30)

22 × 15 mins = 330 mins = +5:30

Command Length 8 Length of command string
Command up to 600 bits (75 bytes) Command with arguments, null-terminated string

Example: SET CUIOCFG:IO1-DI-IGN*IO2_AN_GEN*IO3-DI-PBN*IO4-DO-IMB*

Response Length 8 Length of response string
Response up to 512 bits (64 bytes) Response string from device

Example: IOCFG:IO1-DI-IGN*IO2-AN_GEN*IO3-DI-PBN*IO4-DO-IMB*

Tail
End Character 8 0–7 End character * (ASCII value 42) *
CRC 8 8–15 8-bit XOR CRC from $ to * (excluding both)

Sample Packet

 {"HEX:240340e1cabd09208ca210000000000000006824646f160947455420545355524c1c55524c3a5443503a3134312e3134372e3132382e3135303a383738382aa2",
  "cell_no": 0,
  "command": "GET TSURL",
  "command_length": 9,
  "dateTime": 1747215471,
  "dateTime_tz": "2025-05-14 15:07:51.000",
  "error_status": 0,
  "imei": 860187062240357,
  "insert_time": "Wed, 14 May 2025 09:38:03 GMT",
  "ota_source": 2,
  "packetType": 2,
  "response": "URL:TCP:141.147.128.150:8788",
  "response_length": 28,
  "send_time": "2025-05-14 15:07:51",
  "timezone": 22}

<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: #680022; }
   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>

OTA Packet Parser

<textarea id="hexInput" placeholder="Paste OTA packet hex here..."></textarea>
<button onclick="parseOTAPacket()">Parse OTA Packet</button>

Parsed Output:

<thead></thead>
 <tbody></tbody>
FieldValue


<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 bigIntFromBits(bits) {

 return BigInt('0b' + bits).toString();

}

function bitsToAscii(bits) {

 let ascii = ;
 for (let i = 0; i < bits.length; i += 8) {
   const byte = bits.slice(i, i + 8);
   ascii += String.fromCharCode(parseInt(byte, 2));
 }
 return ascii;

}

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 = `${label}${value}`;

   resultBody.appendChild(row);
 };
 // Parse known fixed fields
 const imei = bigIntFromBits(getBits(25, 75));  // Correct IMEI parse
 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);
 const command = bitsToAscii(cmdBits);
 output("Command", command);
 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);
 const response = bitsToAscii(respBits);
 output("Response", response);

} </script>