You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

657 lines
27 KiB

<!DOCTYPE html>
<html>
<head>
<meta http-equiv="cache-control"
content="max-age=0" />
<meta http-equiv="cache-control"
content="no-cache, no-store, must-revalidate" />
<meta http-equiv="expires"
content="-1" />
<meta http-equiv="expires"
content="Tue, 01 Jan 1980 1:00:00 GMT" />
<meta http-equiv="pragma"
content="no-cache" />
<meta http-equiv="Pragma" content="no-cache">
<meta http-equiv="Expires" content="0">
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta charset="utf-8" />
<!-- <link rel="preload" href="./Icon/Counter_Green_64x64px.png" as="image" /> -->
<!-- <link rel="preload" href="images/icon_alarm.png" as="image" />
<link rel="preload" href="images/icon_output.png" as="image" />
<link rel="preload" href="images/icon_setting.png" as="image" />
<link rel="preload" href="images/icon_license.png" as="image" /> -->
<style>
body, html {
font-family: "Arial";
}
* {
box-sizing: border-box;
}
/* Create two equal columns that floats next to each other */
.column {
float: left;
overflow: hidden;
/*width: 33%;*/
padding-left: 10px;
/*height: 300px;*/
/*margin: auto;*/
/* Should be removed. Only for demonstration */
}
/* Clear floats after the columns */
.row:after {
content: "";
display: table;
clear: both;
}
/* Responsive layout - makes the two columns stack on top of each other instead of next to each other */
@media screen and (max-width: 400px) {
.column {
width: 100%;
}
}
/* hide the up and down arrows which are built in number type input */
/* Chrome, Safari, Edge, Opera */
input::-webkit-outer-spin-button,
input::-webkit-inner-spin-button {
-webkit-appearance: none;
margin: 0;
}
/* Firefox */
input[type=number] {
-moz-appearance: textfield;
}
/* 80 port tab inside OK button style */
.Content_stybtn_ln {
/* display: inline-block; */
background-color: #2a2a2a;
border-radius: 10px;
border: 0px;
padding-left: 20px;
padding-right: 20px;
height: 25px;
color: white;
font-family: "Arial","Helvetica","sans-serif";
font-size: 14px;
}
.Content_stybtn_ln:hover {
background-color: #678cd4;
}
.Content_stybtn_ln:disabled {
background-color: grey;
color: #DCDCDC;
}
</style>
<!-- 原 plugin 是用 "jquery_3_2_1.min.js",初始化直接載入,避免載入時間點太慢導致高度設定問題 -->
<script src="/airelay/jquery_3_2_1.min.js"></script>
<!-- 避免在單一檔案卡太久,以非同步處理 -->
<script src="/airelay/fabric_jquery.easyui.min_compressed_on_nvr.js" async></script>
<script>
function GetUrlPort() {
var url_href = window.location.href;
// console.log(`[GetUrlPort] url_href: ${url_href}`);
var arr_url = url_href.split(":");
var port = 80;
if (arr_url.length > 2) { // plugin 開分頁會有 <ip>:<port_number> 格式
port = arr_url[2].split("/")[0];
}
// console.log(`[GetUrlPort] return: ${port}`);
return port;
}
localStorage.setItem('landing_page_port', GetUrlPort());
// console.log("[airelay_init.html] localStorage landing_page_port: ", localStorage.getItem('landing_page_port'));
var g_tcp_tunnel_token = "airelay";
// 逐步加載腳本列表
var resourcesToLoad = [
"/js/common.js",
`/${g_tcp_tunnel_token}/cookie.min.js`,
`/${g_tcp_tunnel_token}/alarm_on_airelay.js`,
`/${g_tcp_tunnel_token}/lang.js`,
`/${g_tcp_tunnel_token}/lang_cookie.js`,
`/${g_tcp_tunnel_token}/config.js`,
`/${g_tcp_tunnel_token}/unit1.js`,
`/${g_tcp_tunnel_token}/label_names.js`,
`/${g_tcp_tunnel_token}/third_party_label_names.js`,
`/${g_tcp_tunnel_token}/lib/owl.carousel.min.js`
];
var loadCount = 0;
function loadScriptsWithDelay() {
var index = 0;
var interval = 20; // 每次迭代之間的延遲時間,單位是毫秒
var errorReconnectInterval = 100;
function loadNextScript() {
if (index < resourcesToLoad.length) {
(function (currentIndex) {
var src = resourcesToLoad[index];
var script = document.createElement('script');
script.type = "text/javascript";
script.src = src;
script.async = false;
script.onload = function () {
// console.log('[script ' + currentIndex + '] ' + src + ' has been successfully loaded');
index++;
setTimeout(loadNextScript, interval); // 加載下一個腳本之前等待一段時間
loadCount++;
};
script.onerror = function () {
console.error('[Error] Failed to load script: ' + src + ' at index: ' + currentIndex);
setTimeout(() => {
window.location.reload();
}, errorReconnectInterval);
};
document.getElementsByTagName("head")[0].appendChild(script);
})(index);
} else {
// console.log("All scripts loaded successfully!");
}
}
// 開始加載第一個腳本
loadNextScript();
}
// 開始使用延遲加載的方式加載腳本
loadScriptsWithDelay();
// --------------------------------------------------------------------------------
var imagesToPreload = [
`/${g_tcp_tunnel_token}/images/rotate.png`,
`/${g_tcp_tunnel_token}/images/slider_handle.png`
];
function preloadImagesWithDelay() {
var imgIndex = 0;
var interval = 150; // 每次迭代之間的延遲時間,單位是毫秒
function loadNextImage() {
if (imgIndex < imagesToPreload.length) {
var src = imagesToPreload[imgIndex];
// console.log("[img " + imgIndex + "] start to preload: "+src);
var link = document.createElement('link');
link.rel = 'preload';
link.href = src;
link.as = 'image';
link.onload = function () {
// console.log('[img ' + imgIndex + '] ' + src + ' has been successfully preloaded');
imgIndex++;
setTimeout(loadNextImage, interval); // 加載下一個影像之前等待一段時間
};
link.onerror = function () {
// console.error('Failed to preload image: ' + src + ' at index: ' + imgIndex);
// 處理影像加載失敗的情況,可以進行重整頁面或其他操作
window.location.reload();
};
document.head.appendChild(link);
} else {
// console.log("All images preloaded successfully!");
}
}
// 開始預加載第一個影像
loadNextImage();
}
// 開始使用延遲加載的方式預加載影像
// preloadImagesWithDelay();
// --------------------------------------------------------------------------------
var tabsButtonId = [
{ tabId: 'TAB_ALARM', textId: 'HTTP_TITLE05', icon: 'icon_alarm.png', pageId: 'alarm' },
{ tabId: 'TAB_OUTPUT', textId: 'HTTP_TITLE08', icon: 'icon_output.png', pageId: 'output' },
{ tabId: 'TAB_SETTING', textId: 'HTTP_TITLE06', icon: 'icon_setting.png', pageId: 'setting' },
{ tabId: 'TAB_LICENSE', textId: 'HTTP_TITLE07', icon: 'icon_license.png', pageId: 'license' }
];
var iconSize = '60px';
var innerIframeId = "innerIframe";
var loadingElementId = 'percentage';
var preloadImgElementId = 'preloadImg';
// 透過 jQuery 拿到外層 iframe 尺寸
var iframeWidth = window.innerWidth - 80;
function addIframeToBody(src) {
// var iframe = document.createElement('iframe');
var iframe = document.getElementById(innerIframeId);
// iframe.id = innerIframeId;
// 避免預設邊框樣式
iframe.style.border = 'none';
iframe.width = iframeWidth;
iframe.style.border = '0';
iframe.frameBorder = '0'; // 設置 frameborder 屬性
// 設置載入檔案來源
iframe.src = src;
}
function addTmpSnapImageToDiv(imgWidth, imgHeight) {
// console.log("create preload img element");
var img = document.createElement('img');
// 設置 img 屬性
img.width = imgWidth;
img.height = imgHeight;
// 載入影像
var port = localStorage.getItem('landing_page_port');
img.src = 'http://' + window.location.hostname + ':' + port + '/snap';
// 將 img 附加到預設位置
var div = document.getElementById(preloadImgElementId);
if (div) {
div.appendChild(img);
}
}
// --------------------------------------------------------------------------------
// 08-08
function func_getWanPort() {
$.ajax({
url: '/network?get=all',
method: "GET",
async: true,
beforeSend: function (xmlHttp) {
xmlHttp.setRequestHeader("If-Modified-Since", "0");
xmlHttp.setRequestHeader("Cache-Control", "no-cache");
// xmlHttp.setRequestHeader("Referer", window.location.origin);
//xmlHttp.setRequestHeader("Authorization", "Basic " + btoa("username:password"));
},
success: function (retdata) {
// console.log(retdata);
func_filterWanInfo(retdata);
},
error: function () {
setTimeout(func_getWanPort(), 3000);
console.warn();
}
});
return false;
}
function func_filterWanInfo(data) {
var targetNumber = '8592';
// 將回傳的資料以換行符號分割為一個陣列
var lines = data.split('\r\n');
// 過濾出以 'lpkg.wan' 開頭且包含 'info=1' 的行
var filteredLines = lines.filter(line => line.startsWith('lpkg.wan') && line.includes('info=1'));
// 輸出過濾後的結果
// console.log("[filterWanInfo] filtered lines:", filteredLines);
// 沒設定 WAN 的情況,預設 8592
localStorage.setItem("plugin_wan_port", targetNumber);
// 使用迴圈掃掠 filteredLines
for (var line of filteredLines) {
if (line.includes(targetNumber)) { // 有設定 WAN 才會從 info 撈到對應關係
var parts = line.split(','); // 以 ',' 裁切
extractedNumber = parts[parts.length - 1]; // 取出最後一個部分
localStorage.setItem("plugin_wan_port", extractedNumber);
break;
}
}
// console.log("plugin wan port: ", localStorage.getItem("plugin_wan_port"));
return filteredLines;
}
function func_setPluginLang(ipcam_lang_index) {
var lang = 'en_gb'; // 預設 English
if (ipcam_lang_index == 1 || ipcam_lang_index == 2) {
lang = 'zh_tw'; // 繁中 簡中 歸納成 Chinese
} else if (ipcam_lang_index == 4) {
lang = 'it_it'; // Italian
} else if (ipcam_lang_index == 11) {
lang = 'ja_jp'; // Japanese
} // 其他語系,歸納到預設
// console.log(`[SetPluginLang] ipcam_lang_index : ${ipcam_lang_index} , set plugin cookie : ${lang}`);
cookie("LANG", lang, "9999/12/31 12:00:00");
var json_data = '{';
json_data += '"system_setting": {';
json_data += '"language": "' + lang + '"';
json_data += '}}';
func_setconfigfile(json_data);
}
// --------------------------------------------------------------------------------
var checkIntervalTime = 500;
var hideLoadPageDeferTime = 1500;
var preloadImgDisplayTime = 500;
var intervalID = null;
var checkPercentageStuckCounter = 0;
var percentage = 0;
var landingPage = "/airelay/alarm_on_airelay.html";
var progressBarHeight = 8;
var snapImgWidth = 720; // 同 G_VIEW_CANVAS_X 設定
var snapImgHeight = 480; // 同 G_VIEW_CANVAS_Y 設定
clearInterval(intervalID);
// 持續檢核是否加載完成
intervalID = setInterval(function () {
var loadingElement = document.getElementById(loadingElementId);
var prevPercentage = percentage;
var percentageStuckThreshold = 30; // 08-16 原設定 2,網速慢時,容易載一半就當成錯誤,才拉長等待時間
percentage = Math.round(((loadCount / resourcesToLoad.length) * 100), 2);
// console.log("[setInterval] check percentage: " + percentage + " , prev percentage: " + prevPercentage);
if ((percentage == prevPercentage) && (percentage < 100)) {
checkPercentageStuckCounter++;
// console.log("checkPercentageStuckCounter: ", checkPercentageStuckCounter);
if (checkPercentageStuckCounter >= percentageStuckThreshold) {
// console.log("reload init page");
window.location.reload();
}
} else {
// 頻寬差時,不能讓 Counter 在不同 script 載入過程持續累積,容易觸發 reload
checkPercentageStuckCounter = 0;
// console.log("reset checkPercentageStuckCounter: ", checkPercentageStuckCounter);
}
loadingElement.innerText = "Loading scripts ... " + percentage.toString() + " %";
if (loadCount == resourcesToLoad.length) {
localStorage.setItem("loadScriptIndex", 0);
// console.log("prepare to load landing page ...");
// window.parent.document
var outterIframeElement = window.parent.document.querySelector("#content-show iframe");
// console.log(outterIframeElement);
if (outterIframeElement) {
outterIframeElement.height = "1000"; // 調整外框高度
}
func_getWanPort(); // 08-08
// 08-09
//var ipcam_lang_setting = GetCookie('ipcam_lang');
// console.log("[airelay_init.html] get ipcam_lang_setting:", ipcam_lang_setting);
//func_setPluginLang(ipcam_lang_setting);
clearInterval(intervalID);
// 這邊沿用 G_VIEW_CANVAS_X & G_VIEW_CANVAS_Y 仍會是 480 x 320,改設變數同步解析度
addTmpSnapImageToDiv(snapImgWidth, snapImgHeight);
// 08-29 暫時不載第二層,先把 script load 好
addIframeToBody(landingPage);
setTimeout(() => {
// console.log("defer load landing page");
loadingElement.style.top = (progressBarHeight + snapImgHeight) + 'px';
loadingElement.style.position = "absolute";
loadingElement.innerText = "Streaming and Page initialization ...";
var preloadElement = document.getElementById(preloadImgElementId);
if (preloadElement) {
preloadElement.style.top = progressBarHeight + 'px'; // progress bar height
preloadElement.style.display = 'inline';
}
checkH264Streaming();
}, hideLoadPageDeferTime);
}
}, checkIntervalTime)
func_getaboutinfo();
localStorage.setItem("receivedH264", false);
localStorage.setItem('iframeHeight', null);
// console.log("[airelay_init.html] Init localStorage receivedH264: ", localStorage.getItem("receivedH264"));
var defaultBtnOffset = 30; // 預設按鈕往下偏移距離
function checkH264Streaming() {
// console.log("start checkH264Streaming");
var checkH264IntervalID = null;
checkH264IntervalID = setInterval(function () {
var receivedH264 = localStorage.getItem("receivedH264");
// console.log("[airelay_init.html] receivedH264: ", receivedH264);
if (receivedH264 == "true") {
var loadingElement = document.getElementById(loadingElementId);
if (loadingElement) {
loadingElement.style.display = 'none';
}
// console.log("[airelay_init.html] hide preloadElement");
var preloadElement = document.getElementById(preloadImgElementId);
if (preloadElement) {
preloadElement.style.display = 'none';
}
// 顯示預設按鈕
var defaultButtonElement = document.getElementById('defaultBtn');
if (defaultButtonElement) {
defaultButtonElement.style.display = 'block';
defaultButtonElement.style.width = iframeWidth + 'px';
}
// 顯示內層 iframe
var innerIframeElement = document.getElementById(innerIframeId);
if (innerIframeElement) {
innerIframeElement.style.display = 'block'; // 先顯示才能知道高度
// 08-29
var iframeDocument = innerIframeElement.contentDocument || innerIframeElement.contentWindow.document;
var iframeHeight = iframeDocument.body.offsetHeight;
localStorage.setItem('iframeHeight', iframeHeight);
innerIframeElement.height = iframeHeight + defaultBtnOffset;
}
// console.log("[airelay_init.html] set innerIframeElement.height:", iframeHeight + defaultBtnOffset);
clearInterval(checkH264IntervalID);
}
}, checkIntervalTime)
}
// --------------------------------------------------------------------------------
function func_setTcptunnelPage(page) {
$.ajax({
url: "/airelay/settcptunnel?page=" + page,
type: "GET",
async: true,
beforeSend: function (xmlHttp) {
xmlHttp.setRequestHeader("If-Modified-Since", "0");
xmlHttp.setRequestHeader("Cache-Control", "no-cache");
//xmlHttp.setRequestHeader("Authorization", "Basic " + btoa("username:password"));
},
success: function (retdata) {
// console.log(retdata);
},
error: function (retdata) {
console.warn(retdata);
}
});
}
function func_setDefault() {
if (confirm('Do you want to apply default settings?')) {
cookie("enable_only_show_metadata1", "on", "9999/12/31 12:00:00");
$.ajax({
url: '/' + g_tcp_tunnel_token + "/system?default=3",
type: "GET",
async: true,
beforeSend: function (xmlHttp) {
xmlHttp.setRequestHeader("If-Modified-Since", "0");
xmlHttp.setRequestHeader("Cache-Control", "no-cache");
//xmlHttp.setRequestHeader("Authorization", "Basic " + btoa("username:password"));
},
success: function (retdata) {
// console.log("[func_setDefault] retdata: ", retdata);
//var jsonbuf = JSON.parse(retdata);
//$('#CPU_USAGE').val(jsonbuf["CPU_USAGE"] + " %");
//$('#GPU_USAGE').val(jsonbuf["GPU_USAGE"] + " %");
//$('#FPS').val(jsonbuf["FPS"]);
//document.getElementById('CPU_USAGE').innerHTML=jsonbuf["CPU_USAGE"]+" %";
//document.getElementById('GPU_USAGE').innerHTML=jsonbuf["GPU_USAGE"]+" %";
//document.getElementById('FPS').innerHTML=jsonbuf["FPS"];
//func_getreload();
//alert("Close or refresh the browser to reboot the camera.");
/*
var replaceUrl = 'http://' + window.location.hostname + ':' + myport + '/setup.htm';
//alert(replaceUrl);
parent.window.location.replace(replaceUrl);*/
//parent.open(parent.location, '_parent').close();
//console.info(retdata);
},
error: function (retdata) {
console.warn(retdata);
//alert("Close or refresh the browser to reboot the camera.");
//parent.open(parent.location, '_parent').close();
}
});
var port = localStorage.getItem('landing_page_port');
// console.log("[func_setDefault] port:", port);
var innerIframe = document.getElementById(innerIframeId);
if (innerIframe) {
innerIframe.width = iframeWidth;
innerIframe.height = '600px';
innerIframe.style.border = '0';
innerIframe.style.position = "absolute";
innerIframe.frameBorder = '0'; // 設置 frameborder 屬性
innerIframe.src = 'http://' + window.location.hostname + ':' + port + '/' + g_tcp_tunnel_token + '/countdown.html';
}
var defaultButtonElement = document.getElementById('defaultBtn');
if (defaultButtonElement) {
defaultButtonElement.style.display = 'none';
}
window.onload = function () {
window.scrollTo(0, 0);
};
//console.log('Apply default settings!');
return false;
}
}
function func_getaboutinfo() {
$.ajax({
url: '/airelay' + "/getAidaInfo",
type: "GET",
async: true,
beforeSend: function (xmlHttp) {
xmlHttp.setRequestHeader("If-Modified-Since", "0");
xmlHttp.setRequestHeader("Cache-Control", "no-cache");
//xmlHttp.setRequestHeader("Authorization", "Basic " + btoa("username:password"));
},
success: function (retdata) {
//var jsonbuf = JSON.parse('{ "name":"John", "age":30, "city":"New York"}');
var jsonbuf = JSON.parse(retdata);
localStorage.setItem("events_default_version", jsonbuf["events_default_version"]);
if (localStorage.getItem('current_state_hide_or_open_label') == null) {
if (localStorage.getItem("events_default_version") != null && localStorage.getItem("events_default_version") == "4") {
localStorage.setItem('current_state_hide_or_open_label', 0);
}
else {
localStorage.setItem('current_state_hide_or_open_label', 1);
}
}
//console.info(retdata);
},
error: function (retdata) {
console.warn(retdata);
setTimeout(func_getPostEventName(), 3000);
}
});
}
</script>
<!-- 08-29 -->
<link rel="stylesheet" type="text/css" href="/airelay/bootstrap.min.css">
</head>
<body onContextMenu="window.event.returnValue=false" style="margin: 0px;">
<div id="tabs" style="display: none;">
<label id="TAB_ALARM">
<a>
<nobr id="HTTP_TITLE05"></nobr>
</a>
</label>
<label id="TAB_OUTPUT">
<a>
<nobr id="HTTP_TITLE08"></nobr>
</a>
</label>
<label id="TAB_SETTING">
<a>
<nobr id="HTTP_TITLE06"></nobr>
</a>
</label>
<label id="TAB_LICENSE">
<a>
<nobr id="HTTP_TITLE07"></nobr>
</a>
</label>
</div>
<div id="preloadImg" style="position: absolute; display: none;"></div>
<p id="percentage" height="650">
Loading ... 0%
</p>
<iframe id="innerIframe" frameborder="0" style="display: none;"></iframe>
<div id="defaultBtn" align="center" style="display:none;">
<button class="Content_stybtn_ln" onclick="func_setDefault()">Default</button>
</div>
</body>
</html>