OCH Channel List Decoder 2
by Himbeer
HTML
<script src="https://cdnjs.cloudflare.com/ajax/libs/pako/1.0.10/pako.min.js"></script>
<!DOCTYPE HTML>
<html>
<head>
<title>OCH Channel List Decoder</title>
</head>
<body>
<h1>OCH Channel List Decoder</h1>
<h2>For Triax-Hirschmann S-930 and OHS1720IR (possibly other models)</h2>
<div class="formElement">
<label for="upload">Upload .OCH File:</label>
<input id="upload" type="file">
</div>
<div class="formElement">
<label for="showRaw">Display raw data:</label>
<input id="showRaw" type="checkbox">
</div>
<button id="confirm">Decode</button>
<p id="status"></p>
<h3>TV Channels</h3>
<table>
<thead>
<tr>
<th>Number</th><th>Channel Name</th><th>Raw Data</th>
</tr>
</thead>
<tbody id="tvTable"></tbody>
</table>
<h3>Radio Channels</h3>
<table>
<thead>
<tr>
<th>Number</th><th>Channel Name</th><th>Raw Data</th>
</tr>
</thead>
<tbody id="radioTable"></tbody>
</table>
</body>
</html>
CSS
html, body {
font-family: sans-serif;
}
button {
display: block;
}
table {
border: solid 0.1rem black;
}
.formElement {
margin-bottom: 1rem;
}
.tdRaw {
font-family: monospace;
}
JavaScript
const upload = document.getElementById("upload");
const showRaw = document.getElementById("showRaw");
const confirm = document.getElementById("confirm");
const status = document.getElementById("status");
const tvTable = document.getElementById("tvTable");
const radioTable = document.getElementById("radioTable");
confirm.addEventListener("click", async () => {
if (upload.files.length > 0) {
status.innerText = "Processing...";
const file = upload.files[0];
const arrayBuffer = await file.arrayBuffer();
const view = new Uint8Array(arrayBuffer);
const decompressed = pako.inflate(view.slice(96));
const res = convert(decompressed);
if (res === true) {
status.innerText = "Done decoding file.";
console.log("success");
} else {
status.innerText = "Failed decoding file. Reason: " + res;
console.log("failure");
}
} else {
alert("No file selected!");
}
});
function readCName(arr) {
let i = 0, str = "";
while (arr[i] !== 0 && i < arr.length) {
if (!(arr[i] >= 0x85)) str += String.fromCharCode(arr[i]);
//str += String.fromCharCode(arr[i]);
i++;
}
return str;
}
function readmultiByte(array, offset, count) {
let value = 0;
for (let i = 0; i < count; i++) {
value += array[offset + i] * (256 ** (i));
}
return value;
}
function arrToHexStr(arr) {
let str = "";
arr.forEach((e, i) => {
str += e.toString(16).padStart(2, "0");
if (i % 2 === 0) str += " ";
});
return str;
}
const b_start = 100400;
const b_end = 333644;
const b_cLen = 76;
const b_s_start = 556400;
const b_s_end = 560456;
function convert(arr) {
const channels = [];
const usedChannels = [];
tvTable.innerHTML = radioTable.innerHTML = "";
console.log("=======");
console.log("Length: " + arr.length);
let i = b_start;
while (i < b_end) {
const part = arr.slice(i, i + b_cLen);
const cName = readCName(part);
const cRadio = part[23] === 1;
//console.log(`${i} ${cName} (${cName.length})`);
...