OTA (Over-The-Air) Packet: Difference between revisions
No edit summary |
|||
| (5 intermediate revisions by the same user not shown) | |||
| Line 6: | Line 6: | ||
! style="background-color:#680022; color:white;" | Breakdown | ! style="background-color:#680022; color:white;" | Breakdown | ||
|- | |- | ||
! colspan="5" style="background:#D3D3D3;" | Header | ! colspan="5" style="background:#D3D3D3;" | Header (10 Bytes) | ||
|- | |- | ||
| Start byte || 8 || 0–7 || Starting character $ (ASCII value 36) || $ | | Start byte || 8 || 0–7 || Starting character $ (ASCII value 36) || $ | ||
| Line 24: | Line 24: | ||
05 - IP configuration packet | 05 - IP configuration packet | ||
|- | |- | ||
! colspan="5" style="background:#D3D3D3;" | Data | ! colspan="5" style="background:#D3D3D3;" | Data (154 Bytes) | ||
|- | |- | ||
| OTA Source || 5 || | | OTA Source || 5 || 80-84|| Source of OTA || | ||
00 - OTA_SRC_SERIAL<br> | 00 - OTA_SRC_SERIAL<br> | ||
01 - OTA_SRC_SMS<br> | 01 - OTA_SRC_SMS<br> | ||
| Line 32: | Line 32: | ||
03 - OTA_SRC_IP_CUSTOMER | 03 - OTA_SRC_IP_CUSTOMER | ||
|- | |- | ||
| Error status || 8 || | | Error status || 8 || 85-92|| Non-zero value indicates an error || 0 = No Error, Non-zero = Error | ||
|- | |- | ||
| Cell Number || 51 || | | Cell Number || 51 || 93-143|| First bit (MSB) indicates presence of country code. Remaining 50 bits = mobile number || | ||
Example: 400D6276ACF52 (+919784312658) | Example: 400D6276ACF52 (+919784312658) | ||
|- | |- | ||
| Date & Time || 32 || | | Date & Time || 32 || 144-175|| UTC Timestamp || UTC time in seconds | ||
|- | |- | ||
| Timezone || 8 || | | Timezone || 8 || 176-183|| Timezone in quarter-hours (e.g., 22 = +5:30) || | ||
22 × 15 mins = 330 mins = +5:30 | 22 × 15 mins = 330 mins = +5:30 | ||
|- | |- | ||
| Command Length || 8 || | | Command Length || 8 || 184-191|| Length of command string || — | ||
|- | |- | ||
| Command || up to 600 bits (75 bytes) || | | Command || up to 600 bits (75 bytes) || 192-791 || Command with arguments, null-terminated string || | ||
Example: SET CUIOCFG:IO1-DI-IGN*IO2_AN_GEN*IO3-DI-PBN*IO4-DO-IMB* | Example: SET CUIOCFG:IO1-DI-IGN*IO2_AN_GEN*IO3-DI-PBN*IO4-DO-IMB* | ||
|- | |- | ||
| Response Length || 8 || | | Response Length || 8 || 792-799 || Length of response string || — | ||
|- | |- | ||
| Response || up to 512 bits (64 bytes) || | | Response || up to 512 bits (64 bytes) || 800-1311|| Response string from device || | ||
Example: IOCFG:IO1-DI-IGN*IO2-AN_GEN*IO3-DI-PBN*IO4-DO-IMB* | Example: IOCFG:IO1-DI-IGN*IO2-AN_GEN*IO3-DI-PBN*IO4-DO-IMB* | ||
|- | |- | ||
! colspan="5" style="background:#D3D3D3;" | Tail | ! colspan="5" style="background:#D3D3D3;" | Tail (2 Bytes) | ||
|- | |- | ||
| End Character || 8 || 0–7 || End character * (ASCII value 42) || * | | End Character || 8 || 0–7 || End character * (ASCII value 42) || * | ||
| Line 61: | Line 61: | ||
==Sample Packet== | ==Sample Packet== | ||
<pre> | <pre> | ||
{ | {HEX : "240630e21aeb7abfd582100000000000000068abef4a160854534657494e464f4c4657494e464f3a2054534434475f305f332e302e350a4657494e464f3a2054532d4452425f32353231315f332e302e320a4657494e464f3a2054532d4434525f32353231315f332e302e350a2ac3" "imei": 862942074896044, "packet_type": 2, "no_packets": 1, "ota_source": 2, "error_status": 0, "cell_no": 0, "dateTime": 1756098378, "timezone": 22, "dateTime_tz": "2025-08-25 10:36:18", "command_length": 8, "command": "TSFWINFO", "response_length": 76, "response": "FWINFO: TSD4G_0_3.0.5\nFWINFO: TS-DRB_25211_3.0.2\nFWINFO: TS-D4R_25211_3.0.5\n", "error_code": 0 } | ||
</pre> | </pre> | ||
[ | |||
<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> | |||
<h2>OTA Packet Parser</h2> | |||
<textarea id="hexInput" placeholder="Paste OTA packet hex here..."></textarea><br> | |||
<button onclick="parseOTAPacket()">Parse 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 bigIntFromBits(bits) { | |||
return BigInt('0b' + bits).toString(); | |||
} | |||
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 parseOTAPacket() { | |||
const hex = document.getElementById("hexInput").value.trim().toLowerCase(); | |||
const resultBody = document.querySelector("#resultTable tbody"); | |||
resultBody.innerHTML = ""; | |||
if (!hex || !hex.startsWith("24")) { | |||
alert("Invalid packet"); | |||
return; | |||
} | |||
const bits = hexToBits(hex); | |||
const output = (label, value) => { | |||
const row = document.createElement("tr"); | |||
row.innerHTML = `<td>${label}</td><td>${value}</td>`; | |||
resultBody.appendChild(row); | |||
}; | |||
const getBits = (start, end) => bits.slice(start, end); | |||
// Refer to telemetry parser logic — exact structure | |||
output("IMEI", bigIntFromBits(getBits(25, 75))); | |||
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 sign = offsetMinutes >= 0 ? "+" : "-"; | |||
output("Timezone", `${offsetMinutes} mins = UTC${sign}${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)); | |||
} | |||
</script> | |||
</body> | |||
</html> | |||
Latest revision as of 05:09, 25 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 | 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 |
| Data (154 Bytes) | ||||
| OTA Source | 5 | 80-84 | Source of OTA |
00 - OTA_SRC_SERIAL |
| Error status | 8 | 85-92 | Non-zero value indicates an error | 0 = No Error, Non-zero = Error |
| Cell Number | 51 | 93-143 | First bit (MSB) indicates presence of country code. Remaining 50 bits = mobile number |
Example: 400D6276ACF52 (+919784312658) |
| Date & Time | 32 | 144-175 | UTC Timestamp | UTC time in seconds |
| Timezone | 8 | 176-183 | Timezone in quarter-hours (e.g., 22 = +5:30) |
22 × 15 mins = 330 mins = +5:30 |
| Command Length | 8 | 184-191 | Length of command string | — |
| Command | up to 600 bits (75 bytes) | 192-791 | Command with arguments, null-terminated string |
Example: SET CUIOCFG:IO1-DI-IGN*IO2_AN_GEN*IO3-DI-PBN*IO4-DO-IMB* |
| Response Length | 8 | 792-799 | Length of response string | — |
| Response | up to 512 bits (64 bytes) | 800-1311 | Response string from device |
Example: IOCFG:IO1-DI-IGN*IO2-AN_GEN*IO3-DI-PBN*IO4-DO-IMB* |
| Tail (2 Bytes) | ||||
| 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 : "240630e21aeb7abfd582100000000000000068abef4a160854534657494e464f4c4657494e464f3a2054534434475f305f332e302e350a4657494e464f3a2054532d4452425f32353231315f332e302e320a4657494e464f3a2054532d4434525f32353231315f332e302e350a2ac3" "imei": 862942074896044, "packet_type": 2, "no_packets": 1, "ota_source": 2, "error_status": 0, "cell_no": 0, "dateTime": 1756098378, "timezone": 22, "dateTime_tz": "2025-08-25 10:36:18", "command_length": 8, "command": "TSFWINFO", "response_length": 76, "response": "FWINFO: TSD4G_0_3.0.5\nFWINFO: TS-DRB_25211_3.0.2\nFWINFO: TS-D4R_25211_3.0.5\n", "error_code": 0 }
OTA Packet Parser
Parsed Output:
| Field | Value |
|---|