/** * 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 }; })();