fixed file dir locations
This commit is contained in:
@@ -1,35 +0,0 @@
|
||||
#!/bin/bash
|
||||
QUERY_STRING=$(echo "${QUERY_STRING}" | sed 's/;//g')
|
||||
function urldecode() { : "${*//+/ }"; echo -e "${_//%/\\x}"; }
|
||||
|
||||
if [ "${QUERY_STRING}" ]; then
|
||||
export IFS="&"
|
||||
for cmd in ${QUERY_STRING}; do
|
||||
if [ "$(echo $cmd | grep '=')" ]; then
|
||||
key=$(echo $cmd | awk -F '=' '{print $1}')
|
||||
value=$(echo $cmd | awk -F '=' '{print $2}')
|
||||
eval $key=$value
|
||||
fi
|
||||
done
|
||||
fi
|
||||
|
||||
MYATCMD=$(printf '%b\n' "${atcmd//%/\\x}")
|
||||
if [ -n "${MYATCMD}" ]; then
|
||||
x=$(urldecode "$atcmd")
|
||||
# Initialize wait time to 200 ms
|
||||
wait_time=200
|
||||
while true; do
|
||||
runcmd=$(echo -en "$x\r\n" | microcom -t $wait_time /dev/ttyOUT2)
|
||||
# Check if "OK" or "ERROR" is present in the response
|
||||
if [[ $runcmd =~ "OK" ]] || [[ $runcmd =~ "ERROR" ]]; then
|
||||
break # Exit the loop if "OK" or "ERROR" is found
|
||||
fi
|
||||
# If neither "OK" nor "ERROR" is found, increment wait time by 1 second
|
||||
((wait_time++))
|
||||
done
|
||||
fi
|
||||
|
||||
echo "Content-type: text/plain"
|
||||
echo $x
|
||||
echo ""
|
||||
echo $runcmd
|
||||
@@ -1,19 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
# This script will ping 8.8.8.8 and return the result
|
||||
# If the ping is successful, it will return "OK"
|
||||
# If the ping fails, it will return "ERROR"
|
||||
|
||||
# Send the ping command and store the output
|
||||
ping_output=$(ping -c 1 8.8.8.8)
|
||||
|
||||
# Check if the output contains "0% packet loss"
|
||||
if echo "$ping_output" | grep -q "0% packet loss"; then
|
||||
echo "Content-type: text/plain"
|
||||
echo ""
|
||||
echo "OK"
|
||||
else
|
||||
echo "Content-type: text/plain"
|
||||
echo ""
|
||||
echo "ERROR"
|
||||
fi
|
||||
@@ -1,20 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
# This is a simple scrip that fetches the SMS messages from the device
|
||||
SMS_MESSAGE_INDICATION="AT+CNMI=2,1"
|
||||
SMS_FORMAT="AT+CMGF=1"
|
||||
SMS_LIST="AT+CMGL=\"ALL\""
|
||||
|
||||
while true; do
|
||||
runcmd=$(echo -en "$SMS_LIST\r\n" | microcom -t 2000 /dev/ttyOUT2)
|
||||
if [[ $runcmd =~ "OK" ]] || [[ $runcmd =~ "ERROR" ]]; then
|
||||
break
|
||||
fi
|
||||
((wait_time++))
|
||||
done
|
||||
|
||||
|
||||
# Print the list of SMS messages as JSON plain text
|
||||
echo "Content-type: text/plain"
|
||||
echo ""
|
||||
echo $runcmd
|
||||
@@ -1,20 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Check iptables for ttlvalue
|
||||
ttlvalue=$(iptables -t mangle -vnL | awk '/TTL/ {print $13; exit}')
|
||||
ttlenabled=true;
|
||||
|
||||
# Set Variables
|
||||
if [ -z "${ttlvalue}" ]; then
|
||||
ttlvalue=0
|
||||
ttlenabled=false
|
||||
fi
|
||||
|
||||
echo "Content-type: text/json"
|
||||
echo ""
|
||||
cat <<EOT
|
||||
{
|
||||
"isEnabled": $ttlenabled,
|
||||
"ttl": $ttlvalue
|
||||
}
|
||||
EOT
|
||||
@@ -1,44 +0,0 @@
|
||||
#!/bin/bash
|
||||
QUERY_STRING=$(echo "${QUERY_STRING}" | sed 's/;//g')
|
||||
function urldecode() { : "${*//+/ }"; echo -e "${_//%/\\x}"; }
|
||||
|
||||
if [ "${QUERY_STRING}" ]; then
|
||||
export IFS="&"
|
||||
for cmd in ${QUERY_STRING}; do
|
||||
if [ "$(echo $cmd | grep '=')" ]; then
|
||||
key=$(echo $cmd | awk -F '=' '{print $1}')
|
||||
value=$(echo $cmd | awk -F '=' '{print $2}')
|
||||
eval $key=$value
|
||||
fi
|
||||
done
|
||||
fi
|
||||
|
||||
# Extract phone number and message from inputs
|
||||
phone_number="$number"
|
||||
message="$msg"
|
||||
|
||||
# Prepare AT command with phone number and message
|
||||
ATCMD="AT+CMGS=\"$phone_number\""
|
||||
|
||||
MYATCMD=$(printf '%b\n' "${ATCMD//%/\\x}")
|
||||
if [ -n "${MYATCMD}" ]; then
|
||||
x=$(urldecode "$ATCMD")
|
||||
# Send the AT command to initiate message sending
|
||||
echo -en "$x\r\n" | microcom /dev/ttyOUT2
|
||||
# Wait for a brief moment (assuming the message sending is instantaneous)
|
||||
sleep 1
|
||||
fi
|
||||
|
||||
# Send the message
|
||||
echo -en "$message\c"
|
||||
|
||||
# Send Ctrl+Z to terminate the message
|
||||
echo -en "\032"
|
||||
|
||||
# Ensure microcom reads the response (assuming microcom will show response instantly)
|
||||
sleep 1
|
||||
|
||||
# Capture and output the response
|
||||
runcmd=$(microcom /dev/ttyOUT2)
|
||||
echo "Content-type: text/plain"
|
||||
echo "$runcmd"
|
||||
@@ -1,61 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Get query
|
||||
QUERY_STRING=$(echo "${QUERY_STRING}" | sed 's/;//g')
|
||||
|
||||
if [ "${QUERY_STRING}" ]; then
|
||||
|
||||
export IFS="&"
|
||||
for cmd in ${QUERY_STRING}; do
|
||||
|
||||
if [ "$(echo $cmd | grep '=')" ]; then
|
||||
key=$(echo $cmd | awk -F '=' '{print $1}')
|
||||
value=$(echo $cmd | awk -F '=' '{print $2}')
|
||||
eval $key=$value
|
||||
fi
|
||||
|
||||
done
|
||||
|
||||
fi
|
||||
|
||||
setTTL=$(printf '%b\n' "${ttlvalue//%/\\x}")
|
||||
|
||||
if [ -n "${setTTL}" ]; then
|
||||
# Stop Service To Remove Rules
|
||||
/usrdata/simplefirewall/ttl-override stop
|
||||
|
||||
# Check iptables is still set
|
||||
ttlcheck=$(iptables -t mangle -vnL | grep TTL | awk '{print $13}')
|
||||
|
||||
# If TTL is still set manually remove values
|
||||
if [ !-z "${ttlcheck}" ]; then
|
||||
iptables -t mangle -D POSTROUTING -o rmnet+ -j TTL --ttl-set ${ttlcheck} &>/dev/null || true
|
||||
ip6tables -t mangle -D POSTROUTING -o rmnet+ -j HL --hl-set ${ttlcheck} &>/dev/null || true
|
||||
fi
|
||||
|
||||
# Echo TTL to file
|
||||
echo $setTTL > /usrdata/simplefirewall/ttlvalue
|
||||
|
||||
# Set Start Service
|
||||
/usrdata/simplefirewall/ttl-override start
|
||||
fi
|
||||
|
||||
|
||||
|
||||
# Check iptables for ttlvalue
|
||||
ttlvalue=$(iptables -t mangle -vnL | grep TTL | awk '{print $13}')
|
||||
ttlenabled=true;
|
||||
|
||||
# Set Variables
|
||||
if [ -z "${ttlvalue}" ]; then
|
||||
ttlvalue=0
|
||||
ttlenabled=false
|
||||
fi
|
||||
|
||||
echo "Content-type: text/json"
|
||||
echo ""
|
||||
cat <<EOT
|
||||
{
|
||||
"isEnabled": $ttlenabled,
|
||||
"ttl": $ttlvalue
|
||||
}
|
||||
6
simpleadmin/css/bootstrap.min.css
vendored
6
simpleadmin/css/bootstrap.min.css
vendored
File diff suppressed because one or more lines are too long
@@ -1,95 +0,0 @@
|
||||
/* import poppins */
|
||||
@import url("https://fonts.googleapis.com/css2?family=Poppins:wght@300;400;500;600;700&display=swap");
|
||||
|
||||
/* import fontawesome icons */
|
||||
@import url("https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.3/css/all.min.css");
|
||||
|
||||
* {
|
||||
font-family: "Poppins", sans-serif;
|
||||
}
|
||||
|
||||
.custom-checkbox .form-check-input {
|
||||
margin-right: 1px;
|
||||
}
|
||||
|
||||
.modal-overlay {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-color: rgba(0, 0, 0, 0.5);
|
||||
z-index: 1000;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.loading-modal {
|
||||
background-color: #fff;
|
||||
padding: 3rem;
|
||||
border-radius: 10px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.loading-text {
|
||||
font-size: 18px;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.loader {
|
||||
width: 64px;
|
||||
height: 64px;
|
||||
border: 3px dotted #000;
|
||||
border-style: solid solid dotted dotted;
|
||||
border-radius: 50%;
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
box-sizing: border-box;
|
||||
animation: rotation 2s linear infinite;
|
||||
margin-bottom: 2rem;
|
||||
}
|
||||
|
||||
.loader::after {
|
||||
content: "";
|
||||
box-sizing: border-box;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
right: 0;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
margin: auto;
|
||||
border: 3px dotted #0b5ed7;
|
||||
border-style: solid solid dotted;
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
border-radius: 50%;
|
||||
animation: rotationBack 1s linear infinite;
|
||||
transform-origin: center center;
|
||||
}
|
||||
|
||||
@keyframes rotation {
|
||||
0% {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
100% {
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
@keyframes rotationBack {
|
||||
0% {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
100% {
|
||||
transform: rotate(-360deg);
|
||||
}
|
||||
}
|
||||
|
||||
.is-warning {
|
||||
background-color: #ffb70f !important;
|
||||
color: #000 !important;
|
||||
}
|
||||
|
||||
.is-medium {
|
||||
font-weight: 600;
|
||||
}
|
||||
@@ -1,358 +0,0 @@
|
||||
<!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>Simple Admin</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" />
|
||||
|
||||
<!-- 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="fetchDeviceInfo()">
|
||||
<nav class="navbar navbar-expand-lg mt-2">
|
||||
<div class="container-fluid">
|
||||
<a class="navbar-brand" href="/"
|
||||
><span class="mb-0 h4">Simple Admin</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" href="/">Home</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="/network.html">Simple Network</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="/settings.html">Simple Settings</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="/sms.html">SMS</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a
|
||||
class="nav-link active"
|
||||
href="/deviceinfo.html"
|
||||
aria-current="page"
|
||||
>Device Information</a
|
||||
>
|
||||
</li>
|
||||
</ul>
|
||||
<span class="navbar-text">
|
||||
<button class="btn btn-link text-reset" id="darkModeToggle">
|
||||
Dark Mode
|
||||
</button>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<div class="row mt-5 gap-3">
|
||||
<div class="col">
|
||||
<div class="card">
|
||||
<div class="card-header">Device Information</div>
|
||||
<div class="card-body">
|
||||
<div class="card-text">
|
||||
<div class="table-responsive">
|
||||
<table class="table">
|
||||
<tbody>
|
||||
<tr>
|
||||
<th scope="row">Manufacturer</th>
|
||||
<td x-text="manufacturer"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">Model Name</th>
|
||||
<td x-text="modelName"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">Firmware version</th>
|
||||
<td class="col-md-2" x-text="firmwareVersion"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">IMSI</th>
|
||||
<td class="col-md-2" x-text="imsi"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">ICCID</th>
|
||||
<td class="col-md-2" x-text="iccid"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">IMEI</th>
|
||||
<td class="col-md-2">
|
||||
<input
|
||||
class="form-control"
|
||||
type="text"
|
||||
x-model="newImei"
|
||||
x-bind:placeholder="imei === '-' ? 'Fetching IMEI...' : imei"
|
||||
/>
|
||||
</td>
|
||||
<td>
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-primary"
|
||||
@click="openModal()"
|
||||
>
|
||||
Update
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<th scope="row">LAN IP</th>
|
||||
<td class="col-md-2" x-text="lanIp"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">WWAN IPv<sup>4</sup></th>
|
||||
<td class="col-md-2" x-text="wwanIpv4"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">WWAN IPv<sup>6</sup></th>
|
||||
<td class="col-md-2" x-text="wwanIpv6"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">Simple Admin Version</th>
|
||||
<td class="col-md-2">SimpleAdminRev-Alpha-0.3</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-footer">
|
||||
Visit our
|
||||
<a
|
||||
href="https://github.com/iamromulan/quectel-rgmii-toolkit.gits"
|
||||
target="_blank"
|
||||
class="text-reset"
|
||||
>repository</a
|
||||
>
|
||||
or
|
||||
<a
|
||||
href="https://github.com/iamromulan/quectel-rgmii-configuration-notes.git"
|
||||
target="_blank"
|
||||
class="text-reset"
|
||||
>documentation</a
|
||||
>
|
||||
for more information. All rights reserved. 2024
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Loading Modal for Reboot -->
|
||||
<div class="modal-overlay" x-show="showModal">
|
||||
<div class="loading-modal">
|
||||
<div
|
||||
class="loading-text"
|
||||
style="display: flex; flex-direction: column"
|
||||
>
|
||||
<h3>This will reboot the modem.</h3>
|
||||
<p style="margin-top: 0.5rem">Continue?</p>
|
||||
</div>
|
||||
<div class="d-grid gap-2 d-md-block">
|
||||
<button
|
||||
class="btn btn-primary"
|
||||
type="button"
|
||||
@click="updateIMEI()"
|
||||
>
|
||||
Reboot
|
||||
</button>
|
||||
<button
|
||||
class="btn btn-danger"
|
||||
type="button"
|
||||
@click="closeModal()"
|
||||
>
|
||||
Cancel
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Reboot Modal Countdown -->
|
||||
<div class="modal-overlay" x-show="isRebooting">
|
||||
<div class="loading-modal">
|
||||
<div class="loader"></div>
|
||||
<div
|
||||
class="loading-text"
|
||||
style="display: flex; flex-direction: column"
|
||||
>
|
||||
<h3>Rebooting...</h3>
|
||||
<p style="margin-top: 0.5rem">
|
||||
Please wait for
|
||||
<span x-text="countdown" style="font-weight: 500"></span>
|
||||
seconds.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
<script src="/js/dark-mode.js"></script>
|
||||
<script>
|
||||
function fetchDeviceInfo() {
|
||||
return {
|
||||
manufacturer: "-",
|
||||
modelName: "-",
|
||||
firmwareVersion: "-",
|
||||
imsi: "-",
|
||||
iccid: "-",
|
||||
imei: "-",
|
||||
newImei: null,
|
||||
lanIp: "-",
|
||||
wwanIpv4: "-",
|
||||
wwanIpv6: "-",
|
||||
simpleAdminVersion: "-",
|
||||
atcmd: null,
|
||||
atCommandResponse: "",
|
||||
showModal: false,
|
||||
isLoading: false,
|
||||
isRebooting: false,
|
||||
countdown: 3,
|
||||
|
||||
sendATCommand() {
|
||||
if (!this.atcmd) {
|
||||
// Use ATI as default command
|
||||
console.log(
|
||||
"AT Command is empty, using ATI as default command: "
|
||||
);
|
||||
}
|
||||
|
||||
this.isLoading = true;
|
||||
fetch(
|
||||
"/cgi-bin/get_atcommand?" +
|
||||
new URLSearchParams({
|
||||
atcmd: this.atcmd,
|
||||
})
|
||||
)
|
||||
.then((res) => {
|
||||
return res.text();
|
||||
})
|
||||
.then((data) => {
|
||||
this.atCommandResponse = data;
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error("Error: ", error);
|
||||
this.showError = true;
|
||||
});
|
||||
},
|
||||
|
||||
fetchATCommand() {
|
||||
this.atcmd =
|
||||
'AT+CGMI;+CGMM;+QGMR;+CIMI;+ICCID;+CGSN;+QMAP="LANIP";+QMAP="WWAN"';
|
||||
this.isLoading = true;
|
||||
fetch(
|
||||
"/cgi-bin/get_atcommand?" +
|
||||
new URLSearchParams({
|
||||
atcmd: this.atcmd,
|
||||
})
|
||||
)
|
||||
.then((res) => {
|
||||
return res.text();
|
||||
})
|
||||
.then((data) => {
|
||||
this.atCommandResponse = data;
|
||||
this.parseFetchedData();
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error("Error: ", error);
|
||||
this.showError = true;
|
||||
});
|
||||
},
|
||||
|
||||
parseFetchedData() {
|
||||
const lines = this.atCommandResponse.split("\n");
|
||||
|
||||
console.log("AT Command Response: ", lines);
|
||||
|
||||
this.manufacturer = lines[1].trim();
|
||||
this.modelName = lines[3].trim();
|
||||
this.firmwareVersion = lines[5].trim();
|
||||
this.imsi = lines[7].trim();
|
||||
this.iccid = lines[9].trim().replace("+ICCID: ", "");
|
||||
this.imei = lines[11].trim();
|
||||
this.lanIp = lines[13].trim().split(",")[3];
|
||||
this.wwanIpv4 = lines[15].trim().split(",")[4].replace(/"/g, "");
|
||||
this.wwanIpv6 = lines[16].trim().split(",")[4].replace(/"/g, "");
|
||||
this.simpleAdminVersion = "SimpleAdminRev-Alpha-0.5";
|
||||
this.isLoading = false;
|
||||
},
|
||||
|
||||
updateIMEI() {
|
||||
this.atcmd = `AT+EGMR=1,7,"${this.newImei}"`;
|
||||
this.sendATCommand();
|
||||
this.rebootDevice();
|
||||
},
|
||||
|
||||
rebootDevice() {
|
||||
this.atcmd = "AT+CFUN=1,1";
|
||||
this.sendATCommand();
|
||||
|
||||
this.isLoading = true;
|
||||
this.showModal = false;
|
||||
this.isRebooting = true;
|
||||
this.countdown = 40;
|
||||
const interval = setInterval(() => {
|
||||
this.countdown--;
|
||||
if (this.countdown === 0) {
|
||||
clearInterval(interval);
|
||||
this.isLoading = false;
|
||||
this.showModal = false;
|
||||
this.isRebooting = false;
|
||||
this.init();
|
||||
}
|
||||
}, 1000);
|
||||
},
|
||||
|
||||
openModal() {
|
||||
if (!this.newImei) {
|
||||
alert("No new IMEI provided.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.newImei.length !== 15) {
|
||||
alert("IMEI is invalid");
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.newImei === this.imei) {
|
||||
alert("IMEI is the same as the current IMEI");
|
||||
return;
|
||||
}
|
||||
|
||||
this.showModal = true;
|
||||
},
|
||||
|
||||
closeModal() {
|
||||
this.showModal = false;
|
||||
},
|
||||
|
||||
init() {
|
||||
this.fetchATCommand();
|
||||
},
|
||||
};
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
File diff suppressed because it is too large
Load Diff
5
simpleadmin/js/alpinejs.min.js
vendored
5
simpleadmin/js/alpinejs.min.js
vendored
File diff suppressed because one or more lines are too long
7
simpleadmin/js/bootstrap.bundle.min.js
vendored
7
simpleadmin/js/bootstrap.bundle.min.js
vendored
File diff suppressed because one or more lines are too long
@@ -1,29 +0,0 @@
|
||||
// Function to toggle dark mode
|
||||
const toggleDarkMode = () => {
|
||||
const html = document.querySelector('html');
|
||||
const currentTheme = html.getAttribute('data-bs-theme');
|
||||
|
||||
if (currentTheme === 'dark') {
|
||||
html.removeAttribute('data-bs-theme');
|
||||
darkModeToggle.textContent = 'Dark Mode';
|
||||
localStorage.setItem('theme', 'light'); // Store the theme in localStorage
|
||||
} else {
|
||||
html.setAttribute('data-bs-theme', 'dark');
|
||||
darkModeToggle.textContent = 'Light Mode';
|
||||
localStorage.setItem('theme', 'dark'); // Store the theme in localStorage
|
||||
}
|
||||
};
|
||||
|
||||
const darkModeToggle = document.getElementById('darkModeToggle');
|
||||
|
||||
// Check if theme preference is stored in localStorage
|
||||
const storedTheme = localStorage.getItem('theme');
|
||||
if (storedTheme) {
|
||||
const html = document.querySelector('html');
|
||||
html.setAttribute('data-bs-theme', storedTheme);
|
||||
if (storedTheme === 'dark') {
|
||||
darkModeToggle.textContent = 'Light Mode';
|
||||
}
|
||||
}
|
||||
|
||||
darkModeToggle.addEventListener('click', toggleDarkMode);
|
||||
@@ -1,37 +0,0 @@
|
||||
const freqNumbersContainer = document.getElementById(
|
||||
"freqNumbersContainer"
|
||||
);
|
||||
|
||||
function generateFreqNumberInputs(num) {
|
||||
let html = "";
|
||||
const maxFields = Math.min(num, 10); // Limit to a maximum of 10 fields
|
||||
for (let i = 1; i <= maxFields; i++) {
|
||||
html += `
|
||||
<div class="input-group mb-3" x-show="cellNum >= ${i} && networkModeCell == 'LTE'">
|
||||
<input
|
||||
type="text"
|
||||
aria-label="EARFCN"
|
||||
placeholder="EARFCN"
|
||||
class="form-control"
|
||||
x-model="earfcn${i}"
|
||||
/>
|
||||
<input
|
||||
type="text"
|
||||
aria-label="PCI"
|
||||
placeholder="PCI"
|
||||
class="form-control"
|
||||
x-model="pci${i}"
|
||||
/>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
return html;
|
||||
}
|
||||
|
||||
document.addEventListener("DOMContentLoaded", function () {
|
||||
const cellNumInput = document.querySelector("[aria-label='NumCells']");
|
||||
cellNumInput.addEventListener("input", function () {
|
||||
const cellNum = parseInt(this.value);
|
||||
freqNumbersContainer.innerHTML = generateFreqNumberInputs(cellNum);
|
||||
});
|
||||
});
|
||||
@@ -1,60 +0,0 @@
|
||||
function parseCurrentSettings(rawdata) {
|
||||
const data = rawdata;
|
||||
|
||||
const lines = data.split("\n");
|
||||
console.log(lines);
|
||||
|
||||
// Remove QUIMSLOT and only take 1 or 2
|
||||
this.sim = lines[1].split(":")[1].trim();
|
||||
this.apn = lines[3].split(",")[2].replace(/\"/g, "");
|
||||
this.cellLock4GStatus = lines[5].split(",")[1].replace(/\"/g, "");
|
||||
this.cellLock5GStatus = lines[7].split(",")[1].replace(/\"/g, "");
|
||||
this.prefNetwork = lines[9].split(",")[1].replace(/\"/g, "");
|
||||
this.nrModeControlStatus = lines[11].split(",")[1].replace(/\"/g, "");
|
||||
|
||||
|
||||
let bands = [];
|
||||
|
||||
// Append the values if there is separated by comma with a space.
|
||||
// i.e. LTE BAND 3, LTE BAND 1
|
||||
for (let i = 13; i < 17; i++) {
|
||||
if (lines[i].split(",").length > 1) {
|
||||
bands.push(lines[i].split(",")[3].replace(/\"/g, " "));
|
||||
}
|
||||
}
|
||||
|
||||
this.bands = bands;
|
||||
|
||||
|
||||
if (this.cellLock4GStatus == 1 && this.cellLock5GStatus == 1) {
|
||||
this.cellLockStatus = "Locked to 4G and 5G";
|
||||
} else if (this.cellLock4GStatus == 1) {
|
||||
this.cellLockStatus = "Locked to 4G";
|
||||
}
|
||||
else if (this.cellLock5GStatus == 1) {
|
||||
this.cellLockStatus = "Locked to 5G";
|
||||
}
|
||||
else {
|
||||
this.cellLockStatus = "Not Locked";
|
||||
}
|
||||
|
||||
if (this.nrModeControlStatus == 0) {
|
||||
this.nrModeControlStatus = "Not Disabled";
|
||||
}
|
||||
else if (this.nrModeControlStatus == 1) {
|
||||
this.nrModeControlStatus = "SA Disabled";
|
||||
}
|
||||
else {
|
||||
this.nrModeControlStatus = "NSA Disabled";
|
||||
}
|
||||
|
||||
return {
|
||||
sim: sim,
|
||||
apn: apn,
|
||||
cellLockStatus: cellLockStatus,
|
||||
prefNetwork: prefNetwork,
|
||||
nrModeControl: nrModeControlStatus,
|
||||
bands: bands
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,76 +0,0 @@
|
||||
function populateCheckboxes(lte_band, nsa_nr5g_band, nr5g_band, locked_lte_bands, locked_nsa_bands, locked_sa_bands, cellLock) {
|
||||
var checkboxesForm = document.getElementById("checkboxForm");
|
||||
var selectedMode = document.getElementById("networkModeBand").value;
|
||||
var bands;
|
||||
|
||||
// Determine bands based on selected network mode
|
||||
if (selectedMode === "LTE") {
|
||||
bands = lte_band;
|
||||
} else if (selectedMode === "NSA") {
|
||||
bands = nsa_nr5g_band;
|
||||
} else if (selectedMode === "SA") {
|
||||
bands = nr5g_band;
|
||||
}
|
||||
|
||||
checkboxesForm.innerHTML = ""; // Clear existing checkboxes
|
||||
|
||||
var bandsArray;
|
||||
if (bands !== null) {
|
||||
bandsArray = bands.split(":");
|
||||
bandsArray.forEach(function(band, index) {
|
||||
if (index % 5 === 0) {
|
||||
currentRow = document.createElement("div");
|
||||
currentRow.className = "row mb-2 mx-auto"; // Add margin bottom for spacing
|
||||
checkboxesForm.appendChild(currentRow);
|
||||
}
|
||||
|
||||
var checkboxDiv = document.createElement("div");
|
||||
checkboxDiv.className = "form-check form-check-reverse col-2"; // Each checkbox takes a column
|
||||
var checkboxInput = document.createElement("input");
|
||||
checkboxInput.className = "form-check-input";
|
||||
checkboxInput.type = "checkbox";
|
||||
checkboxInput.id = "inlineCheckbox" + band;
|
||||
checkboxInput.value = band;
|
||||
checkboxInput.autocomplete = "off";
|
||||
|
||||
// Store the locked bands in an array
|
||||
var locked_lte_bands_array = locked_lte_bands.split(":");
|
||||
var locked_nsa_bands_array = locked_nsa_bands.split(":");
|
||||
var locked_sa_bands_array = locked_sa_bands.split(":");
|
||||
|
||||
// Check if the current band is locked
|
||||
var isLocked = false;
|
||||
if (selectedMode === "LTE") {
|
||||
if (locked_lte_bands_array.includes(band)) {
|
||||
isLocked = true;
|
||||
}
|
||||
} else if (selectedMode === "NSA") {
|
||||
if (locked_nsa_bands_array.includes(band)) {
|
||||
isLocked = true;
|
||||
}
|
||||
} else if (selectedMode === "SA") {
|
||||
if (locked_sa_bands_array.includes(band)) {
|
||||
isLocked = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (isLocked) {
|
||||
checkboxInput.checked = true;
|
||||
}
|
||||
|
||||
var checkboxLabel = document.createElement("label");
|
||||
checkboxLabel.className = "form-check-label";
|
||||
checkboxLabel.htmlFor = "inlineCheckbox" + band;
|
||||
checkboxLabel.innerText = "B" + band;
|
||||
|
||||
checkboxDiv.appendChild(checkboxInput);
|
||||
checkboxDiv.appendChild(checkboxLabel);
|
||||
currentRow.appendChild(checkboxDiv);
|
||||
});
|
||||
} else {
|
||||
// Do nothing
|
||||
}
|
||||
|
||||
var currentRow;
|
||||
addCheckboxListeners(cellLock);
|
||||
}
|
||||
@@ -1,933 +0,0 @@
|
||||
<!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>Simple Admin</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" />
|
||||
|
||||
<!-- 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="cellLocking()">
|
||||
<nav class="navbar navbar-expand-lg mt-2">
|
||||
<div class="container-fluid">
|
||||
<a class="navbar-brand" href="/"
|
||||
><span class="mb-0 h4">Simple Admin</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" href="/">Home</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a
|
||||
class="nav-link active"
|
||||
href="network.html"
|
||||
aria-current="page"
|
||||
>Simple Network</a
|
||||
>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="/settings.html">Simple Settings</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="/sms.html">SMS</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="deviceinfo.html"
|
||||
>Device Information</a
|
||||
>
|
||||
</li>
|
||||
</ul>
|
||||
<span class="navbar-text">
|
||||
<button class="btn btn-link text-reset" id="darkModeToggle">
|
||||
Dark Mode
|
||||
</button>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<div class="row mt-5 gap-3">
|
||||
<div class="col">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<div class="row align-items-center">
|
||||
<div class="col">Band Locking</div>
|
||||
<div class="col-md-3">
|
||||
<select
|
||||
class="form-select"
|
||||
id="networkModeBand"
|
||||
aria-label="LTE"
|
||||
>
|
||||
<option selected value="LTE">LTE</option>
|
||||
<option value="NSA">NR5G-NSA</option>
|
||||
<option value="SA">NR5G-SA</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<h5 class="card-subtitle" x-show="isLoading">
|
||||
Fetching supported bands...
|
||||
</h5>
|
||||
<form id="checkboxForm" x-show="isLoading === false">
|
||||
<!-- Checkboxes will be populated here -->
|
||||
</form>
|
||||
</div>
|
||||
<div class="card-footer">
|
||||
<div class="d-flex align-items-center">
|
||||
<div class="col">
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-primary m-2"
|
||||
@click="lockSelectedBands()"
|
||||
>
|
||||
Lock Bands
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-info m-2"
|
||||
id="uncheckAll"
|
||||
>
|
||||
Uncheck All
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-danger m-2"
|
||||
@click="resetBandLocking()"
|
||||
>
|
||||
Reset
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-footer">
|
||||
<p x-text="'Active bands: ' + bands"></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row gap-3 mt-4">
|
||||
<div class="col">
|
||||
<form>
|
||||
<div class="card">
|
||||
<div class="card-header">Network Utilities</div>
|
||||
<div class="card-body row">
|
||||
<div class="col">
|
||||
<div class="mb-4">
|
||||
<label for="APN" class="form-label">APN</label>
|
||||
<input
|
||||
type="text"
|
||||
class="form-control"
|
||||
id="APN"
|
||||
x-model="newApn"
|
||||
aria-describedby="APN"
|
||||
x-bind:placeholder="apn === '-' ? 'Fetching...' : apn"
|
||||
/>
|
||||
</div>
|
||||
<div class="mb-4 input-group grid gap-3">
|
||||
<label for="SIM1" class="form-label"> Change SIM</label>
|
||||
<div class="form-check form-check-inline">
|
||||
<input
|
||||
class="form-check-input"
|
||||
type="radio"
|
||||
name="inlineRadioOptions"
|
||||
aria-describedby="SIM1"
|
||||
id="SIM1"
|
||||
value="option1"
|
||||
x-bind:checked="sim === '1'"
|
||||
x-on:click="newSim = '1'"
|
||||
/>
|
||||
<label class="form-check-label" for="inlineRadio1"
|
||||
>1</label
|
||||
>
|
||||
</div>
|
||||
<div class="form-check form-check-inline">
|
||||
<input
|
||||
class="form-check-input"
|
||||
type="radio"
|
||||
name="inlineRadioOptions"
|
||||
aria-describedby="SIM2"
|
||||
id="SIM2"
|
||||
value="option2"
|
||||
x-bind:checked="sim === '2'"
|
||||
x-on:click="newSim = '2'"
|
||||
/>
|
||||
<label class="form-check-label" for="inlineRadio2"
|
||||
>2</label
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col">
|
||||
<div class="mb-4">
|
||||
<label for="nrModeControl" class="form-label"
|
||||
>Select Preferred Network</label
|
||||
>
|
||||
<select
|
||||
class="form-select"
|
||||
id="prefNetworkMode"
|
||||
x-model="prefNetworkMode"
|
||||
aria-label="prefNetworkMode"
|
||||
>
|
||||
<option
|
||||
selected
|
||||
x-text="prefNetwork === '-' ? 'Fetching...' : 'Current: ' + prefNetwork"
|
||||
></option>
|
||||
<option value="AUTO">AUTO</option>
|
||||
<option value="LTE">LTE Only</option>
|
||||
<option value="LTE:NR5G">NR5G-NSA</option>
|
||||
<option value="NR5G">NR5G-SA</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="mb-4">
|
||||
<label for="prefNetwork" class="form-label"
|
||||
>NR5G Mode Control</label
|
||||
>
|
||||
<select
|
||||
class="form-select"
|
||||
id="nrModeControl"
|
||||
x-model="nrModeControl"
|
||||
aria-label="nrModeControl"
|
||||
>
|
||||
<option
|
||||
selected
|
||||
x-text="nrModeControl === '-' ? 'Fetching...' : 'Current: ' + nrModeControl"
|
||||
></option>
|
||||
<option value="0">Enable All</option>
|
||||
<option value="2">Disable NR5G-NSA</option>
|
||||
<option value="1">Disable NR5G-SA</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-footer">
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-primary"
|
||||
@click="saveChanges()"
|
||||
>
|
||||
Save Changes
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div class="col-md-4">
|
||||
<div class="card">
|
||||
<div class="card-header">Cell Locking</div>
|
||||
<div class="card-body">
|
||||
<select
|
||||
class="form-select"
|
||||
id="networkModeCell"
|
||||
x-model="networkModeCell"
|
||||
aria-label="LTE"
|
||||
>
|
||||
<option
|
||||
selected
|
||||
x-text="'Cell Lock: ' + cellLockStatus"
|
||||
></option>
|
||||
<option>LTE</option>
|
||||
<option>NR5G-SA</option>
|
||||
<option>Unlock LTE</option>
|
||||
<option>Unlock NR5G-SA</option>
|
||||
</select>
|
||||
|
||||
<div class="my-4">
|
||||
<!-- For LTE -->
|
||||
<div id="lteElementsCell" x-show="networkModeCell == 'LTE'">
|
||||
<div class="input-group mb-3">
|
||||
<span class="input-group-text" id="basic-addon1"
|
||||
>Num Cells</span
|
||||
>
|
||||
<input
|
||||
type="number"
|
||||
class="form-control"
|
||||
placeholder="1-10"
|
||||
min="1"
|
||||
max="10"
|
||||
aria-label="NumCells"
|
||||
aria-describedby="basic-addon1"
|
||||
x-model="cellNum"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="freqNumbersContainer">
|
||||
<!-- Generate EARFCN and PCI here -->
|
||||
</div>
|
||||
|
||||
<!-- For SA -->
|
||||
<div
|
||||
id="saElementsCell"
|
||||
x-show="networkModeCell == 'NR5G-SA'"
|
||||
>
|
||||
<div
|
||||
class="input-group mb-3"
|
||||
x-show="networkModeCell == 'NR5G-SA'"
|
||||
>
|
||||
<input
|
||||
type="text"
|
||||
aria-label="EARFCN"
|
||||
placeholder="EARFCN"
|
||||
class="form-control"
|
||||
x-model="earfcn1"
|
||||
/>
|
||||
<input
|
||||
type="text"
|
||||
aria-label="PCI"
|
||||
placeholder="PCI"
|
||||
class="form-control"
|
||||
x-model="pci1"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div
|
||||
class="input-group mb-3"
|
||||
x-show="networkModeCell == 'NR5G-SA'"
|
||||
>
|
||||
<select
|
||||
class="form-select"
|
||||
x-model="scs"
|
||||
aria-label="SCS"
|
||||
>
|
||||
<option selected>SCS</option>
|
||||
<option>15</option>
|
||||
<option>30</option>
|
||||
<option>60</option>
|
||||
<option>120</option>
|
||||
<option>240</option>
|
||||
</select>
|
||||
<input
|
||||
type="text"
|
||||
aria-label="band"
|
||||
placeholder="Band"
|
||||
class="form-control"
|
||||
x-model="band"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-primary"
|
||||
x-show="networkModeCell == 'LTE'"
|
||||
@click="cellLockEnableLTE()"
|
||||
>
|
||||
Lock LTE Cells
|
||||
</button>
|
||||
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-primary"
|
||||
x-show="networkModeCell == 'NR5G-SA'"
|
||||
@click="cellLockEnableNR()"
|
||||
>
|
||||
Lock NR5G-SA Cells
|
||||
</button>
|
||||
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-danger"
|
||||
x-show="networkModeCell == 'Unlock LTE'"
|
||||
@click="cellLockDisableLTE()"
|
||||
>
|
||||
Unlock LTE Cells
|
||||
</button>
|
||||
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-danger"
|
||||
x-show="networkModeCell == 'Unlock NR5G-SA'"
|
||||
@click="cellLockDisableNR()"
|
||||
>
|
||||
Unlock NR5G-SA Cells
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Loading Modal for Locking Band -->
|
||||
<div class="modal-overlay" x-show="showModal">
|
||||
<div class="loading-modal">
|
||||
<div class="loader"></div>
|
||||
<div
|
||||
class="loading-text"
|
||||
style="display: flex; flex-direction: column"
|
||||
>
|
||||
<h3>Initializing Network...</h3>
|
||||
<p style="margin-top: 0.5rem">
|
||||
Please wait for
|
||||
<span x-text="countdown" style="font-weight: 500"></span>
|
||||
seconds.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<!-- Import Band Locking GUI JS -->
|
||||
<!-- <script src="js/band-locking.js"></script> -->
|
||||
<script src="js/generate-freq-box.js"></script>
|
||||
<script src="js/populate-checkbox.js"></script>
|
||||
<script src="js/parse-settings.js"></script>
|
||||
<script>
|
||||
function requestATInfo(atcmd) {
|
||||
return fetch(
|
||||
"/cgi-bin/get_atcommand?" +
|
||||
new URLSearchParams({
|
||||
atcmd: atcmd,
|
||||
})
|
||||
)
|
||||
.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;
|
||||
});
|
||||
}
|
||||
|
||||
function getSupportedBands() {
|
||||
const atcmd = 'AT+QNWPREFCFG="policy_band"';
|
||||
return requestATInfo(atcmd).then((rawdata) => {
|
||||
let { lte_bands, nsa_bands, sa_bands } = parseSupportedBands(rawdata);
|
||||
|
||||
return {
|
||||
lte_bands: lte_bands,
|
||||
nsa_bands: nsa_bands,
|
||||
sa_bands: sa_bands,
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
function parseSupportedBands(rawdata) {
|
||||
const data = rawdata;
|
||||
const regex = /"([^"]+)",([0-9:]+)/g;
|
||||
|
||||
// Object to store the results
|
||||
const bands = {};
|
||||
|
||||
let match;
|
||||
while ((match = regex.exec(data)) !== null) {
|
||||
const bandType = match[1];
|
||||
const numbers = match[2].split(":").map(Number);
|
||||
bands[bandType] = numbers;
|
||||
}
|
||||
|
||||
// Seperate the bands for each network mode
|
||||
const lte_bands = bands.lte_band.join(":");
|
||||
const nsa_bands = bands.nsa_nr5g_band.join(":");
|
||||
const sa_bands = bands.nr5g_band.join(":");
|
||||
|
||||
return {
|
||||
lte_bands,
|
||||
nsa_bands,
|
||||
sa_bands,
|
||||
};
|
||||
}
|
||||
|
||||
function parseLockedBands(rawdata) {
|
||||
const data = rawdata;
|
||||
const regex = /"([^"]+)",([0-9:]+)/g;
|
||||
|
||||
// Object to store the results
|
||||
const bands = {};
|
||||
|
||||
let match;
|
||||
while ((match = regex.exec(data)) !== null) {
|
||||
const bandType = match[1];
|
||||
const numbers = match[2].split(":").map(Number);
|
||||
bands[bandType] = numbers;
|
||||
}
|
||||
|
||||
// Seperate the bands for each network mode
|
||||
const locked_lte_bands = bands.lte_band.join(":");
|
||||
const locked_nsa_bands = bands.nsa_nr5g_band.join(":");
|
||||
const locked_sa_bands = bands.nr5g_band.join(":");
|
||||
|
||||
return {
|
||||
locked_lte_bands,
|
||||
locked_nsa_bands,
|
||||
locked_sa_bands,
|
||||
};
|
||||
}
|
||||
|
||||
function getLockedBands() {
|
||||
const atcmd =
|
||||
'AT+QNWPREFCFG="lte_band";+QNWPREFCFG= "nsa_nr5g_band";+QNWPREFCFG= "nr5g_band"';
|
||||
|
||||
return requestATInfo(atcmd).then((rawdata) => {
|
||||
const lockedBandsData = parseLockedBands(rawdata);
|
||||
return lockedBandsData;
|
||||
});
|
||||
}
|
||||
|
||||
function getCurrentSettings() {
|
||||
const atcmd =
|
||||
'AT+QUIMSLOT?;+CGCONTRDP=1;+QNWLOCK="common/4g";+QNWLOCK="common/5g";+QNWPREFCFG="mode_pref";+QNWPREFCFG="nr5g_disable_mode";+QCAINFO';
|
||||
|
||||
return requestATInfo(atcmd).then((rawdata) => {
|
||||
const settings = parseCurrentSettings(rawdata);
|
||||
return {
|
||||
sim: settings.sim,
|
||||
apn: settings.apn,
|
||||
cellLockStatus: settings.cellLockStatus,
|
||||
prefNetwork: settings.prefNetwork,
|
||||
nrModeControl: settings.nrModeControl,
|
||||
bands: settings.bands,
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
function cellLocking() {
|
||||
return {
|
||||
isLoading: false,
|
||||
showModal: false,
|
||||
countdown: 0,
|
||||
networkModeCell: "-",
|
||||
earfcn1: null,
|
||||
pci1: null,
|
||||
earfcn2: null,
|
||||
pci2: null,
|
||||
earfcn3: null,
|
||||
pci3: null,
|
||||
earfcn4: null,
|
||||
pci4: null,
|
||||
earfcn5: null,
|
||||
pci5: null,
|
||||
earfcn6: null,
|
||||
pci6: null,
|
||||
earfcn7: null,
|
||||
pci7: null,
|
||||
earfcn8: null,
|
||||
pci8: null,
|
||||
earfcn9: null,
|
||||
pci9: null,
|
||||
earfcn10: null,
|
||||
pci10: null,
|
||||
scs: null,
|
||||
band: null,
|
||||
apn: "-",
|
||||
newApn: null,
|
||||
prefNetwork: "-",
|
||||
prefNetworkMode: null,
|
||||
nrModeControl: "-",
|
||||
cellNum: null,
|
||||
lte_bands: null,
|
||||
nsa_bands: null,
|
||||
sa_bands: null,
|
||||
locked_lte_bands: null,
|
||||
locked_nsa_bands: null,
|
||||
locked_sa_bands: null,
|
||||
currentNetworkMode: "-",
|
||||
updatedLockedBands: null,
|
||||
sim: "-",
|
||||
newSim: null,
|
||||
cellLockStatus: "Unknown",
|
||||
bands: "Fetching Bands...",
|
||||
init() {
|
||||
// Function to populate checkboxes
|
||||
const showPopulateCheckboxes = () => {
|
||||
this.isLoading = true;
|
||||
Promise.all([getSupportedBands(), getLockedBands()])
|
||||
.then(([supportedBandsData, lockedBandsData]) => {
|
||||
this.lte_bands = supportedBandsData.lte_bands;
|
||||
this.nsa_bands = supportedBandsData.nsa_bands;
|
||||
this.sa_bands = supportedBandsData.sa_bands;
|
||||
this.locked_lte_bands = lockedBandsData.locked_lte_bands;
|
||||
this.locked_nsa_bands = lockedBandsData.locked_nsa_bands;
|
||||
this.locked_sa_bands = lockedBandsData.locked_sa_bands;
|
||||
|
||||
// Once both promises are resolved, call populateCheckboxes
|
||||
populateCheckboxes(
|
||||
this.lte_bands,
|
||||
this.nsa_bands,
|
||||
this.sa_bands,
|
||||
this.locked_lte_bands,
|
||||
this.locked_nsa_bands,
|
||||
this.locked_sa_bands,
|
||||
this
|
||||
);
|
||||
|
||||
// Set isLoading to false after populating checkboxes
|
||||
this.isLoading = false;
|
||||
|
||||
// Add event listeners to checkboxes after populating them
|
||||
addCheckboxListeners(this);
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error("Error:", error);
|
||||
// Handle errors if any
|
||||
});
|
||||
};
|
||||
|
||||
// Function to track checkbox changes
|
||||
this.trackCheckboxChanges = () => {
|
||||
var selectedMode =
|
||||
document.getElementById("networkModeBand").value;
|
||||
var checkboxes = document.querySelectorAll(
|
||||
'input[type="checkbox"]'
|
||||
);
|
||||
var newCheckedValues = [];
|
||||
|
||||
checkboxes.forEach(function (checkbox) {
|
||||
if (checkbox.checked) {
|
||||
newCheckedValues.push(checkbox.value);
|
||||
}
|
||||
});
|
||||
|
||||
// Update currentNetworkMode and updatedLockedBands
|
||||
this.currentNetworkMode = selectedMode;
|
||||
this.updatedLockedBands = newCheckedValues;
|
||||
};
|
||||
|
||||
// Function to get the current settings
|
||||
const getCurrentSettingsData = () => {
|
||||
getCurrentSettings().then((settings) => {
|
||||
this.sim = settings.sim;
|
||||
this.apn = settings.apn;
|
||||
this.cellLockStatus = settings.cellLockStatus;
|
||||
this.prefNetwork = settings.prefNetwork;
|
||||
this.nrModeControl = settings.nrModeControl;
|
||||
this.bands = settings.bands;
|
||||
});
|
||||
};
|
||||
|
||||
// Function to add event listener to network mode dropdown
|
||||
const addNetworkModeListener = () => {
|
||||
document
|
||||
.getElementById("networkModeBand")
|
||||
.addEventListener("change", function () {
|
||||
showPopulateCheckboxes(); // Update checkboxes when network mode changes
|
||||
});
|
||||
};
|
||||
|
||||
// Execute necessary functions on initialization
|
||||
showPopulateCheckboxes();
|
||||
addNetworkModeListener();
|
||||
getCurrentSettingsData();
|
||||
},
|
||||
lockSelectedBands() {
|
||||
// Get the updated this.currentNetworkMode = selectedMode; and this.updatedLockedBands = newCheckedValues;
|
||||
const selectedMode = this.currentNetworkMode;
|
||||
const newCheckedValues = this.updatedLockedBands;
|
||||
let atcmd;
|
||||
|
||||
// Check if both values are null then show the error message
|
||||
if (selectedMode === null || newCheckedValues === null) {
|
||||
} else {
|
||||
if (selectedMode === "LTE") {
|
||||
atcmd = `AT+QNWPREFCFG="lte_band",${newCheckedValues.join(
|
||||
":"
|
||||
)}`;
|
||||
this.sendATcommand(atcmd);
|
||||
} else if (selectedMode === "NSA") {
|
||||
atcmd = `AT+QNWPREFCFG="nsa_nr5g_band",${newCheckedValues.join(
|
||||
":"
|
||||
)}`;
|
||||
this.sendATcommand(atcmd);
|
||||
} else if (selectedMode === "SA") {
|
||||
atcmd = `AT+QNWPREFCFG="nr5g_band",${newCheckedValues.join(
|
||||
":"
|
||||
)}`;
|
||||
this.sendATcommand(atcmd);
|
||||
} else {
|
||||
alert("Invalid network mode selected");
|
||||
}
|
||||
|
||||
// Do a 5 second countdown
|
||||
this.showModal = true;
|
||||
this.countdown = 5;
|
||||
const interval = setInterval(() => {
|
||||
this.countdown--;
|
||||
if (this.countdown === 0) {
|
||||
clearInterval(interval);
|
||||
this.showModal = false;
|
||||
|
||||
// Refresh the page to show the updated bands
|
||||
this.init();
|
||||
}
|
||||
}, 1000);
|
||||
}
|
||||
},
|
||||
resetBandLocking() {
|
||||
// Send the atcmd command to reset the locked bands
|
||||
const atcmd = 'AT+QNWPREFCFG="restore_band"';
|
||||
|
||||
this.showModal = true;
|
||||
|
||||
this.sendATcommand(atcmd);
|
||||
|
||||
this.countdown = 5;
|
||||
const interval = setInterval(() => {
|
||||
this.countdown--;
|
||||
if (this.countdown === 0) {
|
||||
clearInterval(interval);
|
||||
this.showModal = false;
|
||||
|
||||
// Refresh the page to show the updated bands
|
||||
this.init();
|
||||
}
|
||||
}, 1000);
|
||||
|
||||
// Run init function to repopulate the checkboxes
|
||||
this.init();
|
||||
},
|
||||
saveChanges() {
|
||||
const newApn = this.newApn;
|
||||
const newSim = this.newSim;
|
||||
const prefNetworkMode = this.prefNetworkMode;
|
||||
const nrModeControl = this.nrModeControl;
|
||||
|
||||
let atAPN, atSIM, ATNetwork, ATNRMode, atcmd;
|
||||
atAPN = "";
|
||||
atSIM = "";
|
||||
ATNetwork = "";
|
||||
ATNRMode = "";
|
||||
|
||||
if (newApn !== null) {
|
||||
atAPN = `+CGDCONT=1,"IP","${newApn}";`;
|
||||
}
|
||||
|
||||
if (newSim !== null) {
|
||||
atSIM = `+QUIMSLOT=${newSim};`;
|
||||
}
|
||||
|
||||
if (prefNetworkMode !== null) {
|
||||
ATNetwork = `+QNWPREFCFG="mode_pref",${prefNetworkMode};`;
|
||||
}
|
||||
|
||||
if (nrModeControl !== this.nrModeControl) {
|
||||
ATNRMode = `+QNWPREFCFG="nr5g_disable_mode",${nrModeControl}`;
|
||||
}
|
||||
|
||||
atcmd = `AT+${atAPN}${atSIM}${ATNetwork}${ATNRMode}`;
|
||||
// If there is double + (++), remove 1 + from the command
|
||||
atcmd = atcmd.replace("++", "+");
|
||||
if (atcmd !== "AT+") {
|
||||
this.showModal = true;
|
||||
console.log(atcmd);
|
||||
|
||||
this.sendATcommand(atcmd);
|
||||
|
||||
// Do a 15 second countdown
|
||||
this.countdown = 15;
|
||||
|
||||
const interval = setInterval(() => {
|
||||
this.countdown--;
|
||||
if (this.countdown === 0) {
|
||||
clearInterval(interval);
|
||||
this.showModal = false;
|
||||
this.init();
|
||||
}
|
||||
}, 1000);
|
||||
} else {
|
||||
alert("No changes made");
|
||||
}
|
||||
},
|
||||
cellLockEnableLTE() {
|
||||
const cellNum = this.cellNum;
|
||||
|
||||
if (cellNum === null) {
|
||||
alert("Please enter the number of cells to lock");
|
||||
return; // Exit the function early if cellNum is null
|
||||
}
|
||||
|
||||
// Create an array to hold earfcn and pci pairs
|
||||
const earfcnPciPairs = [
|
||||
{ earfcn: this.earfcn1, pci: this.pci1 },
|
||||
{ earfcn: this.earfcn2, pci: this.pci2 },
|
||||
{ earfcn: this.earfcn3, pci: this.pci3 },
|
||||
{ earfcn: this.earfcn4, pci: this.pci4 },
|
||||
{ earfcn: this.earfcn5, pci: this.pci5 },
|
||||
{ earfcn: this.earfcn6, pci: this.pci6 },
|
||||
{ earfcn: this.earfcn7, pci: this.pci7 },
|
||||
{ earfcn: this.earfcn8, pci: this.pci8 },
|
||||
{ earfcn: this.earfcn9, pci: this.pci9 },
|
||||
{ earfcn: this.earfcn10, pci: this.pci10 },
|
||||
];
|
||||
|
||||
// Filter out pairs where either earfcn or pci is null
|
||||
const validPairs = earfcnPciPairs.filter(
|
||||
(pair) => pair.earfcn !== null && pair.pci !== null
|
||||
);
|
||||
|
||||
if (validPairs.length === 0) {
|
||||
alert("Please enter at least one valid earfcn and pci pair");
|
||||
return; // Exit the function early if no valid pairs are found
|
||||
}
|
||||
|
||||
// Construct the AT command using the valid pairs
|
||||
let atcmd = `+QNWLOCK="common/4g",${cellNum},${validPairs
|
||||
.map((pair) => `${pair.earfcn},${pair.pci}`)
|
||||
.join(",")}`;
|
||||
atcmd = "AT+CFUN=0;" + atcmd + ";+CFUN=1";
|
||||
|
||||
// Mock data
|
||||
this.showModal = true;
|
||||
|
||||
this.sendATcommand(atcmd);
|
||||
|
||||
// Do a 15 second countdown
|
||||
this.countdown = 15;
|
||||
const interval = setInterval(() => {
|
||||
this.countdown--;
|
||||
if (this.countdown === 0) {
|
||||
clearInterval(interval);
|
||||
this.showModal = false;
|
||||
}
|
||||
}, 1000);
|
||||
},
|
||||
cellLockEnableNR() {
|
||||
const earfcn = this.earfcn1;
|
||||
const pci = this.pci1;
|
||||
const scs = this.scs;
|
||||
const band = this.band;
|
||||
|
||||
if (
|
||||
earfcn === null ||
|
||||
pci === null ||
|
||||
scs === null ||
|
||||
band === null
|
||||
) {
|
||||
alert("Please enter all the required fields");
|
||||
return; // Exit the function early if any of the fields are null
|
||||
}
|
||||
|
||||
// Construct the AT command using the valid pairs
|
||||
let atcmd = `+QNWLOCK="common/5g",${earfcn},${pci},${scs},${band}`;
|
||||
atcmd = "AT+CFUN=0;" + atcmd + ";+CFUN=1";
|
||||
|
||||
// Mock data
|
||||
this.showModal = true;
|
||||
|
||||
this.sendATcommand(atcmd);
|
||||
|
||||
// Do a 15 second countdown
|
||||
this.countdown = 15;
|
||||
const interval = setInterval(() => {
|
||||
this.countdown--;
|
||||
if (this.countdown === 0) {
|
||||
clearInterval(interval);
|
||||
this.showModal = false;
|
||||
}
|
||||
}, 1000);
|
||||
},
|
||||
cellLockDisableLTE() {
|
||||
// Send the atcmd command to reset the locked bands
|
||||
const atcmd = 'AT+CFUN=0;+QNWLOCK="common/4g,0;+CFUN=1"';
|
||||
this.showModal = true;
|
||||
|
||||
this.sendATcommand(atcmd);
|
||||
|
||||
this.countdown = 15;
|
||||
const interval = setInterval(() => {
|
||||
this.countdown--;
|
||||
if (this.countdown === 0) {
|
||||
clearInterval(interval);
|
||||
this.showModal = false;
|
||||
}
|
||||
}, 1000);
|
||||
},
|
||||
cellLockDisableNR() {
|
||||
// Send the atcmd command to reset the locked bands
|
||||
const atcmd = 'AT+CFUN=0;+QNWLOCK="common/5g,0;+CFUN=1"';
|
||||
|
||||
this.showModal = true;
|
||||
|
||||
this.sendATcommand(atcmd);
|
||||
|
||||
this.countdown = 15;
|
||||
const interval = setInterval(() => {
|
||||
this.countdown--;
|
||||
if (this.countdown === 0) {
|
||||
clearInterval(interval);
|
||||
this.showModal = false;
|
||||
}
|
||||
}, 1000);
|
||||
},
|
||||
sendATcommand(atcmd) {
|
||||
return fetch(
|
||||
"/cgi-bin/get_atcommand?" +
|
||||
new URLSearchParams({
|
||||
atcmd: atcmd,
|
||||
})
|
||||
)
|
||||
.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;
|
||||
});
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
function addCheckboxListeners(cellLock) {
|
||||
// Remove existing event listeners
|
||||
document
|
||||
.querySelectorAll('input[type="checkbox"]')
|
||||
.forEach(function (checkbox) {
|
||||
checkbox.removeEventListener(
|
||||
"change",
|
||||
cellLock.trackCheckboxChanges
|
||||
);
|
||||
});
|
||||
|
||||
// Add new event listeners
|
||||
document
|
||||
.querySelectorAll('input[type="checkbox"]')
|
||||
.forEach(function (checkbox) {
|
||||
checkbox.addEventListener("change", cellLock.trackCheckboxChanges);
|
||||
});
|
||||
}
|
||||
|
||||
// Function for unchecking all checkboxes
|
||||
document
|
||||
.getElementById("uncheckAll")
|
||||
.addEventListener("click", function () {
|
||||
document
|
||||
.querySelectorAll('input[type="checkbox"]')
|
||||
.forEach(function (checkbox) {
|
||||
checkbox.checked = false;
|
||||
});
|
||||
});
|
||||
</script>
|
||||
<script src="/js/dark-mode.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,667 +0,0 @@
|
||||
<!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>Simple Admin</title>
|
||||
<link rel="stylesheet" href="/css/styles.css" />
|
||||
<link rel="stylesheet" href="/css/bootstrap.min.css" />
|
||||
|
||||
<!-- 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="simpleSettings()">
|
||||
<nav class="navbar navbar-expand-lg mt-2">
|
||||
<div class="container-fluid">
|
||||
<a class="navbar-brand" href="/"
|
||||
><span class="mb-0 h4">Simple Admin</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" href="/">Home</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="/network.html">Simple Network</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a
|
||||
class="nav-link active"
|
||||
href="/settings.html"
|
||||
aria-current="page"
|
||||
>Simple Settings</a
|
||||
>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="/sms.html">SMS</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="/deviceinfo.html"
|
||||
>Device Information</a
|
||||
>
|
||||
</li>
|
||||
</ul>
|
||||
<span class="navbar-text">
|
||||
<button class="btn btn-link text-reset" id="darkModeToggle">
|
||||
Dark Mode
|
||||
</button>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<div class="row mt-5 mb-4">
|
||||
<div class="col">
|
||||
<div class="card">
|
||||
<div class="card-header">AT Terminal</div>
|
||||
<div class="card-body">
|
||||
<div class="card-text">
|
||||
<div class="form-floating mb-4">
|
||||
<!-- At commands output here -->
|
||||
<textarea
|
||||
class="form-control"
|
||||
placeholder="ATI"
|
||||
id="atOutputBox"
|
||||
style="height: 220px"
|
||||
x-text="atCommandResponse"
|
||||
readonly
|
||||
>
|
||||
<label for="floatingTextarea">ATI</label>
|
||||
</textarea>
|
||||
</div>
|
||||
<div>
|
||||
<div class="col-md-4 mb-3">
|
||||
<label for="exampleInputEmail1" class="form-label"
|
||||
>AT Command</label
|
||||
>
|
||||
<input
|
||||
type="text"
|
||||
class="form-control"
|
||||
id="atCommandInput"
|
||||
placeholder="ATI"
|
||||
aria-describedby="atCommandInput"
|
||||
x-model="atcmd"
|
||||
@keydown.enter = "sendATCommand()"
|
||||
/>
|
||||
<div id="atCommandInputHelper" class="form-text">
|
||||
Seperate multiple commands with comma (,).
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="d-grid gap-2 d-md-flex justify-content-md-start"
|
||||
>
|
||||
<button
|
||||
class="btn btn-primary me-md-2"
|
||||
type="button"
|
||||
@click="sendATCommand()"
|
||||
:disabled="isLoading"
|
||||
>
|
||||
Submit
|
||||
</button>
|
||||
<button
|
||||
class="btn btn-danger"
|
||||
type="button"
|
||||
@click="clearResponses()"
|
||||
:disabled="isClean"
|
||||
>
|
||||
Clear
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<div class="card">
|
||||
<div class="card-header">One Click Utilities</div>
|
||||
<div class="card-body">
|
||||
<div class="card-text">
|
||||
<div class="table-responsive">
|
||||
<table class="table">
|
||||
<tbody>
|
||||
<tr>
|
||||
<th scope="row">Reboot</th>
|
||||
<td>
|
||||
<button
|
||||
type="submit"
|
||||
class="btn btn-danger"
|
||||
@click="showRebootModal()"
|
||||
:disabled="isLoading"
|
||||
>
|
||||
Reboot
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">Reset AT Commands Settings</th>
|
||||
<td>
|
||||
<button
|
||||
type="submit"
|
||||
class="btn btn-danger"
|
||||
@click="resetATCommands()"
|
||||
:disabled="isLoading"
|
||||
>
|
||||
Reset
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">ETH IP Passthrough</th>
|
||||
<td>
|
||||
<button
|
||||
type="submit"
|
||||
class="btn btn-primary"
|
||||
@click="ethPassthroughEnable()"
|
||||
x-show="ethPassStatus === false"
|
||||
:disabled="isLoading"
|
||||
>
|
||||
Enable
|
||||
</button>
|
||||
<button
|
||||
type="submit"
|
||||
class="btn btn-danger"
|
||||
@click="ethPassthroughDisable()"
|
||||
x-show="ethPassStatus === true"
|
||||
:disabled="isLoading"
|
||||
>
|
||||
Disable
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">Onboard DNS Proxy</th>
|
||||
<td>
|
||||
<button
|
||||
type="submit"
|
||||
class="btn btn-primary"
|
||||
@click="onBoardDNSProxyEnable()"
|
||||
x-show="DNSProxyStatus === false"
|
||||
:disabled="isLoading"
|
||||
>
|
||||
Enable
|
||||
</button>
|
||||
<button
|
||||
type="submit"
|
||||
class="btn btn-danger"
|
||||
@click="onBoardDNSProxyDisable()"
|
||||
x-show="DNSProxyStatus === true"
|
||||
:disabled="isLoading"
|
||||
>
|
||||
Disable
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">USB Mode</th>
|
||||
<td>
|
||||
<button
|
||||
type="submit"
|
||||
class="btn btn-primary"
|
||||
@click="usbModeEnable()"
|
||||
x-show="USBModeStatus === true"
|
||||
:disabled="isLoading"
|
||||
>
|
||||
Enable
|
||||
</button>
|
||||
<button
|
||||
type="submit"
|
||||
class="btn btn-danger"
|
||||
@click="usbModeDisable()"
|
||||
x-show="USBModeStatus === false"
|
||||
:disabled="isLoading"
|
||||
>
|
||||
Disable
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">Scan Neighbour LTE</th>
|
||||
<td>
|
||||
<button
|
||||
type="submit"
|
||||
class="btn btn-primary"
|
||||
@click="scanLTE()"
|
||||
:disabled="isLoading"
|
||||
>
|
||||
Scan LTE
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">Scan Neighbour NSA</th>
|
||||
<td>
|
||||
<button
|
||||
type="submit"
|
||||
class="btn btn-primary"
|
||||
@click="scanNSA()"
|
||||
:disabled="isLoading"
|
||||
>
|
||||
Scan NSA
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col">
|
||||
<div class="card mb-3">
|
||||
<div class="card-header">TTL and Network Scan Settings</div>
|
||||
<div class="card-body">
|
||||
<label for="TTLState" class="form-label"
|
||||
>TTL State and Value</label
|
||||
>
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<div
|
||||
class="p-3 text-primary-emphasis bg-primary-subtle border border-primary-subtle rounded-3"
|
||||
x-show="ttlStatus === true"
|
||||
>
|
||||
TTL is Active
|
||||
</div>
|
||||
|
||||
<div
|
||||
class="p-3 text-danger-emphasis bg-danger-subtle border border-danger-subtle rounded-3"
|
||||
x-show="ttlStatus === false"
|
||||
>
|
||||
TTL is Inactive
|
||||
</div>
|
||||
</div>
|
||||
<div class="col">
|
||||
<div
|
||||
class="p-3 text-info-emphasis bg-info-subtle border border-info-subtle rounded-3 mb-4"
|
||||
x-text="ttlvalue"
|
||||
></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-text mb-3">
|
||||
<div class="mb-4">
|
||||
<input
|
||||
type="text"
|
||||
class="form-control"
|
||||
id="ttlInput"
|
||||
placeholder="TTL Value"
|
||||
x-model="newTTL"
|
||||
/>
|
||||
<div id="ttlValueHelper" class="form-text">
|
||||
Set TTL Value to 0 to disable.
|
||||
</div>
|
||||
</div>
|
||||
<div class="d-grid gap-2">
|
||||
<button
|
||||
class="btn btn-primary"
|
||||
type="button"
|
||||
@click="setTTL()"
|
||||
>
|
||||
Update
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-text">
|
||||
<!-- Select Input Scan Here -->
|
||||
<div class="mb-3">
|
||||
<label for="networkScan" class="form-label"
|
||||
>Network Scan</label
|
||||
>
|
||||
<select
|
||||
class="form-select"
|
||||
id="networkScan"
|
||||
x-model="fullScanModeType"
|
||||
>
|
||||
<option selected>Choose Scan Mode</option>
|
||||
<option value="LTE">LTE</option>
|
||||
<option value="NR5G">NR5G</option>
|
||||
<option value="ALL">ALL</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="d-grid gap-2">
|
||||
<button
|
||||
class="btn btn-primary"
|
||||
type="button"
|
||||
@click="fullScanMode()"
|
||||
:disabled="isLoading"
|
||||
x-text="scanStart ? 'Scanning... Please wait.' : 'Start Scan'"
|
||||
></button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Loading Modal for Reboot -->
|
||||
<div class="modal-overlay" x-show="showModal">
|
||||
<div class="loading-modal">
|
||||
<div
|
||||
class="loading-text"
|
||||
style="display: flex; flex-direction: column"
|
||||
>
|
||||
<h3>This will reboot the modem.</h3>
|
||||
<p style="margin-top: 0.5rem">Continue?</p>
|
||||
</div>
|
||||
<div class="d-grid gap-2 d-md-block">
|
||||
<button
|
||||
class="btn btn-primary"
|
||||
type="button"
|
||||
@click="rebootDevice()"
|
||||
>
|
||||
Reboot
|
||||
</button>
|
||||
<button
|
||||
class="btn btn-danger"
|
||||
type="button"
|
||||
@click="closeModal()"
|
||||
>
|
||||
Cancel
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Reboot Modal Countdown -->
|
||||
<div class="modal-overlay" x-show="isRebooting">
|
||||
<div class="loading-modal">
|
||||
<div class="loader"></div>
|
||||
<div
|
||||
class="loading-text"
|
||||
style="display: flex; flex-direction: column"
|
||||
>
|
||||
<h3>Rebooting...</h3>
|
||||
<p style="margin-top: 0.5rem">
|
||||
Please wait for
|
||||
<span x-text="countdown" style="font-weight: 500"></span>
|
||||
seconds.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
<script src="/js/dark-mode.js"></script>
|
||||
<script>
|
||||
function simpleSettings() {
|
||||
return {
|
||||
isLoading: false,
|
||||
showSuccess: false,
|
||||
showError: false,
|
||||
isClean: true,
|
||||
showModal: false,
|
||||
isRebooting: false,
|
||||
atcmd: "",
|
||||
fetchATCommand: "",
|
||||
countdown: 0,
|
||||
atCommandResponse: "",
|
||||
currentSettingsResponse: "",
|
||||
ttldata: null,
|
||||
ttlvalue: 0,
|
||||
ttlStatus: false,
|
||||
newTTL: null,
|
||||
ethPassStatus: false,
|
||||
DNSProxyStatus: true,
|
||||
USBModeStatus: true,
|
||||
fullScanModeType: "",
|
||||
scanStart: false,
|
||||
|
||||
closeModal() {
|
||||
this.confirmModal = false;
|
||||
this.showModal = false;
|
||||
},
|
||||
|
||||
showRebootModal() {
|
||||
this.showModal = true;
|
||||
},
|
||||
|
||||
sendATCommand() {
|
||||
if (!this.atcmd) {
|
||||
// Use ATI as default command
|
||||
this.atcmd = "ATI";
|
||||
console.log(
|
||||
"AT Command is empty, using ATI as default command: ",
|
||||
this.atcmd
|
||||
);
|
||||
}
|
||||
|
||||
this.isLoading = true;
|
||||
fetch(
|
||||
"/cgi-bin/get_atcommand?" +
|
||||
new URLSearchParams({
|
||||
atcmd: this.atcmd,
|
||||
})
|
||||
)
|
||||
.then((res) => {
|
||||
return res.text();
|
||||
})
|
||||
.then((data) => {
|
||||
this.atCommandResponse = data;
|
||||
this.isLoading = false;
|
||||
this.isClean = false;
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error("Error: ", error);
|
||||
this.showError = true;
|
||||
});
|
||||
},
|
||||
|
||||
clearResponses() {
|
||||
this.atCommandResponse = "";
|
||||
this.isClean = true;
|
||||
},
|
||||
|
||||
rebootDevice() {
|
||||
this.atcmd = "AT+CFUN=1,1";
|
||||
this.sendATCommand();
|
||||
|
||||
this.atCommandResponse = "";
|
||||
this.showModal = false;
|
||||
this.isRebooting = true;
|
||||
this.countdown = 40;
|
||||
|
||||
// Do the countdown
|
||||
const interval = setInterval(() => {
|
||||
this.countdown--;
|
||||
if (this.countdown === 0) {
|
||||
clearInterval(interval);
|
||||
this.isRebooting = false;
|
||||
this.init();
|
||||
}
|
||||
}, 1000);
|
||||
},
|
||||
|
||||
resetATCommands() {
|
||||
this.atcmd = "AT&F";
|
||||
this.sendATCommand();
|
||||
console.log("Resetting AT Commands");
|
||||
this.atcmd = "";
|
||||
this.atCommandResponse = "";
|
||||
this.showRebootModal();
|
||||
},
|
||||
|
||||
ethPassthroughEnable() {
|
||||
this.atcmd = 'AT+QMAP="MPDN_RULE",0,1,0,1,1,"FF:FF:FF:FF:FF:FF"';
|
||||
this.sendATCommand();
|
||||
this.fetchCurrentSettings();
|
||||
},
|
||||
|
||||
ethPassthroughDisable() {
|
||||
this.atcmd = 'AT+QMAP="MPDN_RULE",0';
|
||||
this.sendATCommand();
|
||||
this.fetchCurrentSettings();
|
||||
},
|
||||
|
||||
onBoardDNSProxyEnable() {
|
||||
this.atcmd = 'AT+QMAP="DHCPV4DNS","enable"';
|
||||
this.sendATCommand();
|
||||
this.fetchCurrentSettings();
|
||||
},
|
||||
|
||||
onBoardDNSProxyDisable() {
|
||||
this.atcmd = 'AT+QMAP="DHCPV4DNS","disable"';
|
||||
this.sendATCommand();
|
||||
this.fetchCurrentSettings();
|
||||
},
|
||||
|
||||
usbModeEnable() {
|
||||
this.atcmd = "AT+QMAPWAC=1";
|
||||
this.sendATCommand();
|
||||
this.fetchCurrentSettings();
|
||||
},
|
||||
|
||||
usbModeDisable() {
|
||||
this.atcmd = "AT+QMAPWAC=0";
|
||||
this.sendATCommand();
|
||||
this.fetchCurrentSettings();
|
||||
},
|
||||
|
||||
scanLTE() {
|
||||
this.atcmd = 'AT+QENG="neighbourcell"';
|
||||
this.sendATCommand();
|
||||
},
|
||||
|
||||
scanNSA() {
|
||||
this.atcmd =
|
||||
'AT+QNWCFG="nr5g_meas_info",1;+QNWCFG="nr5g_meas_info"';
|
||||
this.sendATCommand();
|
||||
},
|
||||
|
||||
fullScanMode() {
|
||||
switch (this.fullScanModeType) {
|
||||
case "LTE":
|
||||
this.atcmd = "AT+QSCAN=1,1";
|
||||
this.scanStart = true;
|
||||
this.atCommandResponse = "Scanning all available LTE networks... This might take a while."
|
||||
this.sendATCommand();
|
||||
this.scanStart = false;
|
||||
break;
|
||||
case "NR5G":
|
||||
this.atcmd = "AT+QSCAN=2,1";
|
||||
this.scanStart = true;
|
||||
this.atCommandResponse = "Scanning all available NR5G-SA networks... This might take a while."
|
||||
this.sendATCommand();
|
||||
this.scanStart = false;
|
||||
break;
|
||||
case "ALL":
|
||||
this.atcmd = "AT+QSCAN=3,1";
|
||||
this.scanStart = true;
|
||||
this.atCommandResponse = "Scanning all available networks... This might take a while."
|
||||
this.sendATCommand();
|
||||
this.scanStart = false;
|
||||
break;
|
||||
default:
|
||||
alert("Select a Scan Mode First");
|
||||
}
|
||||
},
|
||||
|
||||
fetchCurrentSettings() {
|
||||
this.fetchATCommand =
|
||||
'AT+QMAP="MPDN_RULE";+QMAP="DHCPV4DNS";+QMAPWAC?';
|
||||
fetch(
|
||||
"/cgi-bin/get_atcommand?" +
|
||||
new URLSearchParams({
|
||||
atcmd: this.fetchATCommand,
|
||||
})
|
||||
)
|
||||
.then((res) => {
|
||||
return res.text();
|
||||
})
|
||||
.then((data) => {
|
||||
// Set the value of currentSettingsResponse
|
||||
this.currentSettingsResponse = data;
|
||||
const currentData = data.split("\n");
|
||||
|
||||
const testEthpass = currentData[1].match(
|
||||
/\+QMAP: "MPDN_rule",0,0,0,0,0/
|
||||
);
|
||||
|
||||
if (testEthpass) {
|
||||
this.ethPassStatus = false;
|
||||
} else {
|
||||
this.ethPassStatus = true;
|
||||
}
|
||||
|
||||
const testDNSProxy = currentData[6].match(
|
||||
/\+QMAP: "DHCPV4DNS","enable"/
|
||||
);
|
||||
|
||||
if (testDNSProxy) {
|
||||
this.DNSProxyStatus = true;
|
||||
} else {
|
||||
this.DNSProxyStatus = false;
|
||||
}
|
||||
|
||||
const testUSBMode = currentData[8].match(/\+QMAPWAC: 1/);
|
||||
|
||||
if (testUSBMode) {
|
||||
this.USBModeStatus = true;
|
||||
} else {
|
||||
this.USBModeStatus = false;
|
||||
}
|
||||
|
||||
// clear atcmd
|
||||
this.atcmd = "";
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error("Error: ", error);
|
||||
this.showError = true;
|
||||
});
|
||||
},
|
||||
|
||||
fetchTTL() {
|
||||
fetch("/cgi-bin/get_ttl_status")
|
||||
.then((res) => res.json())
|
||||
.then((data) => {
|
||||
this.ttldata = data;
|
||||
this.ttlStatus = this.ttldata.isEnabled;
|
||||
this.ttlvalue = this.ttldata.ttl;
|
||||
});
|
||||
},
|
||||
|
||||
setTTL() {
|
||||
this.isLoading = true; // Set loading state while updating TTL
|
||||
|
||||
fetch(
|
||||
"/cgi-bin/set_ttl?" +
|
||||
new URLSearchParams({
|
||||
ttlvalue: this.newTTL,
|
||||
})
|
||||
)
|
||||
.then((res) => res.json())
|
||||
.then((data) => {
|
||||
// Once TTL is updated, fetch the updated TTL data
|
||||
this.fetchTTL();
|
||||
this.isLoading = false; // Set loading state back to false
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error("Error updating TTL: ", error);
|
||||
this.isLoading = false; // Ensure loading state is properly handled in case of error
|
||||
});
|
||||
},
|
||||
|
||||
init() {
|
||||
this.fetchTTL();
|
||||
this.fetchCurrentSettings();
|
||||
},
|
||||
};
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,295 +0,0 @@
|
||||
<!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>Simple Admin</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" />
|
||||
|
||||
<!-- Import BootStrap Javascript -->
|
||||
<script src="/js/bootstrap.bundle.min.js"></script>
|
||||
<script src="/js/alpinejs.min.js" defer></script>
|
||||
<script src="/js/auth.js"></script>
|
||||
</head>
|
||||
<body onload="isAuthenticated()">
|
||||
<main>
|
||||
<div class="container my-4" x-data="fetchSMS()">
|
||||
<nav class="navbar navbar-expand-lg mt-2">
|
||||
<div class="container-fluid">
|
||||
<a class="navbar-brand" href="/"
|
||||
><span class="mb-0 h4">Simple Admin</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 ml-4 mb-lg-0">
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="/">Home</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="/network.html">Simple Network</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="/settings.html">Simple Settings</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a
|
||||
class="nav-link active"
|
||||
href="/sms.html"
|
||||
aria-current="page"
|
||||
>SMS</a
|
||||
>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="/deviceinfo.html"
|
||||
>Device Information</a
|
||||
>
|
||||
</li>
|
||||
</ul>
|
||||
<span class="navbar-text">
|
||||
<button class="btn btn-link text-reset" id="darkModeToggle">
|
||||
Dark Mode
|
||||
</button>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<div class="row mt-5 mb-4">
|
||||
<div class="col">
|
||||
<div class="card">
|
||||
<div class="card-header">SMS Manager</div>
|
||||
<div class="card-body">
|
||||
<div class="card-text">
|
||||
<div class="col">
|
||||
<div
|
||||
style="
|
||||
max-height: 400px;
|
||||
overflow-y: scroll;
|
||||
overflow-x: hidden;
|
||||
"
|
||||
>
|
||||
<table class="table table-hover border-success">
|
||||
<tbody>
|
||||
<div class="card-subtitle" x-show="isLoading">
|
||||
<h4>Fetching SMS...</h4>
|
||||
</div>
|
||||
<!-- Only show template if isLoading is False -->
|
||||
<template x-if="messages.length === 0 && isLoading === false" >
|
||||
<div>
|
||||
<p>Message Empty</p>
|
||||
</div>
|
||||
</template>
|
||||
<template
|
||||
x-for="(message, index) in messages"
|
||||
:key="index"
|
||||
>
|
||||
<tr class="">
|
||||
<td>
|
||||
<div class="row column-gap-1 mb-2">
|
||||
<div class="col-md-3">
|
||||
<p x-text="'Sender: ' + senders[index]"></p>
|
||||
</div>
|
||||
<div class="col">
|
||||
<p
|
||||
x-text="'Date and Time: ' + dates[index]"
|
||||
></p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-9">
|
||||
<p x-text="message"></p>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</template>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<form>
|
||||
<div class="col-md-4 my-4">
|
||||
<label for="PhoneNumber" class="form-label"
|
||||
>Send SMS</label
|
||||
>
|
||||
<input
|
||||
type="text"
|
||||
class="form-control"
|
||||
placeholder="Phone Number"
|
||||
aria-label="Phone Number"
|
||||
x-model="phoneNumber"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="col-md-8 mb-3">
|
||||
<!-- Text Area Here for SMS Input -->
|
||||
<textarea
|
||||
class="form-control"
|
||||
id="smsInputBox"
|
||||
rows="5"
|
||||
placeholder="Enter SMS here (!!!CURRENTLY UNDER DEVELOPMENT!!!)"
|
||||
x-model="messageToSend"
|
||||
></textarea>
|
||||
</div>
|
||||
<div
|
||||
class="d-grid gap-2 d-md-flex justify-content-md-start"
|
||||
>
|
||||
<button class="btn btn-primary me-md-2" type="button" @click="sendSMS()" :disabled="true" >
|
||||
Send SMS
|
||||
</button>
|
||||
<button
|
||||
class="btn btn-success"
|
||||
type="button"
|
||||
@click="init()"
|
||||
>
|
||||
Refresh
|
||||
</button>
|
||||
<button
|
||||
class="btn btn-danger"
|
||||
type="button"
|
||||
@click="deleteAllSMS()"
|
||||
>
|
||||
Delete All SMS
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
<script src="/js/dark-mode.js"></script>
|
||||
<script>
|
||||
function fetchSMS() {
|
||||
return {
|
||||
isLoading: false,
|
||||
atCommandResponse: "",
|
||||
messageToSend: "",
|
||||
phoneNumber: "",
|
||||
messages: [],
|
||||
senders: [],
|
||||
dates: [],
|
||||
requestSMS() {
|
||||
this.isLoading = true;
|
||||
this.atCommandResponse = "Loading...";
|
||||
// Expect a text response from the server
|
||||
fetch("/cgi-bin/get_sms")
|
||||
.then((response) => response.text())
|
||||
.then((data) => {
|
||||
this.isLoading = false;
|
||||
this.atCommandResponse = data;
|
||||
})
|
||||
.finally(() => {
|
||||
this.parseSMSData(this.atCommandResponse);
|
||||
});
|
||||
},
|
||||
|
||||
parseSMSData(data) {
|
||||
const cmglRegex =
|
||||
/^\s*\+CMGL:\s*(\d+),"[^"]*","([^"]*)"[^"]*,"([^"]*)"/gm;
|
||||
|
||||
let match;
|
||||
while ((match = cmglRegex.exec(data)) !== null) {
|
||||
const index = parseInt(match[1]);
|
||||
const sender = match[2];
|
||||
let date = match[3];
|
||||
|
||||
// remove +32 from the date
|
||||
date = date.replace("+32", "");
|
||||
|
||||
// Find the start and end positions of the message
|
||||
const startIndex = cmglRegex.lastIndex;
|
||||
let endIndex = data.indexOf("+CMGL:", startIndex + 1);
|
||||
if (endIndex === -1) {
|
||||
// If no more +CMGL lines, set end index to end of string
|
||||
endIndex = data.length;
|
||||
}
|
||||
|
||||
// Extract the message from start to end index
|
||||
const message = data.substring(startIndex, endIndex).trim();
|
||||
|
||||
this.messages.push(message);
|
||||
this.senders.push(sender);
|
||||
this.dates.push(date);
|
||||
}
|
||||
},
|
||||
|
||||
deleteAllSMS() {
|
||||
const atcmd = "AT+CMGD=,4";
|
||||
fetch(
|
||||
"/cgi-bin/get_atcommand?" +
|
||||
new URLSearchParams({
|
||||
atcmd: atcmd,
|
||||
})
|
||||
)
|
||||
.then((response) => response.text())
|
||||
.then((data) => {
|
||||
console.log(data);
|
||||
})
|
||||
.finally(() => {
|
||||
this.requestSMS();
|
||||
});
|
||||
},
|
||||
|
||||
sendSMS() {
|
||||
this.isLoading = true;
|
||||
fetch(
|
||||
"/cgi-bin/send_sms?" +
|
||||
new URLSearchParams({
|
||||
phone_number: this.phoneNumber,
|
||||
message: this.messageToSend,
|
||||
})
|
||||
)
|
||||
.then((response) => response.text())
|
||||
.then((data) => {
|
||||
console.log(data);
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error("Error:", error);
|
||||
})
|
||||
.finally(() => {
|
||||
this.isLoading = false;
|
||||
this.requestSMS();
|
||||
});
|
||||
},
|
||||
|
||||
init() {
|
||||
// Send AT+CMGF=1 once to set the modem to text mode
|
||||
const atcmd = "AT+CMGF=1";
|
||||
fetch(
|
||||
"/cgi-bin/get_atcommand?" +
|
||||
new URLSearchParams({
|
||||
atcmd: atcmd,
|
||||
})
|
||||
)
|
||||
.then((response) => response.text())
|
||||
.then((data) => {
|
||||
console.log(data);
|
||||
})
|
||||
.finally(() => {
|
||||
this.requestSMS();
|
||||
});
|
||||
},
|
||||
};
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -16,8 +16,8 @@ fi
|
||||
MYATCMD=$(printf '%b\n' "${atcmd//%/\\x}")
|
||||
if [ -n "${MYATCMD}" ]; then
|
||||
x=$(urldecode "$atcmd")
|
||||
# Initialize wait time to 1 second
|
||||
wait_time=1000
|
||||
# Initialize wait time to 200 ms
|
||||
wait_time=200
|
||||
while true; do
|
||||
runcmd=$(echo -en "$x\r\n" | microcom -t $wait_time /dev/ttyOUT2)
|
||||
# Check if "OK" or "ERROR" is present in the response
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Check iptables for ttlvalue
|
||||
ttlvalue=$(/opt/bin/sudo /usr/sbin/iptables -w 5 -t mangle -vnL | grep TTL | awk '{print $13}' | head -n1)
|
||||
ttlvalue=$(iptables -t mangle -vnL | awk '/TTL/ {print $13; exit}')
|
||||
ttlenabled=true;
|
||||
|
||||
# Set Variables
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#!/bin/bash
|
||||
PATH=/bin:/usr/sbin:/usr/bin:/sbin:/opt/sbin:/opt/bin:/usrdata/root/bin
|
||||
|
||||
# Get query
|
||||
QUERY_STRING=$(echo "${QUERY_STRING}" | sed 's/;//g')
|
||||
|
||||
@@ -22,28 +22,28 @@ setTTL=$(printf '%b\n' "${ttlvalue//%/\\x}")
|
||||
|
||||
if [ -n "${setTTL}" ]; then
|
||||
# Stop Service To Remove Rules
|
||||
/opt/bin/sudo /usrdata/simplefirewall/ttl-override stop
|
||||
/usrdata/simplefirewall/ttl-override stop
|
||||
|
||||
# Check iptables is still set
|
||||
ttlcheck=$(/opt/bin/sudo /usr/sbin/iptables -w 5 -t mangle -vnL | grep TTL | awk '{print $13}')
|
||||
ttlcheck=$(iptables -t mangle -vnL | grep TTL | awk '{print $13}')
|
||||
|
||||
# If TTL is still set manually remove values
|
||||
if [ ! -z "${ttlcheck}" ]; then
|
||||
/opt/bin/sudo /usr/sbin/iptables -w 5 -t mangle -D POSTROUTING -o rmnet+ -j TTL --ttl-set ${ttlcheck} &>/dev/null || true
|
||||
/opt/bin/sudo /usr/sbin/ip6tables -w 5 -t mangle -D POSTROUTING -o rmnet+ -j HL --hl-set ${ttlcheck} &>/dev/null || true
|
||||
if [ !-z "${ttlcheck}" ]; then
|
||||
iptables -t mangle -D POSTROUTING -o rmnet+ -j TTL --ttl-set ${ttlcheck} &>/dev/null || true
|
||||
ip6tables -t mangle -D POSTROUTING -o rmnet+ -j HL --hl-set ${ttlcheck} &>/dev/null || true
|
||||
fi
|
||||
|
||||
# Echo TTL to file
|
||||
echo $setTTL > /usrdata/simplefirewall/ttlvalue
|
||||
|
||||
# Set Start Service
|
||||
/opt/bin/sudo /usrdata/simplefirewall/ttl-override start
|
||||
/usrdata/simplefirewall/ttl-override start
|
||||
fi
|
||||
|
||||
|
||||
|
||||
# Check iptables for ttlvalue
|
||||
ttlvalue=$(/opt/bin/sudo /usr/sbin/iptables -w 5 -t mangle -vnL | grep TTL | awk '{print $13}')
|
||||
ttlvalue=$(iptables -t mangle -vnL | grep TTL | awk '{print $13}')
|
||||
ttlenabled=true;
|
||||
|
||||
# Set Variables
|
||||
@@ -59,4 +59,3 @@ cat <<EOT
|
||||
"isEnabled": $ttlenabled,
|
||||
"ttl": $ttlvalue
|
||||
}
|
||||
EOT
|
||||
|
||||
@@ -52,17 +52,18 @@
|
||||
<a class="nav-link" href="/sms.html">SMS</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="/console">Console</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link active" href="/deviceinfo.html" aria-current="page" >Device Information</a>
|
||||
<a
|
||||
class="nav-link active"
|
||||
href="/deviceinfo.html"
|
||||
aria-current="page"
|
||||
>Device Information</a
|
||||
>
|
||||
</li>
|
||||
</ul>
|
||||
<span class="navbar-text">
|
||||
<button class="btn btn-link text-reset" id="darkModeToggle">Dark Mode</button>
|
||||
</span>
|
||||
<span class="navbar-text">
|
||||
<button class="btn btn-link" href="logout.html">Log Out</button>
|
||||
<button class="btn btn-link text-reset" id="darkModeToggle">
|
||||
Dark Mode
|
||||
</button>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -40,7 +40,9 @@
|
||||
<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="/">Home</a>
|
||||
<a class="nav-link active" aria-current="page" href="/"
|
||||
>Home</a
|
||||
>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="network.html">Simple Network</a>
|
||||
@@ -52,17 +54,15 @@
|
||||
<a class="nav-link" href="/sms.html">SMS</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="/console">Console</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="/deviceinfo.html">Device Information</a>
|
||||
<a class="nav-link" href="/deviceinfo.html"
|
||||
>Device Information</a
|
||||
>
|
||||
</li>
|
||||
</ul>
|
||||
<span class="navbar-text">
|
||||
<button class="btn btn-link text-reset" id="darkModeToggle">Dark Mode</button>
|
||||
</span>
|
||||
<span class="navbar-text">
|
||||
<button class="btn btn-link" href="logout.html">Log Out</button>
|
||||
<button class="btn btn-link text-reset" id="darkModeToggle">
|
||||
Dark Mode
|
||||
</button>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
@@ -272,7 +272,6 @@
|
||||
}
|
||||
} }"
|
||||
>
|
||||
|
||||
<div
|
||||
x-show="rsrqLTE != '-'"
|
||||
class="progress w-100"
|
||||
@@ -287,7 +286,9 @@
|
||||
:class="getProgressBarClass()"
|
||||
:style="'width: ' + rsrqLTEPercentage + '%'"
|
||||
>
|
||||
<span x-text="rsrqLTE + ' / ' + rsrqLTEPercentage + '%'"></span>
|
||||
<span
|
||||
x-text="rsrqLTE + ' / ' + rsrqLTEPercentage + '%'"
|
||||
></span>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
@@ -322,7 +323,9 @@
|
||||
:class="getProgressBarClass()"
|
||||
:style="'width: ' + rsrqNRPercentage + '%'"
|
||||
>
|
||||
<span x-text="rsrqNR + ' / ' + rsrqNRPercentage + '%'"></span>
|
||||
<span
|
||||
x-text="rsrqNR + ' / ' + rsrqNRPercentage + '%'"
|
||||
></span>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
@@ -360,7 +363,9 @@
|
||||
:class="getProgressBarClass()"
|
||||
:style="'width: ' + rsrpLTEPercentage + '%'"
|
||||
>
|
||||
<span x-text="rsrpLTE + ' / ' + rsrpLTEPercentage + '%'"></span>
|
||||
<span
|
||||
x-text="rsrpLTE + ' / ' + rsrpLTEPercentage + '%'"
|
||||
></span>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
@@ -398,7 +403,9 @@
|
||||
:class="getProgressBarClass()"
|
||||
:style="'width: ' + rsrpNRPercentage + '%'"
|
||||
>
|
||||
<span x-text="rsrpNR + ' / ' + rsrpNRPercentage + '%'"></span>
|
||||
<span
|
||||
x-text="rsrpNR + ' / ' + rsrpNRPercentage + '%'"
|
||||
></span>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
@@ -436,7 +443,9 @@
|
||||
:class="getProgressBarClass()"
|
||||
:style="'width: ' + sinrLTEPercentage +'%'"
|
||||
>
|
||||
<span x-text="sinrLTE + ' / ' + sinrLTEPercentage +'%'"></span>
|
||||
<span
|
||||
x-text="sinrLTE + ' / ' + sinrLTEPercentage +'%'"
|
||||
></span>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
@@ -474,7 +483,9 @@
|
||||
:class="getProgressBarClass()"
|
||||
:style="'width: ' + sinrNRPercentage +'%'"
|
||||
>
|
||||
<span x-text="sinrNR + ' / ' + sinrNRPercentage +'%'"></span>
|
||||
<span
|
||||
x-text="sinrNR + ' / ' + sinrNRPercentage +'%'"
|
||||
></span>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
@@ -543,7 +554,7 @@
|
||||
internetConnection: "Disconnected",
|
||||
lastUpdate: new Date().toLocaleString(),
|
||||
newRefreshRate: null,
|
||||
refreshRate: 3,
|
||||
refreshRate: 30,
|
||||
intervalId: null,
|
||||
fetchNetworkInfo() {
|
||||
this.atcmd =
|
||||
@@ -607,21 +618,43 @@
|
||||
if (networkMode1 === '"NR5G-SA"') {
|
||||
this.network_mode = networkMode1;
|
||||
this.network_mode = this.network_mode.replace(/"/g, "");
|
||||
} else {
|
||||
}
|
||||
|
||||
else {
|
||||
let networkMode2, networkMode3;
|
||||
|
||||
networkMode2 = lines[28].split(":")[1].replace(/"/g, "");
|
||||
networkMode2 = networkMode2.split(",")[0];
|
||||
|
||||
if (
|
||||
lines[29] !== undefined &&
|
||||
lines[29] !== "OK" &&
|
||||
lines[29] !== ""
|
||||
lines[27] !== undefined &&
|
||||
lines[27] !== "OK" &&
|
||||
lines[27] !== "" &&
|
||||
lines[27] !== "/r"
|
||||
) {
|
||||
networkMode3 = lines[29].split(":")[1].replace(/"/g, "");
|
||||
networkMode3 = networkMode3.split(",")[0];
|
||||
// Check if lines[27] doesnt have TDD or FDD
|
||||
if (lines[27].match(/FDD/) != null || lines[27].match(/TDD/) != null) {
|
||||
networkMode2 = lines[27].split(",")[2].replace(/"/g, "");
|
||||
networkMode2 = networkMode2.split(",")[0].trim();
|
||||
console.log(networkMode2);
|
||||
}
|
||||
|
||||
if (networkMode2 !== "LTE") {
|
||||
networkMode2 = lines[28].split(":")[1].replace(/"/g, "");
|
||||
networkMode2 = networkMode2.split(",")[0];
|
||||
|
||||
if (
|
||||
lines[29] !== undefined &&
|
||||
lines[29] !== "OK" &&
|
||||
lines[29] !== ""
|
||||
) {
|
||||
networkMode3 = lines[29]
|
||||
.split(":")[1]
|
||||
.split(",")[0]
|
||||
.replace(/"/g, "");
|
||||
networkMode3 = networkMode3.split(",")[0];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
console.log(networkMode2, networkMode3);
|
||||
// Check if networkMode3 is not empty
|
||||
if (networkMode3 !== undefined) {
|
||||
this.network_mode = networkMode2 + ", " + networkMode3;
|
||||
@@ -871,6 +904,9 @@
|
||||
this.signalPercentage =
|
||||
(this.signalPercentage + nrSignalPercentage) / 2;
|
||||
|
||||
// Round the signalPercentage value
|
||||
this.signalPercentage = Math.round(this.signalPercentage);
|
||||
|
||||
// Get the Signal Assessment
|
||||
this.signalAssessment = this.signalQuality(
|
||||
this.signalPercentage
|
||||
@@ -998,8 +1034,9 @@
|
||||
const rawdata = data;
|
||||
|
||||
const lines = rawdata.split("\n");
|
||||
console.log("CSQ: ", lines);
|
||||
|
||||
this.csq = lines[0].split(":")[1].split(",")[0].trim();
|
||||
this.csq = lines[1].split(":")[1].split(",")[0].trim();
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -1031,11 +1068,22 @@
|
||||
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() {
|
||||
// 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)
|
||||
: 5; // Change 5 to your desired default value
|
||||
|
||||
this.fetchNetworkInfo();
|
||||
// sleep for 2 seconds
|
||||
setTimeout(() => {
|
||||
@@ -1044,7 +1092,8 @@
|
||||
|
||||
this.requestPing()
|
||||
.then((data) => {
|
||||
const response = data.trim(); // Trim any leading/trailing spaces
|
||||
const response = data.trim();
|
||||
// Trim any leading/trailing spaces
|
||||
if (response === "OK") {
|
||||
this.internetConnection = "Connected";
|
||||
} else {
|
||||
@@ -1069,7 +1118,8 @@
|
||||
|
||||
this.requestPing()
|
||||
.then((data) => {
|
||||
const response = data.trim(); // Trim any leading/trailing spaces
|
||||
const response = data.trim();
|
||||
// Trim any leading/trailing spaces
|
||||
if (response === "OK") {
|
||||
this.internetConnection = "Connected";
|
||||
} else {
|
||||
@@ -1082,7 +1132,6 @@
|
||||
});
|
||||
|
||||
this.lastUpdate = new Date().toLocaleString();
|
||||
|
||||
console.log("Refreshed");
|
||||
}, this.refreshRate * 1000);
|
||||
},
|
||||
|
||||
@@ -15,15 +15,17 @@ function parseCurrentSettings(rawdata) {
|
||||
|
||||
let bands = [];
|
||||
|
||||
// Append the values if there is separated by comma
|
||||
// Append the values if there is separated by comma with a space.
|
||||
// i.e. LTE BAND 3, LTE BAND 1
|
||||
for (let i = 13; i < 17; i++) {
|
||||
if (lines[i].split(",").length > 1) {
|
||||
bands.push(lines[i].split(",")[3].replace(/\"/g, ""));
|
||||
bands.push(lines[i].split(",")[3].replace(/\"/g, " "));
|
||||
}
|
||||
}
|
||||
|
||||
this.bands = bands;
|
||||
|
||||
|
||||
if (this.cellLock4GStatus == 1 && this.cellLock5GStatus == 1) {
|
||||
this.cellLockStatus = "Locked to 4G and 5G";
|
||||
} else if (this.cellLock4GStatus == 1) {
|
||||
|
||||
@@ -43,7 +43,12 @@
|
||||
<a class="nav-link" href="/">Home</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link active" href="network.html" aria-current="page">Simple Network</a>
|
||||
<a
|
||||
class="nav-link active"
|
||||
href="network.html"
|
||||
aria-current="page"
|
||||
>Simple Network</a
|
||||
>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="/settings.html">Simple Settings</a>
|
||||
@@ -52,17 +57,15 @@
|
||||
<a class="nav-link" href="/sms.html">SMS</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="/console">Console</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="deviceinfo.html">Device Information</a>
|
||||
<a class="nav-link" href="deviceinfo.html"
|
||||
>Device Information</a
|
||||
>
|
||||
</li>
|
||||
</ul>
|
||||
<span class="navbar-text">
|
||||
<button class="btn btn-link text-reset" id="darkModeToggle">Dark Mode</button>
|
||||
</span>
|
||||
<span class="navbar-text">
|
||||
<button class="btn btn-link" href="logout.html">Log Out</button>
|
||||
<button class="btn btn-link text-reset" id="darkModeToggle">
|
||||
Dark Mode
|
||||
</button>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
@@ -552,7 +555,7 @@
|
||||
updatedLockedBands: null,
|
||||
sim: "-",
|
||||
newSim: null,
|
||||
cellLockStatus: null,
|
||||
cellLockStatus: "Unknown",
|
||||
bands: "Fetching Bands...",
|
||||
init() {
|
||||
// Function to populate checkboxes
|
||||
|
||||
@@ -39,14 +39,16 @@
|
||||
<a class="nav-link" href="/network.html">Simple Network</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link active" href="/settings.html" aria-current="page">Simple Settings</a>
|
||||
<a
|
||||
class="nav-link active"
|
||||
href="/settings.html"
|
||||
aria-current="page"
|
||||
>Simple Settings</a
|
||||
>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="/sms.html">SMS</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="/console">Console</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="/deviceinfo.html"
|
||||
>Device Information</a
|
||||
@@ -54,10 +56,9 @@
|
||||
</li>
|
||||
</ul>
|
||||
<span class="navbar-text">
|
||||
<button class="btn btn-link text-reset" id="darkModeToggle">Dark Mode</button>
|
||||
</span>
|
||||
<span class="navbar-text">
|
||||
<button class="btn btn-link" href="logout.html">Log Out</button>
|
||||
<button class="btn btn-link text-reset" id="darkModeToggle">
|
||||
Dark Mode
|
||||
</button>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -50,10 +50,12 @@
|
||||
<a class="nav-link" href="/settings.html">Simple Settings</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link active" href="/sms.html" aria-current="page">SMS</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="/console">Console</a>
|
||||
<a
|
||||
class="nav-link active"
|
||||
href="/sms.html"
|
||||
aria-current="page"
|
||||
>SMS</a
|
||||
>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="/deviceinfo.html"
|
||||
@@ -62,10 +64,9 @@
|
||||
</li>
|
||||
</ul>
|
||||
<span class="navbar-text">
|
||||
<button class="btn btn-link text-reset" id="darkModeToggle">Dark Mode</button>
|
||||
</span>
|
||||
<span class="navbar-text">
|
||||
<button class="btn btn-link" href="logout.html">Log Out</button>
|
||||
<button class="btn btn-link text-reset" id="darkModeToggle">
|
||||
Dark Mode
|
||||
</button>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user