- Improved operator name detection logic with PLMN code priority - Added fallback mechanism for hexadecimal encoded operator names
1978 lines
80 KiB
HTML
1978 lines
80 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="en" data-bs-theme="light">
|
||
<head>
|
||
<meta charset="utf-8" />
|
||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||
<title>模块管理</title>
|
||
<!-- <link
|
||
href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css"
|
||
rel="stylesheet"
|
||
integrity="sha384-QWTKZyjpPEjISv5WaRU9OFeRpok6YctnYmDr5pNlyT2bRjXh0JMhjY6hW+ALEwIH"
|
||
crossorigin="anonymous"
|
||
/> -->
|
||
<!-- Import all the bootstrap css files from css folder -->
|
||
<link rel="stylesheet" href="css/styles.css" />
|
||
<link rel="stylesheet" href="css/bootstrap.min.css" />
|
||
|
||
<!-- Logo -->
|
||
<link rel="simpleadmin-logo" href="favicon.ico" />
|
||
|
||
<!-- Import BootStrap Javascript -->
|
||
<script src="js/bootstrap.bundle.min.js"></script>
|
||
<script src="js/alpinejs.min.js" defer></script>
|
||
</head>
|
||
<body>
|
||
<main>
|
||
<div class="container my-4" x-data="processAllInfos()">
|
||
<nav class="navbar navbar-expand-lg mt-2">
|
||
<div class="container-fluid">
|
||
<a class="navbar-brand" href="/"
|
||
><span class="mb-0 h4 fw-bold">模块管理</span></a
|
||
>
|
||
<button
|
||
class="navbar-toggler"
|
||
type="button"
|
||
data-bs-toggle="collapse"
|
||
data-bs-target="#navbarText"
|
||
aria-controls="navbarText"
|
||
aria-expanded="false"
|
||
aria-label="Toggle navigation"
|
||
>
|
||
<span class="navbar-toggler-icon"></span>
|
||
</button>
|
||
<div class="collapse navbar-collapse" id="navbarText">
|
||
<ul class="navbar-nav me-auto mb-2 mb-lg-0">
|
||
<li class="nav-item">
|
||
<a class="nav-link active" aria-current="page" href="/">首页</a>
|
||
</li>
|
||
<li class="nav-item">
|
||
<a class="nav-link" href="network.html">网络</a>
|
||
</li>
|
||
<li class="nav-item">
|
||
<a class="nav-link" href="/scanner.html">扫描</a>
|
||
</li>
|
||
<li class="nav-item">
|
||
<a class="nav-link" href="/settings.html">设置</a>
|
||
</li>
|
||
<li class="nav-item">
|
||
<a class="nav-link" href="/sms.html">短信</a>
|
||
</li>
|
||
<li class="nav-item">
|
||
<a class="nav-link" href="/console">控制台</a>
|
||
</li>
|
||
<li class="nav-item">
|
||
<a class="nav-link" href="/deviceinfo.html"
|
||
>设备信息</a
|
||
>
|
||
</li>
|
||
</ul>
|
||
<span class="navbar-text">
|
||
<button class="btn btn-link text-reset" id="darkModeToggle">
|
||
暗黑模式
|
||
</button>
|
||
</span>
|
||
</div>
|
||
</div>
|
||
</nav>
|
||
|
||
<div class="row align-items-center mt-5 gap-md-3 gap-2">
|
||
<div class="col align-self-center">
|
||
<div class="card">
|
||
<div
|
||
class="card-body d-flex flex-column align-items-center justify-content-center"
|
||
>
|
||
<svg
|
||
xmlns="http://www.w3.org/2000/svg"
|
||
viewBox="0 0 320 512"
|
||
height="85"
|
||
width="85"
|
||
>
|
||
<path
|
||
fill="#fdb53c"
|
||
d="M160 64c-26.5 0-48 21.5-48 48V276.5c0 17.3-7.1 31.9-15.3 42.5C86.2 332.6 80 349.5 80 368c0 44.2 35.8 80 80 80s80-35.8 80-80c0-18.5-6.2-35.4-16.7-48.9c-8.2-10.6-15.3-25.2-15.3-42.5V112c0-26.5-21.5-48-48-48zM48 112C48 50.2 98.1 0 160 0s112 50.1 112 112V276.5c0 .1 .1 .3 .2 .6c.2 .6 .8 1.6 1.7 2.8c18.9 24.4 30.1 55 30.1 88.1c0 79.5-64.5 144-144 144S16 447.5 16 368c0-33.2 11.2-63.8 30.1-88.1c.9-1.2 1.5-2.2 1.7-2.8c.1-.3 .2-.5 .2-.6V112zM208 368c0 26.5-21.5 48-48 48s-48-21.5-48-48c0-20.9 13.4-38.7 32-45.3V272c0-8.8 7.2-16 16-16s16 7.2 16 16v50.7c18.6 6.6 32 24.4 32 45.3z"
|
||
/>
|
||
</svg>
|
||
<h1
|
||
class="card-text mt-4"
|
||
x-text="temperature + ' °C'"
|
||
></h1>
|
||
</div>
|
||
<div class="card-footer"
|
||
style="text-align:center;">
|
||
模块温度
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="col align-self-center">
|
||
<div class="card">
|
||
<div
|
||
class="card-body d-flex flex-column align-items-center justify-content-center"
|
||
>
|
||
<svg
|
||
xmlns="http://www.w3.org/2000/svg"
|
||
viewBox="0 0 384 512"
|
||
height="85"
|
||
width="85"
|
||
>
|
||
<path
|
||
fill="#6a46d8"
|
||
d="M64 0H242.7c17 0 33.3 6.7 45.3 18.7L365.3 96c12 12 18.7 28.3 18.7 45.3V448c0 35.3-28.7 64-64 64H64c-35.3 0-64-28.7-64-64V64C0 28.7 28.7 0 64 0zM96 192c-17.7 0-32 14.3-32 32v32h64V192H96zM64 352h80 96 80V288H240 144 64v64zM320 224c0-17.7-14.3-32-32-32H256v64h64V224zM160 192v64h64V192H160zM288 448c17.7 0 32-14.3 32-32V384H256v64h32zM160 384v64h64V384H160zM64 416c0 17.7 14.3 32 32 32h32V384H64v32z"
|
||
/>
|
||
</svg>
|
||
<h1 class="card-text mt-4" x-text="simStatus"></h1>
|
||
</div>
|
||
<div class="card-footer"
|
||
style="text-align:center;">
|
||
SIM卡状态
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="col align-self-center">
|
||
<div class="card">
|
||
<div
|
||
class="card-body d-flex flex-column align-items-center justify-content-center"
|
||
>
|
||
<svg
|
||
xmlns="http://www.w3.org/2000/svg"
|
||
viewBox="0 0 640 512"
|
||
height="85"
|
||
width="85"
|
||
>
|
||
<path
|
||
fill="#2fa7fb"
|
||
d="M576 0c17.7 0 32 14.3 32 32V480c0 17.7-14.3 32-32 32s-32-14.3-32-32V32c0-17.7 14.3-32 32-32zM448 96c17.7 0 32 14.3 32 32V480c0 17.7-14.3 32-32 32s-32-14.3-32-32V128c0-17.7 14.3-32 32-32zM352 224V480c0 17.7-14.3 32-32 32s-32-14.3-32-32V224c0-17.7 14.3-32 32-32s32 14.3 32 32zM192 288c17.7 0 32 14.3 32 32V480c0 17.7-14.3 32-32 32s-32-14.3-32-32V320c0-17.7 14.3-32 32-32zM96 416v64c0 17.7-14.3 32-32 32s-32-14.3-32-32V416c0-17.7 14.3-32 32-32s32 14.3 32 32z"
|
||
/>
|
||
</svg>
|
||
<h1 class="card-text mt-4" x-text="signalPercentage + '%'"></h1>
|
||
</div>
|
||
<div class="card-footer"
|
||
style="text-align:center;">
|
||
信号强度
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="col align-self-center">
|
||
<div class="card">
|
||
<div
|
||
class="card-body d-flex flex-column align-items-center justify-content-center"
|
||
>
|
||
<svg
|
||
xmlns="http://www.w3.org/2000/svg"
|
||
viewBox="0 0 640 512"
|
||
height="85"
|
||
width="85"
|
||
>
|
||
<path
|
||
fill="#20c0ae"
|
||
d="M0 336c0 79.5 64.5 144 144 144H512c70.7 0 128-57.3 128-128c0-61.9-44-113.6-102.4-125.4c4.1-10.7 6.4-22.4 6.4-34.6c0-53-43-96-96-96c-19.7 0-38.1 6-53.3 16.2C367 64.2 315.3 32 256 32C167.6 32 96 103.6 96 192c0 2.7 .1 5.4 .2 8.1C40.2 219.8 0 273.2 0 336z"
|
||
/>
|
||
</svg>
|
||
<h1
|
||
class="card-text mt-4"
|
||
x-text="internetConnectionStatus"
|
||
></h1>
|
||
</div>
|
||
<div class="card-footer"
|
||
style="text-align:center;">
|
||
网络状态
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="row mt-5 gap-3">
|
||
<div class="col">
|
||
<div class="card">
|
||
<div class="card-header">网络信息</div>
|
||
<div class="card-body">
|
||
<div class="card-text table-responsive-sm">
|
||
<table class="table">
|
||
<style>.table th,.table td { white-space: nowrap; /* 防止换行 */}</style>
|
||
<tbody>
|
||
<tr>
|
||
<th scope="row">SIM卡</th>
|
||
<td x-text="activeSim"></td>
|
||
</tr>
|
||
<tr>
|
||
<th scope="row">运营商</th>
|
||
<td x-text="networkProvider"></td>
|
||
</tr>
|
||
<tr>
|
||
<th scope="row">运营商代码</th>
|
||
<td x-text="mccmnc"></td>
|
||
</tr>
|
||
<tr>
|
||
<th scope="row">接入点APN</th>
|
||
<td x-text="apn"></td>
|
||
</tr>
|
||
<tr>
|
||
<th scope="row">网络模式</th>
|
||
<td x-text="networkMode"></td>
|
||
</tr>
|
||
<tr>
|
||
<th scope="row">Bands</th>
|
||
<td x-text="bands"></td>
|
||
</tr>
|
||
<tr>
|
||
<th scope="row">带宽</th>
|
||
<td x-text="bandwidth"></td>
|
||
</tr>
|
||
<tr>
|
||
<th scope="row">频点</th>
|
||
<td x-text="earfcns"></td>
|
||
</tr>
|
||
<tr>
|
||
<th scope="row">PCI</th>
|
||
<td
|
||
x-show="sccPCI != '-'"
|
||
x-text="pccPCI + ', ' + sccPCI"
|
||
></td>
|
||
<td x-show="sccPCI == '-'" x-text="pccPCI"></td>
|
||
</tr>
|
||
<tr>
|
||
<th scope="row">IPv<sup>4</sup></th>
|
||
<td x-text="ipv4"></td>
|
||
</tr>
|
||
<tr>
|
||
<th scope="row">IPv<sup>6</sup></th>
|
||
<td x-text="ipv6"></td>
|
||
</tr>
|
||
<tr>
|
||
<th scope="row">在线时长</th>
|
||
<td x-text="uptime"></td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
</div>
|
||
<div class="card-footer">
|
||
<div class="row row-cols-2">
|
||
<div class="col">
|
||
<p class="btn">刷新率(>3s)</p>
|
||
</div>
|
||
<div class="col">
|
||
<div class="input-group">
|
||
<input
|
||
x-model="newRefreshRate"
|
||
class="form-control"
|
||
type="number"
|
||
min="3"
|
||
max="60"
|
||
x-bind:placeholder="refreshRate + 's'"
|
||
/>
|
||
<button
|
||
@click="updateRefreshRate()"
|
||
class="btn btn-outline-secondary"
|
||
type="button"
|
||
>
|
||
设置
|
||
</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="col">
|
||
<div class="card">
|
||
<div class="card-header">信号</div>
|
||
<div class="card-body">
|
||
<div class="card-text table-responsive-sm">
|
||
<table class="table">
|
||
<tbody>
|
||
<tr>
|
||
<th scope="row">评估</th>
|
||
<td x-text="signalAssessment"></td>
|
||
</tr>
|
||
<tr>
|
||
<th scope="row">流量统计</th>
|
||
<td
|
||
x-text="downloadStat + ' 上传 / ' + uploadStat + ' 下载'"
|
||
></td>
|
||
</tr>
|
||
<tr x-show="csq != 'NR-SA Mode'">
|
||
<th scope="row">CSQ</th>
|
||
<td x-show="csq != '-'" x-text="csq"></td>
|
||
<td x-show="csq == '-'" class="fst-italic">无</td>
|
||
</tr>
|
||
<tr>
|
||
<th scope="row">小区ID</th>
|
||
<td x-text="cellID"></td>
|
||
</tr>
|
||
<tr>
|
||
<th scope="row">eNB ID</th>
|
||
<td x-text="eNBID"></td>
|
||
</tr>
|
||
<tr>
|
||
<th scope="row">LAC ID</th>
|
||
<td x-text="tac"></td>
|
||
</tr>
|
||
<tr x-show="rsrqLTE != '-'">
|
||
<th scope="row">SS_RSRQ<sup>4G</sup></th>
|
||
<td
|
||
class="gap-4 align-items-center"
|
||
x-data="{ getProgressBarClass: function() {
|
||
// Remove the percentage sign and convert to integer
|
||
var percentage = parseInt(this.rsrqLTEPercentage);
|
||
|
||
if (percentage >= 60) {
|
||
return 'progress-bar bg-success is-medium';
|
||
} else if (percentage >= 40) {
|
||
return 'progress-bar bg-warning is-warning is-medium';
|
||
} else {
|
||
return 'progress-bar bg-danger is-medium';
|
||
}
|
||
} }"
|
||
>
|
||
<div
|
||
x-show="rsrqLTE != '-' && rsrqLTEPercentage != '0'"
|
||
class="progress w-100"
|
||
role="progressbar"
|
||
aria-label="RSRQ BAR"
|
||
:aria-valuenow="rsrqLTEPercentage"
|
||
aria-valuemin="0"
|
||
aria-valuemax="100"
|
||
style="height: 18px"
|
||
>
|
||
<div
|
||
:class="getProgressBarClass()"
|
||
:style="'width: ' + rsrqLTEPercentage + '%'"
|
||
>
|
||
<span
|
||
x-text="rsrqLTE + ' / ' + rsrqLTEPercentage + '%'"
|
||
></span>
|
||
</div>
|
||
</div>
|
||
<span
|
||
x-show="rsrqLTEPercentage == '0'"
|
||
x-text="rsrqLTE"
|
||
></span>
|
||
<span x-show="rsrqLTE == '-'" class="fst-italic">无</span>
|
||
</td>
|
||
</tr>
|
||
<tr x-show="rsrqNR != '-'">
|
||
<th scope="row">SS_RSRQ<sup>5G</sup></th>
|
||
<td
|
||
x-data="{ getProgressBarClass: function() {
|
||
// Remove the percentage sign and convert to integer
|
||
var percentage = parseInt(this.rsrqNRPercentage);
|
||
|
||
if (percentage >= 60) {
|
||
return 'progress-bar bg-success is-medium';
|
||
} else if (percentage >= 40) {
|
||
return 'progress-bar bg-warning is-warning is-medium';
|
||
} else {
|
||
return 'progress-bar bg-danger is-medium';
|
||
}
|
||
} }"
|
||
>
|
||
<div
|
||
x-show="rsrqNR != '-' && rsrqNRPercentage != '0'"
|
||
class="progress w-100"
|
||
role="progressbar"
|
||
aria-label="RSRQ BAR"
|
||
:aria-valuenow="rsrqNRPercentage"
|
||
aria-valuemin="0"
|
||
aria-valuemax="100"
|
||
style="height: 18px"
|
||
>
|
||
<div
|
||
:class="getProgressBarClass()"
|
||
:style="'width: ' + rsrqNRPercentage + '%'"
|
||
>
|
||
<span
|
||
x-text="rsrqNR + ' / ' + rsrqNRPercentage + '%'"
|
||
></span>
|
||
</div>
|
||
</div>
|
||
<span
|
||
x-show="rsrqNRPercentage == '0'"
|
||
x-text="rsrqNR"
|
||
></span>
|
||
<span x-show="rsrqNR == '-'" class="fst-italic">无</span>
|
||
</td>
|
||
</tr>
|
||
<tr x-show="rsrpLTE != '-'">
|
||
<th scope="row">RSRP<sup>4G</sup></th>
|
||
<td
|
||
class="gap-4 align-items-center"
|
||
x-data="{
|
||
getProgressBarClass: function() {
|
||
// Remove the percentage sign and convert to integer
|
||
var percentage = parseInt(this.rsrpLTEPercentage);
|
||
|
||
if (percentage >= 60) {
|
||
return 'progress-bar bg-success is-medium';
|
||
} else if (percentage >= 40) {
|
||
return 'progress-bar bg-warning is-warning is-medium';
|
||
} else {
|
||
return 'progress-bar bg-danger is-medium';
|
||
}
|
||
}
|
||
}"
|
||
>
|
||
<div
|
||
x-show="rsrpLTE != '-' && rsrpLTEPercentage != '0'"
|
||
class="progress w-100"
|
||
role="progressbar"
|
||
aria-label="RSRP BAR"
|
||
:aria-valuenow="rsrpLTEPercentage"
|
||
aria-valuemin="0"
|
||
aria-valuemax="100"
|
||
style="height: 18px"
|
||
>
|
||
<div
|
||
:class="getProgressBarClass()"
|
||
:style="'width: ' + rsrpLTEPercentage + '%'"
|
||
>
|
||
<span
|
||
x-text="rsrpLTE + ' / ' + rsrpLTEPercentage + '%'"
|
||
></span>
|
||
</div>
|
||
</div>
|
||
<span
|
||
x-show="rsrpLTEPercentage == '0'"
|
||
x-text="rsrpLTE"
|
||
></span>
|
||
<span x-show="rsrpLTE == '-'" class="fst-italic">无</span>
|
||
</td>
|
||
</tr>
|
||
<tr x-show="rsrpNR != '-'">
|
||
<th scope="row">SS_RSRP<sup>5G</sup></th>
|
||
<td
|
||
class="gap-4 align-items-center"
|
||
x-data="{
|
||
getProgressBarClass: function() {
|
||
// Remove the percentage sign and convert to integer
|
||
var percentage = parseInt(this.rsrpNRPercentage);
|
||
|
||
if (percentage >= 60) {
|
||
return 'progress-bar bg-success is-medium';
|
||
} else if (percentage >= 40) {
|
||
return 'progress-bar bg-warning is-warning is-medium';
|
||
} else {
|
||
return 'progress-bar bg-danger is-medium';
|
||
}
|
||
}
|
||
}"
|
||
>
|
||
<div
|
||
x-show="rsrpNR != '-' && rsrpNRPercentage != '0'"
|
||
class="progress w-100"
|
||
role="progressbar"
|
||
aria-label="RSRP BAR"
|
||
:aria-valuenow="rsrpNRPercentage"
|
||
aria-valuemin="0"
|
||
aria-valuemax="100"
|
||
style="height: 18px"
|
||
>
|
||
<div
|
||
:class="getProgressBarClass()"
|
||
:style="'width: ' + rsrpNRPercentage + '%'"
|
||
>
|
||
<span
|
||
x-text="rsrpNR + ' / ' + rsrpNRPercentage + '%'"
|
||
></span>
|
||
</div>
|
||
</div>
|
||
<span
|
||
x-show="rsrpNRPercentage == '0'"
|
||
x-text="rsrpNR"
|
||
></span>
|
||
<span x-show="rsrpNR == '-'" class="fst-italic">无</span>
|
||
</td>
|
||
</tr>
|
||
<tr x-show="sinrLTE != '-'">
|
||
<th scope="row">SINR<sup>4G</sup></th>
|
||
<td
|
||
class="gap-4 align-items-center"
|
||
x-data="{
|
||
getProgressBarClass: function() {
|
||
// Remove the percentage sign and convert to integer
|
||
var percentage = parseInt(this.sinrLTEPercentage);
|
||
|
||
if (percentage >= 60) {
|
||
return 'progress-bar bg-success is-medium';
|
||
} else if (percentage >= 40) {
|
||
return 'progress-bar bg-warning is-warning is-medium';
|
||
} else {
|
||
return 'progress-bar bg-danger is-medium';
|
||
}
|
||
}
|
||
}"
|
||
>
|
||
<div
|
||
x-show="sinrLTE != '-' && sinrLTEPercentage != '0'"
|
||
class="progress w-100"
|
||
role="progressbar"
|
||
aria-label="SINR BAR"
|
||
:aria-valuenow="sinrLTEPercentage"
|
||
aria-valuemin="0"
|
||
aria-valuemax="100"
|
||
style="height: 18px"
|
||
>
|
||
<div
|
||
:class="getProgressBarClass()"
|
||
:style="'width: ' + sinrLTEPercentage +'%'"
|
||
>
|
||
<span
|
||
x-text="sinrLTE + ' / ' + sinrLTEPercentage +'%'"
|
||
></span>
|
||
</div>
|
||
</div>
|
||
<span
|
||
x-text="sinrLTE"
|
||
x-show="sinrLTEPercentage == '0'"
|
||
></span>
|
||
<span x-show="sinrLTE == '-'" class="fst-italic">无</span>
|
||
</td>
|
||
</tr>
|
||
<tr x-show="sinrNR != '-'">
|
||
<th scope="row">SINR<sup>5G</sup></th>
|
||
<td
|
||
class="gap-4 align-items-center"
|
||
x-data="{
|
||
getProgressBarClass: function() {
|
||
// Remove the percentage sign and convert to integer
|
||
var percentage = parseInt(this.sinrNRPercentage);
|
||
|
||
if (percentage >= 60) {
|
||
return 'progress-bar bg-success is-medium';
|
||
} else if (percentage >= 40) {
|
||
return 'progress-bar bg-warning is-warning is-medium';
|
||
} else {
|
||
return 'progress-bar bg-danger is-medium';
|
||
}
|
||
}
|
||
}"
|
||
>
|
||
<div
|
||
x-show="sinrNR != '-' && sinrNRPercentage != '0'"
|
||
class="progress w-100"
|
||
role="progressbar"
|
||
aria-label="SINR BAR"
|
||
:aria-valuenow="sinrNRPercentage"
|
||
aria-valuemin="0"
|
||
aria-valuemax="100"
|
||
style="height: 18px"
|
||
>
|
||
<div
|
||
:class="getProgressBarClass()"
|
||
:style="'width: ' + sinrNRPercentage +'%'"
|
||
>
|
||
<span
|
||
x-text="sinrNR + ' / ' + sinrNRPercentage +'%'"
|
||
></span>
|
||
</div>
|
||
</div>
|
||
<span
|
||
x-text="sinrNR"
|
||
x-show="sinrNRPercentage == '0'"
|
||
></span>
|
||
<span x-show="sinrNR == '-'" class="fst-italic">无</span>
|
||
</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
</div>
|
||
<div class="card-footer">
|
||
<div class="card-text">
|
||
<div class="row">
|
||
<div class="col">
|
||
<div>
|
||
<p>更新时间</p>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="col">
|
||
<p x-text="lastUpdate"></p>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</main>
|
||
<script src="js/dark-mode.js"></script>
|
||
|
||
<script>
|
||
function processAllInfos() {
|
||
return {
|
||
atcmd: "",
|
||
internetConnectionStatus: "已断开",
|
||
temperature: "0",
|
||
simStatus: "无SIM卡",
|
||
activeSim: "无SIM卡",
|
||
networkProvider: "未知",
|
||
mccmnc: "00000",
|
||
apn: "未知",
|
||
networkMode: "已断开",
|
||
bands: "未知频段",
|
||
bandwidth: "未知带宽",
|
||
earfcns: "000",
|
||
pccPCI: "0",
|
||
sccPCI: "-",
|
||
ipv4: "000.000.000.000",
|
||
ipv6: "0000:0000:0000:0000:0000:0000:0000:0000",
|
||
cellID: "未知",
|
||
eNBID: "未知",
|
||
tac: "未知",
|
||
csq: "-",
|
||
rsrpLTE: "-",
|
||
rsrpNR: "-",
|
||
rsrpLTEPercentage: "0%",
|
||
rsrpNRPercentage: "0%",
|
||
rsrqLTE: "-",
|
||
rsrqNR: "-",
|
||
rsrqLTEPercentage: "0%",
|
||
rsrqNRPercentage: "0%",
|
||
sinrLTE: "-",
|
||
sinrNR: "-",
|
||
sinrLTEPercentage: "0%",
|
||
sinrNRPercentage: "0%",
|
||
signalPercentage: "0",
|
||
signalAssessment: "未知",
|
||
uptime: "未知时间",
|
||
lastUpdate: new Date().toLocaleString(),
|
||
newRefreshRate: null,
|
||
refreshRate: 3,
|
||
nrDownload: "0",
|
||
nrUpload: "0",
|
||
nonNrDownload: "0",
|
||
nonNrUpload: "0",
|
||
downloadStat: "0",
|
||
uploadStat: "0",
|
||
|
||
fetchAllInfo() {
|
||
this.atcmd =
|
||
'AT+QTEMP;+QUIMSLOT?;+QSPN;+CGCONTRDP=1;+QMAP="WWANIP";+QENG="servingcell";+QCAINFO;+QSIMSTAT?;+CSQ;+QGDNRCNT?;+QGDCNT?';
|
||
|
||
// 定义运营商映射表 | Define operator mapping table
|
||
const operatorMap = {
|
||
// 中国大陆 (460) | Mainland China (460)
|
||
"46000": "中国移动 (CMCC)",
|
||
"46001": "中国联通 (CU)",
|
||
"46002": "中国移动 (CMCC)",
|
||
"46003": "中国电信 (CT)",
|
||
"46004": "中国移动 (CMCC)",
|
||
"46005": "中国电信 (CT)",
|
||
"46006": "中国联通 (CU)",
|
||
"46007": "中国移动 (CMCC)",
|
||
"46008": "中国移动 (CMCC)",
|
||
"46009": "中国联通 (CU)",
|
||
"46011": "中国电信 (CT)",
|
||
|
||
// 中国香港 (454) | Hong Kong, China (454)
|
||
"45400": "香港移动通讯 (CSL)",
|
||
"45401": "香港移动通讯 (CSL)",
|
||
"45402": "香港移动通讯 (CSL)",
|
||
"45403": "和记电讯 (3 HK)",
|
||
"45404": "和记电讯 (3 HK)",
|
||
"45405": "和记电讯 (3 HK)",
|
||
"45406": "数码通 (SmarTone)",
|
||
"45412": "中国移动香港 (CMHK)",
|
||
"45413": "中国移动香港 (CMHK)",
|
||
"45415": "数码通 (SmarTone)",
|
||
"45416": "香港电讯 (PCCW)",
|
||
"45417": "数码通 (SmarTone)",
|
||
"45419": "香港电讯 (PCCW)",
|
||
"45420": "香港电讯 (PCCW)",
|
||
|
||
// 中国澳门 (455) | Macau, China (455)
|
||
"45501": "澳门电讯 (CTM)",
|
||
"45502": "中国电信澳门 (CT Macau)",
|
||
"45503": "和记澳门 (3 Macau)",
|
||
"45505": "和记澳门 (3 Macau)",
|
||
"45506": "数码通澳门 (SmarTone Macau)",
|
||
|
||
// 美国 (310-316) | United States (310-316)
|
||
"310030": "AT&T Mobility",
|
||
"310070": "AT&T Mobility",
|
||
"310150": "AT&T Mobility",
|
||
"310170": "AT&T Mobility",
|
||
"310280": "AT&T Mobility",
|
||
"310410": "AT&T Mobility",
|
||
"310980": "AT&T Mobility",
|
||
"311180": "AT&T Mobility",
|
||
"310120": "Sprint",
|
||
"310260": "T-Mobile USA",
|
||
"310160": "T-Mobile USA",
|
||
"311480": "Verizon Wireless",
|
||
"310004": "Verizon Wireless",
|
||
"310012": "Verizon Wireless",
|
||
|
||
// 加拿大 (302) | Canada (302)
|
||
"302220": "Telus Mobility",
|
||
"302221": "Telus Mobility",
|
||
"302222": "Telus Mobility",
|
||
"302270": "EastLink",
|
||
"302320": "Rogers Wireless",
|
||
"302370": "Rogers Wireless",
|
||
"302720": "Rogers Wireless",
|
||
"302490": "Freedom Mobile",
|
||
"302500": "Videotron",
|
||
"302610": "Bell Mobility",
|
||
"302640": "Bell Mobility",
|
||
"302690": "Bell Mobility",
|
||
|
||
// 西班牙 (214) | Spain (214)
|
||
"21401": "Vodafone España",
|
||
"21403": "Orange España",
|
||
"21404": "Yoigo",
|
||
"21405": "Movistar España",
|
||
"21406": "Vodafone España",
|
||
"21407": "Movistar España",
|
||
"21408": "Euskaltel",
|
||
"21409": "Orange España",
|
||
|
||
// 日本 (440-441) | Japan (440-441)
|
||
"44000": "Y!mobile",
|
||
"44001": "NTT DOCOMO",
|
||
"44002": "NTT DOCOMO",
|
||
"44003": "NTT DOCOMO",
|
||
"44004": "SoftBank",
|
||
"44006": "SoftBank",
|
||
"44007": "KDDI (au)",
|
||
"44008": "KDDI (au)",
|
||
"44009": "NTT DOCOMO",
|
||
"44010": "NTT DOCOMO",
|
||
"44020": "SoftBank",
|
||
"44021": "NTT DOCOMO",
|
||
"44051": "KDDI (au)",
|
||
"44052": "KDDI (au)",
|
||
"44053": "KDDI (au)",
|
||
"44054": "KDDI (au)",
|
||
"44070": "KDDI (au)",
|
||
"44071": "KDDI (au)",
|
||
"44072": "KDDI (au)",
|
||
"44073": "KDDI (au)",
|
||
"44074": "KDDI (au)",
|
||
"44075": "KDDI (au)",
|
||
"44076": "KDDI (au)",
|
||
|
||
// 澳大利亚 (505) | Australia (505)
|
||
"50501": "Telstra",
|
||
"50502": "Optus",
|
||
"50503": "Vodafone Australia",
|
||
"50506": "Three Australia",
|
||
"50507": "Vodafone Australia",
|
||
"50508": "One.Tel",
|
||
"50512": "Three Australia",
|
||
"50571": "Telstra",
|
||
"50572": "Telstra",
|
||
"50590": "Optus"
|
||
};
|
||
|
||
fetch(
|
||
"/cgi-bin/get_atcommand?" +
|
||
new URLSearchParams({
|
||
atcmd: this.atcmd,
|
||
})
|
||
).then((response) => {
|
||
response.text().then((data) => {
|
||
// content here
|
||
if (data.includes("ERROR")) {
|
||
console.log("Error fetching data");
|
||
this.activeSim = "出现错误";
|
||
return;
|
||
} else {
|
||
const rawdata = data;
|
||
const lines = rawdata.split("\n");
|
||
|
||
console.log(lines);
|
||
|
||
// --- Temperature ---
|
||
// find this example value from lines "+QTEMP:"cpuss-0-usr","50"
|
||
try {
|
||
this.temperature = lines
|
||
.find((line) => line.includes('+QTEMP:"cpuss-0-usr"'))
|
||
.split(",")[1]
|
||
.replace(/"/g, "");
|
||
} catch (error) {
|
||
this.temperature = lines
|
||
.find((line) => line.includes('+QTEMP:"cpu0-a7-usr"'))
|
||
.split(",")[1]
|
||
.replace(/"/g, "");
|
||
}
|
||
|
||
// --- SIM Status ---
|
||
// find this example value from lines "+QSIMSTAT: 0,1"
|
||
// Only get the last digit of 0,1
|
||
const sim_status = lines
|
||
.find((line) => line.includes("+QSIMSTAT:"))
|
||
.split(" ")[1]
|
||
.replace(/"/g, "")
|
||
.split(",")[1];
|
||
|
||
if (sim_status == 1) {
|
||
this.simStatus = "已激活";
|
||
} else if (sim_status == 0) {
|
||
this.simStatus = "无SIM卡";
|
||
}
|
||
|
||
// --- Active SIM ---
|
||
// find this example value from lines "+QUIMSLOT: 1"
|
||
const current_sim = lines
|
||
.find((line) => line.includes("+QUIMSLOT:"))
|
||
.split(" ")[1]
|
||
.replace(/"/g, "");
|
||
|
||
if (current_sim == 1) {
|
||
this.activeSim = "SIM 1";
|
||
} else if (current_sim == 2) {
|
||
this.activeSim = "SIM 2";
|
||
} else {
|
||
this.activeSim = "无SIM卡";
|
||
}
|
||
|
||
// --- Network Provider ---
|
||
// 获取 PLMN 码 | Get PLMN code
|
||
const plmn = lines
|
||
.find((line) => line.includes("+QSPN:"))
|
||
.split(",")[4]
|
||
.replace(/"/g, "");
|
||
|
||
// 获取原始运营商名称 | Get original operator name
|
||
const network_provider = lines
|
||
.find((line) => line.includes("+QSPN:"))
|
||
.split(",")[0]
|
||
.replace("+QSPN: ", "")
|
||
.replace(/"/g, "")
|
||
.replace(/ /g, "");
|
||
|
||
// 处理运营商名称显示 | Process operator name display
|
||
if (operatorMap[plmn]) {
|
||
// 如果在映射表中找到对应的运营商名称,直接使用
|
||
// If found in mapping table, use the mapped operator name
|
||
this.networkProvider = operatorMap[plmn];
|
||
} else if (network_provider.length === 24 && /^[0-9A-F]+$/i.test(network_provider)) {
|
||
// 如果是24位十六进制编码,进行解码
|
||
// If it's a 24-bit hexadecimal encoding, decode it
|
||
this.networkProvider = hexToAscii(network_provider);
|
||
} else if (network_provider.match(/^[0-9]+$/) != null) {
|
||
// 如果是纯数字,使用 plmn_name
|
||
// If it's pure numbers, use plmn_name
|
||
this.networkProvider = lines
|
||
.find((line) => line.includes("+QSPN:"))
|
||
.split(",")[2]
|
||
.replace(/"/g, "");
|
||
} else {
|
||
// 其他情况直接使用原始名称
|
||
// For other cases, use the original name
|
||
this.networkProvider = network_provider;
|
||
}
|
||
|
||
// 十六进制解码函数 | Hexadecimal decoding function
|
||
function hexToAscii(hex) {
|
||
let ascii = '';
|
||
for (let i = 0; i < hex.length; i += 2) {
|
||
ascii += String.fromCharCode(parseInt(hex.substr(i, 2), 16));
|
||
}
|
||
return ascii;
|
||
}
|
||
|
||
// --- MCCMNC ---
|
||
this.mccmnc = lines
|
||
.find((line) => line.includes("+QSPN:"))
|
||
.split(",")[4]
|
||
.replace(/"/g, "");
|
||
|
||
// --- APN ---
|
||
// find this example value from lines "+CGCONTRDP: 1,0,\"internet.dito.ph\",\"100.65.141.236\",\"36.5.141.64.76.204.39.68.23.210.251.16.49.239.42.149\", \"254.128.0.0.0.0.0.0.0.0.0.0.0.0.0.1\",\"131.226.72.19\",\"131.226.73.19\"\r"
|
||
this.apn = lines
|
||
.find((line) => line.includes("+CGCONTRDP:"))
|
||
.split(",")[2]
|
||
.replace(/"/g, "");
|
||
|
||
// --- Network Mode ---
|
||
// find this example value from lines "+QENG: \"servingcell\",\"NOCONN\",\"NR5G-SA\",\"TDD\",515,66,7000C4001,475,702000,620640,78,12,-83,-3,16,1,-\r"
|
||
|
||
try {
|
||
const network_mode = lines
|
||
.find((line) => line.includes('+QENG: "servingcell"'))
|
||
.split(",")[2]
|
||
.replace(/"/g, "");
|
||
|
||
const duplex_mode = lines
|
||
.find((line) => line.includes('+QENG: "servingcell"'))
|
||
.split(",")[3]
|
||
.replace(/"/g, "");
|
||
|
||
if (network_mode == "NR5G-SA") {
|
||
if (duplex_mode == "TDD") {
|
||
this.networkMode = "5G SA TDD";
|
||
} else if (duplex_mode == "FDD") {
|
||
this.networkMode = "5G SA FDD";
|
||
}
|
||
}
|
||
|
||
if (network_mode == "LTE") {
|
||
// get the FDD | TDD value
|
||
const is_tdd = lines
|
||
.find((line) => line.includes('+QENG: "servingcell"'))
|
||
.split(",")[3]
|
||
.replace(/"/g, "");
|
||
|
||
if (is_tdd == "TDD") {
|
||
this.networkMode = "4G LTE TDD";
|
||
} else if (is_tdd == "FDD") {
|
||
this.networkMode = "4G LTE FDD";
|
||
}
|
||
}
|
||
} catch (error) {
|
||
// find this example value from lines "+QENG: \"LTE\",\"FDD\",515,03,22AE76D,398,1350,3,4,4,BF82,-110,-13,-78,10,6,200,-\r"
|
||
|
||
const network_mode_lte = lines
|
||
.find((line) => line.includes('+QENG: "LTE"'))
|
||
.split(",")[0]
|
||
.replace("+QENG: ", "")
|
||
.replace(/"/g, "");
|
||
|
||
try {
|
||
// find this example value from lines "+QENG: \"NR5G-NSA\",515,03,843,-95,20,-11,528030,41,8,1\r"
|
||
const network_mode_5g = lines
|
||
.find((line) => line.includes('+QENG: "NR5G-NSA"'))
|
||
.split(",")[0]
|
||
.replace("+QENG: ", "")
|
||
.replace(/"/g, "");
|
||
|
||
this.networkMode = "5G NSA";
|
||
} catch (error) {
|
||
if (network_mode_lte == "FDD") {
|
||
this.networkMode = "4G LTE FDD";
|
||
} else if (network_mode_lte == "TDD") {
|
||
this.networkMode = "4G LTE TDD";
|
||
}
|
||
}
|
||
}
|
||
|
||
// --- Bands ---
|
||
// Get all the values with LTE BAND n (for example, LTE BAND 3, LTE BAND 1) and then store them in an array
|
||
const bands = lines.filter((line) =>
|
||
line.includes("LTE BAND")
|
||
);
|
||
|
||
// since it includes the whole line, we need to extract the band part only
|
||
for (let i = 0; i < bands.length; i++) {
|
||
bands[i] = bands[i].split(",")[3].replace(/"/g, "");
|
||
}
|
||
|
||
// Get all the values with NR BAND n (for example, NR BAND 3, NR BAND 1) and then store them in an array
|
||
const bands_5g = lines.filter((line) =>
|
||
line.includes("NR5G BAND")
|
||
);
|
||
|
||
// since it includes the whole line, we need to extract the band number only
|
||
for (let i = 0; i < bands_5g.length; i++) {
|
||
bands_5g[i] = bands_5g[i].split(",")[3].replace(/"/g, "");
|
||
}
|
||
|
||
// Combine the bands and bands_5g arrays seperated by a comma. however, bands or bands_5g can be empty
|
||
if (bands.length > 0 && bands_5g.length > 0) {
|
||
this.bands = bands.join(", ") + ", " + bands_5g.join(", ");
|
||
} else if (bands.length > 0) {
|
||
this.bands = bands.join(", ");
|
||
} else if (bands_5g.length > 0) {
|
||
this.bands = bands_5g.join(", ");
|
||
} else {
|
||
this.bands = "No Bands";
|
||
}
|
||
|
||
// --- Bandwidth ---
|
||
if (
|
||
this.networkMode == "5G SA TDD" ||
|
||
this.networkMode == "5G SA FDD"
|
||
) {
|
||
// find this example value from lines "+QENG: \"servingcell\"
|
||
const bandwidth_line = lines.find((line) =>
|
||
line.includes('+QENG: "servingcell"')
|
||
);
|
||
const nr_bw = bandwidth_line.split(",")[11];
|
||
const calculated_bandwidth = this.calculate_nr_bw(nr_bw);
|
||
this.bandwidth = "NR " + calculated_bandwidth + " MHz";
|
||
} else if (
|
||
this.networkMode == "4G LTE FDD" ||
|
||
this.networkMode == "4G LTE TDD"
|
||
) {
|
||
// find this example value from lines "+QENG: \"servingcell\"
|
||
const bandwidth_line = lines.find((line) =>
|
||
line.includes('+QENG: "servingcell"')
|
||
);
|
||
|
||
const lte_bw_ul = bandwidth_line.split(",")[10];
|
||
const lte_bw_dl = bandwidth_line.split(",")[11];
|
||
const calculated_bandwidth_ul =
|
||
this.calculate_lte_bw(lte_bw_ul);
|
||
const calculated_bandwidth_dl =
|
||
this.calculate_lte_bw(lte_bw_dl);
|
||
this.bandwidth =
|
||
calculated_bandwidth_ul +
|
||
" UL / " +
|
||
calculated_bandwidth_dl +
|
||
" DL MHz";
|
||
} else if (this.networkMode == "5G NSA") {
|
||
// find this example value from lines "+QENG: \"LTE\" for LTE
|
||
const lte_bandwidth_line = lines.find((line) =>
|
||
line.includes('+QENG: "LTE"')
|
||
);
|
||
|
||
const lte_bw_ul = lte_bandwidth_line.split(",")[8];
|
||
const lte_bw_dl = lte_bandwidth_line.split(",")[9];
|
||
|
||
const calculated_bandwidth_ul =
|
||
this.calculate_lte_bw(lte_bw_ul);
|
||
const calculated_bandwidth_dl =
|
||
this.calculate_lte_bw(lte_bw_dl);
|
||
|
||
// find this example value from lines "+QENG: \"NR5G-NSA\" for NR5G
|
||
const nr_bandwidth_line = lines.find((line) =>
|
||
line.includes('+QENG: "NR5G-NSA"')
|
||
);
|
||
|
||
const nr_bw = nr_bandwidth_line.split(",")[9];
|
||
const calculated_bandwidth = this.calculate_nr_bw(nr_bw);
|
||
|
||
// combine the bandwidths
|
||
this.bandwidth =
|
||
calculated_bandwidth_ul +
|
||
" UL / " +
|
||
calculated_bandwidth_dl +
|
||
" DL MHz" +
|
||
" / NR " +
|
||
calculated_bandwidth +
|
||
" MHz";
|
||
} else {
|
||
this.bandwidth = "Unknown Bandwidth";
|
||
}
|
||
|
||
// --- E/ARFCN ---
|
||
if (
|
||
this.networkMode == "5G SA TDD" ||
|
||
this.networkMode == "5G SA FDD"
|
||
) {
|
||
// find this value from lines "+QCAINFO: \"PCC\"
|
||
const nr_pcc_arfcn = lines
|
||
.find((line) => line.includes('+QCAINFO: "PCC"'))
|
||
.split(",")[1];
|
||
|
||
try {
|
||
// Look for all the lines with this value "+QCAINFO: \"SCC\" and store them in an array
|
||
const nr_scc_arfcn = lines.filter((line) =>
|
||
line.includes('+QCAINFO: "SCC"')
|
||
);
|
||
|
||
// if empty, then proceed to error block
|
||
if (nr_scc_arfcn.length == 0) {
|
||
throw "No SCC ARFCN";
|
||
}
|
||
|
||
// process all the values in the array and extract the ARFCN part only
|
||
for (let i = 0; i < nr_scc_arfcn.length; i++) {
|
||
nr_scc_arfcn[i] = nr_scc_arfcn[i].split(",")[1];
|
||
}
|
||
|
||
// combine the PCC and SCC ARFCN values
|
||
this.earfcns =
|
||
nr_pcc_arfcn + ", " + nr_scc_arfcn.join(", ");
|
||
} catch (error) {
|
||
this.earfcns = nr_pcc_arfcn.replace(/,/g, "");
|
||
}
|
||
} else if (
|
||
this.networkMode == "4G LTE FDD" ||
|
||
this.networkMode == "4G LTE TDD"
|
||
) {
|
||
// find this value from lines "+QCAINFO: \"PCC\"
|
||
const lte_pcc_arfcn = lines
|
||
.find((line) => line.includes('+QCAINFO: "PCC"'))
|
||
.split(",")[1];
|
||
|
||
try {
|
||
// Look for all the lines with this value "+QCAINFO: \"SCC\" and store them in an array
|
||
const lte_scc_arfcn = lines.filter((line) =>
|
||
line.includes('+QCAINFO: "SCC"')
|
||
);
|
||
|
||
// if empty, then proceed to error block
|
||
if (lte_scc_arfcn.length == 0) {
|
||
throw "No SCC ARFCN";
|
||
}
|
||
|
||
// process all the values in the array and extract the ARFCN part only
|
||
for (let i = 0; i < lte_scc_arfcn.length; i++) {
|
||
lte_scc_arfcn[i] = lte_scc_arfcn[i].split(",")[1];
|
||
}
|
||
|
||
// combine the PCC and SCC ARFCN values
|
||
this.earfcns =
|
||
lte_pcc_arfcn + ", " + lte_scc_arfcn.join(", ");
|
||
} catch (error) {
|
||
this.earfcns = lte_pcc_arfcn.replace(/,/g, "");
|
||
}
|
||
} else if (this.networkMode == "5G NSA") {
|
||
// find this value from lines "+QCAINFO: \"PCC\"
|
||
const lte_pcc_arfcn = lines
|
||
.find((line) => line.includes('+QCAINFO: "PCC"'))
|
||
.split(",")[5];
|
||
|
||
try {
|
||
// Look for all the lines with this value "+QCAINFO: \"SCC\" and store them in an array
|
||
const lte_scc_arfcn = lines.filter((line) =>
|
||
line.includes('+QCAINFO: "SCC"')
|
||
);
|
||
|
||
// If empty, then proceed to error block
|
||
if (lte_scc_arfcn.length == 0) {
|
||
throw "No SCC ARFCN";
|
||
}
|
||
|
||
// process all the values in the array and extract the ARFCN part only
|
||
for (let i = 0; i < lte_scc_arfcn.length; i++) {
|
||
lte_scc_arfcn[i] = lte_scc_arfcn[i].split(",")[1];
|
||
}
|
||
|
||
// combine the PCC and SCC ARFCN values
|
||
this.earfcns =
|
||
lte_pcc_arfcn + ", " + lte_scc_arfcn.join(", ");
|
||
} catch (error) {
|
||
this.earfcns = lte_pcc_arfcn.replace(/,/g, "");
|
||
}
|
||
} else {
|
||
this.earfcns = "Unknown E/ARFCN";
|
||
}
|
||
|
||
// --- PCI ---
|
||
if (
|
||
this.networkMode == "5G SA TDD" ||
|
||
this.networkMode == "5G SA FDD"
|
||
) {
|
||
const nr_pcc_pci = lines
|
||
.find((line) => line.includes('+QCAINFO: "PCC"'))
|
||
.split(",")[4];
|
||
|
||
try {
|
||
// Look for all the lines with this value "+QCAINFO: \"SCC\" and store them in an array
|
||
const nr_scc_pci = lines.filter((line) =>
|
||
line.includes('+QCAINFO: "SCC"')
|
||
);
|
||
|
||
// if empty, then proceed to error block
|
||
if (nr_scc_pci.length == 0) {
|
||
throw "No SCC PCI";
|
||
}
|
||
|
||
// process all the values in the array and extract the PCI part only
|
||
for (let i = 0; i < nr_scc_pci.length; i++) {
|
||
nr_scc_pci[i] = nr_scc_pci[i].split(",")[5];
|
||
}
|
||
|
||
// combine the PCC and SCC PCI values
|
||
this.pccPCI = nr_pcc_pci;
|
||
this.sccPCI = nr_scc_pci.join(", ");
|
||
} catch (error) {
|
||
// remove comma if only one value
|
||
this.pccPCI = nr_pcc_pci.replace(/,/g, "");
|
||
this.sccPCI = "-";
|
||
}
|
||
} else if (
|
||
this.networkMode == "4G LTE FDD" ||
|
||
this.networkMode == "4G LTE TDD"
|
||
) {
|
||
// find this value from lines "+QCAINFO: \"PCC\"
|
||
const lte_pcc_pci = lines
|
||
.find((line) => line.includes('+QCAINFO: "PCC"'))
|
||
.split(",")[5];
|
||
|
||
try {
|
||
// Look for all the lines with this value "+QCAINFO: \"SCC\" and store them in an array
|
||
const lte_scc_pci = lines.filter((line) =>
|
||
line.includes('+QCAINFO: "SCC"')
|
||
);
|
||
|
||
// if empty, then proceed to error block
|
||
if (lte_scc_pci.length == 0) {
|
||
throw "No SCC PCI";
|
||
}
|
||
|
||
// process all the values in the array and extract the PCI part only
|
||
for (let i = 0; i < lte_scc_pci.length; i++) {
|
||
lte_scc_pci[i] = lte_scc_pci[i].split(",")[5];
|
||
}
|
||
|
||
// combine the PCC and SCC PCI values
|
||
this.pccPCI = lte_pcc_pci;
|
||
this.sccPCI = lte_scc_pci.join(", ");
|
||
} catch (error) {
|
||
this.pccPCI = lte_pcc_pci;
|
||
this.sccPCI = "-";
|
||
}
|
||
} else if (this.networkMode == "5G NSA") {
|
||
// find this value from lines "+QCAINFO: \"PCC\"
|
||
const lte_pcc_pci = lines
|
||
.find((line) => line.includes('+QCAINFO: "PCC"'))
|
||
.split(",")[5];
|
||
|
||
try {
|
||
// Look for all the lines with this value "+QCAINFO: \"SCC\" and store them in an array
|
||
const lte_scc_pci = lines.filter((line) =>
|
||
line.includes('+QCAINFO: "SCC"')
|
||
);
|
||
|
||
// If empty, then proceed to error block
|
||
if (lte_scc_pci.length == 0) {
|
||
throw "No SCC PCI";
|
||
}
|
||
|
||
// process all the values in the array and extract the PCI part only
|
||
for (let i = 0; i < lte_scc_pci.length; i++) {
|
||
// if line contains LTE BAND then do this process
|
||
if (lte_scc_pci[i].includes("LTE BAND")) {
|
||
lte_scc_pci[i] = lte_scc_pci[i].split(",")[5];
|
||
} else {
|
||
lte_scc_pci[i] = lte_scc_pci[i].split(",")[4];
|
||
}
|
||
}
|
||
|
||
// combine the PCC and SCC PCI values
|
||
this.pccPCI = lte_pcc_pci;
|
||
this.sccPCI = lte_scc_pci.join(", ");
|
||
} catch (error) {
|
||
this.pccPCI = lte_pcc_pci.replace(/,/g, "");
|
||
this.sccPCI = "-";
|
||
}
|
||
} else {
|
||
this.pccPCI = "0";
|
||
this.sccPCI = "-";
|
||
}
|
||
|
||
// --- IPv4 and IPv6 ---
|
||
// find the value from line "IPV4"
|
||
this.ipv4 = lines
|
||
.find((line) => line.includes("IPV4"))
|
||
.split(",")[4]
|
||
.replace(/"/g, "");
|
||
|
||
// find the value from line "IPV6"
|
||
this.ipv6 = lines
|
||
.find((line) => line.includes("IPV6"))
|
||
.split(",")[4]
|
||
.replace(/"/g, "");
|
||
|
||
// Traffic Stats
|
||
// for NR traffic stats: +QGDNRCNT: 3263753367,109876105
|
||
this.nrDownload = lines
|
||
.find((line) => line.includes("+QGDNRCNT:"))
|
||
.split(",")[0]
|
||
// remove the +QGDNRCNT: part
|
||
.replace("+QGDNRCNT: ", "");
|
||
|
||
this.nrUpload = lines
|
||
.find((line) => line.includes("+QGDNRCNT:"))
|
||
.split(",")[1];
|
||
|
||
// for non-NR traffic stats: +QGDCNT: 247357510,6864571506
|
||
this.nonNrDownload = lines
|
||
.find((line) => line.includes("+QGDCNT:"))
|
||
.split(",")[1];
|
||
|
||
this.nonNrUpload = lines
|
||
.find((line) => line.includes("+QGDCNT:"))
|
||
.split(",")[0]
|
||
// remove the +QGDCNT: part
|
||
.replace("+QGDCNT: ", "");
|
||
|
||
// Add the nrDownload and nonNrDownload together
|
||
this.downloadStat =
|
||
parseInt(this.nrDownload) + parseInt(this.nonNrDownload);
|
||
|
||
// Add the nrUpload and nonNrUpload together
|
||
this.uploadStat =
|
||
parseInt(this.nrUpload) + parseInt(this.nonNrUpload);
|
||
|
||
// Convert the downloadStat and uploadStat bytes to readable size
|
||
this.downloadStat = this.bytesToSize(this.downloadStat);
|
||
this.uploadStat = this.bytesToSize(this.uploadStat);
|
||
|
||
console.log(this.downloadStat);
|
||
console.log(this.uploadStat);
|
||
|
||
// Signal Informations
|
||
|
||
const currentNetworkMode = this.networkMode;
|
||
|
||
if (
|
||
currentNetworkMode == "5G SA TDD" ||
|
||
currentNetworkMode == "5G SA FDD" ||
|
||
currentNetworkMode == "4G LTE FDD" ||
|
||
currentNetworkMode == "4G LTE TDD"
|
||
) {
|
||
// find the value from line "+QENG: \"servingcell\""
|
||
// CellID
|
||
const longCID = lines
|
||
.find((line) => line.includes('+QENG: "servingcell"'))
|
||
.split(",")[6]
|
||
.replace(/"/g, "");
|
||
|
||
// Get the eNBID. Its just Cell ID minus the last 2 characters
|
||
this.eNBID = longCID.substring(0, longCID.length - 2);
|
||
|
||
// Get the short Cell ID (Last 2 characters of the Cell ID)
|
||
const shortCID = longCID.substring(longCID.length - 2);
|
||
|
||
if (
|
||
currentNetworkMode == "5G SA TDD" ||
|
||
currentNetworkMode == "5G SA FDD"
|
||
) {
|
||
// TAC
|
||
this.tac = lines
|
||
.find((line) => line.includes('+QENG: "servingcell"'))
|
||
.split(",")[8]
|
||
.replace(/"/g, "");
|
||
|
||
// CSQ
|
||
this.csq = "NR-SA Mode";
|
||
|
||
// RSRP
|
||
this.rsrpNR = lines
|
||
.find((line) => line.includes('+QENG: "servingcell"'))
|
||
.split(",")[12]
|
||
.replace(/"/g, "");
|
||
|
||
// RSRQ
|
||
this.rsrqNR = lines
|
||
.find((line) => line.includes('+QENG: "servingcell"'))
|
||
.split(",")[13]
|
||
.replace(/"/g, "");
|
||
|
||
// SINR
|
||
this.sinrNR = lines
|
||
.find((line) => line.includes('+QENG: "servingcell"'))
|
||
.split(",")[14]
|
||
.replace(/"/g, "");
|
||
|
||
// Calculate the RSRP Percentage
|
||
this.rsrpNRPercentage = this.calculateRSRPPercentage(
|
||
parseInt(this.rsrpNR)
|
||
);
|
||
|
||
// Calculate the RSRQ Percentage
|
||
this.rsrqNRPercentage = this.calculateRSRQPercentage(
|
||
parseInt(this.rsrqNR)
|
||
);
|
||
|
||
// Calculate the SINR Percentage
|
||
this.sinrNRPercentage = this.calculateSINRPercentage(
|
||
parseInt(this.sinrNR)
|
||
);
|
||
|
||
// Calculate the Signal Percentage
|
||
this.signalPercentage = this.calculateSignalPercentage(
|
||
this.rsrpNRPercentage,
|
||
this.sinrNRPercentage
|
||
);
|
||
|
||
// Calculate the Signal Assessment
|
||
this.signalAssessment = this.signalQuality(
|
||
this.signalPercentage
|
||
);
|
||
} else {
|
||
// LTE Only
|
||
// TAC
|
||
this.tac = lines
|
||
.find((line) => line.includes('+QENG: "servingcell"'))
|
||
.split(",")[12]
|
||
.replace(/"/g, "");
|
||
|
||
// CSQ
|
||
this.csq = lines
|
||
.find((line) => line.includes("+CSQ:"))
|
||
.split(" ")[1]
|
||
.replace("+CSQ: ", "")
|
||
.replace(/"/g, "");
|
||
|
||
// RSRP
|
||
this.rsrpLTE = lines
|
||
.find((line) => line.includes('+QENG: "servingcell"'))
|
||
.split(",")[13]
|
||
.replace(/"/g, "");
|
||
|
||
// RSRQ
|
||
this.rsrqLTE = lines
|
||
.find((line) => line.includes('+QENG: "servingcell"'))
|
||
.split(",")[14]
|
||
.replace(/"/g, "");
|
||
|
||
// // RSSI
|
||
// this.rssi = lines
|
||
// .find((line) => line.includes('+QENG: "servingcell"'))
|
||
// .split(",")[15]
|
||
// .replace(/"/g, "");
|
||
|
||
// SINR
|
||
this.sinrLTE = lines
|
||
.find((line) => line.includes('+QENG: "servingcell"'))
|
||
.split(",")[16]
|
||
.replace(/"/g, "");
|
||
|
||
// Calculate the RSRP Percentage
|
||
this.rsrpLTEPercentage = this.calculateRSRPPercentage(
|
||
parseInt(this.rsrpLTE)
|
||
);
|
||
|
||
// Calculate the RSRQ Percentage
|
||
this.rsrqLTEPercentage = this.calculateRSRQPercentage(
|
||
parseInt(this.rsrqLTE)
|
||
);
|
||
|
||
// Calculate the SINR Percentage
|
||
this.sinrLTEPercentage = this.calculateSINRPercentage(
|
||
parseInt(this.sinrLTE)
|
||
);
|
||
|
||
// Calculate the Signal Percentage
|
||
this.signalPercentage = this.calculateSignalPercentage(
|
||
this.rsrpLTEPercentage,
|
||
this.sinrLTEPercentage
|
||
);
|
||
|
||
// Calculate the Signal Assessment
|
||
this.signalAssessment = this.signalQuality(
|
||
this.signalPercentage
|
||
);
|
||
}
|
||
|
||
this.cellID =
|
||
"Short " +
|
||
shortCID +
|
||
"(" +
|
||
parseInt(shortCID, 16) +
|
||
")" +
|
||
", " +
|
||
"Long " +
|
||
longCID +
|
||
"(" +
|
||
parseInt(longCID, 16) +
|
||
")";
|
||
} else if (currentNetworkMode == "5G NSA") {
|
||
// find the value from line "+QENG: \"LTE\" for LTE
|
||
// LongCID
|
||
const longCID = lines
|
||
.find((line) => line.includes('+QENG: "LTE"'))
|
||
.split(",")[4]
|
||
.replace(/"/g, "");
|
||
|
||
// Get the eNBID. Its just Cell ID minus the last 2 characters
|
||
this.eNBID = longCID.substring(0, longCID.length - 2);
|
||
|
||
// Get the short Cell ID (Last 2 characters of the Cell ID)
|
||
const shortCID = longCID.substring(longCID.length - 2);
|
||
|
||
// cellID
|
||
this.cellID =
|
||
"Short " +
|
||
shortCID +
|
||
"(" +
|
||
parseInt(shortCID, 16) +
|
||
")" +
|
||
", " +
|
||
"Long " +
|
||
longCID +
|
||
"(" +
|
||
parseInt(longCID, 16) +
|
||
")";
|
||
|
||
// TAC
|
||
this.tac = lines
|
||
.find((line) => line.includes('+QENG: "LTE"'))
|
||
.split(",")[10]
|
||
.replace(/"/g, "");
|
||
|
||
// CSQ
|
||
this.csq = lines
|
||
.find((line) => line.includes("+CSQ:"))
|
||
.split(" ")[1]
|
||
.replace("+CSQ: ", "")
|
||
.replace(/"/g, "");
|
||
|
||
// RSRP LTE
|
||
this.rsrpLTE = lines
|
||
.find((line) => line.includes('+QENG: "LTE"'))
|
||
.split(",")[11]
|
||
.replace(/"/g, "");
|
||
|
||
// RSRQ LTE
|
||
this.rsrqLTE = lines
|
||
.find((line) => line.includes('+QENG: "LTE"'))
|
||
.split(",")[12]
|
||
.replace(/"/g, "");
|
||
|
||
// // RSSI LTE
|
||
// this.rssi = lines
|
||
// .find((line) => line.includes('+QENG: "LTE"'))
|
||
// .split(",")[13]
|
||
// .replace(/"/g, "");
|
||
|
||
// SINR LTE
|
||
this.sinrLTE = lines
|
||
.find((line) => line.includes('+QENG: "LTE"'))
|
||
.split(",")[14]
|
||
.replace(/"/g, "");
|
||
|
||
// Calculate the RSRP LTE Percentage
|
||
this.rsrpLTEPercentage = this.calculateRSRPPercentage(
|
||
parseInt(this.rsrpLTE)
|
||
);
|
||
|
||
// Calculate the RSRQ LTE Percentage
|
||
this.rsrqLTEPercentage = this.calculateRSRQPercentage(
|
||
parseInt(this.rsrqLTE)
|
||
);
|
||
|
||
// Calculate the SINR LTE Percentage
|
||
this.sinrLTEPercentage = this.calculateSINRPercentage(
|
||
parseInt(this.sinrLTE)
|
||
);
|
||
|
||
// Calculate the Signal Percentage
|
||
const lte_signal_percentage =
|
||
this.calculateSignalPercentage(
|
||
this.rsrpLTEPercentage,
|
||
this.sinrLTEPercentage
|
||
);
|
||
|
||
// find the value from line "+QENG: \"NR5G-NSA\" for NR5G
|
||
// RSRP NR
|
||
this.rsrpNR = lines
|
||
.find((line) => line.includes('+QENG: "NR5G-NSA"'))
|
||
.split(",")[4]
|
||
.replace(/"/g, "");
|
||
|
||
// SINR NR
|
||
this.sinrNR = lines
|
||
.find((line) => line.includes('+QENG: "NR5G-NSA"'))
|
||
.split(",")[5]
|
||
.replace(/"/g, "");
|
||
|
||
// RSRQ NR
|
||
this.rsrqNR = lines
|
||
.find((line) => line.includes('+QENG: "NR5G-NSA"'))
|
||
.split(",")[6]
|
||
.replace(/"/g, "");
|
||
|
||
// Calculate the RSRP NR Percentage
|
||
this.rsrpNRPercentage = this.calculateRSRPPercentage(
|
||
parseInt(this.rsrpNR)
|
||
);
|
||
|
||
// Calculate the RSRQ NR Percentage
|
||
this.rsrqNRPercentage = this.calculateRSRQPercentage(
|
||
parseInt(this.rsrqNR)
|
||
);
|
||
|
||
// Calculate the SINR NR Percentage
|
||
this.sinrNRPercentage = this.calculateSINRPercentage(
|
||
parseInt(this.sinrNR)
|
||
);
|
||
|
||
// Calculate the Signal Percentage
|
||
const nr_signal_percentage = this.calculateSignalPercentage(
|
||
this.rsrpNRPercentage,
|
||
this.sinrNRPercentage
|
||
);
|
||
|
||
// Average the LTE and NR Signal Percentages
|
||
this.signalPercentage =
|
||
(lte_signal_percentage + nr_signal_percentage) / 2;
|
||
|
||
// Calculate the Signal Assessment
|
||
this.signalAssessment = this.signalQuality(
|
||
this.signalPercentage
|
||
);
|
||
} else {
|
||
this.signalAssessment = "No Signal";
|
||
}
|
||
}
|
||
});
|
||
});
|
||
},
|
||
|
||
bytesToSize(bytes) {
|
||
const sizes = ["Bytes", "KB", "MB", "GB", "TB"];
|
||
if (bytes == 0) return "0 Byte";
|
||
const i = parseInt(Math.floor(Math.log(bytes) / Math.log(1024)));
|
||
return Math.round(bytes / Math.pow(1024, i), 2) + " " + sizes[i];
|
||
},
|
||
|
||
requestPing() {
|
||
return fetch("/cgi-bin/get_ping")
|
||
.then((response) => response.text())
|
||
.then((data) => {
|
||
return data;
|
||
})
|
||
.catch((error) => {
|
||
console.error("Error:", error);
|
||
// Throw the error again to ensure it's propagated
|
||
throw error;
|
||
});
|
||
},
|
||
|
||
calculate_lte_bw(lte_bw) {
|
||
switch (true) {
|
||
case 0:
|
||
return 1.4;
|
||
case 1:
|
||
return 3;
|
||
// Now case 2 - 5
|
||
case lte_bw >= 2 && lte_bw <= 5:
|
||
return (lte_bw - 1) * 5;
|
||
default:
|
||
return "Unknown";
|
||
}
|
||
},
|
||
|
||
calculate_nr_bw(nr_bw) {
|
||
switch (true) {
|
||
case nr_bw >= 0 && nr_bw <= 5:
|
||
return (nr_bw + 1) * 5;
|
||
case nr_bw >= 6 && nr_bw <= 12:
|
||
return (nr_bw - 2) * 10;
|
||
case nr_bw === 13:
|
||
return "200";
|
||
case nr_bw === 14:
|
||
return "400";
|
||
default:
|
||
return "Unknown";
|
||
}
|
||
},
|
||
|
||
calculateRSRPPercentage(rsrp) {
|
||
let RSRP_min = -135;
|
||
let RSRP_max = -65;
|
||
|
||
// If rsrp is null, return 0%
|
||
if (isNaN(rsrp) || rsrp < -140) {
|
||
return 0;
|
||
}
|
||
|
||
let percentage = ((rsrp - RSRP_min) / (RSRP_max - RSRP_min)) * 100;
|
||
|
||
if (percentage > 100) {
|
||
percentage = 100;
|
||
}
|
||
|
||
// if percentage is less than 15%, make it 15%
|
||
if (percentage < 15) {
|
||
percentage = 15;
|
||
}
|
||
|
||
return Math.round(percentage);
|
||
},
|
||
|
||
calculateRSRQPercentage(rsrq) {
|
||
let RSRQ_min = -20;
|
||
let RSRQ_max = -8;
|
||
|
||
// If rsrq is null, return 0%
|
||
if (isNaN(rsrq) || rsrq < -20) {
|
||
return 0;
|
||
}
|
||
|
||
let percentage = ((rsrq - RSRQ_min) / (RSRQ_max - RSRQ_min)) * 100;
|
||
|
||
if (percentage > 100) {
|
||
percentage = 100;
|
||
}
|
||
|
||
// if percentage is less than 15%, make it 15%
|
||
if (percentage < 15) {
|
||
percentage = 15;
|
||
}
|
||
|
||
return Math.round(percentage);
|
||
},
|
||
|
||
calculateSINRPercentage(sinr) {
|
||
let SINR_min = -10; // Changed from 0
|
||
let SINR_max = 35;
|
||
|
||
// If sinr is null, return 0%
|
||
if (isNaN(sinr) || sinr < -10) {
|
||
return 0;
|
||
}
|
||
|
||
let percentage = ((sinr - SINR_min) / (SINR_max - SINR_min)) * 100;
|
||
|
||
if (percentage > 100) {
|
||
percentage = 100;
|
||
}
|
||
|
||
// if percentage is less than 15%, make it 15%
|
||
if (percentage < 15) {
|
||
percentage = 15;
|
||
}
|
||
|
||
return Math.round(percentage);
|
||
},
|
||
|
||
// Calculate the overall signal assessment
|
||
calculateSignalPercentage(rsrpNRPercentage, sinrNRPercentage) {
|
||
// Get the average of the RSRP Percentage and SINR Percentage
|
||
let average = (rsrpNRPercentage + sinrNRPercentage) / 2;
|
||
return Math.round(average);
|
||
},
|
||
|
||
signalQuality(percentage) {
|
||
if (percentage >= 80) {
|
||
return "优秀";
|
||
} else if (percentage >= 60) {
|
||
return "良好";
|
||
} else if (percentage >= 40) {
|
||
return "一般";
|
||
} else if (percentage >= 0) {
|
||
return "差";
|
||
} else {
|
||
return "无信号";
|
||
}
|
||
},
|
||
|
||
fetchUpTime() {
|
||
// Content-Type: text/plain
|
||
//
|
||
// 1 hour 44, minute
|
||
fetch("/cgi-bin/get_uptime")
|
||
.then((response) => response.text())
|
||
.then((data) => {
|
||
// Example result
|
||
// 01:17:02 up 3 days, 2:41, load average: 0.65, 0.66, 0.60
|
||
|
||
// Look for xx days in the result
|
||
const days = data.match(/(\d+) day/);
|
||
// Do the same for hours
|
||
const hours = data.match(/(\d+) hour/);
|
||
// Do the same for minutes
|
||
const minutes = data.match(/(\d+) min/);
|
||
// 2:41
|
||
const hoursAndMinutes = data.match(/(\d+):(\d+),/);
|
||
|
||
if (hoursAndMinutes != null) {
|
||
if (days != null) {
|
||
if (days[1] === "1") {
|
||
if (hoursAndMinutes[1] === "1") {
|
||
this.uptime =
|
||
days[1] +
|
||
" day, " +
|
||
hoursAndMinutes[1] +
|
||
" hour " +
|
||
hoursAndMinutes[2] +
|
||
" minutes";
|
||
} else if (hoursAndMinutes[2] === 1) {
|
||
this.uptime =
|
||
days[1] +
|
||
" day, " +
|
||
hoursAndMinutes[1] +
|
||
" hours " +
|
||
hoursAndMinutes[2] +
|
||
" minute";
|
||
} else {
|
||
this.uptime =
|
||
days[1] +
|
||
" day, " +
|
||
hoursAndMinutes[1] +
|
||
" hours " +
|
||
hoursAndMinutes[2] +
|
||
" minutes";
|
||
}
|
||
} else {
|
||
if (hoursAndMinutes[1] === "1") {
|
||
this.uptime =
|
||
days[1] +
|
||
" days, " +
|
||
hoursAndMinutes[1] +
|
||
" hour " +
|
||
hoursAndMinutes[2] +
|
||
" minutes";
|
||
} else if (hoursAndMinutes[2] === 1) {
|
||
this.uptime =
|
||
days[1] +
|
||
" days, " +
|
||
hoursAndMinutes[1] +
|
||
" hours " +
|
||
hoursAndMinutes[2] +
|
||
" minute";
|
||
} else {
|
||
this.uptime =
|
||
days[1] +
|
||
" days, " +
|
||
hoursAndMinutes[1] +
|
||
" hours " +
|
||
hoursAndMinutes[2] +
|
||
" minutes";
|
||
}
|
||
}
|
||
} else {
|
||
if (hoursAndMinutes[1] === "1") {
|
||
this.uptime =
|
||
hoursAndMinutes[1] +
|
||
" hour " +
|
||
hoursAndMinutes[2] +
|
||
" minutes";
|
||
} else if (hoursAndMinutes[2] === 1) {
|
||
this.uptime =
|
||
hoursAndMinutes[1] +
|
||
" hours " +
|
||
hoursAndMinutes[2] +
|
||
" minute";
|
||
} else {
|
||
this.uptime =
|
||
hoursAndMinutes[1] +
|
||
" hours " +
|
||
hoursAndMinutes[2] +
|
||
" minutes";
|
||
}
|
||
}
|
||
} else if (days != null) {
|
||
if (hours != null) {
|
||
if (days[1] === "1") {
|
||
if (hours[1] === "1") {
|
||
this.uptime = days[1] + " day, " + hours[1] + " hour";
|
||
} else {
|
||
this.uptime = days[1] + " day, " + hours[1] + " hours";
|
||
}
|
||
} else {
|
||
if (hours[1] === "1") {
|
||
this.uptime = days[1] + " days, " + hours[1] + " hour";
|
||
} else {
|
||
this.uptime = days[1] + " days, " + hours[1] + " hours";
|
||
}
|
||
}
|
||
} else if (minutes != null) {
|
||
if (days[1] === "1") {
|
||
if (minutes[1] === "1") {
|
||
this.uptime =
|
||
days[1] + " day, " + minutes[1] + " minute";
|
||
} else {
|
||
this.uptime =
|
||
days[1] + " day, " + minutes[1] + " minutes";
|
||
}
|
||
} else {
|
||
if (minutes[1] === "1") {
|
||
this.uptime =
|
||
days[1] + " days, " + minutes[1] + " minute";
|
||
} else {
|
||
this.uptime =
|
||
days[1] + " days, " + minutes[1] + " minutes";
|
||
}
|
||
}
|
||
} else {
|
||
if (days[1] === "1") {
|
||
this.uptime = days[1] + " day";
|
||
} else {
|
||
this.uptime = days[1] + " days";
|
||
}
|
||
}
|
||
} else if (hours != null) {
|
||
if (hours[1] === "1") {
|
||
this.uptime = hours[1] + " hour";
|
||
} else {
|
||
this.uptime = hours[1] + " hours";
|
||
}
|
||
} else if (minutes != null) {
|
||
if (minutes[1] === "1") {
|
||
this.uptime = minutes[1] + " minute";
|
||
} else {
|
||
this.uptime = minutes[1] + " minutes";
|
||
}
|
||
} else {
|
||
this.uptime = "未知时间";
|
||
}
|
||
});
|
||
},
|
||
|
||
updateRefreshRate() {
|
||
// Check if the refresh rate is less than 3
|
||
if (this.newRefreshRate < 3) {
|
||
this.newRefreshRate = 3;
|
||
}
|
||
|
||
// Clear the old interval
|
||
clearInterval(this.intervalId);
|
||
|
||
// Set the refresh rate
|
||
this.refreshRate = this.newRefreshRate;
|
||
console.log("Refresh Rate Updated to " + this.refreshRate);
|
||
|
||
// Store the refresh rate in local storage or session storage
|
||
localStorage.setItem("refreshRate", this.refreshRate);
|
||
|
||
// Initialize with the new refresh rate
|
||
this.init();
|
||
},
|
||
|
||
init() {
|
||
// Fetch uptime
|
||
this.fetchUpTime();
|
||
|
||
// Retrieve the refresh rate from local storage or session storage
|
||
const storedRefreshRate = localStorage.getItem("refreshRate");
|
||
|
||
// If a refresh rate is stored, use it; otherwise, use a default value
|
||
this.refreshRate = storedRefreshRate
|
||
? parseInt(storedRefreshRate)
|
||
: 3; // Change 3 to your desired default value
|
||
|
||
this.fetchAllInfo();
|
||
|
||
this.requestPing()
|
||
.then((data) => {
|
||
const response = data.trim();
|
||
// Trim any leading/trailing spaces
|
||
if (response === "OK") {
|
||
this.internetConnectionStatus = "已连接";
|
||
} else {
|
||
this.internetConnectionStatus = "已断开";
|
||
}
|
||
})
|
||
.catch((error) => {
|
||
console.error("Error:", error);
|
||
this.internetConnectionStatus = "已断开";
|
||
});
|
||
|
||
this.lastUpdate = new Date().toLocaleString();
|
||
console.log("Initialized");
|
||
|
||
// Set the refresh rate for interval
|
||
this.intervalId = setInterval(() => {
|
||
this.fetchUpTime();
|
||
|
||
this.fetchAllInfo();
|
||
|
||
this.requestPing()
|
||
.then((data) => {
|
||
const response = data.trim();
|
||
// Trim any leading/trailing spaces
|
||
if (response === "OK") {
|
||
this.internetConnectionStatus = "已连接";
|
||
} else {
|
||
this.internetConnectionStatus = "已断开";
|
||
}
|
||
})
|
||
.catch((error) => {
|
||
console.error("Error:", error);
|
||
this.internetConnectionStatus = "已断开";
|
||
});
|
||
|
||
this.lastUpdate = new Date().toLocaleString();
|
||
console.log("Refreshed");
|
||
}, this.refreshRate * 1000);
|
||
},
|
||
};
|
||
}
|
||
</script>
|
||
</body>
|
||
</html> |