261 lines
9.8 KiB
JavaScript
Executable File
261 lines
9.8 KiB
JavaScript
Executable File
/**
|
|
* Shared Dashboard Update Module
|
|
* Used by: sys_set.html, sys_rf.html, sys_ts.html, sys_psip.html, log_output.html, status_info.html
|
|
*
|
|
* This module provides a common refreshDashboard() function that updates
|
|
* the summary dashboard cards with status data from the backend.
|
|
*
|
|
* For status_info.html which already fetches data, use updateDashboardCards()
|
|
* to update cards without making an additional AJAX call.
|
|
*/
|
|
(function() {
|
|
'use strict';
|
|
|
|
// Power decimal lookup table
|
|
var POWER_DECIMALS = ["00","05","10","15","20","25","30","35","40","45","50","55","60","65","70","75","80","85","90","95"];
|
|
|
|
// Input source labels
|
|
var INPUT_SOURCES = ["ASI1","ASI2","EAS","Tuner","TSoIP","None"];
|
|
|
|
/**
|
|
* Calculate frequency from channel number
|
|
* @param {number} chan - Channel number (2-83)
|
|
* @returns {number} Frequency in MHz
|
|
*/
|
|
function calcFrequency(chan) {
|
|
var freq = 0;
|
|
if (chan >= 2 && chan <= 6) {
|
|
freq = (chan - 2) * 6 + 57;
|
|
if (freq > 69) freq += 4;
|
|
} else if (chan >= 7 && chan <= 13) {
|
|
freq = 177 + 6 * (chan - 7);
|
|
} else if (chan >= 14 && chan <= 83) {
|
|
freq = 473 + (chan - 14) * 6;
|
|
}
|
|
return freq;
|
|
}
|
|
|
|
/**
|
|
* Convert temperature based on unit
|
|
* @param {number} rawValue - Raw temperature value
|
|
* @param {number} unit - 0 = Fahrenheit, 1 = Celsius
|
|
* @returns {number|string} Temperature in Fahrenheit
|
|
*/
|
|
function convertTemperature(rawValue, unit) {
|
|
if (unit === 0) {
|
|
return rawValue; // Already Fahrenheit
|
|
} else {
|
|
return (rawValue * 1.8 + 32).toFixed(2); // Celsius to Fahrenheit
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Helper function to set card value and status
|
|
* @param {string} id - Element ID for the value
|
|
* @param {string} dotId - Element ID for the status dot
|
|
* @param {*} value - Value to display
|
|
* @param {string} status - Status class (ok, warn, err, off, neutral)
|
|
*/
|
|
function setCard(id, dotId, value, status) {
|
|
var el = document.getElementById(id);
|
|
var dot = document.getElementById(dotId);
|
|
if (el) {
|
|
el.innerText = value;
|
|
el.className = "summary-value value-" + status;
|
|
}
|
|
if (dot) {
|
|
dot.className = "status-dot status-" + status;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Get SNR status based on value
|
|
* @param {string} snr - SNR value or "N/A"
|
|
* @returns {string} Status class
|
|
*/
|
|
function getSnrStatus(snr) {
|
|
if (snr === "N/A") return 'off';
|
|
var val = parseFloat(snr); // already carries the +10 dB display offset
|
|
if (val >= 37) return 'ok';
|
|
if (val >= 30) return 'warn';
|
|
return 'err';
|
|
}
|
|
|
|
/**
|
|
* Get IMD status (UIMD/LIMD)
|
|
* @param {string} imd - IMD value or "N/A"
|
|
* @returns {string} Status class
|
|
*/
|
|
function getImdStatus(imd) {
|
|
if (imd === "N/A") return 'off';
|
|
return parseFloat(imd) >= 47 ? 'ok' : 'err';
|
|
}
|
|
|
|
/**
|
|
* Update all dashboard cards with provided data
|
|
* Use this when you already have the data (e.g., from status_info.html)
|
|
*
|
|
* @param {Object} data - Dashboard data object
|
|
* @param {number} data.freqVal - Frequency in MHz
|
|
* @param {string} data.snr - SNR value
|
|
* @param {string} data.limd - LIMD value
|
|
* @param {string} data.uimd - UIMD value
|
|
* @param {string} data.inputSrc - Input source label
|
|
* @param {string} data.inputStatus - Input status (OK/Err)
|
|
* @param {string} data.bitrate - Bitrate value
|
|
* @param {string} data.temp - Temperature value
|
|
* @param {string} data.agc - AGC status (On/Off)
|
|
* @param {string} data.ctrl - Control mode (Remote/Local)
|
|
* @param {number} data.rfStat - RF switch status (1=On, 0=Off)
|
|
* @param {string} data.finalPower - Output power string
|
|
*/
|
|
window.updateDashboardCards = function(data) {
|
|
setCard('sum_freq', 'dot_freq', data.freqVal, 'neutral');
|
|
setCard('sum_snr', 'dot_snr', data.snr, getSnrStatus(data.snr));
|
|
setCard('sum_uimd', 'dot_uimd', data.uimd, getImdStatus(data.uimd));
|
|
setCard('sum_limd', 'dot_limd', data.limd, getImdStatus(data.limd));
|
|
setCard('sum_input', 'dot_input', data.inputSrc, 'neutral');
|
|
setCard('sum_input_status', 'dot_input_status', data.inputStatus,
|
|
(data.inputStatus === "OK") ? 'ok' : 'err');
|
|
setCard('sum_bitrate', 'dot_bitrate', data.bitrate, 'neutral');
|
|
setCard('sum_temp', 'dot_temp', data.temp,
|
|
(parseFloat(data.temp) >= 160) ? 'err' : 'ok');
|
|
setCard('sum_agc', 'dot_agc', data.agc,
|
|
(data.agc === "On") ? 'ok' : 'off');
|
|
setCard('sum_control', 'dot_control', data.ctrl,
|
|
(data.ctrl.toUpperCase() === "REMOTE") ? 'neutral' : 'warn');
|
|
setCard('sum_rf', 'dot_rf', (data.rfStat === 1) ? "On" : "Off",
|
|
(data.rfStat === 1) ? 'ok' : 'off');
|
|
setCard('sum_outpow', 'dot_outpow', data.finalPower, 'ok');
|
|
};
|
|
|
|
/**
|
|
* Main function to refresh the dashboard
|
|
* Fetches system state and updates all summary cards
|
|
*/
|
|
window.refreshDashboard = function() {
|
|
var queryData = "State_SysState=&sys_rf=&atscmode=&";
|
|
|
|
$.get("atsc_status_cfg.cgi?" + queryData, function(data, status, xhr) {
|
|
// Handle case where data is a JSON object (e.g., session expired)
|
|
if (typeof data === 'object' && data !== null) {
|
|
if (data.error === 'session_expired' && data.redirect) {
|
|
window.location.href = data.redirect;
|
|
return;
|
|
}
|
|
console.error('Received JSON error response instead of expected data:', data);
|
|
return;
|
|
}
|
|
|
|
// Ensure data is a string before attempting to split
|
|
var responseText = typeof data === 'string' ? data : (xhr && xhr.responseText) ? xhr.responseText : String(data || '');
|
|
if (typeof responseText !== 'string') {
|
|
console.error('Dashboard data is not a string:', typeof responseText, responseText);
|
|
return;
|
|
}
|
|
|
|
var table = responseText.split("|");
|
|
if (!Array.isArray(table) || table.length < 2) {
|
|
console.error('Invalid dashboard data format:', responseText);
|
|
return;
|
|
}
|
|
|
|
var form = table[0].split("#");
|
|
if (!Array.isArray(form)) {
|
|
console.error('Invalid form data format:', table[0]);
|
|
return;
|
|
}
|
|
|
|
var rf_form = table[1].split("#");
|
|
if (!Array.isArray(rf_form)) {
|
|
console.error('Invalid rf_form data format:', table[1]);
|
|
return;
|
|
}
|
|
|
|
var atscmod_para = table[2] ? table[2].split("#") : ["", ""];
|
|
if (!Array.isArray(atscmod_para)) {
|
|
console.error('Invalid atscmod_para data format:', table[2]);
|
|
return;
|
|
}
|
|
|
|
// FSSI refresh mode check
|
|
var ab_modenum = Number(form[25]);
|
|
var temp_unit = Number(form[26]);
|
|
|
|
// Frequency
|
|
var chan = Number(form[7]);
|
|
var freqVal = calcFrequency(chan);
|
|
|
|
// SNR: half-dB from the app plus the fixed +10 dB display offset.
|
|
var snr = (ab_modenum === 1) ? "N/A" : (Number(form[11]) / 2 + 10).toFixed(1);
|
|
|
|
// LIMD / UIMD: half-dB from the app plus the fixed +11 dB display offset.
|
|
// Rounding the sum and then appending the half misreports odd half-dB
|
|
// values by 1 dB, so format the sum directly.
|
|
var limd = (ab_modenum === 1) ? "N/A" : (Number(form[12]) / 2 + 11).toFixed(1);
|
|
var uimd = (ab_modenum === 1) ? "N/A" : (Number(form[13]) / 2 + 11).toFixed(1);
|
|
|
|
// Input source
|
|
var inputIdx = Number(form[1]);
|
|
if (inputIdx < 0 || inputIdx > 5) inputIdx = 5;
|
|
var inputSrc = INPUT_SOURCES[inputIdx];
|
|
|
|
// Input status
|
|
var inputStatus = (Number(form[2]) === 0) ? "OK" : "Err";
|
|
|
|
// Bitrate
|
|
var bitrate = form[4];
|
|
|
|
// Temperature with unit conversion
|
|
var temp = convertTemperature(Number(form[5]), temp_unit);
|
|
|
|
// AGC
|
|
var agc = (Number(form[3]) === 0) ? "Off" : "On";
|
|
|
|
// Control
|
|
var ctrl = (Number(form[14]) === 0) ? "Remote" : "Local";
|
|
|
|
// RF Switch
|
|
var rfStat = Number(rf_form[4]);
|
|
|
|
// Output Power
|
|
var p_sign = (Number(rf_form[1]) === 0) ? "+" : "-";
|
|
var p_int = Number(rf_form[2]);
|
|
var p_dec = POWER_DECIMALS[Number(rf_form[3])] || "00";
|
|
var finalPower = p_sign + p_int + "." + p_dec;
|
|
|
|
// Update all cards using the shared function
|
|
window.updateDashboardCards({
|
|
freqVal: freqVal,
|
|
snr: snr,
|
|
limd: limd,
|
|
uimd: uimd,
|
|
inputSrc: inputSrc,
|
|
inputStatus: inputStatus,
|
|
bitrate: bitrate,
|
|
temp: temp,
|
|
agc: agc,
|
|
ctrl: ctrl,
|
|
rfStat: rfStat,
|
|
finalPower: finalPower
|
|
});
|
|
}).fail(function(jqXHR, textStatus, errorThrown) {
|
|
console.error('Failed to fetch dashboard data:', textStatus, errorThrown);
|
|
console.log('Response text:', jqXHR.responseText);
|
|
console.log('Status code:', jqXHR.status);
|
|
});
|
|
};
|
|
|
|
// Export helper functions for status_info.html
|
|
window.DashboardHelpers = {
|
|
calcFrequency: calcFrequency,
|
|
convertTemperature: convertTemperature,
|
|
setCard: setCard,
|
|
getSnrStatus: getSnrStatus,
|
|
getImdStatus: getImdStatus,
|
|
POWER_DECIMALS: POWER_DECIMALS,
|
|
INPUT_SOURCES: INPUT_SOURCES
|
|
};
|
|
|
|
})();
|