V125-260722:(暂时发现DPD/FSSI/网页频谱显示都不正常,临时提交)1.合并增加 Web 端 FPGA .mcs 在线升级功能,支持升级进度及错误状态反馈。2.合并优化 FPGA 升级后的恢复流程,实现无需断电的 FPGA 配置、JESD 链路及 RF 热恢复。3.合并重构 ORx 功率、FSSI 和 FWD 计算;4.合并DPD相关优化和调试日志;5.合并IQ 频谱数据接收由 eth1 调整至 eth0,降低对外部网口连接状态的依赖。

This commit is contained in:
2026-07-22 17:08:03 +08:00
commit c6ab382383
1655 changed files with 516169 additions and 0 deletions
Executable
+3
View File
@@ -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
Binary file not shown.
Binary file not shown.
Binary file not shown.
+8
View File
@@ -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
+13
View File
@@ -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
BIN
View File
Binary file not shown.
+2
View File
@@ -0,0 +1,2 @@
#!/bin/sh
killall http
+8
View File
@@ -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/
+2
View File
@@ -0,0 +1,2 @@
#!/bin/sh
/aw/anywave/web/bin/http -p 80 -d /aw/anywave/web/www -c *.cgi -t utf-8&
+3
View File
@@ -0,0 +1,3 @@
anywavecom:anywavecom
hhee:hhee
Binary file not shown.
+73
View File
@@ -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();
}
})();
Binary file not shown.
Binary file not shown.
Binary file not shown.
File diff suppressed because it is too large Load Diff
Binary file not shown.
Binary file not shown.
Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.
Binary file not shown.
Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.
Binary file not shown.
+73
View File
@@ -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();
}
})();
+260
View File
@@ -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
};
})();
+2
View File
File diff suppressed because one or more lines are too long
+538
View File
@@ -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 &#9662;</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">&#176;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()">&times;</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>
Binary file not shown.
+113
View File
@@ -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>
+4
View File
@@ -0,0 +1,4 @@
#!/bin/sh
./com-status-process
./boot-limit-process
File diff suppressed because it is too large Load Diff
+4
View File
@@ -0,0 +1,4 @@
#!/bin/sh
killall -9 com-status-process
killall -9 boot-limit-process
+847
View File
@@ -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 &#9662;</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">&#176;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()">&times;</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>
+957
View File
@@ -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 &#9662;</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">&#176;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()">&times;</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>
File diff suppressed because it is too large Load Diff
+770
View File
@@ -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 &#9662;</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">&#176;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&hellip;</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">&gt; 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&hellip;</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">&tau;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()">&times;</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>
+867
View File
@@ -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 &#9662;</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">&#176;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()">&times;</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>
Binary file not shown.
+2
View File
@@ -0,0 +1,2 @@
anywavecom:anywavecom
+162
View File
@@ -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 &
+87
View File
@@ -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}
+6
View File
@@ -0,0 +1,6 @@
#!/bin/sh
UPGRADE_FILE_PATH="/tmp/upgrade"
cd ${UPGRADE_FILE_PATH}/EMV* && ./runme.sh
+4
View File
@@ -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
+1
View File
@@ -0,0 +1 @@
7_260722_125
+5
View File
@@ -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
+24
View File
@@ -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.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
Binary file not shown.
BIN
View File
Binary file not shown.
+16
View File
@@ -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
+15
View File
@@ -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
+7
View File
@@ -0,0 +1,7 @@
#!/bin/sh
rm -rf /aw/anywave/web/www/cgi-debug.txt
rm -rf /forlinx/audio/*
rm -rf /forlinx/video/*
sync
+7
View File
@@ -0,0 +1,7 @@
#!/bin/sh
killall logrotateStart daemon_system
sh remove.sh
sh cp.sh
sync
sleep 2
reboot
Binary file not shown.
@@ -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
Binary file not shown.
@@ -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;
}
Binary file not shown.
@@ -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>
Binary file not shown.

After

Width:  |  Height:  |  Size: 883 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 426 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 146 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 324 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 726 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 389 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 145 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 162 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 949 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 986 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 976 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1010 B

Some files were not shown because too many files have changed in this diff Show More