V125-260722:(暂时发现DPD/FSSI/网页频谱显示都不正常,临时提交)1.合并增加 Web 端 FPGA .mcs 在线升级功能,支持升级进度及错误状态反馈。2.合并优化 FPGA 升级后的恢复流程,实现无需断电的 FPGA 配置、JESD 链路及 RF 热恢复。3.合并重构 ORx 功率、FSSI 和 FWD 计算;4.合并DPD相关优化和调试日志;5.合并IQ 频谱数据接收由 eth1 调整至 eth0,降低对外部网口连接状态的依赖。
@@ -0,0 +1,3 @@
|
|||||||
|
#! /bin/sh
|
||||||
|
. /opt/fsl-imx-x11/4.1.15-2.0.0/environment-setup-cortexa7hf-neon-poky-linux-gnueabi
|
||||||
|
#export C_INCLUDE_PATH=/opt/fsl-imx-x11/4.1.15-2.0.0/sysroots/cortexa7hf-neon-poky-linux-gnueabi/usr/include
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
BKP_FILE=/aw/anywave/cfg/bkp/exc_cfg_bkp.conf
|
||||||
|
if [ -f "$BKP_FILE" ];then
|
||||||
|
cp -v -rf /aw/anywave/cfg/bkp/exc_cfg_bkp.conf /aw/anywave/cfg/bkp/exc_cfg_bbkkpp.conf
|
||||||
|
echo "ccooppyy: exc_cfg_bkp.conf"
|
||||||
|
cp -v -rf /aw/anywave/cfg/bkp/exc_cfg_bkp.conf /aw/anywave/cfg/exc_cfg.conf
|
||||||
|
fi
|
||||||
|
sync
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
CFG_FILE=/aw/anywave/cfg/exc_cfg.conf
|
||||||
|
BKP_FILE=/aw/anywave/cfg/bkp/exc_cfg_bkp.conf
|
||||||
|
if [ -f "$BKP_FILE" ];then
|
||||||
|
cp -v -rf /aw/anywave/cfg/bkp/exc_cfg_bkp.conf /aw/anywave/cfg/bkp/exc_cfg_bkp_bbkkpp.conf
|
||||||
|
rm -rf /aw/anywave/cfg/bkp/exc_cfg_bkp.conf
|
||||||
|
echo "ccooppyy1: exc_cfg_bkp.conf"
|
||||||
|
fi
|
||||||
|
if [ -f "$BKP_FILE" ];then
|
||||||
|
cp -v -rf /aw/anywave/cfg/exc_cfg.conf /aw/anywave/cfg/bkp/exc_cfg_bkp.conf
|
||||||
|
echo "ccooppyy2: exc_cfg.conf"
|
||||||
|
fi
|
||||||
|
sync
|
||||||
@@ -0,0 +1,87 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
## ------------------------------
|
||||||
|
# function :
|
||||||
|
# a. check package *.tar.gz in current dir
|
||||||
|
# b. check package extract tar return value of ret
|
||||||
|
# c. check package runme.sh
|
||||||
|
## ------------------------------
|
||||||
|
# return :
|
||||||
|
## 0 ok
|
||||||
|
## 2 Wrong package
|
||||||
|
## 3 Wrong file extension
|
||||||
|
## ------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
#-- This path has been defined in upload.cgi ,so if want to chang this path, you should chang upload.c .
|
||||||
|
TAR_PACKAGE_PATH="/aw/upgrade"
|
||||||
|
UPGRADE_FILE_PATH="/tmp/upgrade"
|
||||||
|
PROJ_NAME="SMOD"
|
||||||
|
|
||||||
|
|
||||||
|
if [ -d ${UPGRADE_FILE_PATH} ] ; then
|
||||||
|
rm -rf ${UPGRADE_FILE_PATH}
|
||||||
|
fi
|
||||||
|
mkdir -p ${UPGRADE_FILE_PATH}
|
||||||
|
|
||||||
|
|
||||||
|
check_tar=`find ${TAR_PACKAGE_PATH} -name '*.tar.gz'`
|
||||||
|
ret=0
|
||||||
|
|
||||||
|
|
||||||
|
if [ -z ${check_tar} ];then # 字符串长度为0
|
||||||
|
let ret=3
|
||||||
|
else
|
||||||
|
cd ${TAR_PACKAGE_PATH} && ls SMOD*.tar.gz > list.txt
|
||||||
|
|
||||||
|
for TAR in `cat list.txt`
|
||||||
|
do
|
||||||
|
FILE_NAME=${TAR%.*.*}
|
||||||
|
###echo "file name :${FILE_NAME}"
|
||||||
|
###echo "tar -zxf $TAR -C ${UPGRADE_FILE_PATH}/"
|
||||||
|
|
||||||
|
tar -zxf $TAR -C ${UPGRADE_FILE_PATH}/
|
||||||
|
|
||||||
|
extract_tar_ret=$?
|
||||||
|
|
||||||
|
if [ ${extract_tar_ret} != "0" ];then
|
||||||
|
let ret=2
|
||||||
|
else
|
||||||
|
let ret=0
|
||||||
|
fi
|
||||||
|
###echo "extract_tar_pg = ${ret}"
|
||||||
|
done
|
||||||
|
|
||||||
|
rm -rf ${TAR_PACKAGE_PATH}/list.txt
|
||||||
|
rm -rf ${TAR_PACKAGE_PATH}/*.tar.gz
|
||||||
|
|
||||||
|
###echo "ret = ${ret}"
|
||||||
|
if [ ${ret} -eq 0 ];then
|
||||||
|
# check package has runme.sh xxx_cp.sh xxx_remove.sh .
|
||||||
|
# path = /dt_update/aics*/
|
||||||
|
cd ${UPGRADE_FILE_PATH}/${PROJ_NAME}*
|
||||||
|
if [ -f "runme.sh" ];then
|
||||||
|
###echo "runme.sh ok"
|
||||||
|
let ret=0
|
||||||
|
else
|
||||||
|
###echo "no runme.sh "
|
||||||
|
let ret=2
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
if [ ${ret} -ne 0 ];then
|
||||||
|
#echo "rm -rf ./package/*"
|
||||||
|
rm ${TAR_PACKAGE_PATH}/* -rf
|
||||||
|
sync
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo ${ret}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
UPGRADE_FILE_PATH="/tmp/upgrade"
|
||||||
|
|
||||||
|
cd ${UPGRADE_FILE_PATH}/SMOD* && ./runme.sh
|
||||||
|
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
killall http
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
rm -rf /var/module_log.tar.gz
|
||||||
|
cd /var
|
||||||
|
tar -czvf module_log.tar.gz ./module_log
|
||||||
|
|
||||||
|
rm -rf /aw/anywave/web/www/module_log.tar.gz
|
||||||
|
mv -f /var/module_log.tar.gz /aw/anywave/web/www/
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
/aw/anywave/web/bin/http -p 80 -d /aw/anywave/web/www -c *.cgi -t utf-8&
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
anywavecom:anywavecom
|
||||||
|
hhee:hhee
|
||||||
|
|
||||||
@@ -0,0 +1,73 @@
|
|||||||
|
(function() {
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
var CHECK_INTERVAL = 30000;
|
||||||
|
var SESSION_CHECK_URL = 'login.cgi';
|
||||||
|
|
||||||
|
|
||||||
|
function initSessionCheck() {
|
||||||
|
if (window.location.pathname.indexOf('login.html') !== -1) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
checkSession();
|
||||||
|
|
||||||
|
setInterval(checkSession, CHECK_INTERVAL);
|
||||||
|
|
||||||
|
document.addEventListener('mousemove', resetTimer);
|
||||||
|
document.addEventListener('keydown', resetTimer);
|
||||||
|
document.addEventListener('click', resetTimer);
|
||||||
|
}
|
||||||
|
|
||||||
|
function checkSession() {
|
||||||
|
var xhr = new XMLHttpRequest();
|
||||||
|
xhr.open('GET', SESSION_CHECK_URL + '?t=' + Date.now(), true);
|
||||||
|
xhr.setRequestHeader('Cache-Control', 'no-cache');
|
||||||
|
|
||||||
|
xhr.onreadystatechange = function() {
|
||||||
|
if (xhr.readyState === 4) {
|
||||||
|
var response = xhr.responseText || '';
|
||||||
|
|
||||||
|
if (response.indexOf('UNAUTHORIZED') !== -1) {
|
||||||
|
redirectToLogin();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (response.indexOf('OK') !== -1) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
try {
|
||||||
|
xhr.send();
|
||||||
|
} catch (e) {
|
||||||
|
console.log('Session check failed:', e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function redirectToLogin() {
|
||||||
|
var currentUrl = window.location.href;
|
||||||
|
var loginUrl = 'login.html?redirect=' + encodeURIComponent(currentUrl);
|
||||||
|
|
||||||
|
if (window.top !== window.self) {
|
||||||
|
window.top.location.href = loginUrl;
|
||||||
|
} else {
|
||||||
|
window.location.href = loginUrl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var sessionTimer;
|
||||||
|
function resetTimer() {
|
||||||
|
clearTimeout(sessionTimer);
|
||||||
|
sessionTimer = setTimeout(function() {
|
||||||
|
checkSession();
|
||||||
|
}, 60000);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (document.readyState === 'loading') {
|
||||||
|
document.addEventListener('DOMContentLoaded', initSessionCheck);
|
||||||
|
} else {
|
||||||
|
initSessionCheck();
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
After Width: | Height: | Size: 1.1 KiB |
|
After Width: | Height: | Size: 4.4 KiB |
|
After Width: | Height: | Size: 12 KiB |
|
After Width: | Height: | Size: 16 KiB |
@@ -0,0 +1,73 @@
|
|||||||
|
(function() {
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
var CHECK_INTERVAL = 30000;
|
||||||
|
var SESSION_CHECK_URL = 'login.cgi';
|
||||||
|
|
||||||
|
|
||||||
|
function initSessionCheck() {
|
||||||
|
if (window.location.pathname.indexOf('login.html') !== -1) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
checkSession();
|
||||||
|
|
||||||
|
setInterval(checkSession, CHECK_INTERVAL);
|
||||||
|
|
||||||
|
document.addEventListener('mousemove', resetTimer);
|
||||||
|
document.addEventListener('keydown', resetTimer);
|
||||||
|
document.addEventListener('click', resetTimer);
|
||||||
|
}
|
||||||
|
|
||||||
|
function checkSession() {
|
||||||
|
var xhr = new XMLHttpRequest();
|
||||||
|
xhr.open('GET', SESSION_CHECK_URL + '?t=' + Date.now(), true);
|
||||||
|
xhr.setRequestHeader('Cache-Control', 'no-cache');
|
||||||
|
|
||||||
|
xhr.onreadystatechange = function() {
|
||||||
|
if (xhr.readyState === 4) {
|
||||||
|
var response = xhr.responseText || '';
|
||||||
|
|
||||||
|
if (response.indexOf('UNAUTHORIZED') !== -1) {
|
||||||
|
redirectToLogin();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (response.indexOf('OK') !== -1) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
try {
|
||||||
|
xhr.send();
|
||||||
|
} catch (e) {
|
||||||
|
console.log('Session check failed:', e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function redirectToLogin() {
|
||||||
|
var currentUrl = window.location.href;
|
||||||
|
var loginUrl = 'login.html?redirect=' + encodeURIComponent(currentUrl);
|
||||||
|
|
||||||
|
if (window.top !== window.self) {
|
||||||
|
window.top.location.href = loginUrl;
|
||||||
|
} else {
|
||||||
|
window.location.href = loginUrl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var sessionTimer;
|
||||||
|
function resetTimer() {
|
||||||
|
clearTimeout(sessionTimer);
|
||||||
|
sessionTimer = setTimeout(function() {
|
||||||
|
checkSession();
|
||||||
|
}, 60000);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (document.readyState === 'loading') {
|
||||||
|
document.addEventListener('DOMContentLoaded', initSessionCheck);
|
||||||
|
} else {
|
||||||
|
initSessionCheck();
|
||||||
|
}
|
||||||
|
})();
|
||||||
@@ -0,0 +1,260 @@
|
|||||||
|
/**
|
||||||
|
* 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
|
||||||
|
};
|
||||||
|
|
||||||
|
})();
|
||||||
@@ -0,0 +1,538 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title id="webtitle"></title>
|
||||||
|
<link href="css/styles.css" rel="stylesheet" media="screen">
|
||||||
|
<script src="js/auth.js"></script>
|
||||||
|
<script src="js/jquery.js"></script>
|
||||||
|
<script src="js/dashboard.js"></script>
|
||||||
|
<script>
|
||||||
|
var lastTime = new Date().getTime();
|
||||||
|
var currentTime = new Date().getTime();
|
||||||
|
var timeOut = 20 * 60 * 1000; // 20 minutes
|
||||||
|
|
||||||
|
$(function(){
|
||||||
|
// Listen to multiple types of user activity to prevent timeout
|
||||||
|
$(document).on('mousemove keydown click scroll touchstart', function(){
|
||||||
|
lastTime = new Date().getTime();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
function testTime(){
|
||||||
|
currentTime = new Date().getTime();
|
||||||
|
if(currentTime - lastTime > timeOut){
|
||||||
|
window.location.href="login.cgi?logout=1";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Timer check (1 second interval)
|
||||||
|
window.setInterval(testTime, 1000);
|
||||||
|
// Dashboard refresh (3 second interval)
|
||||||
|
setInterval(refreshDashboard, 3000);
|
||||||
|
|
||||||
|
function get_remote_local_ctrl()
|
||||||
|
{
|
||||||
|
var queryData = "sys_cfg=&";
|
||||||
|
$.get("atsc_status_cfg.cgi?"+queryData,function(data, status) {
|
||||||
|
// 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:', data);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var table = data.split("|");
|
||||||
|
// g_remot_local_ctrl = Number(table[0].split("#")[5]);
|
||||||
|
// document.title = table[0].split("#")[11];
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function refresh_show(){
|
||||||
|
//get_remote_local_ctrl();
|
||||||
|
SetFormDefaults();
|
||||||
|
refreshDashboard();
|
||||||
|
}
|
||||||
|
|
||||||
|
function SetFormDefaults()
|
||||||
|
{
|
||||||
|
// 1. DISABLE BUTTON START (Optional safety, though HTML handles initial load)
|
||||||
|
$('#get_log_btn').attr("disabled", true).val("Loading...");
|
||||||
|
// Placeholder for future initialization logic
|
||||||
|
var queryData = "web_title=&";
|
||||||
|
$.get("atsc_status_cfg.cgi?"+queryData,function(data, status) {
|
||||||
|
// 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:', data);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var table = data.split("|");
|
||||||
|
var title = table[0].split("#");
|
||||||
|
|
||||||
|
// 2. RE-ENABLE BUTTON END
|
||||||
|
$('#get_log_btn').attr("disabled", false).val("Get");
|
||||||
|
|
||||||
|
document.getElementById('webtitle').textContent = title[1];
|
||||||
|
document.getElementById('webtitle_header').textContent = title[1];
|
||||||
|
}).fail(function() {
|
||||||
|
// Optional: Error handling
|
||||||
|
$('#get_log_btn').val("Load Failed");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function cmd_confirm()
|
||||||
|
{
|
||||||
|
return confirm("Please be patient, log data is being collected!");
|
||||||
|
}
|
||||||
|
|
||||||
|
function log_download_show()
|
||||||
|
{
|
||||||
|
document.getElementById("id_download").style.visibility="visible";
|
||||||
|
}
|
||||||
|
|
||||||
|
function Get_Log_File()
|
||||||
|
{
|
||||||
|
if(cmd_confirm()){
|
||||||
|
var queryData = "log_output=&";
|
||||||
|
$.get("atsc_status_cfg.cgi?"+queryData,function(data, status) {
|
||||||
|
// 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:', data);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var table = data.split("|");
|
||||||
|
var form0 = table[0].split("#");
|
||||||
|
var ret_log = form0[1];
|
||||||
|
|
||||||
|
if(ret_log == 999){
|
||||||
|
setTimeout(log_download_show, 2000);
|
||||||
|
} else {
|
||||||
|
alert("Log generation failed or system busy. Code: " + ret_log);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Opens the modal - gets current username from server
|
||||||
|
function openAccountModal() {
|
||||||
|
// Fetch current username from server
|
||||||
|
$.get("login.cgi?action=get_user", function(data) {
|
||||||
|
var trimmedData = (data || "").trim();
|
||||||
|
if (trimmedData && trimmedData !== "UNAUTHORIZED") {
|
||||||
|
document.getElementById('current_user').value = trimmedData;
|
||||||
|
}
|
||||||
|
document.getElementById('accountModal').style.display = 'block';
|
||||||
|
setTimeout(function() { document.getElementById('current_pwd').focus(); }, 100);
|
||||||
|
}).fail(function() {
|
||||||
|
document.getElementById('accountModal').style.display = 'block';
|
||||||
|
setTimeout(function() { document.getElementById('current_pwd').focus(); }, 100);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Closes the modal and clears the sensitive inputs
|
||||||
|
function closeAccountModal() {
|
||||||
|
document.getElementById('accountModal').style.display = 'none';
|
||||||
|
document.getElementById('current_pwd').value = '';
|
||||||
|
document.getElementById('new_pwd').value = '';
|
||||||
|
document.getElementById('confirm_pwd').value = '';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validates that a string contains only printable characters (excluding space)
|
||||||
|
function isValidPrintableString(str) {
|
||||||
|
// Regular expression to check for printable characters (ASCII 33-126), excluding space
|
||||||
|
// Space is ASCII 32, and we want to exclude it
|
||||||
|
var printableCharRegex = /^[!-~]+$/; // ! is ASCII 33, ~ is ASCII 126
|
||||||
|
return printableCharRegex.test(str);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validates the passwords match before submitting to the CGI script - All required fields must be filled
|
||||||
|
function validateAccountForm() {
|
||||||
|
var currentUser = document.getElementById('current_user').value;
|
||||||
|
var currentPwd = document.getElementById('current_pwd').value;
|
||||||
|
var newUsername = document.getElementById('new_user').value;
|
||||||
|
var newPwd = document.getElementById('new_pwd').value;
|
||||||
|
var confirmPwd = document.getElementById('confirm_pwd').value;
|
||||||
|
|
||||||
|
// Current password is required (cannot be empty)
|
||||||
|
if (!currentPwd || currentPwd.trim() === "") {
|
||||||
|
alert("Current password is required");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate current password contains only printable characters
|
||||||
|
if (!isValidPrintableString(currentPwd)) {
|
||||||
|
alert("Current password contains invalid characters. Only printable characters (excluding space) are allowed.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// New password is required (cannot be empty)
|
||||||
|
if (!newPwd || newPwd.trim() === "") {
|
||||||
|
alert("New password is required");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate new password contains only printable characters
|
||||||
|
if (!isValidPrintableString(newPwd)) {
|
||||||
|
alert("New password contains invalid characters. Only printable characters (excluding space) are allowed.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate new password length (max 16 chars)
|
||||||
|
if (newPwd.length > 16) {
|
||||||
|
alert("New password must be no more than 16 characters");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate new password length
|
||||||
|
if (newPwd.length < 6) {
|
||||||
|
alert("New password must be at least 6 characters");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Confirm password must match new password
|
||||||
|
if (newPwd !== confirmPwd) {
|
||||||
|
alert("New passwords do not match");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate confirm password contains only printable characters
|
||||||
|
if (!isValidPrintableString(confirmPwd)) {
|
||||||
|
alert("Confirm password contains invalid characters. Only printable characters (excluding space) are allowed.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate confirm password length (max 16 chars)
|
||||||
|
if (confirmPwd.length > 16) {
|
||||||
|
alert("Confirm password must be no more than 16 characters");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate new username if provided
|
||||||
|
if (newUsername && newUsername.trim() !== "") {
|
||||||
|
// Validate new username contains only printable characters
|
||||||
|
if (!isValidPrintableString(newUsername)) {
|
||||||
|
alert("New username contains invalid characters. Only printable characters (excluding space) are allowed.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate new username length (max 16 chars)
|
||||||
|
if (newUsername.length > 16) {
|
||||||
|
alert("New username must be no more than 16 characters");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true; // Allows the form to submit
|
||||||
|
}
|
||||||
|
|
||||||
|
// Form submission handler using fetch API
|
||||||
|
document.addEventListener('DOMContentLoaded', function() {
|
||||||
|
var accountForm = document.getElementById('accountForm');
|
||||||
|
if (accountForm) {
|
||||||
|
accountForm.addEventListener('submit', function(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
|
||||||
|
if (!validateAccountForm()) return;
|
||||||
|
|
||||||
|
var formData = new URLSearchParams({
|
||||||
|
Username: document.getElementById('current_user').value,
|
||||||
|
OldPassword: document.getElementById('current_pwd').value,
|
||||||
|
NewUsername: document.getElementById('new_user').value,
|
||||||
|
NewPassword: document.getElementById('new_pwd').value,
|
||||||
|
ConfirmPassword: document.getElementById('confirm_pwd').value
|
||||||
|
});
|
||||||
|
|
||||||
|
fetch('login.cgi?action=change_account', {
|
||||||
|
method: 'POST',
|
||||||
|
body: formData
|
||||||
|
})
|
||||||
|
.then(r => r.json())
|
||||||
|
.then(data => {
|
||||||
|
if (data.success) {
|
||||||
|
alert("Update successful! Please login again.");
|
||||||
|
closeAccountModal();
|
||||||
|
// Redirect to login page after 1.5 seconds
|
||||||
|
setTimeout(function() {
|
||||||
|
window.location.href = 'login.cgi?logout=1';
|
||||||
|
}, 1500);
|
||||||
|
} else {
|
||||||
|
alert(data.error || "Update failed");
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(function(err) {
|
||||||
|
alert("Network error: " + err);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Optional: Closes the modal if the user clicks the dark background outside the box
|
||||||
|
window.onclick = function(event) {
|
||||||
|
var modal = document.getElementById('accountModal');
|
||||||
|
if (event.target == modal) {
|
||||||
|
closeAccountModal();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
</script>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body onload="refresh_show()">
|
||||||
|
|
||||||
|
<div class="app-layout">
|
||||||
|
<aside class="app-sidebar">
|
||||||
|
<ul class="items">
|
||||||
|
<li><a href="status_info.html" title="Status">Status</a></li>
|
||||||
|
<li><a href="sys_set.html" title="Settings">Settings</a></li>
|
||||||
|
<li><a href="sys_rf.html" title="RF Control">RF Control</a></li>
|
||||||
|
<li><a href="sys_psip.html" title="TSID&PSIP">TSID&PSIP</a></li>
|
||||||
|
<li><a href="sys_ts.html" title="TSoIP">TSoIP</a></li>
|
||||||
|
<li><a href="sys_spectrum.html" title="Spectrum">Spectrum</a></li>
|
||||||
|
<li class="active"><a href="log_output.html" title="Log">Log</a></li>
|
||||||
|
</ul>
|
||||||
|
<div class="sidebar-footer">
|
||||||
|
<h4>Anywave Broadcast Inc.</h4>
|
||||||
|
<p>Copyright 2026<br><br><span class="redbox-label">Technical Support</span><br>+1 847 415 2258<br><a href="mailto:support@anywaveus.com">support@anywaveus.com</a></p>
|
||||||
|
</div>
|
||||||
|
</aside>
|
||||||
|
<div class="sidebar-overlay" onclick="toggleSidebar()"></div>
|
||||||
|
|
||||||
|
<header class="app-header">
|
||||||
|
<button class="menu-toggle" onclick="toggleSidebar()" aria-label="Toggle menu">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||||
|
<line x1="3" y1="12" x2="21" y2="12"></line>
|
||||||
|
<line x1="3" y1="6" x2="21" y2="6"></line>
|
||||||
|
<line x1="3" y1="18" x2="21" y2="18"></line>
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
<h1><a href="https://anywavecom.net/" class="logo-bg" title="Anywave Broadcast Inc."></a></h1>
|
||||||
|
<h2 id="webtitle_header"><span></span></h2>
|
||||||
|
<h3>
|
||||||
|
<div class="dropdown">
|
||||||
|
<button class="dropbtn-modern">Admin ▾</button>
|
||||||
|
<div class="dropdown-content">
|
||||||
|
<a href="#" onclick="openAccountModal(); return false;">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||||
|
<circle cx="12" cy="12" r="3"></circle>
|
||||||
|
<path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1 0 2.83 2 2 0 0 1-2.83 0l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-2 2 2 2 0 0 1-2-2v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06-.06a2 2 0 0 1-2.83 0 2 2 0 0 1 0-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1-2-2 2 2 0 0 1 2-2h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 0-2.83 2 2 0 0 1 2.83 0l.06-.06a1.65 1.65 0 0 0 1.82.33H9a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 2-2 2 2 0 0 1 2 2v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 0 2 2 0 0 1 0 2.83l-.06-.06a1.65 1.65 0 0 0-.33 1.82V9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 2 2 2 2 0 0 1-2 2h-.09a1.65 1.65 0 0 0-1.51 1z"></path>
|
||||||
|
</svg>
|
||||||
|
Account Settings
|
||||||
|
</a>
|
||||||
|
<a href="login.cgi?logout=1">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||||
|
<path d="M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4"></path>
|
||||||
|
<polyline points="16 17 21 12 16 7"></polyline>
|
||||||
|
<line x1="21" y1="12" x2="9" y2="12"></line>
|
||||||
|
</svg>
|
||||||
|
Logout
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</h3>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<!-- Fixed Dashboard Summary - Top of page, under header -->
|
||||||
|
<div class="dashboard-fixed">
|
||||||
|
<div class="summary-dashboard">
|
||||||
|
<div class="summary-card">
|
||||||
|
<div class="summary-label-row">
|
||||||
|
<span class="status-dot status-neutral" id="dot_freq" aria-hidden="true"></span>
|
||||||
|
<span class="summary-label">Frequency</span>
|
||||||
|
</div>
|
||||||
|
<div class="summary-value-wrapper">
|
||||||
|
<span class="summary-value value-neutral" id="sum_freq">--</span>
|
||||||
|
<span class="summary-unit">MHz</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="summary-card">
|
||||||
|
<div class="summary-label-row">
|
||||||
|
<span class="status-dot status-ok" id="dot_snr" aria-hidden="true"></span>
|
||||||
|
<span class="summary-label">SNR</span>
|
||||||
|
</div>
|
||||||
|
<div class="summary-value-wrapper">
|
||||||
|
<span class="summary-value value-ok" id="sum_snr">--</span>
|
||||||
|
<span class="summary-unit">dB</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="summary-card">
|
||||||
|
<div class="summary-label-row">
|
||||||
|
<span class="status-dot status-ok" id="dot_uimd" aria-hidden="true"></span>
|
||||||
|
<span class="summary-label">UIMD</span>
|
||||||
|
</div>
|
||||||
|
<div class="summary-value-wrapper">
|
||||||
|
<span class="summary-value value-ok" id="sum_uimd">--</span>
|
||||||
|
<span class="summary-unit">dBc</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="summary-card">
|
||||||
|
<div class="summary-label-row">
|
||||||
|
<span class="status-dot status-ok" id="dot_limd" aria-hidden="true"></span>
|
||||||
|
<span class="summary-label">LIMD</span>
|
||||||
|
</div>
|
||||||
|
<div class="summary-value-wrapper">
|
||||||
|
<span class="summary-value value-ok" id="sum_limd">--</span>
|
||||||
|
<span class="summary-unit">dBc</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="summary-card">
|
||||||
|
<div class="summary-label-row">
|
||||||
|
<span class="status-dot status-off" id="dot_rf" aria-hidden="true"></span>
|
||||||
|
<span class="summary-label">RF Switch</span>
|
||||||
|
</div>
|
||||||
|
<div class="summary-value-wrapper">
|
||||||
|
<span class="summary-value value-muted" id="sum_rf">--</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="summary-card">
|
||||||
|
<div class="summary-label-row">
|
||||||
|
<span class="status-dot status-ok" id="dot_outpow" aria-hidden="true"></span>
|
||||||
|
<span class="summary-label">Output Power</span>
|
||||||
|
</div>
|
||||||
|
<div class="summary-value-wrapper">
|
||||||
|
<span class="summary-value value-ok" id="sum_outpow">--</span>
|
||||||
|
<span class="summary-unit">dBm</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="summary-card">
|
||||||
|
<div class="summary-label-row">
|
||||||
|
<span class="status-dot status-neutral" id="dot_input" aria-hidden="true"></span>
|
||||||
|
<span class="summary-label">Input Source</span>
|
||||||
|
</div>
|
||||||
|
<div class="summary-value-wrapper">
|
||||||
|
<span class="summary-value value-neutral" id="sum_input">--</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="summary-card">
|
||||||
|
<div class="summary-label-row">
|
||||||
|
<span class="status-dot status-neutral" id="dot_input_status" aria-hidden="true"></span>
|
||||||
|
<span class="summary-label">Input Status</span>
|
||||||
|
</div>
|
||||||
|
<div class="summary-value-wrapper">
|
||||||
|
<span class="summary-value value-neutral" id="sum_input_status">--</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="summary-card">
|
||||||
|
<div class="summary-label-row">
|
||||||
|
<span class="status-dot status-neutral" id="dot_bitrate" aria-hidden="true"></span>
|
||||||
|
<span class="summary-label">Bitrate</span>
|
||||||
|
</div>
|
||||||
|
<div class="summary-value-wrapper">
|
||||||
|
<span class="summary-value value-neutral" id="sum_bitrate">--</span>
|
||||||
|
<span class="summary-unit">Mbps</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="summary-card">
|
||||||
|
<div class="summary-label-row">
|
||||||
|
<span class="status-dot status-ok" id="dot_temp" aria-hidden="true"></span>
|
||||||
|
<span class="summary-label">Temperature</span>
|
||||||
|
</div>
|
||||||
|
<div class="summary-value-wrapper">
|
||||||
|
<span class="summary-value value-ok" id="sum_temp">--</span>
|
||||||
|
<span class="summary-unit">°F</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="summary-card">
|
||||||
|
<div class="summary-label-row">
|
||||||
|
<span class="status-dot status-off" id="dot_agc" aria-hidden="true"></span>
|
||||||
|
<span class="summary-label">AGC</span>
|
||||||
|
</div>
|
||||||
|
<div class="summary-value-wrapper">
|
||||||
|
<span class="summary-value value-muted" id="sum_agc">--</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="summary-card">
|
||||||
|
<div class="summary-label-row">
|
||||||
|
<span class="status-dot status-neutral" id="dot_control" aria-hidden="true"></span>
|
||||||
|
<span class="summary-label">Control</span>
|
||||||
|
</div>
|
||||||
|
<div class="summary-value-wrapper">
|
||||||
|
<span class="summary-value value-neutral" id="sum_control">--</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<main class="app-main">
|
||||||
|
<h2>Output Log</h2>
|
||||||
|
<div class="box log-export-box">
|
||||||
|
<table>
|
||||||
|
<tr>
|
||||||
|
<td class="log-export-label">
|
||||||
|
Export System Log
|
||||||
|
</td>
|
||||||
|
<td class="log-export-actions">
|
||||||
|
<input type="button" class="btn-modern" id="get_log_btn" alt="GET" value="Get" disabled onclick="return Get_Log_File();">
|
||||||
|
<a href="/module_log.zip" download="module_log.zip">
|
||||||
|
<input type="button" class="btn-modern" style="visibility:hidden;" id="id_download" alt="DOWNLOAD" value="Download">
|
||||||
|
</a>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</main>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="accountModal" class="modal">
|
||||||
|
<div class="modal-content">
|
||||||
|
<div class="modal-header">
|
||||||
|
<h3>Account Settings</h3>
|
||||||
|
<span class="close" onclick="closeAccountModal()">×</span>
|
||||||
|
</div>
|
||||||
|
<div class="modal-body">
|
||||||
|
<form id="accountForm" method="post" action="login.cgi?action=change_account" onsubmit="return validateAccountForm()">
|
||||||
|
<table class="modal-table">
|
||||||
|
<tr>
|
||||||
|
<td>Current Username</td>
|
||||||
|
<td><input type="text" id="current_user" name="current_user" readonly></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Current Password</td>
|
||||||
|
<td><input type="password" id="current_pwd" name="current_pwd" required></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>New Username</td>
|
||||||
|
<td><input type="text" id="new_user" name="new_user"></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>New Password</td>
|
||||||
|
<td><input type="password" id="new_pwd" name="new_pwd"></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Confirm Password</td>
|
||||||
|
<td><input type="password" id="confirm_pwd" name="confirm_pwd"></td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
<div class="modal-footer">
|
||||||
|
<input type="button" class="btn-modern" style="background-color: #64748b;" value="Cancel" onclick="closeAccountModal()">
|
||||||
|
<input type="submit" class="btn-modern" value="Save Changes">
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
function toggleSidebar(){
|
||||||
|
document.querySelector('.app-sidebar').classList.toggle('sidebar-open');
|
||||||
|
document.querySelector('.sidebar-overlay').classList.toggle('active');
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -0,0 +1,113 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title id="webtitle"></title>
|
||||||
|
<link href="css/styles.css" rel="stylesheet" media="screen">
|
||||||
|
<style>
|
||||||
|
#content .box table td:first-child {
|
||||||
|
width: 45%;
|
||||||
|
min-width: 200px;
|
||||||
|
max-width: none;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<script src="js/jquery.js"></script>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
function checkUser(){
|
||||||
|
var result = document.getElementById("username_id").value;
|
||||||
|
var password = document.getElementById("pwd_id").value;
|
||||||
|
|
||||||
|
if(result == ""){
|
||||||
|
alert("User name cannot be empty!");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(password == ""){
|
||||||
|
alert("Password cannot be empty!");
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function loginsubmit() {
|
||||||
|
if(checkUser() == false){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
document.getElementById('loginformid').submit();
|
||||||
|
}
|
||||||
|
|
||||||
|
function refresh_show(){
|
||||||
|
var queryData = "web_title=&"
|
||||||
|
$.get("atsc_status_cfg.cgi?"+queryData, function(data, status) {
|
||||||
|
var table = data.split("|");
|
||||||
|
var title = table[0].split("#");
|
||||||
|
document.getElementById('webtitle').textContent = title[1];
|
||||||
|
document.getElementById('webtitle_header').textContent = title[1];
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
</script>
|
||||||
|
</head>
|
||||||
|
<body onload="refresh_show()">
|
||||||
|
<div class="app-layout">
|
||||||
|
<aside class="app-sidebar">
|
||||||
|
<ul class="items">
|
||||||
|
<li class="active"><a href="login.html" title="Login">Login</a></li>
|
||||||
|
</ul>
|
||||||
|
<div class="sidebar-footer">
|
||||||
|
<h4>Anywave Broadcast Inc.</h4>
|
||||||
|
<p>Copyright 2026<br><br><span class="redbox-label">Technical Support</span><br>+1 847 415 2258<br><a href="mailto:support@anywaveus.com">support@anywaveus.com</a></p>
|
||||||
|
</div>
|
||||||
|
</aside>
|
||||||
|
<div class="sidebar-overlay" onclick="toggleSidebar()"></div>
|
||||||
|
|
||||||
|
<header class="app-header">
|
||||||
|
<button class="menu-toggle" onclick="toggleSidebar()" aria-label="Toggle menu">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||||
|
<line x1="3" y1="12" x2="21" y2="12"></line>
|
||||||
|
<line x1="3" y1="6" x2="21" y2="6"></line>
|
||||||
|
<line x1="3" y1="18" x2="21" y2="18"></line>
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
<h1><a href="https://anywavecom.net/" class="logo-bg" title="Anywave Broadcast Inc."></a></h1>
|
||||||
|
<h2 id="webtitle_header"><span></span></h2>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<main class="app-main">
|
||||||
|
<div class="login-container">
|
||||||
|
<div class="login-box">
|
||||||
|
<h2>Login</h2>
|
||||||
|
<div class="box">
|
||||||
|
<form method="post" action="login.cgi" name="loginformname" id="loginformid">
|
||||||
|
<table>
|
||||||
|
<tr>
|
||||||
|
<td>User Name</td>
|
||||||
|
<td><input type="text" name="Username" style="max-width: 150px;" id="username_id" value="" size="12" maxlength="12"></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Password</td>
|
||||||
|
<td><input type="password" name="Password" style="max-width: 150px;" id="pwd_id" value="" size="12" maxlength="12"></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td></td>
|
||||||
|
<td><input type="button" class="btn-modern" alt="Up" value="Login" id="loginid" onclick="loginsubmit();"></td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</main>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
function toggleSidebar(){
|
||||||
|
document.querySelector('.app-sidebar').classList.toggle('sidebar-open');
|
||||||
|
document.querySelector('.sidebar-overlay').classList.toggle('active');
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
./com-status-process
|
||||||
|
./boot-limit-process
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
killall -9 com-status-process
|
||||||
|
killall -9 boot-limit-process
|
||||||
@@ -0,0 +1,847 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title id="webtitle"></title>
|
||||||
|
<link href="css/styles.css" rel="stylesheet" media="screen">
|
||||||
|
<script src="js/auth.js"></script>
|
||||||
|
<script src="js/jquery.js"></script>
|
||||||
|
<script src="js/dashboard.js"></script>
|
||||||
|
<script>
|
||||||
|
var time_sec_cnt=0;
|
||||||
|
var g_remot_local_ctrl = 0; // 0 remote 1 local
|
||||||
|
var lastTime = new Date().getTime();
|
||||||
|
var currentTime = new Date().getTime();
|
||||||
|
var timeOut = 20 * 60 * 1000; // 20 min
|
||||||
|
|
||||||
|
$(function(){
|
||||||
|
// Listen to multiple types of user activity to prevent timeout
|
||||||
|
$(document).on('mousemove keydown click scroll touchstart', function(){
|
||||||
|
lastTime = new Date().getTime();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
function testTime(){
|
||||||
|
currentTime = new Date().getTime();
|
||||||
|
if(currentTime - lastTime > timeOut){
|
||||||
|
window.location.href="login.cgi?logout=1"
|
||||||
|
}
|
||||||
|
|
||||||
|
time_sec_cnt=time_sec_cnt+1;
|
||||||
|
if(time_sec_cnt%3==0){
|
||||||
|
get_remote_local_ctrl();
|
||||||
|
if(g_remot_local_ctrl==1) { // local
|
||||||
|
SetFormDefaults();
|
||||||
|
}
|
||||||
|
refreshDashboard();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Timer check
|
||||||
|
window.setInterval(testTime, 1000);
|
||||||
|
refreshDashboard();
|
||||||
|
|
||||||
|
function get_remote_local_ctrl() {
|
||||||
|
var queryData = "sys_cfg=&";
|
||||||
|
$.get("atsc_status_cfg.cgi?"+queryData, function(data, status) {
|
||||||
|
// 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:', data);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var table = data.split("|");
|
||||||
|
g_remot_local_ctrl = Number(table[0].split("#")[5]);
|
||||||
|
document.title = table[0].split("#")[11];
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Updated SetFormDefaults to populate the Single Form
|
||||||
|
function SetFormDefaults() {
|
||||||
|
// 1. DISABLE BUTTONS START (only in Remote mode)
|
||||||
|
if(g_remot_local_ctrl == 1) {
|
||||||
|
// Local mode: just fetch data, don't change button text
|
||||||
|
var queryData = "tsid_psip=&psip_cfg=&web_title=&";
|
||||||
|
} else {
|
||||||
|
// Remote mode: show LOADING indicator
|
||||||
|
$('#tsid_form input[type="button"], #psip_table_form input[type="button"]')
|
||||||
|
.attr("disabled", true)
|
||||||
|
.val("LOADING...");
|
||||||
|
var queryData = "tsid_psip=&psip_cfg=&web_title=&";
|
||||||
|
}
|
||||||
|
$.get("atsc_status_cfg.cgi?" + queryData, function(data, status) {
|
||||||
|
// 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:', data);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var table = data.split("|");
|
||||||
|
var form = table[0].split("#");
|
||||||
|
var title= table[1].split("#");
|
||||||
|
|
||||||
|
// 1. Handle Top Settings (Form 0)
|
||||||
|
var cf = document.getElementById("tsid_form");
|
||||||
|
var i = 1;
|
||||||
|
cf.ts_edit.value = form[i++];
|
||||||
|
cf.tsid.value = form[i++];
|
||||||
|
var index_max = Number(form[i++]);
|
||||||
|
|
||||||
|
// 2. Handle PSIP Table (Form 1 - The new single form)
|
||||||
|
var psipForm = document.getElementById("psip_table_form");
|
||||||
|
|
||||||
|
// Loop through all 13 potential rows (0 to 12)
|
||||||
|
for (var k = 0; k < 13; k++) {
|
||||||
|
// Populate inputs by name (e.g., "index0", "sht_name0")
|
||||||
|
if(psipForm.elements['index' + k]) {
|
||||||
|
psipForm.elements['index' + k].value = form[i++];
|
||||||
|
psipForm.elements['sht_name' + k].value = form[i++];
|
||||||
|
psipForm.elements['maj_num' + k].value = form[i++];
|
||||||
|
psipForm.elements['min_num' + k].value = form[i++];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Hide unused rows
|
||||||
|
var row = document.getElementById("psip" + k);
|
||||||
|
if (row) {
|
||||||
|
if (k >= index_max && k != 0) {
|
||||||
|
row.style.display = "none";
|
||||||
|
} else {
|
||||||
|
row.style.display = "table-row"; // Ensure visible rows display correctly
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 2. RE-ENABLE BUTTONS END (only in Remote mode)
|
||||||
|
if(g_remot_local_ctrl == 1) {
|
||||||
|
// Local mode: keep buttons disabled
|
||||||
|
$('#tsid_form input[type="button"], #psip_table_form input[type="button"]')
|
||||||
|
.attr("disabled", true)
|
||||||
|
.val("Local Mode");
|
||||||
|
} else {
|
||||||
|
// Remote mode: enable buttons
|
||||||
|
$('#tsid_form input[type="button"], #psip_table_form input[type="button"]')
|
||||||
|
.attr("disabled", false)
|
||||||
|
.val("Set");
|
||||||
|
}
|
||||||
|
if (typeof setTsidFormSnapshotUpdate === 'function') setTsidFormSnapshotUpdate();
|
||||||
|
if (typeof psipFormSnapshotUpdate === 'function') psipFormSnapshotUpdate();
|
||||||
|
|
||||||
|
document.getElementById('webtitle').textContent = title[1];
|
||||||
|
document.getElementById('webtitle_header').textContent = title[1];
|
||||||
|
}).fail(function() {
|
||||||
|
// Optional: Error handling
|
||||||
|
$('#tsid_form input[type="button"], #psip_table_form input[type="button"]').val("LOAD FAILED");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----- SET (unsaved) reminder: tsid_form (per-row: CTRL vs TSID) + psip_table_form (per-row), vanilla JS -----
|
||||||
|
var tsidFormSnapshotPerRow = [];
|
||||||
|
function getFormSnapshot(formId) {
|
||||||
|
var f = document.getElementById(formId);
|
||||||
|
if (!f) return [];
|
||||||
|
var out = [], els = f.querySelectorAll('select, input:not([type="button"])'), i, el, v;
|
||||||
|
for (i = 0; i < els.length; i++) {
|
||||||
|
el = els[i];
|
||||||
|
v = el.tagName === 'SELECT' ? (el.options[el.selectedIndex] ? el.options[el.selectedIndex].value : '') : (el.value || '');
|
||||||
|
out.push({ name: el.name || el.id, value: String(v) });
|
||||||
|
}
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
function getFormSnapshotPerRowTsid(formId) {
|
||||||
|
var f = document.getElementById(formId);
|
||||||
|
if (!f) return [];
|
||||||
|
var rows = f.querySelectorAll('table tr'), out = [], i;
|
||||||
|
for (i = 0; i < rows.length; i++) {
|
||||||
|
if (rows[i].querySelector('input[type="button"]')) out.push(getRowValues(rows[i]));
|
||||||
|
}
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
function setTsidRowButtonState(tr, unsaved) {
|
||||||
|
var btn = tr.querySelector('input[type="button"]');
|
||||||
|
if (!btn || btn.disabled) return;
|
||||||
|
btn.value = unsaved ? 'Set (unsaved)' : 'Set';
|
||||||
|
if (unsaved) btn.classList.add('is-unsaved'); else btn.classList.remove('is-unsaved');
|
||||||
|
}
|
||||||
|
function setTsidFormSnapshotUpdate() {
|
||||||
|
var f = document.getElementById('tsid_form');
|
||||||
|
if (f) tsidFormSnapshotPerRow = getFormSnapshotPerRowTsid('tsid_form');
|
||||||
|
f = document.getElementById('tsid_form');
|
||||||
|
if (f) {
|
||||||
|
var rows = f.querySelectorAll('table tr');
|
||||||
|
for (var i = 0; i < rows.length; i++) {
|
||||||
|
if (rows[i].querySelector('input[type="button"]')) setTsidRowButtonState(rows[i], false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function updateTsidFormRowButtonStates() {
|
||||||
|
var f = document.getElementById('tsid_form');
|
||||||
|
if (!f || !tsidFormSnapshotPerRow.length) return;
|
||||||
|
var rows = f.querySelectorAll('table tr');
|
||||||
|
var rowIdx = 0;
|
||||||
|
for (var i = 0; i < rows.length; i++) {
|
||||||
|
if (!rows[i].querySelector('input[type="button"]')) continue;
|
||||||
|
var dirty = rowIdx < tsidFormSnapshotPerRow.length && isRowDirty(getRowValues(rows[i]), tsidFormSnapshotPerRow[rowIdx]);
|
||||||
|
setTsidRowButtonState(rows[i], dirty);
|
||||||
|
rowIdx++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var psipFormSnapshotPerRow = [];
|
||||||
|
function getRowValues(tr) {
|
||||||
|
var out = [], els = tr.querySelectorAll('select, input:not([type="button"])'), i, el, v;
|
||||||
|
for (i = 0; i < els.length; i++) {
|
||||||
|
el = els[i];
|
||||||
|
v = el.tagName === 'SELECT' ? (el.options[el.selectedIndex] ? el.options[el.selectedIndex].value : '') : (el.value || '');
|
||||||
|
out.push({ name: el.name || el.id, value: String(v) });
|
||||||
|
}
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
function getFormSnapshotPerRow(formId) {
|
||||||
|
var f = document.getElementById(formId);
|
||||||
|
if (!f) return [];
|
||||||
|
var rows = f.querySelectorAll('table tr'), out = [], i;
|
||||||
|
for (i = 0; i < rows.length; i++) {
|
||||||
|
if (rows[i].querySelector('input[type="button"]')) out.push(getRowValues(rows[i]));
|
||||||
|
}
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
function isRowDirty(rowValues, rowSnapshot) {
|
||||||
|
if (rowValues.length !== rowSnapshot.length) return true;
|
||||||
|
for (var i = 0; i < rowValues.length; i++) {
|
||||||
|
if (rowValues[i].name !== rowSnapshot[i].name || rowValues[i].value !== rowSnapshot[i].value) return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
function setPsipRowButtonState(tr, unsaved) {
|
||||||
|
var btn = tr.querySelector('input[type="button"]');
|
||||||
|
if (!btn || btn.disabled) return;
|
||||||
|
btn.value = unsaved ? 'Set (unsaved)' : 'Set';
|
||||||
|
if (unsaved) btn.classList.add('is-unsaved'); else btn.classList.remove('is-unsaved');
|
||||||
|
}
|
||||||
|
function updateAllPsipRowButtonStates(formId) {
|
||||||
|
var f = document.getElementById(formId);
|
||||||
|
if (!f || !psipFormSnapshotPerRow.length) return;
|
||||||
|
var rows = f.querySelectorAll('table tr');
|
||||||
|
var rowIdx = 0;
|
||||||
|
for (var i = 0; i < rows.length; i++) {
|
||||||
|
if (!rows[i].querySelector('input[type="button"]')) continue;
|
||||||
|
setPsipRowButtonState(rows[i], rowIdx < psipFormSnapshotPerRow.length && isRowDirty(getRowValues(rows[i]), psipFormSnapshotPerRow[rowIdx]));
|
||||||
|
rowIdx++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function setAllPsipRowButtonsSaved() {
|
||||||
|
var f = document.getElementById('psip_table_form');
|
||||||
|
if (!f) return;
|
||||||
|
var rows = f.querySelectorAll('table tr');
|
||||||
|
for (var i = 0; i < rows.length; i++) setPsipRowButtonState(rows[i], false);
|
||||||
|
}
|
||||||
|
function psipFormSnapshotUpdate() {
|
||||||
|
psipFormSnapshotPerRow = getFormSnapshotPerRow('psip_table_form');
|
||||||
|
setAllPsipRowButtonsSaved();
|
||||||
|
}
|
||||||
|
function attachPsipUnsavedListeners() {
|
||||||
|
var f = document.getElementById('tsid_form');
|
||||||
|
if (f) {
|
||||||
|
f.addEventListener('change', updateTsidFormRowButtonStates);
|
||||||
|
f.addEventListener('input', updateTsidFormRowButtonStates);
|
||||||
|
}
|
||||||
|
var pf = document.getElementById('psip_table_form');
|
||||||
|
if (pf) pf.addEventListener('change', function() { updateAllPsipRowButtonStates('psip_table_form'); });
|
||||||
|
}
|
||||||
|
if (document.readyState === 'loading') {
|
||||||
|
document.addEventListener('DOMContentLoaded', attachPsipUnsavedListeners);
|
||||||
|
} else {
|
||||||
|
attachPsipUnsavedListeners();
|
||||||
|
}
|
||||||
|
|
||||||
|
function refresh_show(){
|
||||||
|
get_remote_local_ctrl();
|
||||||
|
SetFormDefaults();
|
||||||
|
refreshDashboard();
|
||||||
|
}
|
||||||
|
|
||||||
|
function cmd_confirm() {
|
||||||
|
return confirm("Please choose to confirm or cancel!");
|
||||||
|
}
|
||||||
|
|
||||||
|
function tsid_psip_top_set() {
|
||||||
|
var postData = "tsid_psip=";
|
||||||
|
var cf = document.forms[0];
|
||||||
|
|
||||||
|
postData += "#"+cf.ts_edit.value;
|
||||||
|
postData += "#"+cf.tsid.value;
|
||||||
|
if(cmd_confirm()){
|
||||||
|
|
||||||
|
$.post("atsc_status_cfg.cgi", postData, function(data, status){
|
||||||
|
if(status=="success"){
|
||||||
|
setTimeout(function() { SetFormDefaults(); }, 2000);
|
||||||
|
} else {
|
||||||
|
alert("post val err");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Updated Sub Set Function to read from Single Form
|
||||||
|
function tsid_psip_sub_set(clickedIndex) {
|
||||||
|
var postData = "psip_cfg=";
|
||||||
|
var psipForm = document.getElementById("psip_table_form");
|
||||||
|
|
||||||
|
// Iterate through all 13 rows to build the data string
|
||||||
|
for(var k=0; k<13; k++) {
|
||||||
|
// Access values directly from the single form using names
|
||||||
|
postData += "#" + psipForm.elements['index'+k].value;
|
||||||
|
postData += "#" + psipForm.elements['sht_name'+k].value;
|
||||||
|
postData += "#" + psipForm.elements['maj_num'+k].value;
|
||||||
|
postData += "#" + psipForm.elements['min_num'+k].value;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(cmd_confirm()){
|
||||||
|
$.post("atsc_status_cfg.cgi", postData, function(data, status){
|
||||||
|
if(status=="success"){
|
||||||
|
setTimeout(function() { SetFormDefaults(); }, 2000);
|
||||||
|
} else {
|
||||||
|
alert("post val err");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Modal Logic - Open and close account modal
|
||||||
|
function openAccountModal() {
|
||||||
|
// Fetch current username from server
|
||||||
|
$.get("login.cgi?action=get_user", function(data) {
|
||||||
|
var trimmedData = (data || "").trim();
|
||||||
|
if (trimmedData && trimmedData !== "UNAUTHORIZED") {
|
||||||
|
document.getElementById('current_user').value = trimmedData;
|
||||||
|
}
|
||||||
|
document.getElementById('accountModal').style.display = 'block';
|
||||||
|
setTimeout(function() { document.getElementById('current_pwd').focus(); }, 100);
|
||||||
|
}).fail(function() {
|
||||||
|
document.getElementById('accountModal').style.display = 'block';
|
||||||
|
setTimeout(function() { document.getElementById('current_pwd').focus(); }, 100);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function closeAccountModal() {
|
||||||
|
document.getElementById('accountModal').style.display = 'none';
|
||||||
|
// Clear sensitive fields
|
||||||
|
document.getElementById('current_pwd').value = '';
|
||||||
|
document.getElementById('new_pwd').value = '';
|
||||||
|
document.getElementById('confirm_pwd').value = '';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validates that a string contains only printable characters (excluding space)
|
||||||
|
function isValidPrintableString(str) {
|
||||||
|
// Regular expression to check for printable characters (ASCII 33-126), excluding space
|
||||||
|
// Space is ASCII 32, and we want to exclude it
|
||||||
|
var printableCharRegex = /^[!-~]+$/; // ! is ASCII 33, ~ is ASCII 126
|
||||||
|
return printableCharRegex.test(str);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validation - All required fields must be filled
|
||||||
|
function validateAccountForm() {
|
||||||
|
var currentUser = document.getElementById('current_user').value;
|
||||||
|
var currentPwd = document.getElementById('current_pwd').value;
|
||||||
|
var newUsername = document.getElementById('new_user').value;
|
||||||
|
var newPwd = document.getElementById('new_pwd').value;
|
||||||
|
var confirmPwd = document.getElementById('confirm_pwd').value;
|
||||||
|
|
||||||
|
// Current password is required (cannot be empty)
|
||||||
|
if (!currentPwd || currentPwd.trim() === "") {
|
||||||
|
alert("Current password is required");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate current password contains only printable characters
|
||||||
|
if (!isValidPrintableString(currentPwd)) {
|
||||||
|
alert("Current password contains invalid characters. Only printable characters (excluding space) are allowed.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// New password is required (cannot be empty)
|
||||||
|
if (!newPwd || newPwd.trim() === "") {
|
||||||
|
alert("New password is required");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate new password contains only printable characters
|
||||||
|
if (!isValidPrintableString(newPwd)) {
|
||||||
|
alert("New password contains invalid characters. Only printable characters (excluding space) are allowed.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate new password length (max 16 chars)
|
||||||
|
if (newPwd.length > 16) {
|
||||||
|
alert("New password must be no more than 16 characters");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate new password length
|
||||||
|
if (newPwd.length < 6) {
|
||||||
|
alert("New password must be at least 6 characters");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Confirm password must match new password
|
||||||
|
if (newPwd !== confirmPwd) {
|
||||||
|
alert("New passwords do not match");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate confirm password contains only printable characters
|
||||||
|
if (!isValidPrintableString(confirmPwd)) {
|
||||||
|
alert("Confirm password contains invalid characters. Only printable characters (excluding space) are allowed.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate confirm password length (max 16 chars)
|
||||||
|
if (confirmPwd.length > 16) {
|
||||||
|
alert("Confirm password must be no more than 16 characters");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate new username if provided
|
||||||
|
if (newUsername && newUsername.trim() !== "") {
|
||||||
|
// Validate new username contains only printable characters
|
||||||
|
if (!isValidPrintableString(newUsername)) {
|
||||||
|
alert("New username contains invalid characters. Only printable characters (excluding space) are allowed.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate new username length (max 16 chars)
|
||||||
|
if (newUsername.length > 16) {
|
||||||
|
alert("New username must be no more than 16 characters");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Form submission handler using fetch API
|
||||||
|
document.addEventListener('DOMContentLoaded', function() {
|
||||||
|
var accountForm = document.getElementById('accountForm');
|
||||||
|
if (accountForm) {
|
||||||
|
accountForm.addEventListener('submit', function(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
|
||||||
|
if (!validateAccountForm()) return;
|
||||||
|
|
||||||
|
var formData = new URLSearchParams({
|
||||||
|
Username: document.getElementById('current_user').value,
|
||||||
|
OldPassword: document.getElementById('current_pwd').value,
|
||||||
|
NewUsername: document.getElementById('new_user').value,
|
||||||
|
NewPassword: document.getElementById('new_pwd').value,
|
||||||
|
ConfirmPassword: document.getElementById('confirm_pwd').value
|
||||||
|
});
|
||||||
|
|
||||||
|
fetch('login.cgi?action=change_account', {
|
||||||
|
method: 'POST',
|
||||||
|
body: formData
|
||||||
|
})
|
||||||
|
.then(r => r.json())
|
||||||
|
.then(data => {
|
||||||
|
if (data.success) {
|
||||||
|
alert("Update successful! Please login again.");
|
||||||
|
closeAccountModal();
|
||||||
|
// Redirect to login page after 1.5 seconds
|
||||||
|
setTimeout(function() {
|
||||||
|
window.location.href = 'login.cgi?logout=1';
|
||||||
|
}, 1500);
|
||||||
|
} else {
|
||||||
|
alert(data.error || "Update failed");
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(function(err) {
|
||||||
|
alert("Network error: " + err);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body onload="refresh_show()">
|
||||||
|
<div class="app-layout">
|
||||||
|
<aside class="app-sidebar">
|
||||||
|
<ul class="items">
|
||||||
|
<li><a href="status_info.html" title="Status">Status</a></li>
|
||||||
|
<li><a href="sys_set.html" title="Settings">Settings</a></li>
|
||||||
|
<li><a href="sys_rf.html" title="RF Control">RF Control</a></li>
|
||||||
|
<li class="active"><a href="sys_psip.html" title="TSID&PSIP">TSID&PSIP</a></li>
|
||||||
|
<li><a href="sys_ts.html" title="TSoIP">TSoIP</a></li>
|
||||||
|
<li><a href="sys_spectrum.html" title="Spectrum">Spectrum</a></li>
|
||||||
|
<li><a href="log_output.html" title="Log">Log</a></li>
|
||||||
|
</ul>
|
||||||
|
<div class="sidebar-footer">
|
||||||
|
<h4>Anywave Broadcast Inc.</h4>
|
||||||
|
<p>Copyright 2026<br><br><span class="redbox-label">Technical Support</span><br>+1 847 415 2258<br><a href="mailto:support@anywaveus.com">support@anywaveus.com</a></p>
|
||||||
|
</div>
|
||||||
|
</aside>
|
||||||
|
<div class="sidebar-overlay" onclick="toggleSidebar()"></div>
|
||||||
|
|
||||||
|
<header class="app-header">
|
||||||
|
<button class="menu-toggle" onclick="toggleSidebar()" aria-label="Toggle menu">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||||
|
<line x1="3" y1="12" x2="21" y2="12"></line>
|
||||||
|
<line x1="3" y1="6" x2="21" y2="6"></line>
|
||||||
|
<line x1="3" y1="18" x2="21" y2="18"></line>
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
<h1><a href="https://anywavecom.net/" class="logo-bg" title="Anywave Broadcast Inc."></a></h1>
|
||||||
|
<h2 id="webtitle_header"><span></span></h2>
|
||||||
|
<h3>
|
||||||
|
<div class="dropdown">
|
||||||
|
<button class="dropbtn-modern">Admin ▾</button>
|
||||||
|
<div class="dropdown-content">
|
||||||
|
<a href="#" onclick="openAccountModal(); return false;">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||||
|
<circle cx="12" cy="12" r="3"></circle>
|
||||||
|
<path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1 0 2.83 2 2 0 0 1-2.83 0l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-2 2 2 2 0 0 1-2-2v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06-.06a2 2 0 0 1-2.83 0 2 2 0 0 1 0-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1-2-2 2 2 0 0 1 2-2h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 0-2.83 2 2 0 0 1 2.83 0l.06-.06a1.65 1.65 0 0 0 1.82.33H9a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 2-2 2 2 0 0 1 2 2v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 0 2 2 0 0 1 0 2.83l-.06-.06a1.65 1.65 0 0 0-.33 1.82V9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 2 2 2 2 0 0 1-2 2h-.09a1.65 1.65 0 0 0-1.51 1z"></path>
|
||||||
|
</svg>
|
||||||
|
Account Settings
|
||||||
|
</a>
|
||||||
|
<a href="login.cgi?logout=1">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||||
|
<path d="M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4"></path>
|
||||||
|
<polyline points="16 17 21 12 16 7"></polyline>
|
||||||
|
<line x1="21" y1="12" x2="9" y2="12"></line>
|
||||||
|
</svg>
|
||||||
|
Logout
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</h3>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<!-- Fixed Dashboard Summary - Top of page, under header -->
|
||||||
|
<div class="dashboard-fixed">
|
||||||
|
<div class="summary-dashboard">
|
||||||
|
<div class="summary-card">
|
||||||
|
<div class="summary-label-row">
|
||||||
|
<span class="status-dot status-neutral" id="dot_freq" aria-hidden="true"></span>
|
||||||
|
<span class="summary-label">Frequency</span>
|
||||||
|
</div>
|
||||||
|
<div class="summary-value-wrapper">
|
||||||
|
<span class="summary-value value-neutral" id="sum_freq">--</span>
|
||||||
|
<span class="summary-unit">MHz</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="summary-card">
|
||||||
|
<div class="summary-label-row">
|
||||||
|
<span class="status-dot status-ok" id="dot_snr" aria-hidden="true"></span>
|
||||||
|
<span class="summary-label">SNR</span>
|
||||||
|
</div>
|
||||||
|
<div class="summary-value-wrapper">
|
||||||
|
<span class="summary-value value-ok" id="sum_snr">--</span>
|
||||||
|
<span class="summary-unit">dB</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="summary-card">
|
||||||
|
<div class="summary-label-row">
|
||||||
|
<span class="status-dot status-ok" id="dot_uimd" aria-hidden="true"></span>
|
||||||
|
<span class="summary-label">UIMD</span>
|
||||||
|
</div>
|
||||||
|
<div class="summary-value-wrapper">
|
||||||
|
<span class="summary-value value-ok" id="sum_uimd">--</span>
|
||||||
|
<span class="summary-unit">dBc</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="summary-card">
|
||||||
|
<div class="summary-label-row">
|
||||||
|
<span class="status-dot status-ok" id="dot_limd" aria-hidden="true"></span>
|
||||||
|
<span class="summary-label">LIMD</span>
|
||||||
|
</div>
|
||||||
|
<div class="summary-value-wrapper">
|
||||||
|
<span class="summary-value value-ok" id="sum_limd">--</span>
|
||||||
|
<span class="summary-unit">dBc</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="summary-card">
|
||||||
|
<div class="summary-label-row">
|
||||||
|
<span class="status-dot status-off" id="dot_rf" aria-hidden="true"></span>
|
||||||
|
<span class="summary-label">RF Switch</span>
|
||||||
|
</div>
|
||||||
|
<div class="summary-value-wrapper">
|
||||||
|
<span class="summary-value value-muted" id="sum_rf">--</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="summary-card">
|
||||||
|
<div class="summary-label-row">
|
||||||
|
<span class="status-dot status-ok" id="dot_outpow" aria-hidden="true"></span>
|
||||||
|
<span class="summary-label">Output Power</span>
|
||||||
|
</div>
|
||||||
|
<div class="summary-value-wrapper">
|
||||||
|
<span class="summary-value value-ok" id="sum_outpow">--</span>
|
||||||
|
<span class="summary-unit">dBm</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="summary-card">
|
||||||
|
<div class="summary-label-row">
|
||||||
|
<span class="status-dot status-neutral" id="dot_input" aria-hidden="true"></span>
|
||||||
|
<span class="summary-label">Input Source</span>
|
||||||
|
</div>
|
||||||
|
<div class="summary-value-wrapper">
|
||||||
|
<span class="summary-value value-neutral" id="sum_input">--</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="summary-card">
|
||||||
|
<div class="summary-label-row">
|
||||||
|
<span class="status-dot status-neutral" id="dot_input_status" aria-hidden="true"></span>
|
||||||
|
<span class="summary-label">Input Status</span>
|
||||||
|
</div>
|
||||||
|
<div class="summary-value-wrapper">
|
||||||
|
<span class="summary-value value-neutral" id="sum_input_status">--</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="summary-card">
|
||||||
|
<div class="summary-label-row">
|
||||||
|
<span class="status-dot status-neutral" id="dot_bitrate" aria-hidden="true"></span>
|
||||||
|
<span class="summary-label">Bitrate</span>
|
||||||
|
</div>
|
||||||
|
<div class="summary-value-wrapper">
|
||||||
|
<span class="summary-value value-neutral" id="sum_bitrate">--</span>
|
||||||
|
<span class="summary-unit">Mbps</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="summary-card">
|
||||||
|
<div class="summary-label-row">
|
||||||
|
<span class="status-dot status-ok" id="dot_temp" aria-hidden="true"></span>
|
||||||
|
<span class="summary-label">Temperature</span>
|
||||||
|
</div>
|
||||||
|
<div class="summary-value-wrapper">
|
||||||
|
<span class="summary-value value-ok" id="sum_temp">--</span>
|
||||||
|
<span class="summary-unit">°F</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="summary-card">
|
||||||
|
<div class="summary-label-row">
|
||||||
|
<span class="status-dot status-off" id="dot_agc" aria-hidden="true"></span>
|
||||||
|
<span class="summary-label">AGC</span>
|
||||||
|
</div>
|
||||||
|
<div class="summary-value-wrapper">
|
||||||
|
<span class="summary-value value-muted" id="sum_agc">--</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="summary-card">
|
||||||
|
<div class="summary-label-row">
|
||||||
|
<span class="status-dot status-neutral" id="dot_control" aria-hidden="true"></span>
|
||||||
|
<span class="summary-label">Control</span>
|
||||||
|
</div>
|
||||||
|
<div class="summary-value-wrapper">
|
||||||
|
<span class="summary-value value-neutral" id="sum_control">--</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<main class="app-main">
|
||||||
|
<h2>TSID&PSIP</h2>
|
||||||
|
<div class="box">
|
||||||
|
<form id="tsid_form">
|
||||||
|
<table>
|
||||||
|
<tr>
|
||||||
|
<td>CTRL</td>
|
||||||
|
<td>
|
||||||
|
<select name="ts_edit" id="ts_edit">
|
||||||
|
<option value="0">Disable
|
||||||
|
<option value="1">Enable
|
||||||
|
<option value="2">Clear
|
||||||
|
</select>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<input type="button" class="btn-modern" alt="Set" value="Set" disabled onclick="return tsid_psip_top_set();">
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>TSID</td>
|
||||||
|
<td>
|
||||||
|
<input type="text" maxlength="5" size="8" name="tsid" id="tsid" value="">
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<input type="button" class="btn-modern" alt="Set" value="Set" disabled onclick="return tsid_psip_top_set();">
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
<br>
|
||||||
|
|
||||||
|
<div class="box">
|
||||||
|
<form name="psip_table_form" id="psip_table_form">
|
||||||
|
<table id="psip_table">
|
||||||
|
<tr class="header-row">
|
||||||
|
<td style="width: 25%">Program</td>
|
||||||
|
<td style="width: 25%">Short Name</td>
|
||||||
|
<td style="width: 25%">Major Channel Number</td>
|
||||||
|
<td style="width: 25%">Minor Channel Number</td>
|
||||||
|
<td></td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<tr id="psip0">
|
||||||
|
<td><input type="text" name="index0" readonly></td>
|
||||||
|
<td><input type="text" name="sht_name0"></td>
|
||||||
|
<td><input type="text" name="maj_num0"></td>
|
||||||
|
<td><input type="text" name="min_num0"></td>
|
||||||
|
<td><input type="button" class="btn-modern" value="Set" disabled onclick="return tsid_psip_sub_set(0);"></td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<tr id="psip1">
|
||||||
|
<td><input type="text" name="index1" readonly></td>
|
||||||
|
<td><input type="text" name="sht_name1"></td>
|
||||||
|
<td><input type="text" name="maj_num1"></td>
|
||||||
|
<td><input type="text" name="min_num1"></td>
|
||||||
|
<td><input type="button" class="btn-modern" value="Set" disabled onclick="return tsid_psip_sub_set(1);"></td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<tr id="psip2">
|
||||||
|
<td><input type="text" name="index2" readonly></td>
|
||||||
|
<td><input type="text" name="sht_name2"></td>
|
||||||
|
<td><input type="text" name="maj_num2"></td>
|
||||||
|
<td><input type="text" name="min_num2"></td>
|
||||||
|
<td><input type="button" class="btn-modern" value="Set" disabled disabled onclick="return tsid_psip_sub_set(2);"></td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<tr id="psip3">
|
||||||
|
<td><input type="text" name="index3" readonly></td>
|
||||||
|
<td><input type="text" name="sht_name3"></td>
|
||||||
|
<td><input type="text" name="maj_num3"></td>
|
||||||
|
<td><input type="text" name="min_num3"></td>
|
||||||
|
<td><input type="button" class="btn-modern" value="Set" disabled disabled onclick="return tsid_psip_sub_set(3);"></td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<tr id="psip4">
|
||||||
|
<td><input type="text" name="index4" readonly></td>
|
||||||
|
<td><input type="text" name="sht_name4"></td>
|
||||||
|
<td><input type="text" name="maj_num4"></td>
|
||||||
|
<td><input type="text" name="min_num4"></td>
|
||||||
|
<td><input type="button" class="btn-modern" value="Set" disabled onclick="return tsid_psip_sub_set(4);"></td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<tr id="psip5">
|
||||||
|
<td><input type="text" name="index5" readonly></td>
|
||||||
|
<td><input type="text" name="sht_name5"></td>
|
||||||
|
<td><input type="text" name="maj_num5"></td>
|
||||||
|
<td><input type="text" name="min_num5"></td>
|
||||||
|
<td><input type="button" class="btn-modern" value="Set" disabled onclick="return tsid_psip_sub_set(5);"></td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<tr id="psip6">
|
||||||
|
<td><input type="text" name="index6" readonly></td>
|
||||||
|
<td><input type="text" name="sht_name6"></td>
|
||||||
|
<td><input type="text" name="maj_num6"></td>
|
||||||
|
<td><input type="text" name="min_num6"></td>
|
||||||
|
<td><input type="button" class="btn-modern" value="Set" disabled onclick="return tsid_psip_sub_set(6);"></td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<tr id="psip7">
|
||||||
|
<td><input type="text" name="index7" readonly></td>
|
||||||
|
<td><input type="text" name="sht_name7"></td>
|
||||||
|
<td><input type="text" name="maj_num7"></td>
|
||||||
|
<td><input type="text" name="min_num7"></td>
|
||||||
|
<td><input type="button" class="btn-modern" value="Set" disabled onclick="return tsid_psip_sub_set(7);"></td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<tr id="psip8">
|
||||||
|
<td><input type="text" name="index8" readonly></td>
|
||||||
|
<td><input type="text" name="sht_name8"></td>
|
||||||
|
<td><input type="text" name="maj_num8"></td>
|
||||||
|
<td><input type="text" name="min_num8"></td>
|
||||||
|
<td><input type="button" class="btn-modern" value="Set" disabled onclick="return tsid_psip_sub_set(8);"></td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<tr id="psip9">
|
||||||
|
<td><input type="text" name="index9" readonly></td>
|
||||||
|
<td><input type="text" name="sht_name9"></td>
|
||||||
|
<td><input type="text" name="maj_num9"></td>
|
||||||
|
<td><input type="text" name="min_num9"></td>
|
||||||
|
<td><input type="button" class="btn-modern" value="Set" disabled onclick="return tsid_psip_sub_set(9);"></td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<tr id="psip10">
|
||||||
|
<td><input type="text" name="index10" readonly></td>
|
||||||
|
<td><input type="text" name="sht_name10"></td>
|
||||||
|
<td><input type="text" name="maj_num10"></td>
|
||||||
|
<td><input type="text" name="min_num10"></td>
|
||||||
|
<td><input type="button" class="btn-modern" value="Set" disabled onclick="return tsid_psip_sub_set(10);"></td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<tr id="psip11">
|
||||||
|
<td><input type="text" name="index11" readonly></td>
|
||||||
|
<td><input type="text" name="sht_name11"></td>
|
||||||
|
<td><input type="text" name="maj_num11"></td>
|
||||||
|
<td><input type="text" name="min_num11"></td>
|
||||||
|
<td><input type="button" class="btn-modern" value="Set" disabled onclick="return tsid_psip_sub_set(11);"></td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<tr id="psip12">
|
||||||
|
<td><input type="text" name="index12" readonly></td>
|
||||||
|
<td><input type="text" name="sht_name12"></td>
|
||||||
|
<td><input type="text" name="maj_num12"></td>
|
||||||
|
<td><input type="text" name="min_num12"></td>
|
||||||
|
<td><input type="button" class="btn-modern" value="Set" disabled onclick="return tsid_psip_sub_set(12);"></td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
</table>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</main>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="accountModal" class="modal">
|
||||||
|
<div class="modal-content">
|
||||||
|
<div class="modal-header">
|
||||||
|
<h3>Account Settings</h3>
|
||||||
|
<span class="close" onclick="closeAccountModal()">×</span>
|
||||||
|
</div>
|
||||||
|
<div class="modal-body">
|
||||||
|
<form id="accountForm" method="post" action="login.cgi?action=change_account" onsubmit="return validateAccountForm()">
|
||||||
|
<table class="modal-table">
|
||||||
|
<tr>
|
||||||
|
<td>Current Username</td>
|
||||||
|
<td><input type="text" id="current_user" name="current_user" readonly></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Current Password</td>
|
||||||
|
<td><input type="password" id="current_pwd" name="current_pwd" required></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>New Username</td>
|
||||||
|
<td><input type="text" id="new_user" name="new_user"></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>New Password</td>
|
||||||
|
<td><input type="password" id="new_pwd" name="new_pwd"></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Confirm Password</td>
|
||||||
|
<td><input type="password" id="confirm_pwd" name="confirm_pwd"></td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
<div class="modal-footer">
|
||||||
|
<input type="button" class="btn-modern" style="background-color: #64748b;" value="Cancel" onclick="closeAccountModal()">
|
||||||
|
<input type="submit" class="btn-modern" value="Save Changes">
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
function toggleSidebar(){
|
||||||
|
document.querySelector('.app-sidebar').classList.toggle('sidebar-open');
|
||||||
|
document.querySelector('.sidebar-overlay').classList.toggle('active');
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -0,0 +1,957 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title id="webtitle"></title>
|
||||||
|
<link href="css/styles.css" rel="stylesheet" media="screen">
|
||||||
|
<script src="js/auth.js"></script>
|
||||||
|
<script src="js/jquery.js"></script>
|
||||||
|
<script src="js/dashboard.js"></script>
|
||||||
|
<script>
|
||||||
|
var time_sec_cnt=0;
|
||||||
|
var g_remot_local_ctrl = 3; //0 remote 1 local
|
||||||
|
var g_old_power = 0;
|
||||||
|
var g_old_power_p0 = 0;
|
||||||
|
var g_old_power_p1 = 0;
|
||||||
|
var g_old_power_p2 = 0;
|
||||||
|
var g_old_freq_channel = -1;
|
||||||
|
var g_rx_freq=0;
|
||||||
|
var wait_freq_flg = 0;
|
||||||
|
var g_rx_freq_countdown_active = false; // Flag to prevent rx_freq update during countdown
|
||||||
|
var arry_sign = [1, -1];
|
||||||
|
var arry_p = [0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75, 80, 85, 90, 95];
|
||||||
|
var lastTime = new Date().getTime();
|
||||||
|
var currentTime = new Date().getTime();
|
||||||
|
var timeOut = 20 * 60 * 1000; // 20 min timeout
|
||||||
|
|
||||||
|
$(function(){
|
||||||
|
// Listen to multiple types of user activity to prevent timeout
|
||||||
|
$(document).on('mousemove keydown click scroll touchstart', function(){
|
||||||
|
lastTime = new Date().getTime();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
function testTime(){
|
||||||
|
currentTime = new Date().getTime();
|
||||||
|
if(currentTime - lastTime > timeOut){
|
||||||
|
window.location.href="login.cgi?logout=1"
|
||||||
|
}
|
||||||
|
|
||||||
|
time_sec_cnt=time_sec_cnt+1;
|
||||||
|
if(time_sec_cnt%3==0){
|
||||||
|
get_remote_local_ctrl();
|
||||||
|
if(g_remot_local_ctrl==1) { // local
|
||||||
|
SetFormDefaults();
|
||||||
|
}
|
||||||
|
refreshDashboard();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Timer check
|
||||||
|
window.setInterval(testTime, 1000);
|
||||||
|
|
||||||
|
function get_remote_local_ctrl() {
|
||||||
|
var queryData = "sys_cfg=&";
|
||||||
|
$.get("atsc_status_cfg.cgi?"+queryData, function(data, status) {
|
||||||
|
// 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:', data);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var table = data.split("|");
|
||||||
|
g_remot_local_ctrl = Number(table[0].split("#")[5]);
|
||||||
|
document.title = table[0].split("#")[11];
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function cmd_confirm() {
|
||||||
|
return confirm("Please choose to confirm or cancel!");
|
||||||
|
}
|
||||||
|
|
||||||
|
function SetFormDefaults() {
|
||||||
|
// 1. DISABLE BUTTONS START (only in Remote mode)
|
||||||
|
if(g_remot_local_ctrl == 1) {
|
||||||
|
// Local mode: just fetch data, don't change button
|
||||||
|
var queryData = "sys_rf=&web_title=&";
|
||||||
|
} else {
|
||||||
|
// Remote mode: show LOADING indicator
|
||||||
|
$('#rf_form input[type="button"]').attr("disabled", true).val("LOADING...");
|
||||||
|
var queryData = "sys_rf=&web_title=&";
|
||||||
|
}
|
||||||
|
|
||||||
|
$.get("atsc_status_cfg.cgi?"+queryData, function(data, status) {
|
||||||
|
// 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:', data);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var table = data.split("|");
|
||||||
|
var rfpara= table[0].split("#");
|
||||||
|
var title = table[1].split("#");
|
||||||
|
var cf = document.getElementById("rf_form");
|
||||||
|
|
||||||
|
g_old_power_p0 = Number(rfpara[1]);
|
||||||
|
g_old_power_p1 = Number(rfpara[2]);
|
||||||
|
g_old_power_p2 = Number(rfpara[3]);
|
||||||
|
|
||||||
|
cf.pw0.value = Number(rfpara[1]);
|
||||||
|
cf.pw1.value = Number(rfpara[2]);
|
||||||
|
cf.pw2.value = Number(rfpara[3]);
|
||||||
|
cf.rfy.value = Number(rfpara[4]);
|
||||||
|
cf.agc.value = Number(rfpara[5]);
|
||||||
|
|
||||||
|
var tmp = Number(rfpara[6]);
|
||||||
|
cf.tx.value = Number(rfpara[7]);
|
||||||
|
cf.freq6m.value = Number(rfpara[8]);
|
||||||
|
|
||||||
|
// Only update rx_freq if not in countdown mode (to prevent jumping back to old value)
|
||||||
|
if (!g_rx_freq_countdown_active) {
|
||||||
|
cf.rx_freq.value = Number(rfpara[9]);
|
||||||
|
g_rx_freq = Number(rfpara[9]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. RE-ENABLE BUTTONS END (only in Remote mode)
|
||||||
|
if(g_remot_local_ctrl == 1) {
|
||||||
|
// Local mode: keep button disabled
|
||||||
|
$('#rf_form input[type="button"]').attr("disabled", true).val("Local Mode");
|
||||||
|
} else {
|
||||||
|
// Remote mode: enable button
|
||||||
|
$('#rf_form input[type="button"]').attr("disabled", false).val("Set");
|
||||||
|
}
|
||||||
|
|
||||||
|
document.getElementById('webtitle').textContent = title[1];
|
||||||
|
document.getElementById('webtitle_header').textContent = title[1];
|
||||||
|
if (typeof rfFormSnapshotUpdate === 'function') rfFormSnapshotUpdate();
|
||||||
|
}).fail(function() {
|
||||||
|
// Optional: Error handling
|
||||||
|
if(g_remot_local_ctrl == 0) {
|
||||||
|
$('#rf_form input[type="button"]').val("Load Failed");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function refresh_show(){
|
||||||
|
get_remote_local_ctrl();
|
||||||
|
SetFormDefaults();
|
||||||
|
refreshDashboard();
|
||||||
|
m10_load();
|
||||||
|
}
|
||||||
|
|
||||||
|
// PR07: 10 MHz reference output enable (FPGA reg_map_dpd seg5 0x1f bit0).
|
||||||
|
// Independent of the RF form and of Local/Remote mode: it is a hardware
|
||||||
|
// reference-clock output, applied live and reset to OFF on every power-up.
|
||||||
|
function m10_load(){
|
||||||
|
$.get("atsc_status_cfg.cgi?sys_m10=&", function(data, status){
|
||||||
|
if(typeof data === 'object' && data !== null){
|
||||||
|
if(data.error === 'session_expired' && data.redirect){ window.location.href = data.redirect; }
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var v = Number(data.split("|")[0].split("#")[1]); // "#<0|1>|"
|
||||||
|
var sel = document.getElementById("m10_en");
|
||||||
|
if(sel && !isNaN(v)) sel.value = v;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
function m10_set(){
|
||||||
|
var sel = document.getElementById("m10_en");
|
||||||
|
if(!sel) return false;
|
||||||
|
$.post("atsc_status_cfg.cgi", "sys_m10="+sel.value, function(data, status){
|
||||||
|
m10_load();
|
||||||
|
});
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
function set_rxfreq_button_enable(is_enable){
|
||||||
|
if(is_enable == 0){
|
||||||
|
$('#rx_freq').attr("disabled", true);
|
||||||
|
$('#id_rxfreq_button').attr("disabled", true);
|
||||||
|
}else{
|
||||||
|
$('#rx_freq').attr("disabled", false);
|
||||||
|
$('#id_rxfreq_button').attr("disabled", false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function exc_sysRfSet() {
|
||||||
|
var postData = "sys_rf=";
|
||||||
|
var cf = document.forms[0];
|
||||||
|
|
||||||
|
var new_power = (arry_sign[Number(cf.pw0.value)]) * (Number(cf.pw1.value)*100+(arry_p[Number(cf.pw2.value)]));
|
||||||
|
g_old_power = arry_sign[g_old_power_p0]*(g_old_power_p1*100+arry_p[g_old_power_p2]);
|
||||||
|
|
||||||
|
if((new_power - g_old_power) > 100){
|
||||||
|
alert("Please do not increase power for more than 1dB each time, change will be discarded!");
|
||||||
|
SetFormDefaults();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
postData += "#"+cf.pw0.value;
|
||||||
|
postData += "#"+cf.pw1.value;
|
||||||
|
postData += "#"+cf.pw2.value;
|
||||||
|
postData += "#"+cf.rfy.value;
|
||||||
|
postData += "#"+cf.agc.value;
|
||||||
|
postData += "#"+0;
|
||||||
|
postData += "#"+cf.tx.value;
|
||||||
|
postData += "#"+cf.freq6m.value;
|
||||||
|
postData += "#"+cf.rx_freq.value;
|
||||||
|
|
||||||
|
cur_rx_freq = Number($("#rx_freq").val());
|
||||||
|
|
||||||
|
if(cmd_confirm()){
|
||||||
|
if(g_rx_freq != cur_rx_freq){
|
||||||
|
g_rx_freq_countdown_active = true; // Start countdown, prevent rx_freq update
|
||||||
|
$("#set_rxfreq_note").text(" wait 10 s");
|
||||||
|
set_rxfreq_button_enable(0);
|
||||||
|
var note_sec = 10;
|
||||||
|
var set_tnote_intv = setInterval(function() {
|
||||||
|
if(note_sec == 0) {
|
||||||
|
clearInterval(set_tnote_intv);
|
||||||
|
$("#set_rxfreq_note").text(" ");
|
||||||
|
set_rxfreq_button_enable(1);
|
||||||
|
g_rx_freq_countdown_active = false; // End countdown, allow rx_freq update
|
||||||
|
SetFormDefaults();
|
||||||
|
return;
|
||||||
|
}else{
|
||||||
|
note_sec = note_sec-1;
|
||||||
|
$("#set_rxfreq_note").text(" wait "+note_sec+" s ");
|
||||||
|
set_rxfreq_button_enable(0);
|
||||||
|
}
|
||||||
|
}, 2000);
|
||||||
|
}
|
||||||
|
setAllRfRowButtonsSaved();
|
||||||
|
$.post("atsc_status_cfg.cgi", postData, function(data, status){
|
||||||
|
if(status=="success"){
|
||||||
|
SetFormDefaults();
|
||||||
|
}else{
|
||||||
|
alert("post val err");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Modal Logic - Open and close account modal
|
||||||
|
function openAccountModal() {
|
||||||
|
// Fetch current username from server
|
||||||
|
$.get("login.cgi?action=get_user", function(data) {
|
||||||
|
var trimmedData = (data || "").trim();
|
||||||
|
if (trimmedData && trimmedData !== "UNAUTHORIZED") {
|
||||||
|
document.getElementById('current_user').value = trimmedData;
|
||||||
|
}
|
||||||
|
document.getElementById('accountModal').style.display = 'block';
|
||||||
|
setTimeout(function() { document.getElementById('current_pwd').focus(); }, 100);
|
||||||
|
}).fail(function() {
|
||||||
|
document.getElementById('accountModal').style.display = 'block';
|
||||||
|
setTimeout(function() { document.getElementById('current_pwd').focus(); }, 100);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function closeAccountModal() {
|
||||||
|
document.getElementById('accountModal').style.display = 'none';
|
||||||
|
// Clear sensitive fields
|
||||||
|
document.getElementById('current_pwd').value = '';
|
||||||
|
document.getElementById('new_pwd').value = '';
|
||||||
|
document.getElementById('confirm_pwd').value = '';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validates that a string contains only printable characters (excluding space)
|
||||||
|
function isValidPrintableString(str) {
|
||||||
|
// Regular expression to check for printable characters (ASCII 33-126), excluding space
|
||||||
|
// Space is ASCII 32, and we want to exclude it
|
||||||
|
var printableCharRegex = /^[!-~]+$/; // ! is ASCII 33, ~ is ASCII 126
|
||||||
|
return printableCharRegex.test(str);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate Account Form - All required fields must be filled
|
||||||
|
function validateAccountForm() {
|
||||||
|
var currentUser = document.getElementById('current_user').value;
|
||||||
|
var currentPwd = document.getElementById('current_pwd').value;
|
||||||
|
var newUsername = document.getElementById('new_user').value;
|
||||||
|
var newPwd = document.getElementById('new_pwd').value;
|
||||||
|
var confirmPwd = document.getElementById('confirm_pwd').value;
|
||||||
|
|
||||||
|
// Current password is required (cannot be empty)
|
||||||
|
if (!currentPwd || currentPwd.trim() === "") {
|
||||||
|
alert("Current password is required");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate current password contains only printable characters
|
||||||
|
if (!isValidPrintableString(currentPwd)) {
|
||||||
|
alert("Current password contains invalid characters. Only printable characters (excluding space) are allowed.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// New password is required (cannot be empty)
|
||||||
|
if (!newPwd || newPwd.trim() === "") {
|
||||||
|
alert("New password is required");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate new password contains only printable characters
|
||||||
|
if (!isValidPrintableString(newPwd)) {
|
||||||
|
alert("New password contains invalid characters. Only printable characters (excluding space) are allowed.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate new password length (max 16 chars)
|
||||||
|
if (newPwd.length > 16) {
|
||||||
|
alert("New password must be no more than 16 characters");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate new password length
|
||||||
|
if (newPwd.length < 6) {
|
||||||
|
alert("New password must be at least 6 characters");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Confirm password must match new password
|
||||||
|
if (newPwd !== confirmPwd) {
|
||||||
|
alert("New passwords do not match");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate confirm password contains only printable characters
|
||||||
|
if (!isValidPrintableString(confirmPwd)) {
|
||||||
|
alert("Confirm password contains invalid characters. Only printable characters (excluding space) are allowed.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate confirm password length (max 16 chars)
|
||||||
|
if (confirmPwd.length > 16) {
|
||||||
|
alert("Confirm password must be no more than 16 characters");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate new username if provided
|
||||||
|
if (newUsername && newUsername.trim() !== "") {
|
||||||
|
// Validate new username contains only printable characters
|
||||||
|
if (!isValidPrintableString(newUsername)) {
|
||||||
|
alert("New username contains invalid characters. Only printable characters (excluding space) are allowed.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate new username length (max 16 chars)
|
||||||
|
if (newUsername.length > 16) {
|
||||||
|
alert("New username must be no more than 16 characters");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true; // Allows the form to submit
|
||||||
|
}
|
||||||
|
|
||||||
|
// Form submission handler using fetch API
|
||||||
|
document.addEventListener('DOMContentLoaded', function() {
|
||||||
|
var accountForm = document.getElementById('accountForm');
|
||||||
|
if (accountForm) {
|
||||||
|
accountForm.addEventListener('submit', function(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
|
||||||
|
if (!validateAccountForm()) return;
|
||||||
|
|
||||||
|
var formData = new URLSearchParams({
|
||||||
|
Username: document.getElementById('current_user').value,
|
||||||
|
OldPassword: document.getElementById('current_pwd').value,
|
||||||
|
NewUsername: document.getElementById('new_user').value,
|
||||||
|
NewPassword: document.getElementById('new_pwd').value,
|
||||||
|
ConfirmPassword: document.getElementById('confirm_pwd').value
|
||||||
|
});
|
||||||
|
|
||||||
|
fetch('login.cgi?action=change_account', {
|
||||||
|
method: 'POST',
|
||||||
|
body: formData
|
||||||
|
})
|
||||||
|
.then(r => r.json())
|
||||||
|
.then(data => {
|
||||||
|
if (data.success) {
|
||||||
|
alert("Update successful! Please login again.");
|
||||||
|
closeAccountModal();
|
||||||
|
// Redirect to login page after 1.5 seconds
|
||||||
|
setTimeout(function() {
|
||||||
|
window.location.href = 'login.cgi?logout=1';
|
||||||
|
}, 1500);
|
||||||
|
} else {
|
||||||
|
alert(data.error || "Update failed");
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(function(err) {
|
||||||
|
alert("Network error: " + err);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// ----- SET (unsaved) reminder: per-row, vanilla JS -----
|
||||||
|
var rfFormSnapshotPerRow = [];
|
||||||
|
function getRowValues(tr) {
|
||||||
|
var out = [], els = tr.querySelectorAll('select, input:not([type="button"])'), i, el, v;
|
||||||
|
for (i = 0; i < els.length; i++) {
|
||||||
|
el = els[i];
|
||||||
|
v = el.tagName === 'SELECT' ? (el.options[el.selectedIndex] ? el.options[el.selectedIndex].value : '') : el.value;
|
||||||
|
out.push({ name: el.name, value: String(v) });
|
||||||
|
}
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
function getFormSnapshotPerRow(formId) {
|
||||||
|
var f = document.getElementById(formId);
|
||||||
|
if (!f) return [];
|
||||||
|
var rows = f.querySelectorAll('table tr'), out = [], i;
|
||||||
|
for (i = 0; i < rows.length; i++) {
|
||||||
|
if (rows[i].querySelector('input[type="button"]')) out.push(getRowValues(rows[i]));
|
||||||
|
}
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
function isRowDirty(rowValues, rowSnapshot) {
|
||||||
|
if (rowValues.length !== rowSnapshot.length) return true;
|
||||||
|
for (var i = 0; i < rowValues.length; i++) {
|
||||||
|
if (rowValues[i].name !== rowSnapshot[i].name || rowValues[i].value !== rowSnapshot[i].value) return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
function setRowButtonState(tr, unsaved) {
|
||||||
|
var btn = tr.querySelector('input[type="button"]');
|
||||||
|
if (!btn || btn.disabled) return;
|
||||||
|
btn.value = unsaved ? 'Set (unsaved)' : 'Set';
|
||||||
|
if (unsaved) btn.classList.add('is-unsaved'); else btn.classList.remove('is-unsaved');
|
||||||
|
}
|
||||||
|
function updateAllRowButtonStates(formId) {
|
||||||
|
var f = document.getElementById(formId);
|
||||||
|
if (!f || !rfFormSnapshotPerRow.length) return;
|
||||||
|
var rows = f.querySelectorAll('table tr');
|
||||||
|
var rowIdx = 0;
|
||||||
|
for (var i = 0; i < rows.length; i++) {
|
||||||
|
if (!rows[i].querySelector('input[type="button"]')) continue;
|
||||||
|
setRowButtonState(rows[i], rowIdx < rfFormSnapshotPerRow.length && isRowDirty(getRowValues(rows[i]), rfFormSnapshotPerRow[rowIdx]));
|
||||||
|
rowIdx++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function setAllRfRowButtonsSaved() {
|
||||||
|
var f = document.getElementById('rf_form');
|
||||||
|
if (!f) return;
|
||||||
|
var rows = f.querySelectorAll('table tr');
|
||||||
|
for (var i = 0; i < rows.length; i++) setRowButtonState(rows[i], false);
|
||||||
|
}
|
||||||
|
function rfFormSnapshotUpdate() {
|
||||||
|
rfFormSnapshotPerRow = getFormSnapshotPerRow('rf_form');
|
||||||
|
setAllRfRowButtonsSaved();
|
||||||
|
}
|
||||||
|
function attachRfFormUnsavedListener() {
|
||||||
|
var f = document.getElementById('rf_form');
|
||||||
|
if (!f) return;
|
||||||
|
f.addEventListener('change', function() {
|
||||||
|
updateAllRowButtonStates('rf_form');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (document.readyState === 'loading') {
|
||||||
|
document.addEventListener('DOMContentLoaded', attachRfFormUnsavedListener);
|
||||||
|
} else {
|
||||||
|
attachRfFormUnsavedListener();
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body onload="refresh_show()">
|
||||||
|
<div class="app-layout">
|
||||||
|
<aside class="app-sidebar">
|
||||||
|
<ul class="items">
|
||||||
|
<li><a href="status_info.html" title="Status">Status</a></li>
|
||||||
|
<li><a href="sys_set.html" title="Settings">Settings</a></li>
|
||||||
|
<li class="active"><a href="sys_rf.html" title="RF Control">RF Control</a></li>
|
||||||
|
<li><a href="sys_psip.html" title="TSID&PSIP">TSID&PSIP</a></li>
|
||||||
|
<li><a href="sys_ts.html" title="TSoIP">TSoIP</a></li>
|
||||||
|
<li><a href="sys_spectrum.html" title="Spectrum">Spectrum</a></li>
|
||||||
|
<li><a href="log_output.html" title="Log">Log</a></li>
|
||||||
|
</ul>
|
||||||
|
<div class="sidebar-footer">
|
||||||
|
<h4>Anywave Broadcast Inc.</h4>
|
||||||
|
<p>Copyright 2026<br><br><span class="redbox-label">Technical Support</span><br>+1 847 415 2258<br><a href="mailto:support@anywaveus.com">support@anywaveus.com</a></p>
|
||||||
|
</div>
|
||||||
|
</aside>
|
||||||
|
<div class="sidebar-overlay" onclick="toggleSidebar()"></div>
|
||||||
|
|
||||||
|
<header class="app-header">
|
||||||
|
<button class="menu-toggle" onclick="toggleSidebar()" aria-label="Toggle menu">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||||
|
<line x1="3" y1="12" x2="21" y2="12"></line>
|
||||||
|
<line x1="3" y1="6" x2="21" y2="6"></line>
|
||||||
|
<line x1="3" y1="18" x2="21" y2="18"></line>
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
<h1><a href="https://anywavecom.net/" class="logo-bg" title="Anywave Broadcast Inc."></a></h1>
|
||||||
|
<h2 id="webtitle_header"><span></span></h2>
|
||||||
|
<h3>
|
||||||
|
<div class="dropdown">
|
||||||
|
<button class="dropbtn-modern">Admin ▾</button>
|
||||||
|
<div class="dropdown-content">
|
||||||
|
<a href="#" onclick="openAccountModal(); return false;">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||||
|
<circle cx="12" cy="12" r="3"></circle>
|
||||||
|
<path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1 0 2.83 2 2 0 0 1-2.83 0l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-2 2 2 2 0 0 1-2-2v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06-.06a2 2 0 0 1-2.83 0 2 2 0 0 1 0-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1-2-2 2 2 0 0 1 2-2h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 0-2.83 2 2 0 0 1 2.83 0l.06-.06a1.65 1.65 0 0 0 1.82.33H9a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 2-2 2 2 0 0 1 2 2v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 0 2 2 0 0 1 0 2.83l-.06-.06a1.65 1.65 0 0 0-.33 1.82V9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 2 2 2 2 0 0 1-2 2h-.09a1.65 1.65 0 0 0-1.51 1z"></path>
|
||||||
|
</svg>
|
||||||
|
Account Settings
|
||||||
|
</a>
|
||||||
|
<a href="login.cgi?logout=1">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||||
|
<path d="M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4"></path>
|
||||||
|
<polyline points="16 17 21 12 16 7"></polyline>
|
||||||
|
<line x1="21" y1="12" x2="9" y2="12"></line>
|
||||||
|
</svg>
|
||||||
|
Logout
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</h3>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<!-- Fixed Dashboard Summary - Top of page, under header -->
|
||||||
|
<div class="dashboard-fixed">
|
||||||
|
<div class="summary-dashboard">
|
||||||
|
<div class="summary-card">
|
||||||
|
<div class="summary-label-row">
|
||||||
|
<span class="status-dot status-neutral" id="dot_freq" aria-hidden="true"></span>
|
||||||
|
<span class="summary-label">Frequency</span>
|
||||||
|
</div>
|
||||||
|
<div class="summary-value-wrapper">
|
||||||
|
<span class="summary-value value-neutral" id="sum_freq">--</span>
|
||||||
|
<span class="summary-unit">MHz</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="summary-card">
|
||||||
|
<div class="summary-label-row">
|
||||||
|
<span class="status-dot status-ok" id="dot_snr" aria-hidden="true"></span>
|
||||||
|
<span class="summary-label">SNR</span>
|
||||||
|
</div>
|
||||||
|
<div class="summary-value-wrapper">
|
||||||
|
<span class="summary-value value-ok" id="sum_snr">--</span>
|
||||||
|
<span class="summary-unit">dB</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="summary-card">
|
||||||
|
<div class="summary-label-row">
|
||||||
|
<span class="status-dot status-ok" id="dot_uimd" aria-hidden="true"></span>
|
||||||
|
<span class="summary-label">UIMD</span>
|
||||||
|
</div>
|
||||||
|
<div class="summary-value-wrapper">
|
||||||
|
<span class="summary-value value-ok" id="sum_uimd">--</span>
|
||||||
|
<span class="summary-unit">dBc</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="summary-card">
|
||||||
|
<div class="summary-label-row">
|
||||||
|
<span class="status-dot status-ok" id="dot_limd" aria-hidden="true"></span>
|
||||||
|
<span class="summary-label">LIMD</span>
|
||||||
|
</div>
|
||||||
|
<div class="summary-value-wrapper">
|
||||||
|
<span class="summary-value value-ok" id="sum_limd">--</span>
|
||||||
|
<span class="summary-unit">dBc</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="summary-card">
|
||||||
|
<div class="summary-label-row">
|
||||||
|
<span class="status-dot status-off" id="dot_rf" aria-hidden="true"></span>
|
||||||
|
<span class="summary-label">RF Switch</span>
|
||||||
|
</div>
|
||||||
|
<div class="summary-value-wrapper">
|
||||||
|
<span class="summary-value value-muted" id="sum_rf">--</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="summary-card">
|
||||||
|
<div class="summary-label-row">
|
||||||
|
<span class="status-dot status-ok" id="dot_outpow" aria-hidden="true"></span>
|
||||||
|
<span class="summary-label">Output Power</span>
|
||||||
|
</div>
|
||||||
|
<div class="summary-value-wrapper">
|
||||||
|
<span class="summary-value value-ok" id="sum_outpow">--</span>
|
||||||
|
<span class="summary-unit">dBm</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="summary-card">
|
||||||
|
<div class="summary-label-row">
|
||||||
|
<span class="status-dot status-neutral" id="dot_input" aria-hidden="true"></span>
|
||||||
|
<span class="summary-label">Input Source</span>
|
||||||
|
</div>
|
||||||
|
<div class="summary-value-wrapper">
|
||||||
|
<span class="summary-value value-neutral" id="sum_input">--</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="summary-card">
|
||||||
|
<div class="summary-label-row">
|
||||||
|
<span class="status-dot status-neutral" id="dot_input_status" aria-hidden="true"></span>
|
||||||
|
<span class="summary-label">Input Status</span>
|
||||||
|
</div>
|
||||||
|
<div class="summary-value-wrapper">
|
||||||
|
<span class="summary-value value-neutral" id="sum_input_status">--</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="summary-card">
|
||||||
|
<div class="summary-label-row">
|
||||||
|
<span class="status-dot status-neutral" id="dot_bitrate" aria-hidden="true"></span>
|
||||||
|
<span class="summary-label">Bitrate</span>
|
||||||
|
</div>
|
||||||
|
<div class="summary-value-wrapper">
|
||||||
|
<span class="summary-value value-neutral" id="sum_bitrate">--</span>
|
||||||
|
<span class="summary-unit">Mbps</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="summary-card">
|
||||||
|
<div class="summary-label-row">
|
||||||
|
<span class="status-dot status-ok" id="dot_temp" aria-hidden="true"></span>
|
||||||
|
<span class="summary-label">Temperature</span>
|
||||||
|
</div>
|
||||||
|
<div class="summary-value-wrapper">
|
||||||
|
<span class="summary-value value-ok" id="sum_temp">--</span>
|
||||||
|
<span class="summary-unit">°F</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="summary-card">
|
||||||
|
<div class="summary-label-row">
|
||||||
|
<span class="status-dot status-off" id="dot_agc" aria-hidden="true"></span>
|
||||||
|
<span class="summary-label">AGC</span>
|
||||||
|
</div>
|
||||||
|
<div class="summary-value-wrapper">
|
||||||
|
<span class="summary-value value-muted" id="sum_agc">--</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="summary-card">
|
||||||
|
<div class="summary-label-row">
|
||||||
|
<span class="status-dot status-neutral" id="dot_control" aria-hidden="true"></span>
|
||||||
|
<span class="summary-label">Control</span>
|
||||||
|
</div>
|
||||||
|
<div class="summary-value-wrapper">
|
||||||
|
<span class="summary-value value-neutral" id="sum_control">--</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<main class="app-main">
|
||||||
|
<h2>RF Control</h2>
|
||||||
|
<div class="box">
|
||||||
|
<form name="rf_control_form" id="rf_form">
|
||||||
|
<table>
|
||||||
|
<tr>
|
||||||
|
<td>Output Power</td>
|
||||||
|
<td><fieldset>
|
||||||
|
<select style="width:40px" name="pw0" id="pw0">
|
||||||
|
<option value="0">+
|
||||||
|
<option value="1">-
|
||||||
|
</select>
|
||||||
|
<select style="width:40px" name="pw1" id="pw1">
|
||||||
|
<option value="0">0 <option value="1">1 <option value="2">2 <option value="3">3 <option value="4">4 <option value="5">5
|
||||||
|
<option value="6">6 <option value="7">7 <option value="8">8 <option value="9">9 <option value="10">10 <option value="11">11
|
||||||
|
<option value="12">12 <option value="13">13 <option value="14">14 <option value="15">15 <option value="16">16 <option value="17">17
|
||||||
|
<option value="18">18 <option value="19">19 <option value="20">20 <option value="21">21 <option value="22">22 <option value="23">23
|
||||||
|
<option value="24">24 <option value="25">25
|
||||||
|
</select>.
|
||||||
|
<select style="width:40px" name="pw2" id="pw2">
|
||||||
|
<option value="0">00
|
||||||
|
<option value="1">05
|
||||||
|
<option value="2">10
|
||||||
|
<option value="3">15
|
||||||
|
<option value="4">20
|
||||||
|
<option value="5">25
|
||||||
|
<option value="6">30
|
||||||
|
<option value="7">35
|
||||||
|
<option value="8">40
|
||||||
|
<option value="9">45
|
||||||
|
<option value="10">50
|
||||||
|
<option value="11">55
|
||||||
|
<option value="12">60
|
||||||
|
<option value="13">65
|
||||||
|
<option value="14">70
|
||||||
|
<option value="15">75
|
||||||
|
<option value="16">80
|
||||||
|
<option value="17">85
|
||||||
|
<option value="18">90
|
||||||
|
<option value="19">95
|
||||||
|
</select>dBm (-25.00 ~ +5.00dBm)
|
||||||
|
</fieldset></td>
|
||||||
|
<td>
|
||||||
|
<input type="button" class="btn-modern" alt="Set" value="Set" disabled onclick="return exc_sysRfSet();">
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
<td>RF</td>
|
||||||
|
<td>
|
||||||
|
<select name="rfy" id="rfy">
|
||||||
|
<option value="0">Off
|
||||||
|
<option value="1">On
|
||||||
|
</select>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<input type="button" class="btn-modern" alt="Set" value="Set" disabled onclick="return exc_sysRfSet();">
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
<td>AGC</td>
|
||||||
|
<td>
|
||||||
|
<select name="agc" id="agc">
|
||||||
|
<option value="0">Off
|
||||||
|
<option value="1">On
|
||||||
|
</select>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<input type="button" class="btn-modern" alt="Set" value="Set" disabled onclick="return exc_sysRfSet();">
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<tr id="tx_form" style="display: none" >
|
||||||
|
<td >TX</td>
|
||||||
|
<td>
|
||||||
|
<select name="tx" id="tx">
|
||||||
|
<option value="0">Off
|
||||||
|
<option value="1">On
|
||||||
|
</select>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<input type="button" class="btn-modern" alt="Set" value="Set" disabled onclick="return exc_sysRfSet();">
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
<td>RX Frequency</td>
|
||||||
|
<td>
|
||||||
|
<select name="rx_freq" id="rx_freq">
|
||||||
|
<option value="0">57
|
||||||
|
<option value="1">63
|
||||||
|
<option value="2">69
|
||||||
|
<option value="3">79
|
||||||
|
<option value="4">85
|
||||||
|
<option value="5">177
|
||||||
|
<option value="6">183
|
||||||
|
<option value="7">189
|
||||||
|
<option value="8">195
|
||||||
|
<option value="9">201
|
||||||
|
<option value="10">207
|
||||||
|
<option value="11">213
|
||||||
|
<option value="12">473
|
||||||
|
<option value="13">479
|
||||||
|
<option value="14">485
|
||||||
|
<option value="15">491
|
||||||
|
<option value="16">497
|
||||||
|
<option value="17">503
|
||||||
|
<option value="18">509
|
||||||
|
<option value="19">515
|
||||||
|
<option value="20">521
|
||||||
|
<option value="21">527
|
||||||
|
<option value="22">533
|
||||||
|
<option value="23">539
|
||||||
|
<option value="24">545
|
||||||
|
<option value="25">551
|
||||||
|
<option value="26">557
|
||||||
|
<option value="27">563
|
||||||
|
<option value="28">569
|
||||||
|
<option value="29">575
|
||||||
|
<option value="30">581
|
||||||
|
<option value="31">587
|
||||||
|
<option value="32">593
|
||||||
|
<option value="33">599
|
||||||
|
<option value="34">605
|
||||||
|
<option value="35">611
|
||||||
|
<option value="36">617
|
||||||
|
<option value="37">623
|
||||||
|
<option value="38">629
|
||||||
|
<option value="39">635
|
||||||
|
<option value="40">641
|
||||||
|
<option value="41">647
|
||||||
|
<option value="42">653
|
||||||
|
<option value="43">659
|
||||||
|
<option value="44">665
|
||||||
|
<option value="45">671
|
||||||
|
<option value="46">677
|
||||||
|
<option value="47">683
|
||||||
|
<option value="48">689
|
||||||
|
<option value="49">695
|
||||||
|
<option value="50">701
|
||||||
|
<option value="51">707
|
||||||
|
<option value="52">713
|
||||||
|
<option value="53">719
|
||||||
|
<option value="54">725
|
||||||
|
<option value="55">731
|
||||||
|
<option value="56">737
|
||||||
|
<option value="57">743
|
||||||
|
<option value="58">749
|
||||||
|
<option value="59">755
|
||||||
|
<option value="60">761
|
||||||
|
<option value="61">767
|
||||||
|
<option value="62">773
|
||||||
|
<option value="63">779
|
||||||
|
<option value="64">785
|
||||||
|
<option value="65">791
|
||||||
|
<option value="66">797
|
||||||
|
<option value="67">803
|
||||||
|
</select> MHz
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<input type="button" class="btn-modern" id="id_rxfreq_button" alt="Set" value="Set" disabled onclick="return exc_sysRfSet();">
|
||||||
|
<span id="set_rxfreq_note"></span>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td id="freq6m_h">TX Frequency</td>
|
||||||
|
<td id="freq6m_i">
|
||||||
|
<select name="freq6m" id="freq6m">
|
||||||
|
<option value="0">57
|
||||||
|
<option value="1">63
|
||||||
|
<option value="2">69
|
||||||
|
<option value="3">79
|
||||||
|
<option value="4">85
|
||||||
|
<option value="5">177
|
||||||
|
<option value="6">183
|
||||||
|
<option value="7">189
|
||||||
|
<option value="8">195
|
||||||
|
<option value="9">201
|
||||||
|
<option value="10">207
|
||||||
|
<option value="11">213
|
||||||
|
<option value="12">473
|
||||||
|
<option value="13">479
|
||||||
|
<option value="14">485
|
||||||
|
<option value="15">491
|
||||||
|
<option value="16">497
|
||||||
|
<option value="17">503
|
||||||
|
<option value="18">509
|
||||||
|
<option value="19">515
|
||||||
|
<option value="20">521
|
||||||
|
<option value="21">527
|
||||||
|
<option value="22">533
|
||||||
|
<option value="23">539
|
||||||
|
<option value="24">545
|
||||||
|
<option value="25">551
|
||||||
|
<option value="26">557
|
||||||
|
<option value="27">563
|
||||||
|
<option value="28">569
|
||||||
|
<option value="29">575
|
||||||
|
<option value="30">581
|
||||||
|
<option value="31">587
|
||||||
|
<option value="32">593
|
||||||
|
<option value="33">599
|
||||||
|
<option value="34">605
|
||||||
|
<option value="35">611
|
||||||
|
<option value="36">617
|
||||||
|
<option value="37">623
|
||||||
|
<option value="38">629
|
||||||
|
<option value="39">635
|
||||||
|
<option value="40">641
|
||||||
|
<option value="41">647
|
||||||
|
<option value="42">653
|
||||||
|
<option value="43">659
|
||||||
|
<option value="44">665
|
||||||
|
<option value="45">671
|
||||||
|
<option value="46">677
|
||||||
|
<option value="47">683
|
||||||
|
<option value="48">689
|
||||||
|
<option value="49">695
|
||||||
|
<option value="50">701
|
||||||
|
<option value="51">707
|
||||||
|
<option value="52">713
|
||||||
|
<option value="53">719
|
||||||
|
<option value="54">725
|
||||||
|
<option value="55">731
|
||||||
|
<option value="56">737
|
||||||
|
<option value="57">743
|
||||||
|
<option value="58">749
|
||||||
|
<option value="59">755
|
||||||
|
<option value="60">761
|
||||||
|
<option value="61">767
|
||||||
|
<option value="62">773
|
||||||
|
<option value="63">779
|
||||||
|
<option value="64">785
|
||||||
|
<option value="65">791
|
||||||
|
<option value="66">797
|
||||||
|
<option value="67">803
|
||||||
|
</select> MHz
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<input type="button" class="btn-modern" alt="Set" value="Set" disabled onclick="return exc_sysRfSet();">
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
<h2>Reference Output</h2>
|
||||||
|
<table>
|
||||||
|
<tr>
|
||||||
|
<td>10 MHz Output</td>
|
||||||
|
<td>
|
||||||
|
<select name="m10_en" id="m10_en">
|
||||||
|
<option value="0">Off
|
||||||
|
<option value="1">On
|
||||||
|
</select>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<input type="button" class="btn-modern" value="Set" onclick="return m10_set();">
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
<div style="padding: 4px 10px; color: #64748b; font-size: 12px;">
|
||||||
|
Enables the AB5 10 MHz reference clock output. Default Off; resets to Off on every power-up.
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div style="padding: 10px; color: #b91c1c; font-weight: 500;">
|
||||||
|
Warning: Exciter RF Output Power will be reset to -25dBm when the channel(TX Frequency) is changed.
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</main>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="accountModal" class="modal">
|
||||||
|
<div class="modal-content">
|
||||||
|
<div class="modal-header">
|
||||||
|
<h3>ACCOUNT SETTINGS</h3>
|
||||||
|
<span class="close" onclick="closeAccountModal()">×</span>
|
||||||
|
</div>
|
||||||
|
<div class="modal-body">
|
||||||
|
<form id="accountForm" method="post" action="login.cgi?action=change_account" onsubmit="return validateAccountForm()">
|
||||||
|
<table class="modal-table">
|
||||||
|
<tr>
|
||||||
|
<td>Current Username</td>
|
||||||
|
<td><input type="text" id="current_user" name="current_user" readonly></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Current Password</td>
|
||||||
|
<td><input type="password" id="current_pwd" name="current_pwd" required></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>New Username</td>
|
||||||
|
<td><input type="text" id="new_user" name="new_user"></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>New Password</td>
|
||||||
|
<td><input type="password" id="new_pwd" name="new_pwd"></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Confirm Password</td>
|
||||||
|
<td><input type="password" id="confirm_pwd" name="confirm_pwd"></td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
<div class="modal-footer">
|
||||||
|
<input type="button" class="btn-modern" style="background-color: #64748b;" value="Cancel" onclick="closeAccountModal()">
|
||||||
|
<input type="submit" class="btn-modern" value="Save Changes">
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
function toggleSidebar(){
|
||||||
|
document.querySelector('.app-sidebar').classList.toggle('sidebar-open');
|
||||||
|
document.querySelector('.sidebar-overlay').classList.toggle('active');
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -0,0 +1,770 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title id="webtitle"></title>
|
||||||
|
<link href="css/styles.css" rel="stylesheet" media="screen">
|
||||||
|
<script src="js/auth.js"></script>
|
||||||
|
<script src="js/jquery.js"></script>
|
||||||
|
<script src="js/dashboard.js"></script>
|
||||||
|
<style>
|
||||||
|
/* inherit the page's colours: styles.css themes this shell light or dark */
|
||||||
|
.spec-toolbar { display:flex; flex-wrap:wrap; gap:18px; align-items:center; margin-bottom:10px; }
|
||||||
|
.spec-toolbar label { font-size:13px; color:inherit; }
|
||||||
|
.spec-readouts { display:flex; flex-wrap:wrap; gap:10px; margin-top:12px; }
|
||||||
|
.spec-readout { min-width:130px; padding:8px 12px; border:1px solid rgba(148,163,184,0.35); border-radius:6px; }
|
||||||
|
.spec-readout .k { display:block; font-size:11px; letter-spacing:.04em; text-transform:uppercase; opacity:.7; }
|
||||||
|
.spec-readout .v { display:block; font-size:18px; font-weight:600; }
|
||||||
|
#spec_canvas { width:100%; height:420px; display:block; background:#0b1220; border-radius:6px; }
|
||||||
|
#eye_canvas { width:100%; height:380px; display:block; background:#0b1220; border-radius:6px; }
|
||||||
|
#eye_state { font-size:13px; opacity:.7; margin-left:auto; }
|
||||||
|
#spec_state { font-size:13px; opacity:.7; margin-left:auto; }
|
||||||
|
</style>
|
||||||
|
<script>
|
||||||
|
var lastTime = new Date().getTime();
|
||||||
|
var currentTime = new Date().getTime();
|
||||||
|
var timeOut = 20 * 60 * 1000; // 20 minutes
|
||||||
|
|
||||||
|
$(function(){
|
||||||
|
$(document).on('mousemove keydown click scroll touchstart', function(){
|
||||||
|
lastTime = new Date().getTime();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
function testTime(){
|
||||||
|
currentTime = new Date().getTime();
|
||||||
|
if(currentTime - lastTime > timeOut){
|
||||||
|
window.location.href="login.cgi?logout=1";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
window.setInterval(testTime, 1000);
|
||||||
|
setInterval(refreshDashboard, 3000);
|
||||||
|
|
||||||
|
function get_remote_local_ctrl()
|
||||||
|
{
|
||||||
|
$.get("atsc_status_cfg.cgi?sys_cfg=&", function(data, status){
|
||||||
|
if (typeof data === 'object' && data !== null) return;
|
||||||
|
var table = String(data).split("|");
|
||||||
|
document.title = table[0].split("#")[11];
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function refresh_show(){
|
||||||
|
get_remote_local_ctrl();
|
||||||
|
refreshDashboard();
|
||||||
|
specInit();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ================= ORx IQ spectrum =================
|
||||||
|
* iq_spectrum.cgi hands back the newest window analysed by the app's iq_rx
|
||||||
|
* thread: a 1024-point Welch over one 26.2 ms window of the 10 MSPS complex
|
||||||
|
* ORx stream. psd[] is in dB relative to the mean in-band flat density
|
||||||
|
* (|f| < 2.5 MHz) -- the only shoulder yardstick that does not move when the
|
||||||
|
* FFT length changes. See Notes/Result06-5.md section 7.
|
||||||
|
*/
|
||||||
|
var SPEC_TIMER = null;
|
||||||
|
var specPeak = null; // peak-hold trace
|
||||||
|
var specLast = null;
|
||||||
|
var specFails = 0;
|
||||||
|
|
||||||
|
var Y_TOP = 30, Y_BOT = -80; // dB rel in-band flat density
|
||||||
|
var SH_LO = 3.5, SH_HI = 4.8; // shoulder band the app takes the median over
|
||||||
|
|
||||||
|
function specInit(){
|
||||||
|
window.addEventListener('resize', function(){ if (specLast) drawSpectrum(specLast); else drawGrid(); });
|
||||||
|
drawGrid();
|
||||||
|
specRestart();
|
||||||
|
eyeRestart();
|
||||||
|
}
|
||||||
|
|
||||||
|
function specRestart(){
|
||||||
|
if (SPEC_TIMER) clearInterval(SPEC_TIMER);
|
||||||
|
if (document.getElementById('spec_pause').checked) { setState('paused'); return; }
|
||||||
|
var ms = Number(document.getElementById('spec_rate').value);
|
||||||
|
specFetch();
|
||||||
|
SPEC_TIMER = setInterval(specFetch, ms);
|
||||||
|
}
|
||||||
|
|
||||||
|
function setState(s){ document.getElementById('spec_state').innerText = s; }
|
||||||
|
|
||||||
|
function specFetch(){
|
||||||
|
$.ajax({url: 'iq_spectrum.cgi?t=' + Date.now(), dataType: 'json', cache: false})
|
||||||
|
.done(function(d){
|
||||||
|
if (!d || d.error){
|
||||||
|
if (d && d.redirect) { window.location.href = d.redirect; return; }
|
||||||
|
setState(d && d.error === 'nodata' ? 'no window captured yet' : 'error');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
specFails = 0;
|
||||||
|
specLast = d;
|
||||||
|
updateReadouts(d);
|
||||||
|
drawSpectrum(d);
|
||||||
|
setState('window ' + d.wid + ' | updated ' + new Date().toLocaleTimeString());
|
||||||
|
})
|
||||||
|
.fail(function(){ specFails++; setState('fetch failed (' + specFails + ')'); });
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateReadouts(d){
|
||||||
|
document.getElementById('rd_shoulder').innerText = d.shoulder.toFixed(1);
|
||||||
|
document.getElementById('rd_limd').innerText = (d.limd === undefined) ? '--' : d.limd.toFixed(1);
|
||||||
|
document.getElementById('rd_uimd').innerText = (d.uimd === undefined) ? '--' : d.uimd.toFixed(1);
|
||||||
|
document.getElementById('rd_pilot').innerText = d.pilot.toFixed(4);
|
||||||
|
document.getElementById('rd_peak').innerText = d.peak.toFixed(1);
|
||||||
|
document.getElementById('rd_rbw').innerText = d.rbw_khz.toFixed(2);
|
||||||
|
document.getElementById('rd_pkts').innerText = d.pkts + '/' + d.npkt;
|
||||||
|
document.getElementById('rd_ms').innerText = d.ms.toFixed(2);
|
||||||
|
document.getElementById('rd_pkts').style.color = (d.pkts === d.npkt) ? '' : '#ef4444';
|
||||||
|
var fld = document.getElementById('rd_field');
|
||||||
|
fld.innerText = (d.ms > 24.2) ? 'yes' : 'no'; // one ATSC data field = 24.2 ms
|
||||||
|
fld.style.color = (d.ms > 24.2) ? '#22c55e' : '#ef4444';
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* ================= 8VSB eye =================
|
||||||
|
* iq_eye.cgi returns the newest window demodulated by the app's iq_vsb thread:
|
||||||
|
* matched filter -> j^k derotation -> 130 x 192 persistence map (base64, log-scaled).
|
||||||
|
* The demod is expensive and nice'd, so a new eye lands roughly every 10 s; the page
|
||||||
|
* polls at the same rate as the spectrum and redraws only when the window id changes.
|
||||||
|
*/
|
||||||
|
var EYE_TIMER = null, eyeWid = -1, eyeFails = 0;
|
||||||
|
|
||||||
|
function eyeRestart(){
|
||||||
|
if (EYE_TIMER) clearInterval(EYE_TIMER);
|
||||||
|
if (document.getElementById('spec_pause').checked) return;
|
||||||
|
eyeFetch();
|
||||||
|
EYE_TIMER = setInterval(eyeFetch, Number(document.getElementById('spec_rate').value));
|
||||||
|
}
|
||||||
|
|
||||||
|
function eyeFetch(){
|
||||||
|
$.ajax({url: 'iq_eye.cgi?t=' + Date.now(), dataType: 'json', cache: false})
|
||||||
|
.done(function(d){
|
||||||
|
var st = document.getElementById('eye_state');
|
||||||
|
if (!d || d.error){
|
||||||
|
if (d && d.redirect) { window.location.href = d.redirect; return; }
|
||||||
|
st.innerText = (d && d.error === 'nodata') ? 'no window demodulated yet' : 'error';
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!d.sync){ st.innerText = 'no symbol lock'; return; }
|
||||||
|
eyeFails = 0;
|
||||||
|
eyeReadouts(d);
|
||||||
|
if (d.wid !== eyeWid){ eyeWid = d.wid; drawEye(d); }
|
||||||
|
st.innerText = 'window ' + d.wid + ' | ' + d.nsym + ' symbols | updated ' +
|
||||||
|
new Date(d.ts * 1000).toLocaleTimeString();
|
||||||
|
})
|
||||||
|
.fail(function(){ eyeFails++;
|
||||||
|
document.getElementById('eye_state').innerText = 'fetch failed (' + eyeFails + ')'; });
|
||||||
|
}
|
||||||
|
|
||||||
|
function eyeReadouts(d){
|
||||||
|
var minh = Math.min.apply(null, d.eye_h);
|
||||||
|
var sAvg = d.sigma.reduce(function(a,b){ return a + b; }, 0) / d.sigma.length;
|
||||||
|
document.getElementById('rd_snr').innerText = d.snr_db.toFixed(2);
|
||||||
|
document.getElementById('rd_eyeh').innerText = minh.toFixed(2);
|
||||||
|
document.getElementById('rd_eyew').innerText = d.eye_w_ui.toFixed(3);
|
||||||
|
document.getElementById('rd_tau').innerText = d.tau.toFixed(4);
|
||||||
|
document.getElementById('rd_segsync').innerText = d.segsync_ratio.toFixed(1);
|
||||||
|
document.getElementById('rd_coff').innerText = d.carrier_off_hz.toFixed(3);
|
||||||
|
document.getElementById('rd_snrraw').innerText = (d.snr_raw_db === undefined) ? '--' : d.snr_raw_db.toFixed(2);
|
||||||
|
document.getElementById('rd_gjit').innerText = (d.gain_jitter_pct === undefined) ? '--' : d.gain_jitter_pct.toFixed(2);
|
||||||
|
var gj = document.getElementById('rd_gjit');
|
||||||
|
gj.style.color = (d.gain_jitter_pct < 1.0) ? '#22c55e' : (d.gain_jitter_pct < 4 ? '#f59e0b' : '#ef4444');
|
||||||
|
/* min(eye_h) should track 2 - 6*sigma. A big shortfall means ISI or non-Gaussian
|
||||||
|
* distortion -- something a single SNR number cannot show. Guard the absolute
|
||||||
|
* value too: once sigma is large, 2-6*sigma goes negative and a shut eye would
|
||||||
|
* otherwise pass the relative test. */
|
||||||
|
var el = document.getElementById('rd_eyeh');
|
||||||
|
el.style.color = (minh > 0.6 && minh > 2 - 6 * sAvg - 0.35) ? '#22c55e'
|
||||||
|
: (minh > 0.3 ? '#f59e0b' : '#ef4444');
|
||||||
|
var sn = document.getElementById('rd_snr');
|
||||||
|
sn.style.color = (d.snr_db >= 27) ? '#22c55e' : (d.snr_db >= 20 ? '#f59e0b' : '#ef4444');
|
||||||
|
}
|
||||||
|
|
||||||
|
function drawEye(d){
|
||||||
|
var c = document.getElementById('eye_canvas');
|
||||||
|
var dpr = window.devicePixelRatio || 1;
|
||||||
|
var W = c.clientWidth, H = c.clientHeight;
|
||||||
|
if (c.width !== Math.round(W*dpr) || c.height !== Math.round(H*dpr)){
|
||||||
|
c.width = Math.round(W*dpr); c.height = Math.round(H*dpr);
|
||||||
|
}
|
||||||
|
var g = c.getContext('2d');
|
||||||
|
g.setTransform(dpr,0,0,dpr,0,0);
|
||||||
|
g.clearRect(0,0,W,H);
|
||||||
|
g.fillStyle = '#0b1220'; g.fillRect(0,0,W,H);
|
||||||
|
|
||||||
|
var cols = d.eye.cols, rows = d.eye.rows, amp = d.eye.amp;
|
||||||
|
var bin = atob(d.eye.data), x, y;
|
||||||
|
/* Build the histogram off-screen at its native size and let the browser scale it:
|
||||||
|
* one putImageData beats stroking a thousand paths. */
|
||||||
|
var off = document.createElement('canvas');
|
||||||
|
off.width = cols; off.height = rows;
|
||||||
|
var og = off.getContext('2d');
|
||||||
|
var img = og.createImageData(cols, rows);
|
||||||
|
for (x = 0; x < cols; x++){
|
||||||
|
for (y = 0; y < rows; y++){
|
||||||
|
var v = bin.charCodeAt(x * rows + y) / 255; /* column-major, row 0 = -amp */
|
||||||
|
var p = ((rows - 1 - y) * cols + x) * 4; /* canvas y grows downward */
|
||||||
|
img.data[p] = Math.min(255, 40 + 255 * Math.pow(v, 0.75));
|
||||||
|
img.data[p + 1] = Math.min(255, 20 + 200 * Math.pow(v, 1.6));
|
||||||
|
img.data[p + 2] = Math.min(255, 60 + 120 * Math.pow(v, 2.6));
|
||||||
|
img.data[p + 3] = v > 0 ? 255 : 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
og.putImageData(img, 0, 0);
|
||||||
|
|
||||||
|
var L = 46, R = 12, T = 10, B = 28;
|
||||||
|
g.imageSmoothingEnabled = true;
|
||||||
|
g.drawImage(off, L, T, W - L - R, H - T - B);
|
||||||
|
|
||||||
|
function yOfLvl(v){ return T + (amp - v) / (2 * amp) * (H - T - B); }
|
||||||
|
g.strokeStyle = 'rgba(57,208,255,0.45)'; g.lineWidth = 0.7;
|
||||||
|
[-7,-5,-3,-1,1,3,5,7].forEach(function(v){
|
||||||
|
var yy = yOfLvl(v);
|
||||||
|
g.beginPath(); g.moveTo(L,yy); g.lineTo(W-R,yy); g.stroke();
|
||||||
|
});
|
||||||
|
var xc = L + (W - L - R) / 2; /* decision instant = centre column */
|
||||||
|
g.strokeStyle = '#a3e635'; g.setLineDash([4,3]);
|
||||||
|
g.beginPath(); g.moveTo(xc,T); g.lineTo(xc,H-B); g.stroke();
|
||||||
|
g.setLineDash([]);
|
||||||
|
|
||||||
|
g.fillStyle = '#94a3b8'; g.font = '11px sans-serif';
|
||||||
|
g.textAlign = 'right'; g.textBaseline = 'middle';
|
||||||
|
[-7,-5,-3,-1,1,3,5,7].forEach(function(v){ g.fillText(v.toFixed(0), L-6, yOfLvl(v)); });
|
||||||
|
g.textAlign = 'center'; g.textBaseline = 'top';
|
||||||
|
[-1,-0.5,0,0.5,1].forEach(function(u){
|
||||||
|
g.fillText(u.toFixed(1), L + (u+1)/2*(W-L-R), H-B+5);
|
||||||
|
});
|
||||||
|
g.fillStyle = '#64748b'; g.textBaseline = 'bottom';
|
||||||
|
g.fillText('symbol periods (UI) - decision instant at 0', (L+W-R)/2, H-2);
|
||||||
|
g.save(); g.translate(12,(T+H-B)/2); g.rotate(-Math.PI/2);
|
||||||
|
g.textBaseline = 'top'; g.fillText('normalised I level', 0, 0); g.restore();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ---- canvas ---- */
|
||||||
|
function specGeom(){
|
||||||
|
var c = document.getElementById('spec_canvas');
|
||||||
|
var dpr = window.devicePixelRatio || 1;
|
||||||
|
var w = c.clientWidth, h = c.clientHeight;
|
||||||
|
if (c.width !== Math.round(w*dpr) || c.height !== Math.round(h*dpr)){
|
||||||
|
c.width = Math.round(w*dpr); c.height = Math.round(h*dpr);
|
||||||
|
}
|
||||||
|
var g = c.getContext('2d');
|
||||||
|
g.setTransform(dpr,0,0,dpr,0,0);
|
||||||
|
return {g:g, w:w, h:h, l:56, r:14, t:14, b:30};
|
||||||
|
}
|
||||||
|
function xOf(m, f, fmin, fmax){ return m.l + (f - fmin)/(fmax - fmin) * (m.w - m.l - m.r); }
|
||||||
|
function yOf(m, db){ return m.t + (Y_TOP - db)/(Y_TOP - Y_BOT) * (m.h - m.t - m.b); }
|
||||||
|
|
||||||
|
function drawGrid(fmin, fmax){
|
||||||
|
if (fmin === undefined){ fmin = -5; fmax = 5; }
|
||||||
|
var m = specGeom(), g = m.g, f, db;
|
||||||
|
g.clearRect(0,0,m.w,m.h);
|
||||||
|
g.fillStyle = '#0b1220'; g.fillRect(0,0,m.w,m.h);
|
||||||
|
|
||||||
|
g.fillStyle = 'rgba(56,189,248,0.10)'; // the band the shoulder is measured in
|
||||||
|
[[SH_LO,SH_HI],[-SH_HI,-SH_LO]].forEach(function(b){
|
||||||
|
var x0 = xOf(m,Math.max(b[0],fmin),fmin,fmax), x1 = xOf(m,Math.min(b[1],fmax),fmin,fmax);
|
||||||
|
g.fillRect(x0, m.t, x1-x0, m.h-m.t-m.b);
|
||||||
|
});
|
||||||
|
|
||||||
|
g.lineWidth = 1;
|
||||||
|
g.font = '11px sans-serif';
|
||||||
|
g.textAlign = 'center'; g.textBaseline = 'top';
|
||||||
|
for (f = Math.ceil(fmin); f <= fmax; f++){
|
||||||
|
var x = Math.round(xOf(m,f,fmin,fmax)) + 0.5;
|
||||||
|
g.strokeStyle = '#1e293b';
|
||||||
|
g.beginPath(); g.moveTo(x,m.t); g.lineTo(x,m.h-m.b); g.stroke();
|
||||||
|
g.fillStyle = '#94a3b8'; g.fillText(f.toFixed(0), x, m.h-m.b+5);
|
||||||
|
}
|
||||||
|
g.textAlign = 'right'; g.textBaseline = 'middle';
|
||||||
|
for (db = Y_TOP; db >= Y_BOT; db -= 10){
|
||||||
|
var y = Math.round(yOf(m,db)) + 0.5;
|
||||||
|
g.strokeStyle = (db === 0) ? '#334155' : '#1e293b';
|
||||||
|
g.beginPath(); g.moveTo(m.l,y); g.lineTo(m.w-m.r,y); g.stroke();
|
||||||
|
g.fillStyle = '#94a3b8'; g.fillText(db.toFixed(0), m.l-6, y);
|
||||||
|
}
|
||||||
|
g.fillStyle = '#64748b'; g.textAlign = 'center'; g.textBaseline = 'bottom';
|
||||||
|
g.fillText('MHz from carrier', (m.l+m.w-m.r)/2, m.h-2);
|
||||||
|
g.save(); g.translate(12,(m.t+m.h-m.b)/2); g.rotate(-Math.PI/2);
|
||||||
|
g.textBaseline = 'top'; g.fillText('dB rel. in-band flat density', 0, 0); g.restore();
|
||||||
|
return m;
|
||||||
|
}
|
||||||
|
|
||||||
|
function trace(m, psd, f0, df, fmin, fmax, color, width){
|
||||||
|
var g = m.g, i, started = false;
|
||||||
|
g.strokeStyle = color; g.lineWidth = width; g.beginPath();
|
||||||
|
for (i = 0; i < psd.length; i++){
|
||||||
|
var f = f0 + i*df;
|
||||||
|
if (f < fmin || f > fmax) continue;
|
||||||
|
var x = xOf(m,f,fmin,fmax), y = yOf(m, Math.max(Math.min(psd[i],Y_TOP),Y_BOT));
|
||||||
|
if (!started){ g.moveTo(x,y); started = true; } else g.lineTo(x,y);
|
||||||
|
}
|
||||||
|
g.stroke();
|
||||||
|
}
|
||||||
|
|
||||||
|
function drawSpectrum(d){
|
||||||
|
var fmin = d.f0, fmax = d.f0 + (d.n-1)*d.df;
|
||||||
|
var m = drawGrid(fmin, fmax), i;
|
||||||
|
|
||||||
|
if (document.getElementById('spec_hold').checked){
|
||||||
|
if (!specPeak || specPeak.length !== d.psd.length) specPeak = d.psd.slice();
|
||||||
|
else for (i = 0; i < d.psd.length; i++) if (d.psd[i] > specPeak[i]) specPeak[i] = d.psd[i];
|
||||||
|
trace(m, specPeak, d.f0, d.df, fmin, fmax, '#f59e0b', 1);
|
||||||
|
} else specPeak = null;
|
||||||
|
|
||||||
|
trace(m, d.psd, d.f0, d.df, fmin, fmax, '#38bdf8', 1.2);
|
||||||
|
|
||||||
|
var y = yOf(m, d.shoulder); // measured shoulder level
|
||||||
|
m.g.strokeStyle = '#f87171'; m.g.setLineDash([5,4]); m.g.lineWidth = 1;
|
||||||
|
m.g.beginPath(); m.g.moveTo(m.l,y); m.g.lineTo(m.w-m.r,y); m.g.stroke();
|
||||||
|
m.g.setLineDash([]);
|
||||||
|
m.g.fillStyle = '#f87171'; m.g.textAlign = 'left'; m.g.textBaseline = 'bottom';
|
||||||
|
m.g.fillText('shoulder ' + d.shoulder.toFixed(1) + ' dB', m.l+6, y-3);
|
||||||
|
|
||||||
|
var xp = xOf(m, d.pilot, fmin, fmax); // pilot marker
|
||||||
|
m.g.strokeStyle = '#a3e635'; m.g.beginPath();
|
||||||
|
m.g.moveTo(xp, m.t); m.g.lineTo(xp, m.h-m.b); m.g.stroke();
|
||||||
|
m.g.fillStyle = '#a3e635'; m.g.textAlign = 'left'; m.g.textBaseline = 'top';
|
||||||
|
m.g.fillText('pilot ' + d.pilot.toFixed(3) + ' MHz', xp+4, m.t+2);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Opens the modal - gets current username from server
|
||||||
|
function openAccountModal() {
|
||||||
|
// Fetch current username from server
|
||||||
|
$.get("login.cgi?action=get_user", function(data) {
|
||||||
|
var trimmedData = (data || "").trim();
|
||||||
|
if (trimmedData && trimmedData !== "UNAUTHORIZED") {
|
||||||
|
document.getElementById('current_user').value = trimmedData;
|
||||||
|
}
|
||||||
|
document.getElementById('accountModal').style.display = 'block';
|
||||||
|
setTimeout(function() { document.getElementById('current_pwd').focus(); }, 100);
|
||||||
|
}).fail(function() {
|
||||||
|
document.getElementById('accountModal').style.display = 'block';
|
||||||
|
setTimeout(function() { document.getElementById('current_pwd').focus(); }, 100);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Closes the modal and clears the sensitive inputs
|
||||||
|
function closeAccountModal() {
|
||||||
|
document.getElementById('accountModal').style.display = 'none';
|
||||||
|
document.getElementById('current_pwd').value = '';
|
||||||
|
document.getElementById('new_pwd').value = '';
|
||||||
|
document.getElementById('confirm_pwd').value = '';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validates that a string contains only printable characters (excluding space)
|
||||||
|
function isValidPrintableString(str) {
|
||||||
|
// Regular expression to check for printable characters (ASCII 33-126), excluding space
|
||||||
|
// Space is ASCII 32, and we want to exclude it
|
||||||
|
var printableCharRegex = /^[!-~]+$/; // ! is ASCII 33, ~ is ASCII 126
|
||||||
|
return printableCharRegex.test(str);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validates the passwords match before submitting to the CGI script - All required fields must be filled
|
||||||
|
function validateAccountForm() {
|
||||||
|
var currentUser = document.getElementById('current_user').value;
|
||||||
|
var currentPwd = document.getElementById('current_pwd').value;
|
||||||
|
var newUsername = document.getElementById('new_user').value;
|
||||||
|
var newPwd = document.getElementById('new_pwd').value;
|
||||||
|
var confirmPwd = document.getElementById('confirm_pwd').value;
|
||||||
|
|
||||||
|
// Current password is required (cannot be empty)
|
||||||
|
if (!currentPwd || currentPwd.trim() === "") {
|
||||||
|
alert("Current password is required");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate current password contains only printable characters
|
||||||
|
if (!isValidPrintableString(currentPwd)) {
|
||||||
|
alert("Current password contains invalid characters. Only printable characters (excluding space) are allowed.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// New password is required (cannot be empty)
|
||||||
|
if (!newPwd || newPwd.trim() === "") {
|
||||||
|
alert("New password is required");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate new password contains only printable characters
|
||||||
|
if (!isValidPrintableString(newPwd)) {
|
||||||
|
alert("New password contains invalid characters. Only printable characters (excluding space) are allowed.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate new password length (max 16 chars)
|
||||||
|
if (newPwd.length > 16) {
|
||||||
|
alert("New password must be no more than 16 characters");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate new password length
|
||||||
|
if (newPwd.length < 6) {
|
||||||
|
alert("New password must be at least 6 characters");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Confirm password must match new password
|
||||||
|
if (newPwd !== confirmPwd) {
|
||||||
|
alert("New passwords do not match");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate confirm password contains only printable characters
|
||||||
|
if (!isValidPrintableString(confirmPwd)) {
|
||||||
|
alert("Confirm password contains invalid characters. Only printable characters (excluding space) are allowed.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate confirm password length (max 16 chars)
|
||||||
|
if (confirmPwd.length > 16) {
|
||||||
|
alert("Confirm password must be no more than 16 characters");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate new username if provided
|
||||||
|
if (newUsername && newUsername.trim() !== "") {
|
||||||
|
// Validate new username contains only printable characters
|
||||||
|
if (!isValidPrintableString(newUsername)) {
|
||||||
|
alert("New username contains invalid characters. Only printable characters (excluding space) are allowed.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate new username length (max 16 chars)
|
||||||
|
if (newUsername.length > 16) {
|
||||||
|
alert("New username must be no more than 16 characters");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true; // Allows the form to submit
|
||||||
|
}
|
||||||
|
|
||||||
|
// Form submission handler using fetch API
|
||||||
|
document.addEventListener('DOMContentLoaded', function() {
|
||||||
|
var accountForm = document.getElementById('accountForm');
|
||||||
|
if (accountForm) {
|
||||||
|
accountForm.addEventListener('submit', function(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
|
||||||
|
if (!validateAccountForm()) return;
|
||||||
|
|
||||||
|
var formData = new URLSearchParams({
|
||||||
|
Username: document.getElementById('current_user').value,
|
||||||
|
OldPassword: document.getElementById('current_pwd').value,
|
||||||
|
NewUsername: document.getElementById('new_user').value,
|
||||||
|
NewPassword: document.getElementById('new_pwd').value,
|
||||||
|
ConfirmPassword: document.getElementById('confirm_pwd').value
|
||||||
|
});
|
||||||
|
|
||||||
|
fetch('login.cgi?action=change_account', {
|
||||||
|
method: 'POST',
|
||||||
|
body: formData
|
||||||
|
})
|
||||||
|
.then(r => r.json())
|
||||||
|
.then(data => {
|
||||||
|
if (data.success) {
|
||||||
|
alert("Update successful! Please login again.");
|
||||||
|
closeAccountModal();
|
||||||
|
// Redirect to login page after 1.5 seconds
|
||||||
|
setTimeout(function() {
|
||||||
|
window.location.href = 'login.cgi?logout=1';
|
||||||
|
}, 1500);
|
||||||
|
} else {
|
||||||
|
alert(data.error || "Update failed");
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(function(err) {
|
||||||
|
alert("Network error: " + err);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Optional: Closes the modal if the user clicks the dark background outside the box
|
||||||
|
window.onclick = function(event) {
|
||||||
|
var modal = document.getElementById('accountModal');
|
||||||
|
if (event.target == modal) {
|
||||||
|
closeAccountModal();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
</script>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body onload="refresh_show()">
|
||||||
|
|
||||||
|
|
||||||
|
<div class="app-layout">
|
||||||
|
<aside class="app-sidebar">
|
||||||
|
<ul class="items">
|
||||||
|
<li><a href="status_info.html" title="Status">Status</a></li>
|
||||||
|
<li><a href="sys_set.html" title="Settings">Settings</a></li>
|
||||||
|
<li><a href="sys_rf.html" title="RF Control">RF Control</a></li>
|
||||||
|
<li><a href="sys_psip.html" title="TSID&PSIP">TSID&PSIP</a></li>
|
||||||
|
<li><a href="sys_ts.html" title="TSoIP">TSoIP</a></li>
|
||||||
|
<li class="active"><a href="sys_spectrum.html" title="Spectrum">Spectrum</a></li>
|
||||||
|
<li><a href="log_output.html" title="Log">Log</a></li>
|
||||||
|
</ul>
|
||||||
|
<div class="sidebar-footer">
|
||||||
|
<h4>Anywave Broadcast Inc.</h4>
|
||||||
|
<p>Copyright 2026<br><br><span class="redbox-label">Technical Support</span><br>+1 847 415 2258<br><a href="mailto:support@anywaveus.com">support@anywaveus.com</a></p>
|
||||||
|
</div>
|
||||||
|
</aside>
|
||||||
|
<div class="sidebar-overlay" onclick="toggleSidebar()"></div>
|
||||||
|
|
||||||
|
<header class="app-header">
|
||||||
|
<button class="menu-toggle" onclick="toggleSidebar()" aria-label="Toggle menu">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||||
|
<line x1="3" y1="12" x2="21" y2="12"></line>
|
||||||
|
<line x1="3" y1="6" x2="21" y2="6"></line>
|
||||||
|
<line x1="3" y1="18" x2="21" y2="18"></line>
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
<h1><a href="https://anywavecom.net/" class="logo-bg" title="Anywave Broadcast Inc."></a></h1>
|
||||||
|
<h2 id="webtitle_header"><span></span></h2>
|
||||||
|
<h3>
|
||||||
|
<div class="dropdown">
|
||||||
|
<button class="dropbtn-modern">Admin ▾</button>
|
||||||
|
<div class="dropdown-content">
|
||||||
|
<a href="#" onclick="openAccountModal(); return false;">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||||
|
<circle cx="12" cy="12" r="3"></circle>
|
||||||
|
<path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1 0 2.83 2 2 0 0 1-2.83 0l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-2 2 2 2 0 0 1-2-2v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06-.06a2 2 0 0 1-2.83 0 2 2 0 0 1 0-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1-2-2 2 2 0 0 1 2-2h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 0-2.83 2 2 0 0 1 2.83 0l.06-.06a1.65 1.65 0 0 0 1.82.33H9a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 2-2 2 2 0 0 1 2 2v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 0 2 2 0 0 1 0 2.83l-.06-.06a1.65 1.65 0 0 0-.33 1.82V9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 2 2 2 2 0 0 1-2 2h-.09a1.65 1.65 0 0 0-1.51 1z"></path>
|
||||||
|
</svg>
|
||||||
|
Account Settings
|
||||||
|
</a>
|
||||||
|
<a href="login.cgi?logout=1">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||||
|
<path d="M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4"></path>
|
||||||
|
<polyline points="16 17 21 12 16 7"></polyline>
|
||||||
|
<line x1="21" y1="12" x2="9" y2="12"></line>
|
||||||
|
</svg>
|
||||||
|
Logout
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</h3>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<!-- Fixed Dashboard Summary - Top of page, under header -->
|
||||||
|
<div class="dashboard-fixed">
|
||||||
|
<div class="summary-dashboard">
|
||||||
|
<div class="summary-card">
|
||||||
|
<div class="summary-label-row">
|
||||||
|
<span class="status-dot status-neutral" id="dot_freq" aria-hidden="true"></span>
|
||||||
|
<span class="summary-label">Frequency</span>
|
||||||
|
</div>
|
||||||
|
<div class="summary-value-wrapper">
|
||||||
|
<span class="summary-value value-neutral" id="sum_freq">--</span>
|
||||||
|
<span class="summary-unit">MHz</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="summary-card">
|
||||||
|
<div class="summary-label-row">
|
||||||
|
<span class="status-dot status-ok" id="dot_snr" aria-hidden="true"></span>
|
||||||
|
<span class="summary-label">SNR</span>
|
||||||
|
</div>
|
||||||
|
<div class="summary-value-wrapper">
|
||||||
|
<span class="summary-value value-ok" id="sum_snr">--</span>
|
||||||
|
<span class="summary-unit">dB</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="summary-card">
|
||||||
|
<div class="summary-label-row">
|
||||||
|
<span class="status-dot status-ok" id="dot_uimd" aria-hidden="true"></span>
|
||||||
|
<span class="summary-label">UIMD</span>
|
||||||
|
</div>
|
||||||
|
<div class="summary-value-wrapper">
|
||||||
|
<span class="summary-value value-ok" id="sum_uimd">--</span>
|
||||||
|
<span class="summary-unit">dBc</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="summary-card">
|
||||||
|
<div class="summary-label-row">
|
||||||
|
<span class="status-dot status-ok" id="dot_limd" aria-hidden="true"></span>
|
||||||
|
<span class="summary-label">LIMD</span>
|
||||||
|
</div>
|
||||||
|
<div class="summary-value-wrapper">
|
||||||
|
<span class="summary-value value-ok" id="sum_limd">--</span>
|
||||||
|
<span class="summary-unit">dBc</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="summary-card">
|
||||||
|
<div class="summary-label-row">
|
||||||
|
<span class="status-dot status-off" id="dot_rf" aria-hidden="true"></span>
|
||||||
|
<span class="summary-label">RF Switch</span>
|
||||||
|
</div>
|
||||||
|
<div class="summary-value-wrapper">
|
||||||
|
<span class="summary-value value-muted" id="sum_rf">--</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="summary-card">
|
||||||
|
<div class="summary-label-row">
|
||||||
|
<span class="status-dot status-ok" id="dot_outpow" aria-hidden="true"></span>
|
||||||
|
<span class="summary-label">Output Power</span>
|
||||||
|
</div>
|
||||||
|
<div class="summary-value-wrapper">
|
||||||
|
<span class="summary-value value-ok" id="sum_outpow">--</span>
|
||||||
|
<span class="summary-unit">dBm</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="summary-card">
|
||||||
|
<div class="summary-label-row">
|
||||||
|
<span class="status-dot status-neutral" id="dot_input" aria-hidden="true"></span>
|
||||||
|
<span class="summary-label">Input Source</span>
|
||||||
|
</div>
|
||||||
|
<div class="summary-value-wrapper">
|
||||||
|
<span class="summary-value value-neutral" id="sum_input">--</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="summary-card">
|
||||||
|
<div class="summary-label-row">
|
||||||
|
<span class="status-dot status-neutral" id="dot_input_status" aria-hidden="true"></span>
|
||||||
|
<span class="summary-label">Input Status</span>
|
||||||
|
</div>
|
||||||
|
<div class="summary-value-wrapper">
|
||||||
|
<span class="summary-value value-neutral" id="sum_input_status">--</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="summary-card">
|
||||||
|
<div class="summary-label-row">
|
||||||
|
<span class="status-dot status-neutral" id="dot_bitrate" aria-hidden="true"></span>
|
||||||
|
<span class="summary-label">Bitrate</span>
|
||||||
|
</div>
|
||||||
|
<div class="summary-value-wrapper">
|
||||||
|
<span class="summary-value value-neutral" id="sum_bitrate">--</span>
|
||||||
|
<span class="summary-unit">Mbps</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="summary-card">
|
||||||
|
<div class="summary-label-row">
|
||||||
|
<span class="status-dot status-ok" id="dot_temp" aria-hidden="true"></span>
|
||||||
|
<span class="summary-label">Temperature</span>
|
||||||
|
</div>
|
||||||
|
<div class="summary-value-wrapper">
|
||||||
|
<span class="summary-value value-ok" id="sum_temp">--</span>
|
||||||
|
<span class="summary-unit">°F</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="summary-card">
|
||||||
|
<div class="summary-label-row">
|
||||||
|
<span class="status-dot status-off" id="dot_agc" aria-hidden="true"></span>
|
||||||
|
<span class="summary-label">AGC</span>
|
||||||
|
</div>
|
||||||
|
<div class="summary-value-wrapper">
|
||||||
|
<span class="summary-value value-muted" id="sum_agc">--</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="summary-card">
|
||||||
|
<div class="summary-label-row">
|
||||||
|
<span class="status-dot status-neutral" id="dot_control" aria-hidden="true"></span>
|
||||||
|
<span class="summary-label">Control</span>
|
||||||
|
</div>
|
||||||
|
<div class="summary-value-wrapper">
|
||||||
|
<span class="summary-value value-neutral" id="sum_control">--</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<main class="app-main">
|
||||||
|
<h2>ORx Receive Spectrum</h2>
|
||||||
|
<div class="box">
|
||||||
|
<div class="spec-toolbar">
|
||||||
|
<label>Refresh
|
||||||
|
<select id="spec_rate" onchange="specRestart()">
|
||||||
|
<option value="500">0.5 s</option>
|
||||||
|
<option value="1000" selected>1 s</option>
|
||||||
|
<option value="2000">2 s</option>
|
||||||
|
<option value="5000">5 s</option>
|
||||||
|
</select>
|
||||||
|
</label>
|
||||||
|
<label><input type="checkbox" id="spec_pause" onchange="specRestart()"> Pause</label>
|
||||||
|
<label><input type="checkbox" id="spec_hold" onchange="specPeak=null"> Peak hold</label>
|
||||||
|
<span id="spec_state">starting…</span>
|
||||||
|
</div>
|
||||||
|
<canvas id="spec_canvas"></canvas>
|
||||||
|
<div class="spec-readouts">
|
||||||
|
<div class="spec-readout"><span class="k">Shoulder</span><span class="v"><span id="rd_shoulder">--</span> dB</span></div>
|
||||||
|
<div class="spec-readout" title="10log10(P@+24kHz / P@3.1494MHz on the pilot side), 11 bins each. Raw dB, without the +11 dB offset the Status page adds."><span class="k">LIMD raw</span><span class="v"><span id="rd_limd">--</span> dB</span></div>
|
||||||
|
<div class="spec-readout" title="10log10(P@+24kHz / P@3.1494MHz opposite the pilot), 11 bins each. Raw dB, without the +11 dB offset the Status page adds."><span class="k">UIMD raw</span><span class="v"><span id="rd_uimd">--</span> dB</span></div>
|
||||||
|
<div class="spec-readout"><span class="k">Pilot</span><span class="v"><span id="rd_pilot">--</span> MHz</span></div>
|
||||||
|
<div class="spec-readout"><span class="k">Peak</span><span class="v"><span id="rd_peak">--</span> dB</span></div>
|
||||||
|
<div class="spec-readout"><span class="k">RBW</span><span class="v"><span id="rd_rbw">--</span> kHz</span></div>
|
||||||
|
<div class="spec-readout"><span class="k">Packets</span><span class="v" id="rd_pkts">--</span></div>
|
||||||
|
<div class="spec-readout"><span class="k">Contiguous</span><span class="v"><span id="rd_ms">--</span> ms</span></div>
|
||||||
|
<div class="spec-readout"><span class="k">> 1 field</span><span class="v" id="rd_field">--</span></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h2>8VSB Eye Diagram</h2>
|
||||||
|
<div class="box">
|
||||||
|
<div class="spec-toolbar">
|
||||||
|
<span style="font-size:13px;opacity:.75">Matched-filtered I rail, 2 symbol periods, log persistence</span>
|
||||||
|
<span id="eye_state">waiting for the demodulator…</span>
|
||||||
|
</div>
|
||||||
|
<canvas id="eye_canvas"></canvas>
|
||||||
|
<div class="spec-readouts">
|
||||||
|
<div class="spec-readout" title="MER, I-path definition: 10log10(sum d^2 / sum (r-d)^2)"><span class="k">SNR / MER</span><span class="v"><span id="rd_snr">--</span> dB</span></div>
|
||||||
|
<div class="spec-readout" title="Smallest of the 7 eye openings at the decision instant (1%/99% percentiles); ideal 2.00"><span class="k">Min eye height</span><span class="v" id="rd_eyeh">--</span></div>
|
||||||
|
<div class="spec-readout" title="Time span over which the central eye stays open"><span class="k">Eye width</span><span class="v"><span id="rd_eyew">--</span> UI</span></div>
|
||||||
|
<div class="spec-readout" title="Sampling phase offset; re-solved for every window because the capture start is not symbol-locked"><span class="k">τ0</span><span class="v"><span id="rd_tau">--</span> sa</span></div>
|
||||||
|
<div class="spec-readout" title="Correlation peak / rms of the 4-symbol segment sync, period 832. Above 10 means locked"><span class="k">Seg sync</span><span class="v" id="rd_segsync">--</span></div>
|
||||||
|
<div class="spec-readout" title="Pilot phase drift across the window. TX and ORx share the LO, so this must be ~0"><span class="k">Carrier offset</span><span class="v"><span id="rd_coff">--</span> Hz</span></div>
|
||||||
|
<div class="spec-readout" title="MER before the ORx AGC gain steps are tracked out. The gap to SNR/MER is what the observation receiver costs you, not the transmitter."><span class="k">SNR raw</span><span class="v"><span id="rd_snrraw">--</span> dB</span></div>
|
||||||
|
<div class="spec-readout" title="rms of the ORx RF AGC gain steps over the window (0.43 dB per gain index). This is a receiver artifact; a dead zone in dpd_rx_rfagc would remove it at the source."><span class="k">ORx AGC jitter</span><span class="v"><span id="rd_gjit">--</span> %</span></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</main>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<div id="accountModal" class="modal">
|
||||||
|
<div class="modal-content">
|
||||||
|
<div class="modal-header">
|
||||||
|
<h3>Account Settings</h3>
|
||||||
|
<span class="close" onclick="closeAccountModal()">×</span>
|
||||||
|
</div>
|
||||||
|
<div class="modal-body">
|
||||||
|
<form id="accountForm" method="post" action="login.cgi?action=change_account" onsubmit="return validateAccountForm()">
|
||||||
|
<table class="modal-table">
|
||||||
|
<tr>
|
||||||
|
<td>Current Username</td>
|
||||||
|
<td><input type="text" id="current_user" name="current_user" readonly></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Current Password</td>
|
||||||
|
<td><input type="password" id="current_pwd" name="current_pwd" required></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>New Username</td>
|
||||||
|
<td><input type="text" id="new_user" name="new_user"></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>New Password</td>
|
||||||
|
<td><input type="password" id="new_pwd" name="new_pwd"></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Confirm Password</td>
|
||||||
|
<td><input type="password" id="confirm_pwd" name="confirm_pwd"></td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
<div class="modal-footer">
|
||||||
|
<input type="button" class="btn-modern" style="background-color: #64748b;" value="Cancel" onclick="closeAccountModal()">
|
||||||
|
<input type="submit" class="btn-modern" value="Save Changes">
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
function toggleSidebar(){
|
||||||
|
document.querySelector('.app-sidebar').classList.toggle('sidebar-open');
|
||||||
|
document.querySelector('.sidebar-overlay').classList.toggle('active');
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -0,0 +1,867 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title id="webtitle"></title>
|
||||||
|
<link href="css/styles.css" rel="stylesheet" media="screen">
|
||||||
|
<script src="js/auth.js"></script>
|
||||||
|
<script src="js/jquery.js"></script>
|
||||||
|
<script src="js/dashboard.js"></script>
|
||||||
|
<script>
|
||||||
|
var time_sec_cnt=0;
|
||||||
|
var g_remot_local_ctrl = 0;// 0 remote 1 local
|
||||||
|
|
||||||
|
var lastTime = new Date().getTime();
|
||||||
|
var currentTime = new Date().getTime();
|
||||||
|
var timeOut = 20 * 60 * 1000; // 20 min
|
||||||
|
|
||||||
|
$(function(){
|
||||||
|
// Listen to multiple types of user activity to prevent timeout
|
||||||
|
$(document).on('mousemove keydown click scroll touchstart', function(){
|
||||||
|
lastTime = new Date().getTime();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
function testTime(){
|
||||||
|
currentTime = new Date().getTime();
|
||||||
|
if(currentTime - lastTime > timeOut){
|
||||||
|
window.location.href="login.cgi?logout=1"
|
||||||
|
}
|
||||||
|
|
||||||
|
time_sec_cnt=time_sec_cnt+1;
|
||||||
|
if(time_sec_cnt%3==0){
|
||||||
|
get_remote_local_ctrl();
|
||||||
|
if(g_remot_local_ctrl==1) { // local
|
||||||
|
SetFormDefaults();
|
||||||
|
}
|
||||||
|
refreshDashboard();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Timer check (1s)
|
||||||
|
window.setInterval(testTime, 1000);
|
||||||
|
refreshDashboard();
|
||||||
|
|
||||||
|
function get_remote_local_ctrl() {
|
||||||
|
var queryData = "sys_cfg=&";
|
||||||
|
$.get("atsc_status_cfg.cgi?"+queryData, function(data, status) {
|
||||||
|
// 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:', data);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var table = data.split("|");
|
||||||
|
g_remot_local_ctrl = Number(table[0].split("#")[5]);
|
||||||
|
document.title = table[0].split("#")[11];
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function SetFormDefaults() {
|
||||||
|
// 1. DISABLE BUTTONS START (only in Remote mode)
|
||||||
|
if(g_remot_local_ctrl == 1) {
|
||||||
|
// Local mode: just fetch data, don't change button text
|
||||||
|
var ops = 0;
|
||||||
|
var i = 0;
|
||||||
|
var queryData = "tsoip_num=&tsoip_systs1=&tsoip_systs2=&web_title=&"
|
||||||
|
} else {
|
||||||
|
// Remote mode: show Loading indicator
|
||||||
|
$('#setnet_id_1, #setcfg_id1').attr("disabled", true).val("Loading...");
|
||||||
|
var ops = 0;
|
||||||
|
var i = 0;
|
||||||
|
var queryData = "tsoip_num=&tsoip_systs1=&tsoip_systs2=&web_title=&"
|
||||||
|
}
|
||||||
|
|
||||||
|
$.get("atsc_status_cfg.cgi?"+queryData, function(data, status) {
|
||||||
|
// 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:', data);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate response structure
|
||||||
|
var table = data.split("|");
|
||||||
|
if (table.length < 4) {
|
||||||
|
console.error("TSoIP: Invalid response - expected 4 sections, got", table.length);
|
||||||
|
$('#setnet_id_1, #setcfg_id1').val("Data Error");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var form = table[0].split("#"); // tsoip_num
|
||||||
|
var tsoip_total_num = Number(form[1]);
|
||||||
|
var tb_systs = table[1].split("#"); // tsoip_systs1
|
||||||
|
var tb_systs2 = table[2].split("#");// tsoip_systs2
|
||||||
|
var title = table[3].split("#");
|
||||||
|
|
||||||
|
// Validate field counts for TSoIP configuration
|
||||||
|
// Expected: Network config (13 fields) + Rx config (12 fields) = 25+ fields
|
||||||
|
if (tb_systs.length < 25) {
|
||||||
|
console.warn("TSoIP: Incomplete data - expected 25+ fields, got", tb_systs.length);
|
||||||
|
console.log("TSoIP data:", tb_systs);
|
||||||
|
}
|
||||||
|
|
||||||
|
var fnet1 = document.getElementById('ts1_net_form');
|
||||||
|
var fcfg1 = document.getElementById('ts1_cfg_form');
|
||||||
|
|
||||||
|
ops = 1;
|
||||||
|
fnet1.ip1.value = tb_systs[ops];
|
||||||
|
ops++;
|
||||||
|
fnet1.ip2.value = (Number(tb_systs[ops])&0x00ff0000)>>16;
|
||||||
|
fnet1.ip3.value = (Number(tb_systs[ops])&0x0000ff00)>>8;
|
||||||
|
fnet1.ip4.value = (Number(tb_systs[ops])&0x000000ff)>>0;
|
||||||
|
ops++;
|
||||||
|
|
||||||
|
fnet1.gt1.value = tb_systs[ops];
|
||||||
|
ops++;
|
||||||
|
fnet1.gt2.value = (Number(tb_systs[ops])&0x00ff0000)>>16;
|
||||||
|
fnet1.gt3.value = (Number(tb_systs[ops])&0x0000ff00)>>8;
|
||||||
|
fnet1.gt4.value = (Number(tb_systs[ops])&0x000000ff)>>0;
|
||||||
|
ops++;
|
||||||
|
|
||||||
|
fnet1.mk1.value = tb_systs[ops];
|
||||||
|
ops++;
|
||||||
|
fnet1.mk2.value = (Number(tb_systs[ops])&0x00ff0000)>>16;
|
||||||
|
fnet1.mk3.value = (Number(tb_systs[ops])&0x0000ff00)>>8;
|
||||||
|
fnet1.mk4.value = (Number(tb_systs[ops])&0x000000ff)>>0;
|
||||||
|
ops++;
|
||||||
|
|
||||||
|
$("#tsoipmac").html(tb_systs[ops]);
|
||||||
|
ops++;
|
||||||
|
|
||||||
|
// Read all 4 octets of Multicast IP
|
||||||
|
fcfg1.ma1.value = tb_systs[ops];
|
||||||
|
ops++;
|
||||||
|
fcfg1.ma2.value = (Number(tb_systs[ops])&0x00ff0000)>>16;
|
||||||
|
fcfg1.ma3.value = (Number(tb_systs[ops])&0x0000ff00)>>8;
|
||||||
|
fcfg1.ma4.value = (Number(tb_systs[ops])&0x000000ff)>>0;
|
||||||
|
ops++;
|
||||||
|
// Then read Port
|
||||||
|
fcfg1.uport.value = tb_systs[ops];
|
||||||
|
ops++;
|
||||||
|
var lpk_para = Number(tb_systs[ops]);
|
||||||
|
ops++;
|
||||||
|
|
||||||
|
i = (lpk_para&0xff0000)>>16;
|
||||||
|
if(i >= 2) i = 2;
|
||||||
|
fcfg1.pktp.selectedIndex = i;
|
||||||
|
|
||||||
|
i = (lpk_para&0x00ff00)>>8;
|
||||||
|
if(i >= 2) i = 2;
|
||||||
|
fcfg1.pklen.selectedIndex = i;
|
||||||
|
|
||||||
|
i = (lpk_para&0x0000ff);
|
||||||
|
if(i >= 2) i = 2;
|
||||||
|
fcfg1.pkrec.selectedIndex = i;
|
||||||
|
|
||||||
|
fcfg1.fec_swh.selectedIndex=Number(tb_systs[ops]);
|
||||||
|
ops++;
|
||||||
|
fcfg1.fec_dly.value=Number(tb_systs[ops]);
|
||||||
|
ops++;
|
||||||
|
fcfg1.fec_row.value=Number(tb_systs[ops]);
|
||||||
|
ops++;
|
||||||
|
fcfg1.fec_col.value=Number(tb_systs[ops]);
|
||||||
|
ops++;
|
||||||
|
|
||||||
|
// Logic for a second TS input (if enabled in backend)
|
||||||
|
if(tsoip_total_num == 2){
|
||||||
|
// Note: The original file did NOT have forms[2] and forms[3] in the HTML
|
||||||
|
// If you need the second interface, you must duplicate the HTML blocks below
|
||||||
|
// and ensure the IDs/Forms exist. For now, this follows the source file provided.
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. RE-ENABLE BUTTONS END (only in Remote mode)
|
||||||
|
if(g_remot_local_ctrl == 1) {
|
||||||
|
// Local mode: keep button disabled
|
||||||
|
$('#setnet_id_1, #setcfg_id1').attr("disabled", true).val("Local Mode");
|
||||||
|
} else {
|
||||||
|
// Remote mode: enable button
|
||||||
|
$('#setnet_id_1, #setcfg_id1').attr("disabled", false).val("Set");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof setFormSnapshotUpdate === 'function') setFormSnapshotUpdate();
|
||||||
|
|
||||||
|
document.getElementById('webtitle').textContent = title[1];
|
||||||
|
document.getElementById('webtitle_header').textContent = title[1];
|
||||||
|
}).fail(function() {
|
||||||
|
// Optional: Handle error case
|
||||||
|
$('#setnet_id_1, #setcfg_id1').val("Load Failed");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----- SET (unsaved) reminder: per-form, vanilla JS -----
|
||||||
|
var setFormSnapshots = {};
|
||||||
|
var setFormConfig = [
|
||||||
|
{ formId: 'ts1_net_form', buttonId: 'setnet_id_1' },
|
||||||
|
{ formId: 'ts1_cfg_form', buttonId: 'setcfg_id1' }
|
||||||
|
];
|
||||||
|
function getFormSnapshot(formId) {
|
||||||
|
var f = document.getElementById(formId);
|
||||||
|
if (!f) return [];
|
||||||
|
var out = [], els = f.querySelectorAll('select, input:not([type="button"])'), i, el, v;
|
||||||
|
for (i = 0; i < els.length; i++) {
|
||||||
|
el = els[i];
|
||||||
|
v = el.tagName === 'SELECT' ? (el.options[el.selectedIndex] ? el.options[el.selectedIndex].value : '') : (el.value || '');
|
||||||
|
out.push({ name: el.name || el.id, value: String(v) });
|
||||||
|
}
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
function isFormDirty(formId, snapshot) {
|
||||||
|
var current = getFormSnapshot(formId);
|
||||||
|
if (current.length !== snapshot.length) return true;
|
||||||
|
for (var i = 0; i < current.length; i++) {
|
||||||
|
if (current[i].name !== snapshot[i].name || current[i].value !== snapshot[i].value) return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
function setSetButtonState(btnId, unsaved) {
|
||||||
|
var btn = document.getElementById(btnId);
|
||||||
|
if (!btn || btn.disabled) return;
|
||||||
|
btn.value = unsaved ? 'Set (unsaved)' : 'Set';
|
||||||
|
if (unsaved) btn.classList.add('is-unsaved'); else btn.classList.remove('is-unsaved');
|
||||||
|
}
|
||||||
|
function setFormSnapshotUpdate() {
|
||||||
|
for (var i = 0; i < setFormConfig.length; i++) {
|
||||||
|
var c = setFormConfig[i];
|
||||||
|
var f = document.getElementById(c.formId);
|
||||||
|
if (f) setFormSnapshots[c.formId] = getFormSnapshot(c.formId);
|
||||||
|
setSetButtonState(c.buttonId, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function updateSetButtonForForm(formId) {
|
||||||
|
for (var i = 0; i < setFormConfig.length; i++) {
|
||||||
|
if (setFormConfig[i].formId !== formId) continue;
|
||||||
|
var c = setFormConfig[i];
|
||||||
|
var snap = setFormSnapshots[c.formId];
|
||||||
|
var dirty = !snap || snap.length === 0 || isFormDirty(c.formId, snap);
|
||||||
|
setSetButtonState(c.buttonId, dirty);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function attachSetFormUnsavedListeners() {
|
||||||
|
for (var i = 0; i < setFormConfig.length; i++) {
|
||||||
|
var f = document.getElementById(setFormConfig[i].formId);
|
||||||
|
if (!f) continue;
|
||||||
|
f.addEventListener('change', function() { updateSetButtonForForm(this.id); });
|
||||||
|
f.addEventListener('input', function() { updateSetButtonForForm(this.id); });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (document.readyState === 'loading') {
|
||||||
|
document.addEventListener('DOMContentLoaded', attachSetFormUnsavedListeners);
|
||||||
|
} else {
|
||||||
|
attachSetFormUnsavedListeners();
|
||||||
|
}
|
||||||
|
|
||||||
|
function refresh_show(){
|
||||||
|
get_remote_local_ctrl();
|
||||||
|
SetFormDefaults();
|
||||||
|
refreshDashboard();
|
||||||
|
}
|
||||||
|
|
||||||
|
function cmd_confirm() {
|
||||||
|
return confirm("Please choose to confirm or cancel!");
|
||||||
|
}
|
||||||
|
|
||||||
|
function tsoip_setnet(ts_index) {
|
||||||
|
var postData;
|
||||||
|
var forms_net;
|
||||||
|
|
||||||
|
if(ts_index==0){
|
||||||
|
postData = "tsoip_net1=";
|
||||||
|
forms_net = document.forms[0];
|
||||||
|
}
|
||||||
|
else if(ts_index==1){
|
||||||
|
postData = "tsoip_net2=";
|
||||||
|
forms_net = document.forms[2];
|
||||||
|
}
|
||||||
|
|
||||||
|
postData += "#"+forms_net.ip1.value;
|
||||||
|
postData += "#"+forms_net.ip2.value;
|
||||||
|
postData += "#"+forms_net.ip3.value;
|
||||||
|
postData += "#"+forms_net.ip4.value;
|
||||||
|
|
||||||
|
postData += "#"+forms_net.gt1.value;
|
||||||
|
postData += "#"+forms_net.gt2.value;
|
||||||
|
postData += "#"+forms_net.gt3.value;
|
||||||
|
postData += "#"+forms_net.gt4.value;
|
||||||
|
|
||||||
|
postData += "#"+forms_net.mk1.value;
|
||||||
|
postData += "#"+forms_net.mk2.value;
|
||||||
|
postData += "#"+forms_net.mk3.value;
|
||||||
|
postData += "#"+forms_net.mk4.value;
|
||||||
|
|
||||||
|
postData += "#"+forms_net.eth_spd.value;
|
||||||
|
|
||||||
|
if(cmd_confirm()){
|
||||||
|
$.post("atsc_status_cfg.cgi?", postData, function(data, status){
|
||||||
|
if(status=="success"){
|
||||||
|
SetFormDefaults();
|
||||||
|
} else{
|
||||||
|
alert("post val err");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function tsoip_setcfg(ts_index) {
|
||||||
|
var postData = "";
|
||||||
|
var forms;
|
||||||
|
|
||||||
|
if(ts_index==0){
|
||||||
|
postData = "tsoip_systs1=";
|
||||||
|
forms = document.forms[1];
|
||||||
|
}
|
||||||
|
else if(ts_index==1){
|
||||||
|
postData = "tsoip_systs2=";
|
||||||
|
forms = document.forms[3];
|
||||||
|
}
|
||||||
|
|
||||||
|
postData += "#"+forms.ma1.value;
|
||||||
|
postData += "#"+forms.ma2.value;
|
||||||
|
postData += "#"+forms.ma3.value;
|
||||||
|
postData += "#"+forms.ma4.value;
|
||||||
|
|
||||||
|
postData += "#"+forms.uport.value;
|
||||||
|
postData += "#"+forms.pktp.value;
|
||||||
|
postData += "#"+forms.pklen.value;
|
||||||
|
postData += "#"+forms.pkrec.value;
|
||||||
|
postData += "#"+forms.fec_swh.value;
|
||||||
|
|
||||||
|
postData += "#"+forms.fec_dly.value;
|
||||||
|
postData += "#"+forms.fec_row.value;
|
||||||
|
postData += "#"+forms.fec_col.value;
|
||||||
|
postData += "#0"; // force 0
|
||||||
|
|
||||||
|
if(cmd_confirm()){
|
||||||
|
$.post("atsc_status_cfg.cgi?", postData, function(data, status){
|
||||||
|
if(status=="success"){
|
||||||
|
SetFormDefaults();
|
||||||
|
} else{
|
||||||
|
alert("post val err");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Modal & Dropdown Logic - Open and close account modal
|
||||||
|
function openAccountModal() {
|
||||||
|
// Fetch current username from server
|
||||||
|
$.get("login.cgi?action=get_user", function(data) {
|
||||||
|
var trimmedData = (data || "").trim();
|
||||||
|
if (trimmedData && trimmedData !== "UNAUTHORIZED") {
|
||||||
|
document.getElementById('current_user').value = trimmedData;
|
||||||
|
}
|
||||||
|
document.getElementById('accountModal').style.display = 'block';
|
||||||
|
setTimeout(function() { document.getElementById('current_pwd').focus(); }, 100);
|
||||||
|
}).fail(function() {
|
||||||
|
document.getElementById('accountModal').style.display = 'block';
|
||||||
|
setTimeout(function() { document.getElementById('current_pwd').focus(); }, 100);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function closeAccountModal() {
|
||||||
|
document.getElementById('accountModal').style.display = 'none';
|
||||||
|
// Clear sensitive fields
|
||||||
|
document.getElementById('current_pwd').value = '';
|
||||||
|
document.getElementById('new_pwd').value = '';
|
||||||
|
document.getElementById('confirm_pwd').value = '';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validates that a string contains only printable characters (excluding space)
|
||||||
|
function isValidPrintableString(str) {
|
||||||
|
// Regular expression to check for printable characters (ASCII 33-126), excluding space
|
||||||
|
// Space is ASCII 32, and we want to exclude it
|
||||||
|
var printableCharRegex = /^[!-~]+$/; // ! is ASCII 33, ~ is ASCII 126
|
||||||
|
return printableCharRegex.test(str);
|
||||||
|
}
|
||||||
|
|
||||||
|
function validateAccountForm() {
|
||||||
|
var currentUser = document.getElementById('current_user').value;
|
||||||
|
var currentPwd = document.getElementById('current_pwd').value;
|
||||||
|
var newUsername = document.getElementById('new_user').value;
|
||||||
|
var newPwd = document.getElementById('new_pwd').value;
|
||||||
|
var confirmPwd = document.getElementById('confirm_pwd').value;
|
||||||
|
|
||||||
|
// Current password is required (cannot be empty)
|
||||||
|
if (!currentPwd || currentPwd.trim() === "") {
|
||||||
|
alert("Current password is required");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate current password contains only printable characters
|
||||||
|
if (!isValidPrintableString(currentPwd)) {
|
||||||
|
alert("Current password contains invalid characters. Only printable characters (excluding space) are allowed.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// New password is required (cannot be empty)
|
||||||
|
if (!newPwd || newPwd.trim() === "") {
|
||||||
|
alert("New password is required");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate new password contains only printable characters
|
||||||
|
if (!isValidPrintableString(newPwd)) {
|
||||||
|
alert("New password contains invalid characters. Only printable characters (excluding space) are allowed.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate new password length (max 16 chars)
|
||||||
|
if (newPwd.length > 16) {
|
||||||
|
alert("New password must be no more than 16 characters");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate new password length
|
||||||
|
if (newPwd.length < 6) {
|
||||||
|
alert("New password must be at least 6 characters");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Confirm password must match new password
|
||||||
|
if (newPwd !== confirmPwd) {
|
||||||
|
alert("New passwords do not match");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate confirm password contains only printable characters
|
||||||
|
if (!isValidPrintableString(confirmPwd)) {
|
||||||
|
alert("Confirm password contains invalid characters. Only printable characters (excluding space) are allowed.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate confirm password length (max 16 chars)
|
||||||
|
if (confirmPwd.length > 16) {
|
||||||
|
alert("Confirm password must be no more than 16 characters");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate new username if provided
|
||||||
|
if (newUsername && newUsername.trim() !== "") {
|
||||||
|
// Validate new username contains only printable characters
|
||||||
|
if (!isValidPrintableString(newUsername)) {
|
||||||
|
alert("New username contains invalid characters. Only printable characters (excluding space) are allowed.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate new username length (max 16 chars)
|
||||||
|
if (newUsername.length > 16) {
|
||||||
|
alert("New username must be no more than 16 characters");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Form submission handler using fetch API
|
||||||
|
document.addEventListener('DOMContentLoaded', function() {
|
||||||
|
var accountForm = document.getElementById('accountForm');
|
||||||
|
if (accountForm) {
|
||||||
|
accountForm.addEventListener('submit', function(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
|
||||||
|
if (!validateAccountForm()) return;
|
||||||
|
|
||||||
|
var formData = new URLSearchParams({
|
||||||
|
Username: document.getElementById('current_user').value,
|
||||||
|
OldPassword: document.getElementById('current_pwd').value,
|
||||||
|
NewUsername: document.getElementById('new_user').value,
|
||||||
|
NewPassword: document.getElementById('new_pwd').value,
|
||||||
|
ConfirmPassword: document.getElementById('confirm_pwd').value
|
||||||
|
});
|
||||||
|
|
||||||
|
fetch('login.cgi?action=change_account', {
|
||||||
|
method: 'POST',
|
||||||
|
body: formData
|
||||||
|
})
|
||||||
|
.then(r => r.json())
|
||||||
|
.then(data => {
|
||||||
|
if (data.success) {
|
||||||
|
alert("Update successful! Please login again.");
|
||||||
|
closeAccountModal();
|
||||||
|
// Redirect to login page after 1.5 seconds
|
||||||
|
setTimeout(function() {
|
||||||
|
window.location.href = 'login.cgi?logout=1';
|
||||||
|
}, 1500);
|
||||||
|
} else {
|
||||||
|
alert(data.error || "Update failed");
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(function(err) {
|
||||||
|
alert("Network error: " + err);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body onload="refresh_show()">
|
||||||
|
|
||||||
|
<div class="app-layout">
|
||||||
|
<aside class="app-sidebar">
|
||||||
|
<ul class="items">
|
||||||
|
<li><a href="status_info.html" title="Status">Status</a></li>
|
||||||
|
<li><a href="sys_set.html" title="Settings">Settings</a></li>
|
||||||
|
<li><a href="sys_rf.html" title="RF Control">RF Control</a></li>
|
||||||
|
<li><a href="sys_psip.html" title="TSID&PSIP">TSID&PSIP</a></li>
|
||||||
|
<li class="active"><a href="sys_ts.html" title="TSoIP">TSoIP</a></li>
|
||||||
|
<li><a href="sys_spectrum.html" title="Spectrum">Spectrum</a></li>
|
||||||
|
<li><a href="log_output.html" title="Log">Log</a></li>
|
||||||
|
</ul>
|
||||||
|
<div class="sidebar-footer">
|
||||||
|
<h4>Anywave Broadcast Inc.</h4>
|
||||||
|
<p>Copyright 2026<br><br><span class="redbox-label">Technical Support</span><br>+1 847 415 2258<br><a href="mailto:support@anywaveus.com">support@anywaveus.com</a></p>
|
||||||
|
</div>
|
||||||
|
</aside>
|
||||||
|
<div class="sidebar-overlay" onclick="toggleSidebar()"></div>
|
||||||
|
|
||||||
|
<header class="app-header">
|
||||||
|
<button class="menu-toggle" onclick="toggleSidebar()" aria-label="Toggle menu">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||||
|
<line x1="3" y1="12" x2="21" y2="12"></line>
|
||||||
|
<line x1="3" y1="6" x2="21" y2="6"></line>
|
||||||
|
<line x1="3" y1="18" x2="21" y2="18"></line>
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
<h1><a href="https://anywavecom.net/" class="logo-bg" title="Anywave Broadcast Inc."></a></h1>
|
||||||
|
<h2 id="webtitle_header"><span></span></h2>
|
||||||
|
<h3>
|
||||||
|
<div class="dropdown">
|
||||||
|
<button class="dropbtn-modern">Admin ▾</button>
|
||||||
|
<div class="dropdown-content">
|
||||||
|
<a href="#" onclick="openAccountModal(); return false;">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||||
|
<circle cx="12" cy="12" r="3"></circle>
|
||||||
|
<path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1 0 2.83 2 2 0 0 1-2.83 0l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-2 2 2 2 0 0 1-2-2v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06-.06a2 2 0 0 1-2.83 0 2 2 0 0 1 0-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1-2-2 2 2 0 0 1 2-2h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 0-2.83 2 2 0 0 1 2.83 0l.06-.06a1.65 1.65 0 0 0 1.82.33H9a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 2-2 2 2 0 0 1 2 2v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 0 2 2 0 0 1 0 2.83l-.06-.06a1.65 1.65 0 0 0-.33 1.82V9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 2 2 2 2 0 0 1-2 2h-.09a1.65 1.65 0 0 0-1.51 1z"></path>
|
||||||
|
</svg>
|
||||||
|
Account Settings
|
||||||
|
</a>
|
||||||
|
<a href="login.cgi?logout=1">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||||
|
<path d="M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4"></path>
|
||||||
|
<polyline points="16 17 21 12 16 7"></polyline>
|
||||||
|
<line x1="21" y1="12" x2="9" y2="12"></line>
|
||||||
|
</svg>
|
||||||
|
Logout
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</h3>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<!-- Fixed Dashboard Summary - Top of page, under header -->
|
||||||
|
<div class="dashboard-fixed">
|
||||||
|
<div class="summary-dashboard">
|
||||||
|
<div class="summary-card">
|
||||||
|
<div class="summary-label-row">
|
||||||
|
<span class="status-dot status-neutral" id="dot_freq" aria-hidden="true"></span>
|
||||||
|
<span class="summary-label">Frequency</span>
|
||||||
|
</div>
|
||||||
|
<div class="summary-value-wrapper">
|
||||||
|
<span class="summary-value value-neutral" id="sum_freq">--</span>
|
||||||
|
<span class="summary-unit">MHz</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="summary-card">
|
||||||
|
<div class="summary-label-row">
|
||||||
|
<span class="status-dot status-ok" id="dot_snr" aria-hidden="true"></span>
|
||||||
|
<span class="summary-label">SNR</span>
|
||||||
|
</div>
|
||||||
|
<div class="summary-value-wrapper">
|
||||||
|
<span class="summary-value value-ok" id="sum_snr">--</span>
|
||||||
|
<span class="summary-unit">dB</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="summary-card">
|
||||||
|
<div class="summary-label-row">
|
||||||
|
<span class="status-dot status-ok" id="dot_uimd" aria-hidden="true"></span>
|
||||||
|
<span class="summary-label">UIMD</span>
|
||||||
|
</div>
|
||||||
|
<div class="summary-value-wrapper">
|
||||||
|
<span class="summary-value value-ok" id="sum_uimd">--</span>
|
||||||
|
<span class="summary-unit">dBc</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="summary-card">
|
||||||
|
<div class="summary-label-row">
|
||||||
|
<span class="status-dot status-ok" id="dot_limd" aria-hidden="true"></span>
|
||||||
|
<span class="summary-label">LIMD</span>
|
||||||
|
</div>
|
||||||
|
<div class="summary-value-wrapper">
|
||||||
|
<span class="summary-value value-ok" id="sum_limd">--</span>
|
||||||
|
<span class="summary-unit">dBc</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="summary-card">
|
||||||
|
<div class="summary-label-row">
|
||||||
|
<span class="status-dot status-off" id="dot_rf" aria-hidden="true"></span>
|
||||||
|
<span class="summary-label">RF Switch</span>
|
||||||
|
</div>
|
||||||
|
<div class="summary-value-wrapper">
|
||||||
|
<span class="summary-value value-muted" id="sum_rf">--</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="summary-card">
|
||||||
|
<div class="summary-label-row">
|
||||||
|
<span class="status-dot status-ok" id="dot_outpow" aria-hidden="true"></span>
|
||||||
|
<span class="summary-label">Output Power</span>
|
||||||
|
</div>
|
||||||
|
<div class="summary-value-wrapper">
|
||||||
|
<span class="summary-value value-ok" id="sum_outpow">--</span>
|
||||||
|
<span class="summary-unit">dBm</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="summary-card">
|
||||||
|
<div class="summary-label-row">
|
||||||
|
<span class="status-dot status-neutral" id="dot_input" aria-hidden="true"></span>
|
||||||
|
<span class="summary-label">Input Source</span>
|
||||||
|
</div>
|
||||||
|
<div class="summary-value-wrapper">
|
||||||
|
<span class="summary-value value-neutral" id="sum_input">--</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="summary-card">
|
||||||
|
<div class="summary-label-row">
|
||||||
|
<span class="status-dot status-neutral" id="dot_input_status" aria-hidden="true"></span>
|
||||||
|
<span class="summary-label">Input Status</span>
|
||||||
|
</div>
|
||||||
|
<div class="summary-value-wrapper">
|
||||||
|
<span class="summary-value value-neutral" id="sum_input_status">--</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="summary-card">
|
||||||
|
<div class="summary-label-row">
|
||||||
|
<span class="status-dot status-neutral" id="dot_bitrate" aria-hidden="true"></span>
|
||||||
|
<span class="summary-label">Bitrate</span>
|
||||||
|
</div>
|
||||||
|
<div class="summary-value-wrapper">
|
||||||
|
<span class="summary-value value-neutral" id="sum_bitrate">--</span>
|
||||||
|
<span class="summary-unit">Mbps</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="summary-card">
|
||||||
|
<div class="summary-label-row">
|
||||||
|
<span class="status-dot status-ok" id="dot_temp" aria-hidden="true"></span>
|
||||||
|
<span class="summary-label">Temperature</span>
|
||||||
|
</div>
|
||||||
|
<div class="summary-value-wrapper">
|
||||||
|
<span class="summary-value value-ok" id="sum_temp">--</span>
|
||||||
|
<span class="summary-unit">°F</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="summary-card">
|
||||||
|
<div class="summary-label-row">
|
||||||
|
<span class="status-dot status-off" id="dot_agc" aria-hidden="true"></span>
|
||||||
|
<span class="summary-label">AGC</span>
|
||||||
|
</div>
|
||||||
|
<div class="summary-value-wrapper">
|
||||||
|
<span class="summary-value value-muted" id="sum_agc">--</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="summary-card">
|
||||||
|
<div class="summary-label-row">
|
||||||
|
<span class="status-dot status-neutral" id="dot_control" aria-hidden="true"></span>
|
||||||
|
<span class="summary-label">Control</span>
|
||||||
|
</div>
|
||||||
|
<div class="summary-value-wrapper">
|
||||||
|
<span class="summary-value value-neutral" id="sum_control">--</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<main class="app-main">
|
||||||
|
<h2>TSoIP (IP1) Network Configuration</h2>
|
||||||
|
<div class="box">
|
||||||
|
<form name="ts1_net" id="ts1_net_form">
|
||||||
|
<table>
|
||||||
|
<tr>
|
||||||
|
<td>IP</td>
|
||||||
|
<td><fieldset>
|
||||||
|
<input style="width:40px" maxlength="3" size="3" name="ip1" id="ip1" value="">.
|
||||||
|
<input style="width:40px" maxlength="3" size="3" name="ip2" id="ip2" value="">.
|
||||||
|
<input style="width:40px" maxlength="3" size="3" name="ip3" id="ip3" value="">.
|
||||||
|
<input style="width:40px" maxlength="3" size="3" name="ip4" id="ip4" value="">
|
||||||
|
</fieldset></td>
|
||||||
|
|
||||||
|
<td>Gateway</td>
|
||||||
|
<td><fieldset>
|
||||||
|
<input style="width:40px" maxlength="3" size="3" name="gt1" id="gt1" value="">.
|
||||||
|
<input style="width:40px" maxlength="3" size="3" name="gt2" id="gt2" value="">.
|
||||||
|
<input style="width:40px" maxlength="3" size="3" name="gt3" id="gt3" value="">.
|
||||||
|
<input style="width:40px" maxlength="3" size="3" name="gt4" id="gt4" value="">
|
||||||
|
</fieldset></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Mask</td>
|
||||||
|
<td><fieldset>
|
||||||
|
<input style="width:40px" maxlength="3" size="3" name="mk1" id="mk1" value="">.
|
||||||
|
<input style="width:40px" maxlength="3" size="3" name="mk2" id="mk2" value="">.
|
||||||
|
<input style="width:40px" maxlength="3" size="3" name="mk3" id="mk3" value="">.
|
||||||
|
<input style="width:40px" maxlength="3" size="3" name="mk4" id="mk4" value="">
|
||||||
|
</fieldset></td>
|
||||||
|
|
||||||
|
<td>MAC</td>
|
||||||
|
<td><span id="tsoipmac"></span></td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<tr style="display: none;">
|
||||||
|
<td>NET SPEED</td>
|
||||||
|
<td>
|
||||||
|
<select name="eth_spd" id="eth_spd">
|
||||||
|
<option value="0">100Mbps
|
||||||
|
<option value="1">1000Mbps
|
||||||
|
<option value="2">Auto
|
||||||
|
</select>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
<td> <input type="button" class="btn-modern" alt="Set" value="Set" disabled id="setnet_id_1" onclick="return tsoip_setnet(0);"> </td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
<br><br>
|
||||||
|
|
||||||
|
<h2>TSoIP (IP1) Rx Configuration</h2>
|
||||||
|
<div class="box">
|
||||||
|
<form name="ts1_cfg" id="ts1_cfg_form">
|
||||||
|
<table>
|
||||||
|
<tr>
|
||||||
|
<td>Multicast IP</td>
|
||||||
|
<td><fieldset>
|
||||||
|
<input style="width:40px" maxlength="3" size="3" name="ma1" id="ma1" value="">.
|
||||||
|
<input style="width:40px" maxlength="3" size="3" name="ma2" id="ma2" value="">.
|
||||||
|
<input style="width:40px" maxlength="3" size="3" name="ma3" id="ma3" value="">.
|
||||||
|
<input style="width:40px" maxlength="3" size="3" name="ma4" id="ma4" value="">
|
||||||
|
</fieldset></td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
<td>Port</td>
|
||||||
|
<td>
|
||||||
|
<input maxlength="6" size="6" name="uport" id="uport" value="">
|
||||||
|
</td>
|
||||||
|
<td>Protocol</td>
|
||||||
|
<td>
|
||||||
|
<select name="pktp" id="pktp">
|
||||||
|
<option value="0">UDP
|
||||||
|
<option value="1">RTP
|
||||||
|
<option value="2">Invalid
|
||||||
|
</select>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Length</td>
|
||||||
|
<td>
|
||||||
|
<select name="pklen" id="pklen">
|
||||||
|
<option value="0">188
|
||||||
|
<option value="1">204
|
||||||
|
<option value="2">Invalid
|
||||||
|
</select>
|
||||||
|
</td>
|
||||||
|
<td>Type</td>
|
||||||
|
<td>
|
||||||
|
<select name="pkrec" id="pkrec">
|
||||||
|
<option value="0">Multicast
|
||||||
|
<option value="1">Unicast
|
||||||
|
<option value="2">Invalid
|
||||||
|
</select>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<tr style="display: none">
|
||||||
|
<td>FEC</td>
|
||||||
|
<td>
|
||||||
|
<select name="fec_swh" id="fec_swh">
|
||||||
|
<option value="0">Disable
|
||||||
|
<option value="1">Enable
|
||||||
|
</select>
|
||||||
|
</td>
|
||||||
|
<td>Delay</td>
|
||||||
|
<td>
|
||||||
|
<input maxlength="6" size="6" name="fec_dly" id="fec_dly" value="">
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr style="display: none">
|
||||||
|
<td>FEC Row</td>
|
||||||
|
<td>
|
||||||
|
<input maxlength="4" size="4" name="fec_row" id="fec_row" value="">
|
||||||
|
</td>
|
||||||
|
<td>FEC Col</td>
|
||||||
|
<td>
|
||||||
|
<input maxlength="4" size="4" name="fec_col" id="fec_col" value="">
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
<td> <input type="button" class="btn-modern" alt="Set" value="Set" disabled id="setcfg_id1" onclick="return tsoip_setcfg(0);"> </td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</main>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="accountModal" class="modal">
|
||||||
|
<div class="modal-content">
|
||||||
|
<div class="modal-header">
|
||||||
|
<h3>Account Settings</h3>
|
||||||
|
<span class="close" onclick="closeAccountModal()">×</span>
|
||||||
|
</div>
|
||||||
|
<div class="modal-body">
|
||||||
|
<form id="accountForm" method="post" action="login.cgi?action=change_account" onsubmit="return validateAccountForm()">
|
||||||
|
<table class="modal-table">
|
||||||
|
<tr>
|
||||||
|
<td>Current Username</td>
|
||||||
|
<td><input type="text" id="current_user" name="current_user" readonly></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Current Password</td>
|
||||||
|
<td><input type="password" id="current_pwd" name="current_pwd" required></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>New Username</td>
|
||||||
|
<td><input type="text" id="new_user" name="new_user"></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>New Password</td>
|
||||||
|
<td><input type="password" id="new_pwd" name="new_pwd"></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Confirm Password</td>
|
||||||
|
<td><input type="password" id="confirm_pwd" name="confirm_pwd"></td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
<div class="modal-footer">
|
||||||
|
<input type="button" class="btn-modern" style="background-color: #64748b;" value="Cancel" onclick="closeAccountModal()">
|
||||||
|
<input type="submit" class="btn-modern" value="Save Changes">
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
function toggleSidebar(){
|
||||||
|
document.querySelector('.app-sidebar').classList.toggle('sidebar-open');
|
||||||
|
document.querySelector('.sidebar-overlay').classList.toggle('active');
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
anywavecom:anywavecom
|
||||||
|
|
||||||
@@ -0,0 +1,162 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
### Auther : F
|
||||||
|
### Date : 2021-12-7
|
||||||
|
### Function: Start anywave work
|
||||||
|
echo " "
|
||||||
|
echo " "
|
||||||
|
echo "--------------------------------"
|
||||||
|
echo " ... HELLO , ANYWAVE ... "
|
||||||
|
echo "--------------------------------"
|
||||||
|
echo " "
|
||||||
|
echo " "
|
||||||
|
|
||||||
|
setnetmac.sh
|
||||||
|
|
||||||
|
ifconfig eth0 192.168.1.143
|
||||||
|
ifconfig eth1 192.168.2.143
|
||||||
|
route add default gw 192.168.1.1
|
||||||
|
|
||||||
|
echo "clk prepare..."
|
||||||
|
sleep 5
|
||||||
|
echo "clk rdy"
|
||||||
|
|
||||||
|
init_ad9528_reset_gpio.sh
|
||||||
|
imx_cfgad9528
|
||||||
|
|
||||||
|
mkdir -p /aw/anywave/dpd_log
|
||||||
|
|
||||||
|
### Path for web upgrade
|
||||||
|
mkdir -p /aw/upgrade
|
||||||
|
mkdir -p /aw/tmp
|
||||||
|
mkdir -p /aw/anywave/cfg
|
||||||
|
mkdir -p /aw/anywave/cfg/bkp
|
||||||
|
mkdir -p /aw/anywave/dpd_curve
|
||||||
|
mkdir -p /aw/anywave/lib
|
||||||
|
mkdir -p /aw/log
|
||||||
|
mkdir -p /etc/logrotate.d/
|
||||||
|
echo "== web start =="
|
||||||
|
cd /aw/anywave/web/sh && ./start_web.sh
|
||||||
|
|
||||||
|
MODULE_LOG_PATH=/var/module_log/
|
||||||
|
mkdir -p $MODULE_LOG_PATH
|
||||||
|
|
||||||
|
echo 10 > /sys/class/gpio/export
|
||||||
|
echo 11 > /sys/class/gpio/export
|
||||||
|
echo 12 > /sys/class/gpio/export
|
||||||
|
echo 13 > /sys/class/gpio/export
|
||||||
|
echo 14 > /sys/class/gpio/export
|
||||||
|
echo 15 > /sys/class/gpio/export
|
||||||
|
insmod /aw/anywave/lib/key-bsp.ko
|
||||||
|
|
||||||
|
#logconf
|
||||||
|
LOG_CONF_FILE=/etc/logrotate.d/log.conf
|
||||||
|
rm -f $LOG_CONF_FILE
|
||||||
|
set_log_conf()
|
||||||
|
{
|
||||||
|
echo "$1$2{
|
||||||
|
$3
|
||||||
|
daily
|
||||||
|
rotate 3
|
||||||
|
size 1K
|
||||||
|
dateext
|
||||||
|
extension .log
|
||||||
|
compress
|
||||||
|
notifempty
|
||||||
|
sharedscripts
|
||||||
|
create 644 root root
|
||||||
|
sharedscripts
|
||||||
|
postrotate
|
||||||
|
$4
|
||||||
|
endscript
|
||||||
|
}
|
||||||
|
" >> $LOG_CONF_FILE
|
||||||
|
}
|
||||||
|
|
||||||
|
start_and_log()
|
||||||
|
{
|
||||||
|
if [ $# -lt 4 ];then
|
||||||
|
echo 'Usage:start_and_log command_path command_with_param log_path log_name enable_output &'
|
||||||
|
echo "For example:"
|
||||||
|
echo "start_and_log /app ./app /var/module_log/ app.log 0 &"
|
||||||
|
echo "or start_and_log /app ./app /var/module_log/ app.log 1 &"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
set_log_conf $3 $4
|
||||||
|
cd $1 && $2 2>&1 | loglog $3 $4 $5 $6
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
set_longlog_conf()
|
||||||
|
{
|
||||||
|
echo "$1$2{
|
||||||
|
$3
|
||||||
|
daily
|
||||||
|
rotate 3
|
||||||
|
size 500K
|
||||||
|
dateext
|
||||||
|
extension .log
|
||||||
|
compress
|
||||||
|
notifempty
|
||||||
|
create 644 root root
|
||||||
|
sharedscripts
|
||||||
|
postrotate
|
||||||
|
$4
|
||||||
|
endscript
|
||||||
|
}
|
||||||
|
" >> $LOG_CONF_FILE
|
||||||
|
}
|
||||||
|
start_and_longlog()
|
||||||
|
{
|
||||||
|
if [ $# -lt 4 ];then
|
||||||
|
echo 'Usage:start_and_longlog command_path command_with_param log_path log_name enable_output &'
|
||||||
|
echo "For example:"
|
||||||
|
echo "start_and_longlog /app ./app /var/module_log/ app.log 0 &"
|
||||||
|
echo "or start_and_longlog /app ./app /var/module_log/ app.log 1 &"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
set_longlog_conf $3 $4
|
||||||
|
cd $1 && $2 2>&1 | loglog $3 $4 $5 $6
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
echo "== app start =="
|
||||||
|
#cd /aw/anywave/app/ && ./imx_atsc_app&
|
||||||
|
start_and_log /aw/anywave/app ./imx_atsc_app $MODULE_LOG_PATH imx_atsc_app.log 1 &
|
||||||
|
|
||||||
|
echo "== daemon_system start =="
|
||||||
|
#daemon_system
|
||||||
|
start_and_longlog /usr/sbin daemon_system $MODULE_LOG_PATH daemon_system.log 1 &
|
||||||
|
|
||||||
|
echo " "
|
||||||
|
echo "== start finished =="
|
||||||
|
echo " "
|
||||||
|
|
||||||
|
|
||||||
|
#----------daemon_app-------------
|
||||||
|
#ProcNumber=`ps -ef |grep -w daemon_app|grep -v grep|wc -l`
|
||||||
|
#if [ $ProcNumber -le 0 ];then
|
||||||
|
#/usr/sbin/daemon_app &
|
||||||
|
#echo "daemon_app first run"
|
||||||
|
#else
|
||||||
|
#echo "daemon_app have been run"
|
||||||
|
#fi
|
||||||
|
|
||||||
|
|
||||||
|
start_and_longlog /usr/sbin logrotateStart $MODULE_LOG_PATH logrotateStart.log 0 &
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,87 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
## ------------------------------
|
||||||
|
# function :
|
||||||
|
# a. check package *.tar.gz in current dir
|
||||||
|
# b. check package extract tar return value of ret
|
||||||
|
# c. check package runme.sh
|
||||||
|
## ------------------------------
|
||||||
|
# return :
|
||||||
|
## 0 ok
|
||||||
|
## 2 Wrong package
|
||||||
|
## 3 Wrong file extension
|
||||||
|
## ------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
#-- This path has been defined in upload.cgi ,so if want to chang this path, you should chang upload.c .
|
||||||
|
TAR_PACKAGE_PATH="/aw/upgrade"
|
||||||
|
UPGRADE_FILE_PATH="/tmp/upgrade"
|
||||||
|
PROJ_NAME="EMV"
|
||||||
|
|
||||||
|
|
||||||
|
if [ -d ${UPGRADE_FILE_PATH} ] ; then
|
||||||
|
rm -rf ${UPGRADE_FILE_PATH}
|
||||||
|
fi
|
||||||
|
mkdir -p ${UPGRADE_FILE_PATH}
|
||||||
|
|
||||||
|
|
||||||
|
check_tar=`find ${TAR_PACKAGE_PATH} -name '*.tar.gz'`
|
||||||
|
ret=0
|
||||||
|
|
||||||
|
|
||||||
|
if [ -z ${check_tar} ];then # 字符串长度为0
|
||||||
|
let ret=3
|
||||||
|
else
|
||||||
|
cd ${TAR_PACKAGE_PATH} && ls *.tar.gz > list.txt
|
||||||
|
|
||||||
|
for TAR in `cat list.txt`
|
||||||
|
do
|
||||||
|
FILE_NAME=${TAR%.*.*}
|
||||||
|
###echo "file name :${FILE_NAME}"
|
||||||
|
###echo "tar -zxf $TAR -C ${UPGRADE_FILE_PATH}/"
|
||||||
|
|
||||||
|
tar -zxf $TAR -C ${UPGRADE_FILE_PATH}/
|
||||||
|
|
||||||
|
extract_tar_ret=$?
|
||||||
|
|
||||||
|
if [ ${extract_tar_ret} != "0" ];then
|
||||||
|
let ret=2
|
||||||
|
else
|
||||||
|
let ret=0
|
||||||
|
fi
|
||||||
|
###echo "extract_tar_pg = ${ret}"
|
||||||
|
done
|
||||||
|
|
||||||
|
rm -rf ${TAR_PACKAGE_PATH}/list.txt
|
||||||
|
rm -rf ${TAR_PACKAGE_PATH}/*.tar.gz
|
||||||
|
|
||||||
|
###echo "ret = ${ret}"
|
||||||
|
if [ ${ret} -eq 0 ];then
|
||||||
|
# check package has runme.sh xxx_cp.sh xxx_remove.sh .
|
||||||
|
# path = /dt_update/aics*/
|
||||||
|
cd ${UPGRADE_FILE_PATH}/${PROJ_NAME}*
|
||||||
|
if [ -f "runme.sh" ];then
|
||||||
|
###echo "runme.sh ok"
|
||||||
|
let ret=0
|
||||||
|
else
|
||||||
|
###echo "no runme.sh "
|
||||||
|
let ret=2
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
if [ ${ret} -ne 0 ];then
|
||||||
|
#echo "rm -rf ./package/*"
|
||||||
|
rm ${TAR_PACKAGE_PATH}/* -rf
|
||||||
|
sync
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo ${ret}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
UPGRADE_FILE_PATH="/tmp/upgrade"
|
||||||
|
|
||||||
|
cd ${UPGRADE_FILE_PATH}/EMV* && ./runme.sh
|
||||||
|
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
cp -v -rf /aw/anywave/cfg/exc_cfg_bkp.conf /aw/anywave/cfg/exc_cfg_bbkkpp.conf
|
||||||
|
cp -v -rf /aw/anywave/cfg/bkp/exc_cfg_bkp.conf /aw/anywave/cfg/exc_cfg.conf
|
||||||
|
sync
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
7_260722_125
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
cp -v -rf /aw/anywave/cfg/bkp/exc_cfg_bkp.conf /aw/anywave/cfg/bkp/exc_cfg_bkp_bbkkpp.conf
|
||||||
|
rm -rf /aw/anywave/cfg/bkp/exc_cfg_bkp.conf
|
||||||
|
cp -v -rf /aw/anywave/cfg/exc_cfg.conf /aw/anywave/cfg/bkp/exc_cfg_bkp.conf
|
||||||
|
sync
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
# see "man logrotate" for details
|
||||||
|
# rotate log files weekly
|
||||||
|
daily
|
||||||
|
|
||||||
|
# keep 4 weeks worth of backlogs
|
||||||
|
rotate 3
|
||||||
|
|
||||||
|
# create new (empty) log files after rotating old ones
|
||||||
|
create
|
||||||
|
|
||||||
|
# use date as a suffix of the rotated file
|
||||||
|
dateext
|
||||||
|
|
||||||
|
# uncomment this if you want your log files compressed
|
||||||
|
compress
|
||||||
|
|
||||||
|
|
||||||
|
# RPM packages drop log rotation information into this directory
|
||||||
|
include /etc/logrotate.d
|
||||||
|
|
||||||
|
# no packages own wtmp and btmp -- we'll rotate them here
|
||||||
|
|
||||||
|
|
||||||
|
# system-specific logs may be also be configured here.
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
cp -v -rf ./src/usr/sbin/* /usr/sbin/
|
||||||
|
cp -v -r ./src/etc/* /etc/
|
||||||
|
cp -v -r ./src/lib/* /lib/
|
||||||
|
|
||||||
|
cp -rf ./src/aw/anywave_exc_start.sh /aw/anywave_exc_start.sh
|
||||||
|
cp -rf ./src/aw/anywave/sync_to_bkp_file.sh /aw/anywave/sync_to_bkp_file.sh
|
||||||
|
cp -rf ./src/aw/anywave/load_to_cfg_file.sh /aw/anywave/load_to_cfg_file.sh
|
||||||
|
cp -rf ./src/aw/anywave/upgrade_shell/* /aw/anywave/upgrade_shell/
|
||||||
|
|
||||||
|
mkdir -p /aw/anywave/web && cp -v -rf ./src/aw/anywave/web/* /aw/anywave/web/
|
||||||
|
mkdir -p /aw/anywave/web/www && cp -v -rf ./src/aw/anywave/web/www/* /aw/anywave/web/www/
|
||||||
|
mkdir -p /aw/anywave/app && cp -v -rf ./src/aw/anywave/app/imx_atsc_app /aw/anywave/app/imx_atsc_app
|
||||||
|
cp -v -rf ./src/aw/anywave/web/www/* /aw/anywave/web/www
|
||||||
|
cp -v -rf ./src/aw/release_version.ini /aw/release_version.ini
|
||||||
|
sync
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
cp -v -rf ./src/usr/sbin/* /usr/sbin/
|
||||||
|
cp -v -r ./src/etc/* /etc/
|
||||||
|
cp -v -r ./src/lib/* /lib/
|
||||||
|
cp -rf ./src/aw/anywave_exc_start.sh /aw/anywave_exc_start.sh
|
||||||
|
cp -rf ./src/aw/anywave/sync_to_bkp_file.sh /aw/anywave/sync_to_bkp_file.sh
|
||||||
|
cp -rf ./src/aw/anywave/load_to_cfg_file.sh /aw/anywave/load_to_cfg_file.sh
|
||||||
|
cp -rf ./src/aw/anywave/upgrade_shell/* /aw/anywave/load_to_cfg_file.sh
|
||||||
|
|
||||||
|
mkdir -p /aw/anywave/web && cp -v -rf ./src/aw/anywave/web/* /aw/anywave/web/
|
||||||
|
mkdir -p /aw/anywave/web/www && cp -v -rf ./src/aw/anywave/web/www/* /aw/anywave/web/www/
|
||||||
|
mkdir -p /aw/anywave/app && cp -v -rf ./src/aw/anywave/app/imx_atsc_app /aw/anywave/app/imx_atsc_app
|
||||||
|
cp -v -rf ./src/aw/anywave/web/www/* /aw/anywave/web/www
|
||||||
|
cp -v -rf ./src/aw/release_version.ini /aw/release_version.ini
|
||||||
|
sync
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
rm -rf /aw/anywave/web/www/cgi-debug.txt
|
||||||
|
rm -rf /forlinx/audio/*
|
||||||
|
rm -rf /forlinx/video/*
|
||||||
|
sync
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
killall logrotateStart daemon_system
|
||||||
|
sh remove.sh
|
||||||
|
sh cp.sh
|
||||||
|
sync
|
||||||
|
sleep 2
|
||||||
|
reboot
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
BKP_FILE=/aw/anywave/cfg/bkp/exc_cfg_bkp.conf
|
||||||
|
if [ -f "$BKP_FILE" ];then
|
||||||
|
cp -v -rf /aw/anywave/cfg/bkp/exc_cfg_bkp.conf /aw/anywave/cfg/bkp/exc_cfg_bbkkpp.conf
|
||||||
|
echo "ccooppyy: exc_cfg_bkp.conf"
|
||||||
|
cp -v -rf /aw/anywave/cfg/bkp/exc_cfg_bkp.conf /aw/anywave/cfg/exc_cfg.conf
|
||||||
|
fi
|
||||||
|
sync
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
CFG_FILE=/aw/anywave/cfg/exc_cfg.conf
|
||||||
|
BKP_FILE=/aw/anywave/cfg/bkp/exc_cfg_bkp.conf
|
||||||
|
if [ -f "$BKP_FILE" ];then
|
||||||
|
cp -v -rf /aw/anywave/cfg/bkp/exc_cfg_bkp.conf /aw/anywave/cfg/bkp/exc_cfg_bkp_bbkkpp.conf
|
||||||
|
rm -rf /aw/anywave/cfg/bkp/exc_cfg_bkp.conf
|
||||||
|
echo "ccooppyy1: exc_cfg_bkp.conf"
|
||||||
|
fi
|
||||||
|
if [ -f "$BKP_FILE" ];then
|
||||||
|
cp -v -rf /aw/anywave/cfg/exc_cfg.conf /aw/anywave/cfg/bkp/exc_cfg_bkp.conf
|
||||||
|
echo "ccooppyy2: exc_cfg.conf"
|
||||||
|
fi
|
||||||
|
sync
|
||||||
@@ -0,0 +1,87 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
## ------------------------------
|
||||||
|
# function :
|
||||||
|
# a. check package *.tar.gz in current dir
|
||||||
|
# b. check package extract tar return value of ret
|
||||||
|
# c. check package runme.sh
|
||||||
|
## ------------------------------
|
||||||
|
# return :
|
||||||
|
## 0 ok
|
||||||
|
## 2 Wrong package
|
||||||
|
## 3 Wrong file extension
|
||||||
|
## ------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
#-- This path has been defined in upload.cgi ,so if want to chang this path, you should chang upload.c .
|
||||||
|
TAR_PACKAGE_PATH="/aw/upgrade"
|
||||||
|
UPGRADE_FILE_PATH="/tmp/upgrade"
|
||||||
|
PROJ_NAME="EXV"
|
||||||
|
|
||||||
|
|
||||||
|
if [ -d ${UPGRADE_FILE_PATH} ] ; then
|
||||||
|
rm -rf ${UPGRADE_FILE_PATH}
|
||||||
|
fi
|
||||||
|
mkdir -p ${UPGRADE_FILE_PATH}
|
||||||
|
|
||||||
|
|
||||||
|
check_tar=`find ${TAR_PACKAGE_PATH} -name '*.tar.gz'`
|
||||||
|
ret=0
|
||||||
|
|
||||||
|
|
||||||
|
if [ -z ${check_tar} ];then # 字符串长度为0
|
||||||
|
let ret=3
|
||||||
|
else
|
||||||
|
cd ${TAR_PACKAGE_PATH} && ls EXV*.tar.gz > list.txt
|
||||||
|
|
||||||
|
for TAR in `cat list.txt`
|
||||||
|
do
|
||||||
|
FILE_NAME=${TAR%.*.*}
|
||||||
|
###echo "file name :${FILE_NAME}"
|
||||||
|
###echo "tar -zxf $TAR -C ${UPGRADE_FILE_PATH}/"
|
||||||
|
|
||||||
|
tar -zxf $TAR -C ${UPGRADE_FILE_PATH}/
|
||||||
|
|
||||||
|
extract_tar_ret=$?
|
||||||
|
|
||||||
|
if [ ${extract_tar_ret} != "0" ];then
|
||||||
|
let ret=2
|
||||||
|
else
|
||||||
|
let ret=0
|
||||||
|
fi
|
||||||
|
###echo "extract_tar_pg = ${ret}"
|
||||||
|
done
|
||||||
|
|
||||||
|
rm -rf ${TAR_PACKAGE_PATH}/list.txt
|
||||||
|
rm -rf ${TAR_PACKAGE_PATH}/*.tar.gz
|
||||||
|
|
||||||
|
###echo "ret = ${ret}"
|
||||||
|
if [ ${ret} -eq 0 ];then
|
||||||
|
# check package has runme.sh xxx_cp.sh xxx_remove.sh .
|
||||||
|
# path = /dt_update/aics*/
|
||||||
|
cd ${UPGRADE_FILE_PATH}/${PROJ_NAME}*
|
||||||
|
if [ -f "runme.sh" ];then
|
||||||
|
###echo "runme.sh ok"
|
||||||
|
let ret=0
|
||||||
|
else
|
||||||
|
###echo "no runme.sh "
|
||||||
|
let ret=2
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
if [ ${ret} -ne 0 ];then
|
||||||
|
#echo "rm -rf ./package/*"
|
||||||
|
rm ${TAR_PACKAGE_PATH}/* -rf
|
||||||
|
sync
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo ${ret}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
UPGRADE_FILE_PATH="/tmp/upgrade"
|
||||||
|
|
||||||
|
cd ${UPGRADE_FILE_PATH}/EXV* && ./runme.sh
|
||||||
|
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
killall http
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
rm -rf /var/module_log.*
|
||||||
|
cd /var
|
||||||
|
#tar -czvf module_log.tar.gz ./module_log
|
||||||
|
zip -r module_log.zip module_log/
|
||||||
|
|
||||||
|
rm -rf /aw/anywave/web/www/module_log.*
|
||||||
|
mv -f /var/module_log.zip /aw/anywave/web/www/module_log.zip
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
/aw/anywave/web/bin/http -p 80 -d /aw/anywave/web/www -c *.cgi -t utf-8&
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
anywavecom:anywavecom
|
||||||
|
hhee:hhee
|
||||||
|
|
||||||
@@ -0,0 +1,260 @@
|
|||||||
|
* {
|
||||||
|
border:0;
|
||||||
|
margin:0;
|
||||||
|
padding:0;
|
||||||
|
outline:0;
|
||||||
|
font-size:100%;
|
||||||
|
list-style:none;
|
||||||
|
font-style:normal;
|
||||||
|
font-weight:normal;
|
||||||
|
line-height:inherit;
|
||||||
|
font-family:inherit;
|
||||||
|
text-decoration:none;
|
||||||
|
}
|
||||||
|
body {
|
||||||
|
font:normal normal 62.5%/1 'Lucida Grande', Arial, Helvetica, sans-serif;
|
||||||
|
background-color:#333;
|
||||||
|
}
|
||||||
|
body,td,th {
|
||||||
|
font-family: "Lucida Grande", Arial, Helvetica, sans-serif;
|
||||||
|
}
|
||||||
|
body {
|
||||||
|
background-color:#FFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*PAGE LAYOUT*/
|
||||||
|
#wrap{
|
||||||
|
width:1100px;
|
||||||
|
height:900px;
|
||||||
|
}
|
||||||
|
#header{
|
||||||
|
height:110px;
|
||||||
|
width:1100px;
|
||||||
|
}
|
||||||
|
#sidebar{
|
||||||
|
float:left;
|
||||||
|
width:235px;
|
||||||
|
height:900px;
|
||||||
|
background:url(../images/bg_wrap.png) repeat-y;
|
||||||
|
}
|
||||||
|
#content{
|
||||||
|
float:left;
|
||||||
|
width:835px;
|
||||||
|
padding-left:10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*GLOBAL STYLES*/
|
||||||
|
|
||||||
|
cite, em{
|
||||||
|
font-style:italic;
|
||||||
|
}
|
||||||
|
strong{
|
||||||
|
font-weight:bold;
|
||||||
|
}
|
||||||
|
.hid{
|
||||||
|
display:none;
|
||||||
|
}
|
||||||
|
.bg{
|
||||||
|
top:0;
|
||||||
|
left:0;
|
||||||
|
width:100%;
|
||||||
|
height:100%;
|
||||||
|
display:block;
|
||||||
|
position:absolute;
|
||||||
|
}
|
||||||
|
.clear{
|
||||||
|
height:0;
|
||||||
|
clear:both;
|
||||||
|
display:block;
|
||||||
|
overflow:hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*HEADER STYLES*/
|
||||||
|
#header h1{
|
||||||
|
color:#fff;
|
||||||
|
float:left;
|
||||||
|
width:235px;
|
||||||
|
height:110px;
|
||||||
|
font-size:1.8em;
|
||||||
|
line-height:3em;
|
||||||
|
margin-right:30px;
|
||||||
|
position:relative;
|
||||||
|
text-align:center;
|
||||||
|
}
|
||||||
|
#header h1 .bg{
|
||||||
|
height:110px;
|
||||||
|
background:url(../images/bg_h1.png) no-repeat left top;
|
||||||
|
}
|
||||||
|
#header h2{
|
||||||
|
clear:right;
|
||||||
|
color:#343434;
|
||||||
|
font-size:2.5em;
|
||||||
|
letter-spacing:-1px;
|
||||||
|
padding:5px 0 10px 0;
|
||||||
|
}
|
||||||
|
#header h2 span{
|
||||||
|
font-weight:bold;
|
||||||
|
font-family:"黑体", Arial, Helvetica, sans-serif;
|
||||||
|
padding-right:80px;
|
||||||
|
background:url(../images/bg_header_h2.png) no-repeat right top;
|
||||||
|
}
|
||||||
|
#description{
|
||||||
|
color:#660000;
|
||||||
|
font-size:1.5em;
|
||||||
|
}
|
||||||
|
/*SIDEBAR STYLES*/
|
||||||
|
#sidebar *{
|
||||||
|
text-align:right;
|
||||||
|
}
|
||||||
|
#sidebar h3{
|
||||||
|
height:28px;
|
||||||
|
font-size:1.3em;
|
||||||
|
font-weight:bold;
|
||||||
|
padding:14px 20px 0 0;
|
||||||
|
background:url(../images/bg_sidebar_h2.png) no-repeat left top;
|
||||||
|
}
|
||||||
|
#sidebar ul{
|
||||||
|
margin:0 0 0 32px;
|
||||||
|
}
|
||||||
|
#sidebar ul ul{
|
||||||
|
display:none;
|
||||||
|
}
|
||||||
|
#sidebar li{
|
||||||
|
float:left;
|
||||||
|
width:100%;
|
||||||
|
display:inline;
|
||||||
|
margin-bottom:1px;
|
||||||
|
cursor:pointer;
|
||||||
|
}
|
||||||
|
#sidebar li a, #sidebar li a:visited{
|
||||||
|
color:#fff;
|
||||||
|
height:24px;
|
||||||
|
display:block;
|
||||||
|
font-size:1.3em;
|
||||||
|
font-weight:bold;
|
||||||
|
padding:8px 20px 0 0;
|
||||||
|
background:url(../images/bg_sidebar_a.png) no-repeat right top;
|
||||||
|
}
|
||||||
|
#sidebar li.active{
|
||||||
|
width:235px;
|
||||||
|
margin:0 0 0 -32px;
|
||||||
|
}
|
||||||
|
#sidebar li.active a, #sidebar li.active a:visited{
|
||||||
|
color:#000;
|
||||||
|
height:28px;
|
||||||
|
font-size:1.3em;
|
||||||
|
font-weight:bold;
|
||||||
|
padding:14px 20px 0 0;
|
||||||
|
background:#fff url(../images/bg_sidebar_h2.png) no-repeat left top;
|
||||||
|
}
|
||||||
|
#sidebar li ul, #sidebar li.active ul{
|
||||||
|
margin:0;
|
||||||
|
}
|
||||||
|
#sidebar li.active li a{
|
||||||
|
width:203px;
|
||||||
|
margin-left:32px;
|
||||||
|
}
|
||||||
|
#sidebar li li a, #sidebar li li a:visited, #sidebar li.active li a, #sidebar li.active li a:visited, #sidebar li.subitems li a, #sidebar li.subitems li a:visited{
|
||||||
|
color:#fff;
|
||||||
|
width:183px;
|
||||||
|
height:auto;
|
||||||
|
background:none;
|
||||||
|
font-size:1.1em;
|
||||||
|
padding:10px 20px 10px 0;
|
||||||
|
}
|
||||||
|
#sidebar li li a:hover, #sidebar li.active li a:hover{
|
||||||
|
text-decoration:underline;
|
||||||
|
}
|
||||||
|
#redbox{
|
||||||
|
height:115px;
|
||||||
|
margin-top:190px;
|
||||||
|
padding-right:20px;
|
||||||
|
}
|
||||||
|
#sidebar h4{
|
||||||
|
color:#fff;
|
||||||
|
font-size:1.1em;
|
||||||
|
font-weight:bold;
|
||||||
|
padding-top:10px;
|
||||||
|
}
|
||||||
|
#sidebar p{
|
||||||
|
color:#fff;
|
||||||
|
line-height:1.5em;
|
||||||
|
}
|
||||||
|
#sidebar big{
|
||||||
|
display:block;
|
||||||
|
font-size:1.1em;
|
||||||
|
padding:5px 0 15px 0;
|
||||||
|
}
|
||||||
|
/*CONTENT STYLES*/
|
||||||
|
#content h2{
|
||||||
|
color:#fff;
|
||||||
|
font-size:1.7em;
|
||||||
|
font-weight:bold;
|
||||||
|
padding:13px 0 0 0;
|
||||||
|
width:920px;
|
||||||
|
height:40;
|
||||||
|
background:url(../images/bg_content_h2.png) repeat-x;
|
||||||
|
}
|
||||||
|
#content form p{
|
||||||
|
clear:both;
|
||||||
|
color:#aeaeae;
|
||||||
|
padding:5px 0;
|
||||||
|
font-size:1.1em;
|
||||||
|
}
|
||||||
|
#content table{
|
||||||
|
width:920px;
|
||||||
|
margin:0 auto;
|
||||||
|
border-collapse:collapse;
|
||||||
|
}
|
||||||
|
#content tr{
|
||||||
|
background:#f2f2f2 url(../images/bg_td_highlight.png) repeat-x left top;
|
||||||
|
}
|
||||||
|
#content td{
|
||||||
|
height:28px;
|
||||||
|
width:460px;
|
||||||
|
color:#6c6c6c;
|
||||||
|
font-size:1.4em;
|
||||||
|
text-align:left;
|
||||||
|
vertical-align:middle;
|
||||||
|
border:solid 1px #d5d5d5;
|
||||||
|
border-left:0;
|
||||||
|
font-weight:bold;
|
||||||
|
text-indent:20px;
|
||||||
|
}
|
||||||
|
#content button{
|
||||||
|
height:28px;
|
||||||
|
width:80px;
|
||||||
|
color:#6c6c6c;
|
||||||
|
font-size:1.4em;
|
||||||
|
text-align:left;
|
||||||
|
border:solid 1px #d5d5d5;
|
||||||
|
border-left:0;
|
||||||
|
font-weight:bold;
|
||||||
|
text-indent:20px;
|
||||||
|
position:relative;
|
||||||
|
top:10px;
|
||||||
|
}
|
||||||
|
#content button.lpre{
|
||||||
|
left:30px;
|
||||||
|
}
|
||||||
|
#content button.lnxt{
|
||||||
|
left:720px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wangshu {
|
||||||
|
background-color: white;
|
||||||
|
/* //groove ; */
|
||||||
|
border :outset ;
|
||||||
|
font-size:1em;
|
||||||
|
padding-top:2.5px;
|
||||||
|
padding-right: 5px;
|
||||||
|
padding-bottom: 2.5px;
|
||||||
|
padding-left: 5px;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,258 @@
|
|||||||
|
<!DOCTYPE html >
|
||||||
|
<html >
|
||||||
|
<head>
|
||||||
|
<meta http-equiv="content-language" content="text/html" charset="utf-8"/>
|
||||||
|
<title>地面数字电视广播激励器</title>
|
||||||
|
<link href="css/styles.css" rel="stylesheet" type="text/css" media="screen"/>
|
||||||
|
<script src="js/jquery.js"></script>
|
||||||
|
<script type="text/javascript">
|
||||||
|
|
||||||
|
|
||||||
|
//var lastTime = new Date().getTime();
|
||||||
|
//var currentTime = new Date().getTime();
|
||||||
|
//var timeOut = 20 * 60 * 1000; //设置超时时间: 20分
|
||||||
|
//$(function(){
|
||||||
|
// /* 鼠标移动事件 */
|
||||||
|
// $(document).mouseover(function(){
|
||||||
|
// lastTime = new Date().getTime(); //更新操作时间
|
||||||
|
// });
|
||||||
|
//});
|
||||||
|
//function testTime(){
|
||||||
|
// currentTime = new Date().getTime(); //更新当前时间
|
||||||
|
// if(currentTime - lastTime > timeOut){ //判断是否超时
|
||||||
|
// window.location.href="login.html"
|
||||||
|
// }
|
||||||
|
//}
|
||||||
|
/* 定时器 间隔1秒检测是否长时间未操作页面 */
|
||||||
|
//window.setInterval(testTime, 1000);
|
||||||
|
|
||||||
|
|
||||||
|
var addr_data_arry = [
|
||||||
|
[ 3, 0xC080],
|
||||||
|
[ 2, 0x20D3],
|
||||||
|
[26, 0x0020],
|
||||||
|
[27, 0x0000]
|
||||||
|
|
||||||
|
|
||||||
|
];
|
||||||
|
|
||||||
|
function show_dac_table(addr_data_arry){
|
||||||
|
var i = 0;
|
||||||
|
var htmlstr = "";
|
||||||
|
for(i=0;i<addr_data_arry.length;i+2){
|
||||||
|
|
||||||
|
htmlstr += '<tr>';
|
||||||
|
htmlstr += '<td>'+addr_data_arry[i][0]+'</td><td><input maxlength="6" size="6" name="ccdata_'+i+'" id="ccdata_"'+i+' value="'+(addr_data_arry[i][1])+'"></td>';
|
||||||
|
htmlstr += '<td>'+addr_data_arry[i+1][0]+'</td><td><input maxlength="6" size="6" name="ccdata_'+(i+1)+'" id="ccdata_"'+(i+1)+' value="'+(addr_data_arry[i+1][1])+'"></td>';
|
||||||
|
htmlstr += '</tr>';
|
||||||
|
}
|
||||||
|
document.getElementById('dactab').innerHTML=htmlstr;
|
||||||
|
|
||||||
|
}
|
||||||
|
function SetFormDefaults( ) {
|
||||||
|
var htmlstr = "";
|
||||||
|
var queryData = "dac38j82=&";
|
||||||
|
$.get("dac.cgi?"+queryData,function(data, status)
|
||||||
|
{
|
||||||
|
var table = data.split("|");
|
||||||
|
var form0 = table[0].split("#");
|
||||||
|
var i = 1;
|
||||||
|
for(i=1; i<=57;i++){
|
||||||
|
document.getElementById("ccdata"+i).value = "0x"+('0000' +Number(form0[i]).toString(16).toUpperCase()).slice(-4);;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function cmd_confirm()
|
||||||
|
{
|
||||||
|
var txt;
|
||||||
|
if (confirm("Please choose to confirm or cancel!")){
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function setdac()
|
||||||
|
{
|
||||||
|
var postData = "dac38j82=";
|
||||||
|
var cf = document.forms[0];
|
||||||
|
var i = 1;
|
||||||
|
|
||||||
|
for(i=1; i<=57; i++){
|
||||||
|
postData += "#"+parseInt(Number(document.getElementById("ccdata"+i).value),10);
|
||||||
|
}
|
||||||
|
//alert("data="+postData);
|
||||||
|
if(cmd_confirm()){
|
||||||
|
$.ajaxSettings.async = false;
|
||||||
|
$.post("dac.cgi", postData,function(data, status){
|
||||||
|
|
||||||
|
var table = data.split("|");
|
||||||
|
var form0 = table[0].split("#");
|
||||||
|
var cf = document.forms[0];
|
||||||
|
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
$.ajaxSettings.async = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
$(document).ready(function(){
|
||||||
|
SetFormDefaults();
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</script>
|
||||||
|
<link href="css/styles.css" rel="stylesheet" type="text/css" media="screen"/>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<div id="wrap">
|
||||||
|
|
||||||
|
<div id="header">
|
||||||
|
<h1></h1>
|
||||||
|
<br/><br/>
|
||||||
|
<h2><span>地面数字电视广播激励器</span></h2>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="sidebar">
|
||||||
|
<ul class="items">
|
||||||
|
|
||||||
|
</ul>
|
||||||
|
<span class="clear"></span>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="content">
|
||||||
|
<script type='text/javascript' language='JavaScript'>
|
||||||
|
</script>
|
||||||
|
<h2>38j82</h2>
|
||||||
|
<div class="box">
|
||||||
|
<table>
|
||||||
|
<form ><!-- document.forms[0] -->
|
||||||
|
<tr>
|
||||||
|
<td>地址(十进制)</td> <td>值(十六进制)</td>
|
||||||
|
<td>地址(十进制)</td> <td>值(十六进制)</td>
|
||||||
|
<td>地址(十进制)</td> <td>值(十六进制)</td>
|
||||||
|
<td>地址(十进制)</td> <td>值(十六进制)</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
<td> 3</td><td><input maxlength="6" size="6" name="ccdata1" id="ccdata1" value=""> </td>
|
||||||
|
<td> 2</td><td><input maxlength="6" size="6" name="ccdata2" id="ccdata2" value=""> </td>
|
||||||
|
<td>26</td><td><input maxlength="6" size="6" name="ccdata3" id="ccdata3" value=""> </td>
|
||||||
|
<td>27</td><td><input maxlength="6" size="6" name="ccdata4" id="ccdata4" value=""> </td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>47</td><td><input maxlength="6" size="6" name="ccdata5" id="ccdata5" value=""> </td>
|
||||||
|
<td>49</td><td><input maxlength="6" size="6" name="ccdata6" id="ccdata6" value=""> </td>
|
||||||
|
<td>50</td><td><input maxlength="6" size="6" name="ccdata7" id="ccdata7" value=""> </td>
|
||||||
|
<td>51</td><td><input maxlength="6" size="6" name="ccdata8" id="ccdata8" value=""> </td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
<td> 7</td><td><input maxlength="6" size="6" name="ccdata9" id="ccdata9" value=""> </td>
|
||||||
|
<td>59</td><td><input maxlength="6" size="6" name="ccdata10" id="ccdata10" value=""> </td>
|
||||||
|
<td>60</td><td><input maxlength="6" size="6" name="ccdata11" id="ccdata11" value=""> </td>
|
||||||
|
<td>61</td><td><input maxlength="6" size="6" name="ccdata12" id="ccdata12" value=""> </td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
<td>62</td><td><input maxlength="6" size="6" name="ccdata13" id="ccdata13" value=""> </td>
|
||||||
|
<td>63</td><td><input maxlength="6" size="6" name="ccdata14" id="ccdata14" value=""> </td>
|
||||||
|
<td>70</td><td><input maxlength="6" size="6" name="ccdata15" id="ccdata15" value=""> </td>
|
||||||
|
<td>71</td><td><input maxlength="6" size="6" name="ccdata16" id="ccdata16" value=""> </td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>72</td><td><input maxlength="6" size="6" name="ccdata17" id="ccdata17" value=""> </td>
|
||||||
|
<td>73</td><td><input maxlength="6" size="6" name="ccdata18" id="ccdata18" value=""> </td>
|
||||||
|
<td>96</td><td><input maxlength="6" size="6" name="ccdata19" id="ccdata19" value=""> </td>
|
||||||
|
<td>37</td><td><input maxlength="6" size="6" name="ccdata20" id="ccdata20" value=""> </td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
<td>36</td><td><input maxlength="6" size="6" name="ccdata21" id="ccdata21" value=""> </td>
|
||||||
|
<td> 0</td><td><input maxlength="6" size="6" name="ccdata22" id="ccdata22" value=""> </td>
|
||||||
|
<td> 3</td><td><input maxlength="6" size="6" name="ccdata23" id="ccdata23" value=""> </td>
|
||||||
|
<td>74</td><td><input maxlength="6" size="6" name="ccdata24" id="ccdata24" value=""> </td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
<td>75</td><td><input maxlength="6" size="6" name="ccdata25" id="ccdata25" value=""> </td>
|
||||||
|
<td>76</td><td><input maxlength="6" size="6" name="ccdata26" id="ccdata26" value=""> </td>
|
||||||
|
<td>77</td><td><input maxlength="6" size="6" name="ccdata27" id="ccdata27" value=""> </td>
|
||||||
|
<td>78</td><td><input maxlength="6" size="6" name="ccdata28" id="ccdata28" value=""> </td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
<td>79</td><td><input maxlength="6" size="6" name="ccdata29" id="ccdata29" value=""> </td>
|
||||||
|
<td>80</td><td><input maxlength="6" size="6" name="ccdata30" id="ccdata30" value=""> </td>
|
||||||
|
<td>81</td><td><input maxlength="6" size="6" name="ccdata31" id="ccdata31" value=""> </td>
|
||||||
|
<td>82</td><td><input maxlength="6" size="6" name="ccdata32" id="ccdata32" value=""> </td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>83</td><td><input maxlength="6" size="6" name="ccdata33" id="ccdata33" value=""> </td>
|
||||||
|
<td>84</td><td><input maxlength="6" size="6" name="ccdata34" id="ccdata34" value=""> </td>
|
||||||
|
<td>85</td><td><input maxlength="6" size="6" name="ccdata35" id="ccdata35" value=""> </td>
|
||||||
|
<td>92</td><td><input maxlength="6" size="6" name="ccdata36" id="ccdata36" value=""> </td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
<td>94</td><td><input maxlength="6" size="6" name="ccdata37" id="ccdata37" value=""> </td>
|
||||||
|
<td>95</td><td><input maxlength="6" size="6" name="ccdata38" id="ccdata38" value=""> </td>
|
||||||
|
<td>97</td><td><input maxlength="6" size="6" name="ccdata39" id="ccdata39" value=""> </td>
|
||||||
|
<td> 2</td><td><input maxlength="6" size="6" name="ccdata40" id="ccdata40" value=""> </td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
<td>12</td><td><input maxlength="6" size="6" name="ccdata41" id="ccdata41" value=""> </td>
|
||||||
|
<td>13</td><td><input maxlength="6" size="6" name="ccdata42" id="ccdata42" value=""> </td>
|
||||||
|
<td>16</td><td><input maxlength="6" size="6" name="ccdata43" id="ccdata43" value=""> </td>
|
||||||
|
<td>18</td><td><input maxlength="6" size="6" name="ccdata44" id="ccdata44" value=""> </td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>19</td><td><input maxlength="6" size="6" name="ccdata45" id="ccdata45" value=""> </td>
|
||||||
|
<td>20</td><td><input maxlength="6" size="6" name="ccdata46" id="ccdata46" value=""> </td>
|
||||||
|
<td>21</td><td><input maxlength="6" size="6" name="ccdata47" id="ccdata47" value=""> </td>
|
||||||
|
<td>22</td><td><input maxlength="6" size="6" name="ccdata48" id="ccdata48" value=""> </td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>30</td><td><input maxlength="6" size="6" name="ccdata49" id="ccdata49" value=""> </td>
|
||||||
|
<td>31</td><td><input maxlength="6" size="6" name="ccdata50" id="ccdata50" value=""> </td>
|
||||||
|
<td>31</td><td><input maxlength="6" size="6" name="ccdata51" id="ccdata51" value=""> </td>
|
||||||
|
<td>32</td><td><input maxlength="6" size="6" name="ccdata52" id="ccdata52" value=""> </td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>34</td><td><input maxlength="6" size="6" name="ccdata53" id="ccdata53" value=""> </td>
|
||||||
|
<td>38</td><td><input maxlength="6" size="6" name="ccdata54" id="ccdata54" value=""> </td>
|
||||||
|
<td> 1</td><td><input maxlength="6" size="6" name="ccdata55" id="ccdata55" value=""> </td>
|
||||||
|
<td>74</td><td><input maxlength="6" size="6" name="ccdata56" id="ccdata56" value=""> </td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td> 3</td><td><input maxlength="6" size="6" name="ccdata57" id="ccdata57" value=""> </td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
<td><input type="button" class="wangshu" alt="设置" value="设 置" onclick="return setdac();"> </td>
|
||||||
|
</tr>
|
||||||
|
</form>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
After Width: | Height: | Size: 883 B |
|
After Width: | Height: | Size: 426 B |
|
After Width: | Height: | Size: 146 B |
|
After Width: | Height: | Size: 324 B |
|
After Width: | Height: | Size: 1.7 KiB |
|
After Width: | Height: | Size: 3.1 KiB |
|
After Width: | Height: | Size: 4.4 KiB |
|
After Width: | Height: | Size: 12 KiB |
|
After Width: | Height: | Size: 726 B |
|
After Width: | Height: | Size: 389 B |
|
After Width: | Height: | Size: 145 B |
|
After Width: | Height: | Size: 162 B |
|
After Width: | Height: | Size: 949 B |
|
After Width: | Height: | Size: 4.8 KiB |
|
After Width: | Height: | Size: 5.1 KiB |
|
After Width: | Height: | Size: 4.0 KiB |
|
After Width: | Height: | Size: 986 B |
|
After Width: | Height: | Size: 976 B |
|
After Width: | Height: | Size: 1.2 KiB |
|
After Width: | Height: | Size: 1.1 KiB |
|
After Width: | Height: | Size: 1.3 KiB |
|
After Width: | Height: | Size: 1.0 KiB |
|
After Width: | Height: | Size: 1010 B |