Merge pull request #57 from dr-dolomite/development-socat
Added Changes for Version 0.9
This commit is contained in:
@@ -1,20 +1,12 @@
|
|||||||
#!/bin/bash
|
#!/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_FORMAT="AT+CMGF=1"
|
||||||
SMS_LIST="AT+CMGL=\"ALL\""
|
SMS_LIST="AT+CMGL=\"ALL\""
|
||||||
|
send_at_command() {
|
||||||
|
local command="$1"
|
||||||
|
echo -en "$command\r\n" | microcom -t 2000 /dev/ttyOUT2
|
||||||
|
}
|
||||||
|
send_at_command "$SMS_FORMAT"
|
||||||
|
runcmd=$(send_at_command "$SMS_LIST")
|
||||||
|
|
||||||
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 "Content-type: text/plain"
|
||||||
echo ""
|
echo "$runcmd"
|
||||||
echo $runcmd
|
|
||||||
18
simpleadmin/www/cgi-bin/get_watchcat_status
Normal file
18
simpleadmin/www/cgi-bin/get_watchcat_status
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Content type header
|
||||||
|
echo "Content-type: application/json"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# This script fetches the watchCat parameters from the /tmp/watchCatParams.json file and returns it as JSON
|
||||||
|
|
||||||
|
# Check if the file exists
|
||||||
|
if [ -f /tmp/watchCatParams.json ]; then
|
||||||
|
# Read the file and return the content
|
||||||
|
cat /tmp/watchCatParams.json
|
||||||
|
else
|
||||||
|
# Return an empty JSON object
|
||||||
|
echo "{}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
exit 0
|
||||||
@@ -1,44 +1,54 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
QUERY_STRING=$(echo "${QUERY_STRING}" | sed 's/;//g')
|
QUERY_STRING=$(echo "${QUERY_STRING}" | sed 's/;//g')
|
||||||
function urldecode() { : "${*//+/ }"; echo -e "${_//%/\\x}"; }
|
urldecode() {
|
||||||
|
local data
|
||||||
|
data="${*//+/ }"
|
||||||
|
echo -e "${data//%/\\x}"
|
||||||
|
}
|
||||||
|
|
||||||
if [ "${QUERY_STRING}" ]; then
|
if [ "${QUERY_STRING}" ]; then
|
||||||
export IFS="&"
|
export IFS="&"
|
||||||
for cmd in ${QUERY_STRING}; do
|
for cmd in ${QUERY_STRING}; do
|
||||||
if [ "$(echo $cmd | grep '=')" ]; then
|
if [[ "$cmd" == *=* ]]; then
|
||||||
key=$(echo $cmd | awk -F '=' '{print $1}')
|
key=$(echo "$cmd" | awk -F '=' '{print $1}')
|
||||||
value=$(echo $cmd | awk -F '=' '{print $2}')
|
value=$(echo "$cmd" | awk -F '=' '{print $2}')
|
||||||
eval $key=$value
|
eval "$key"="$(urldecode "$value")"
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Extract phone number and message from inputs
|
|
||||||
phone_number="$number"
|
phone_number="$number"
|
||||||
message="$msg"
|
message_encoded="$msg"
|
||||||
|
|
||||||
# Prepare AT command with phone number and message
|
phone_number="+86$phone_number"
|
||||||
ATCMD="AT+CMGS=\"$phone_number\""
|
|
||||||
|
|
||||||
MYATCMD=$(printf '%b\n' "${ATCMD//%/\\x}")
|
send_at_command() {
|
||||||
if [ -n "${MYATCMD}" ]; then
|
local cmd=$1
|
||||||
x=$(urldecode "$ATCMD")
|
echo "Sending command: $cmd" >&2
|
||||||
# Send the AT command to initiate message sending
|
echo -en "$cmd\r" | microcom -t 1000 /dev/ttyOUT2
|
||||||
echo -en "$x\r\n" | microcom /dev/ttyOUT2
|
sleep 2
|
||||||
# Wait for a brief moment (assuming the message sending is instantaneous)
|
local response=$(microcom -t 1000 /dev/ttyOUT2)
|
||||||
sleep 1
|
echo "Response: $response" >&2
|
||||||
fi
|
echo "$response"
|
||||||
|
}
|
||||||
|
|
||||||
# Send the message
|
send_at_command "AT+CMGF=1"
|
||||||
echo -en "$message\c"
|
send_at_command "AT+CSCS=\"UCS2\""
|
||||||
|
|
||||||
# Send Ctrl+Z to terminate the message
|
encode_ucs2() {
|
||||||
echo -en "\032"
|
local input="$1"
|
||||||
|
local output=""
|
||||||
|
local i
|
||||||
|
for ((i=0; i<${#input}; i++)); do
|
||||||
|
hex=$(printf "%04X" "'${input:$i:1}")
|
||||||
|
output="$output$hex"
|
||||||
|
done
|
||||||
|
echo "$output"
|
||||||
|
}
|
||||||
|
|
||||||
# Ensure microcom reads the response (assuming microcom will show response instantly)
|
phone_number_ucs2=$(encode_ucs2 "$phone_number")
|
||||||
sleep 1
|
ATCMD="AT+CMGS=\"$phone_number_ucs2\""
|
||||||
|
send_at_command "$ATCMD"
|
||||||
|
|
||||||
# Capture and output the response
|
runcmd=$((echo -en "$message_encoded"; sleep 1; echo -en "\x1A") | microcom -t 1000 /dev/ttyOUT2)
|
||||||
runcmd=$(microcom /dev/ttyOUT2)
|
|
||||||
echo "Content-type: text/plain"
|
|
||||||
echo "$runcmd"
|
echo "$runcmd"
|
||||||
125
simpleadmin/www/cgi-bin/set_watchcat
Normal file
125
simpleadmin/www/cgi-bin/set_watchcat
Normal file
@@ -0,0 +1,125 @@
|
|||||||
|
#!/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 [[ "$cmd" == *"="* ]]; then
|
||||||
|
key=$(echo $cmd | awk -F '=' '{print $1}')
|
||||||
|
value=$(echo $cmd | awk -F '=' '{print $2}')
|
||||||
|
eval $key=$(urldecode $value)
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -z "$status" ] || [ -z "$IpDNS" ] || [ -z "$cooldown" ] || [ -z "$failures" ] || [ -z "$action" ]; then
|
||||||
|
response="Missing parameters. Please provide the following parameters: IpDNS, cooldown, failures, action."
|
||||||
|
echo "Content-type: text/plain"
|
||||||
|
echo ""
|
||||||
|
echo "$response"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "$status" == "enabled" ]; then
|
||||||
|
watch_script="/usrdata/simpleadmin/script/watchat.sh"
|
||||||
|
mount -o remount,rw /
|
||||||
|
|
||||||
|
cat <<EOF > $watch_script
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
ip_or_dns="$IpDNS"
|
||||||
|
cooldown=$cooldown
|
||||||
|
action="$action"
|
||||||
|
fail_count=0
|
||||||
|
max_failures=$failures
|
||||||
|
|
||||||
|
# Process the action variable.
|
||||||
|
|
||||||
|
# Create a JSON file containing the parameters of the script
|
||||||
|
echo -n '{"ip_or_dns":"$ip_or_dns","cooldown":$cooldown,"action":"$action","fail_count":$fail_count,"max_failures":$max_failures}' > /tmp/watchatParams.json
|
||||||
|
|
||||||
|
|
||||||
|
while true; do
|
||||||
|
if ping -c 1 -W 1 \$ip_or_dns > /dev/null; then
|
||||||
|
fail_count=0
|
||||||
|
echo "Success at \$(date)" >> /tmp/watchat.log
|
||||||
|
# Convert /tmp/watchat.log to json format
|
||||||
|
echo -n '{"log":[' > /tmp/watchat.json
|
||||||
|
cat /tmp/watchat.log | sed 's/$/,/' | tr -d '\n' | sed 's/,$//' >> /tmp/watchat.json
|
||||||
|
echo -n ']}' >> /tmp/watchat.json
|
||||||
|
else
|
||||||
|
((fail_count++))
|
||||||
|
if [ \$fail_count -ge \$max_failures ]; then
|
||||||
|
case "\$action" in
|
||||||
|
reboot)
|
||||||
|
echo "Rebooting system..."
|
||||||
|
/sbin/reboot
|
||||||
|
;;
|
||||||
|
switch_sim)
|
||||||
|
echo "Switching SIM..."
|
||||||
|
echo -ne "AT+CNMI=2,1\r" > /dev/ttyOUT2
|
||||||
|
sleep 1
|
||||||
|
echo "Switching SIM at \$(date)" >> /tmp/watchat.log
|
||||||
|
;;
|
||||||
|
none)
|
||||||
|
echo "No action taken."
|
||||||
|
echo "No action taken at \$(date)" >> /tmp/watchat.log
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "Unknown action: \$action"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
# Reset fail count
|
||||||
|
fail_count=0
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
echo "Fail count: \$fail_count at \$(date)" >> /tmp/watchat.log
|
||||||
|
# Convert /tmp/watchat.log to json format
|
||||||
|
echo -n '{"log":[' > /tmp/watchat.json
|
||||||
|
cat /tmp/watchat.log | sed 's/$/,/' | tr -d '\n' | sed 's/,$//' >> /tmp/watchat.json
|
||||||
|
echo -n ']}' >> /tmp/watchat.json
|
||||||
|
sleep \$cooldown
|
||||||
|
done
|
||||||
|
EOF
|
||||||
|
|
||||||
|
chmod +x $watch_script
|
||||||
|
|
||||||
|
cat <<EOF > /lib/systemd/system/watchcat.service
|
||||||
|
[Unit]
|
||||||
|
Description=Ping Watcher Service
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
ExecStart=$watch_script
|
||||||
|
Restart=always
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
||||||
|
EOF
|
||||||
|
|
||||||
|
ln -s /lib/systemd/system/watchcat.service /etc/systemd/system/multi-user.target.wants/watchcat.service
|
||||||
|
|
||||||
|
systemctl daemon-reload
|
||||||
|
systemctl start watchcat.service
|
||||||
|
|
||||||
|
response="Script created at $watch_script and made executable. Service created and started."
|
||||||
|
|
||||||
|
elif [ "$status" == "disabled" ]; then
|
||||||
|
watch_script="/usrdata/simpleadmin/script/watchat.sh"
|
||||||
|
rm -f $watch_script
|
||||||
|
|
||||||
|
systemctl stop watchcat.service
|
||||||
|
rm -f /lib/systemd/system/watchcat.service
|
||||||
|
rm -f /etc/systemd/system/multi-user.target.wants/watchcat.service
|
||||||
|
|
||||||
|
systemctl daemon-reload
|
||||||
|
|
||||||
|
response="Script removed at $watch_script. Service stopped and removed."
|
||||||
|
else
|
||||||
|
response="Invalid status. Please provide either enabled or disabled."
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Content-type: text/plain"
|
||||||
|
echo ""
|
||||||
|
echo "$response"
|
||||||
@@ -139,7 +139,99 @@
|
|||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<th scope="row">Simple Admin Version</th>
|
<th scope="row">Simple Admin Version</th>
|
||||||
<td class="col-md-2">SimpleAdminRev-Alpha-0.8</td>
|
<td class="col-md-2">SimpleAdminRev-Alpha-0.9</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th>Project Contributors</th>
|
||||||
|
<td>
|
||||||
|
<!-- Button trigger modal -->
|
||||||
|
<p type="button" class="link-info link-opacity-50-hover link-offset-2" data-bs-toggle="modal" data-bs-target="#staticBackdrop">
|
||||||
|
Show Contributors
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<!-- Modal -->
|
||||||
|
<div class="modal fade" id="staticBackdrop" data-bs-backdrop="static" data-bs-keyboard="false" tabindex="-1" aria-labelledby="staticBackdropLabel" aria-hidden="true">
|
||||||
|
<div class="modal-dialog modal-dialog-centered">
|
||||||
|
<div class="modal-content">
|
||||||
|
<div class="modal-header">
|
||||||
|
<h1 class="modal-title fs-5" id="staticBackdropLabel">Contributors</h1>
|
||||||
|
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||||
|
</div>
|
||||||
|
<div class="modal-body">
|
||||||
|
<table>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<th>
|
||||||
|
RGMII Toolkit and Documentation
|
||||||
|
</th>
|
||||||
|
<td class="col-md-2">
|
||||||
|
<a href="https://github.com/iamromulan" target="_blank">iamromulan</a>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
<th>
|
||||||
|
Simple Admin 2.0
|
||||||
|
</th>
|
||||||
|
<td class="col-md-2">
|
||||||
|
<a href="https://github.com/dr-dolomite" target="_blank">dr-dolomite</a>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
<th>
|
||||||
|
SMS Feature
|
||||||
|
</th>
|
||||||
|
<td class="col-md-2">
|
||||||
|
<a href="https://github.com/snjzb" target="_blank">snjzb</a>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
<th>
|
||||||
|
Original Simple Admin
|
||||||
|
</th>
|
||||||
|
<td class="col-md-2">
|
||||||
|
<a href="https://github.com/aesthernr" target="_blank">aesthernr</a>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
<th>
|
||||||
|
Original Socat Bridge
|
||||||
|
</th>
|
||||||
|
<td class="col-md-2">
|
||||||
|
<a href="https://github.com/natecarlson" target="_blank">natecarlson</a>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
<th>
|
||||||
|
Original Simple Admin Fixes
|
||||||
|
</th>
|
||||||
|
<td class="col-md-2">
|
||||||
|
<a href="https://github.com/rbflurry/" target="_blank">rbflurry</a>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
<th>
|
||||||
|
SA Parsing Patch
|
||||||
|
</th>
|
||||||
|
<td class="col-md-2">
|
||||||
|
<a href="https://github.com/tarunVreddy" target="_blank">tarunVreddy</a>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
<div class="modal-footer">
|
||||||
|
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
|||||||
@@ -315,17 +315,18 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="card-text">
|
<div class="card-text">
|
||||||
<label class="form-label">Cell Scanner</label>
|
<div class="d-flex flex-row gap-4 w-full">
|
||||||
<div class="d-grid gap-1 w-full">
|
|
||||||
<!-- -->
|
<!-- -->
|
||||||
<a
|
<!-- <a
|
||||||
class="btn btn-warning"
|
class="btn btn-warning"
|
||||||
type="button"
|
type="button"
|
||||||
href="/scanner.html"
|
href="/scanner.html"
|
||||||
role="button"
|
role="button"
|
||||||
>
|
>
|
||||||
Go to Cell Scanner
|
Go to Cell Scanner
|
||||||
</a>
|
</a> -->
|
||||||
|
<p><a class="link-info link-opacity-50-hover link-offset-2" href="/scanner.html">Go to Cell Scanner</a></p>
|
||||||
|
<p><a class="link-info link-opacity-50-hover link-offset-2" href="/watchcat.html">Go to WatchCat</a></p>
|
||||||
<!-- </a> -->
|
<!-- </a> -->
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -525,30 +526,23 @@
|
|||||||
if (this.usbNetMode != "Unspecified") {
|
if (this.usbNetMode != "Unspecified") {
|
||||||
if (this.usbNetMode == "RMNET") {
|
if (this.usbNetMode == "RMNET") {
|
||||||
this.atcmd = 'AT+QCFG="usbnet",0;';
|
this.atcmd = 'AT+QCFG="usbnet",0;';
|
||||||
this.sendATCommand().then(() => {
|
this.sendATCommand();
|
||||||
this.rebootDevice();
|
|
||||||
});
|
|
||||||
} else if (this.usbNetMode == "ECM") {
|
} else if (this.usbNetMode == "ECM") {
|
||||||
this.atcmd = 'AT+QCFG="usbnet",1;';
|
this.atcmd = 'AT+QCFG="usbnet",1;';
|
||||||
this.sendATCommand().then(() => {
|
this.sendATCommand();
|
||||||
this.rebootDevice();
|
|
||||||
});
|
|
||||||
} else if (this.usbNetMode == "MBIM") {
|
} else if (this.usbNetMode == "MBIM") {
|
||||||
this.atcmd = 'AT+QCFG="usbnet",2;';
|
this.atcmd = 'AT+QCFG="usbnet",2;';
|
||||||
this.sendATCommand().then(() => {
|
this.sendATCommand();
|
||||||
this.rebootDevice();
|
|
||||||
});
|
|
||||||
} else if (this.usbNetMode == "RNDIS") {
|
} else if (this.usbNetMode == "RNDIS") {
|
||||||
this.atcmd = 'AT+QCFG="usbnet",3;';
|
this.atcmd = 'AT+QCFG="usbnet",3;';
|
||||||
this.sendATCommand().then(() => {
|
this.sendATCommand();
|
||||||
this.rebootDevice();
|
|
||||||
});
|
|
||||||
} else {
|
} else {
|
||||||
console.log("USB Net Mode Invalid");
|
console.log("USB Net Mode Invalid");
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
console.error("USB Net Mode not specified");
|
console.error("USB Net Mode not specified");
|
||||||
}
|
}
|
||||||
|
this.rebootDevice();
|
||||||
},
|
},
|
||||||
|
|
||||||
fetchCurrentSettings() {
|
fetchCurrentSettings() {
|
||||||
|
|||||||
@@ -1,302 +1,422 @@
|
|||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="en" data-bs-theme="light">
|
<html lang="zh-CN" data-bs-theme="light">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8" />
|
<meta charset="utf-8" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||||
<title>Simple Admin</title>
|
<title>Simple Admin</title>
|
||||||
<!-- <link
|
<!-- 导入自定义和Bootstrap样式 -->
|
||||||
href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css"
|
<link rel="stylesheet" href="css/styles.css" />
|
||||||
rel="stylesheet"
|
<link rel="stylesheet" href="css/bootstrap.min.css" />
|
||||||
integrity="sha384-QWTKZyjpPEjISv5WaRU9OFeRpok6YctnYmDr5pNlyT2bRjXh0JMhjY6hW+ALEwIH"
|
<!-- 网站图标 -->
|
||||||
crossorigin="anonymous"
|
<link rel="icon" href="favicon.ico" />
|
||||||
/> -->
|
<!-- 导入Bootstrap和Alpine.js脚本 -->
|
||||||
<!-- Import all the bootstrap css files from css folder -->
|
<script src="js/bootstrap.bundle.min.js"></script>
|
||||||
<link rel="stylesheet" href="css/styles.css" />
|
<script src="js/alpinejs.min.js" defer></script>
|
||||||
<link rel="stylesheet" href="css/bootstrap.min.css" />
|
|
||||||
|
|
||||||
<!-- Logo -->
|
<!-- Contributed By: snjzb -->
|
||||||
<link rel="simpleadmin-logo" href="favicon.ico">
|
</head>
|
||||||
|
|
||||||
<!-- Import BootStrap Javascript -->
|
<body>
|
||||||
<script src="js/bootstrap.bundle.min.js"></script>
|
<main>
|
||||||
<script src="js/alpinejs.min.js" defer></script>
|
<div class="container my-4" x-data="fetchSMS()">
|
||||||
<script src="js/auth.js"></script>
|
<nav class="navbar navbar-expand-lg mt-2">
|
||||||
</head>
|
<div class="container-fluid">
|
||||||
<body onload="isAuthenticated()">
|
<a class="navbar-brand" href="/"
|
||||||
<main>
|
><span class="mb-0 h4">Simple Admin</span></a
|
||||||
<div class="container my-4" x-data="fetchSMS()">
|
>
|
||||||
<nav class="navbar navbar-expand-lg mt-2">
|
<button
|
||||||
<div class="container-fluid">
|
class="navbar-toggler"
|
||||||
<a class="navbar-brand" href="/"
|
type="button"
|
||||||
><span class="mb-0 h4">Simple Admin</span></a
|
data-bs-toggle="collapse"
|
||||||
>
|
data-bs-target="#navbarText"
|
||||||
<button
|
aria-controls="navbarText"
|
||||||
class="navbar-toggler"
|
aria-expanded="false"
|
||||||
type="button"
|
aria-label="切换导航"
|
||||||
data-bs-toggle="collapse"
|
>
|
||||||
data-bs-target="#navbarText"
|
<span class="navbar-toggler-icon"></span>
|
||||||
aria-controls="navbarText"
|
</button>
|
||||||
aria-expanded="false"
|
<div class="collapse navbar-collapse" id="navbarText">
|
||||||
aria-label="Toggle navigation"
|
<ul class="navbar-nav me-auto mb-2 ml-4 mb-lg-0">
|
||||||
>
|
<li class="nav-item">
|
||||||
<span class="navbar-toggler-icon"></span>
|
<a class="nav-link" href="/">Home</a>
|
||||||
</button>
|
</li>
|
||||||
<div class="collapse navbar-collapse" id="navbarText">
|
<li class="nav-item">
|
||||||
<ul class="navbar-nav me-auto mb-2 ml-4 mb-lg-0">
|
<a class="nav-link" href="/network.html">Simple Network</a>
|
||||||
<li class="nav-item">
|
</li>
|
||||||
<a class="nav-link" href="/">Home</a>
|
<li class="nav-item">
|
||||||
</li>
|
<a class="nav-link" href="/settings.html">Simple Settings</a>
|
||||||
<li class="nav-item">
|
</li>
|
||||||
<a class="nav-link" href="/network.html">Simple Network</a>
|
<li class="nav-item">
|
||||||
</li>
|
<a
|
||||||
<li class="nav-item">
|
class="nav-link active"
|
||||||
<a class="nav-link" href="/settings.html">Simple Settings</a>
|
aria-current="page"
|
||||||
</li>
|
href="/sms.html"
|
||||||
<li class="nav-item">
|
>SMS</a
|
||||||
<a
|
>
|
||||||
class="nav-link active"
|
</li>
|
||||||
href="/sms.html"
|
<li class="nav-item">
|
||||||
aria-current="page"
|
<a class="nav-link" href="/console">Console</a>
|
||||||
>SMS</a
|
</li>
|
||||||
>
|
<li class="nav-item">
|
||||||
</li>
|
<a class="nav-link" href="/deviceinfo.html"
|
||||||
<li class="nav-item">
|
>Device Information</a
|
||||||
<a class="nav-link" href="/console">Console</a>
|
>
|
||||||
</li>
|
</li>
|
||||||
<li class="nav-item">
|
</ul>
|
||||||
<a class="nav-link" href="/deviceinfo.html"
|
<span class="navbar-text">
|
||||||
>Device Information</a
|
<button class="btn btn-link text-reset" id="darkModeToggle">
|
||||||
>
|
Dark Mode
|
||||||
</li>
|
</button>
|
||||||
</ul>
|
</span>
|
||||||
<span class="navbar-text">
|
</div>
|
||||||
<button class="btn btn-link text-reset" id="darkModeToggle">
|
</div>
|
||||||
Dark Mode
|
</nav>
|
||||||
</button>
|
<div class="row mt-5 mb-4">
|
||||||
</span>
|
<div class="col">
|
||||||
</div>
|
<div class="card">
|
||||||
</div>
|
<div class="card-header">SMS Inbox</div>
|
||||||
</nav>
|
<div class="card-body">
|
||||||
<div class="row mt-5 mb-4">
|
<div class="card-text">
|
||||||
<div class="col">
|
<div class="col">
|
||||||
<div class="card">
|
<div
|
||||||
<div class="card-header">SMS Manager</div>
|
style="
|
||||||
<div class="card-body">
|
max-height: 400px;
|
||||||
<div class="card-text">
|
overflow-y: scroll;
|
||||||
<div class="col">
|
overflow-x: hidden;
|
||||||
<div
|
"
|
||||||
style="
|
>
|
||||||
max-height: 400px;
|
<div x-show="isLoading">
|
||||||
overflow-y: scroll;
|
<h4>Fetching SMS...</h4>
|
||||||
overflow-x: hidden;
|
</div>
|
||||||
"
|
<table
|
||||||
>
|
class="table table-hover border-success"
|
||||||
<table class="table table-hover border-success">
|
x-show="!isLoading"
|
||||||
<tbody>
|
>
|
||||||
<div class="card-subtitle" x-show="isLoading">
|
<tbody>
|
||||||
<h4>Fetching SMS...</h4>
|
<!-- 没有消息时显示 -->
|
||||||
</div>
|
<!-- Display when there are no messages -->
|
||||||
<!-- Only show template if isLoading is False -->
|
<template x-if="messages.length === 0 && !isLoading">
|
||||||
<template x-if="messages.length === 0 && isLoading === false" >
|
<div>
|
||||||
<div>
|
<p>Inbox is Empty</p>
|
||||||
<p>Message Empty</p>
|
</div>
|
||||||
</div>
|
</template>
|
||||||
</template>
|
<!-- 循环显示短信消息 -->
|
||||||
<template
|
<!-- "Loop display SMS messages" -->
|
||||||
x-for="(message, index) in messages"
|
<template
|
||||||
:key="index"
|
x-for="(message, index) in messages"
|
||||||
>
|
:key="index"
|
||||||
<tr class="">
|
>
|
||||||
<td>
|
<tr>
|
||||||
<div class="row column-gap-1 mb-2">
|
<td>
|
||||||
<div class="col-md-3">
|
<div class="form-check">
|
||||||
<p x-text="'Sender: ' + senders[index]"></p>
|
<input
|
||||||
</div>
|
class="form-check-input"
|
||||||
<div class="col">
|
type="checkbox"
|
||||||
<p
|
:value="index"
|
||||||
x-text="'Date and Time: ' + dates[index]"
|
x-model="selectedMessages"
|
||||||
></p>
|
/>
|
||||||
</div>
|
<div class="row column-gap-1 mb-2">
|
||||||
</div>
|
<div class="col-md-3">
|
||||||
<div class="col-md-9">
|
<p
|
||||||
<p x-text="message"></p>
|
x-text="'Sender: ' + senders[index]"
|
||||||
</div>
|
></p>
|
||||||
</td>
|
</div>
|
||||||
</tr>
|
<div class="col">
|
||||||
</template>
|
<p
|
||||||
</tbody>
|
x-text="'Date and Time: ' + dates[index]"
|
||||||
</table>
|
></p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<form>
|
<div class="col-md-9">
|
||||||
<!-- <div class="col-md-4 my-4">
|
<p x-text="message"></p>
|
||||||
<label for="PhoneNumber" class="form-label"
|
</div>
|
||||||
>Send SMS</label
|
</div>
|
||||||
>
|
</td>
|
||||||
<input
|
</tr>
|
||||||
type="text"
|
</template>
|
||||||
class="form-control"
|
</tbody>
|
||||||
placeholder="Phone Number"
|
</table>
|
||||||
aria-label="Phone Number"
|
</div>
|
||||||
x-model="phoneNumber"
|
</div>
|
||||||
/>
|
</div>
|
||||||
</div> -->
|
</div>
|
||||||
|
<!-- 添加判断,只有当messages数组有内容时才显示全选复选框及其区域 -->
|
||||||
|
<!-- Add a judgment, only when the messages array has content will the select all checkbox and its area be displayed" -->
|
||||||
|
<div class="card-body border-top" x-show="messages.length > 0">
|
||||||
|
<div class="form-check">
|
||||||
|
<input
|
||||||
|
id="selectAllCheckbox"
|
||||||
|
class="form-check-input"
|
||||||
|
type="checkbox"
|
||||||
|
@change="toggleAll($event)"
|
||||||
|
/>
|
||||||
|
<label class="form-check-label">Select All</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="card-footer">
|
||||||
|
<div class="d-grid gap-2 d-md-flex justify-content-md-start">
|
||||||
|
<!-- 刷新按钮 -->
|
||||||
|
<!-- Refresh button -->
|
||||||
|
<button class="btn btn-success" type="button" @click="init()">
|
||||||
|
Refresh
|
||||||
|
</button>
|
||||||
|
<!-- 删除选中短信按钮 -->
|
||||||
|
<!-- Delete selected SMS button -->
|
||||||
|
<button
|
||||||
|
class="btn btn-danger"
|
||||||
|
type="button"
|
||||||
|
@click="deleteSelectedSMS()"
|
||||||
|
>
|
||||||
|
Delete Selected SMS
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row mt-5 mb-4">
|
||||||
|
<div class="col">
|
||||||
|
<div class="card">
|
||||||
|
<div class="card-header">Send Message</div>
|
||||||
|
<div class="card-body">
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="phoneNumber" class="form-label">Recipient's Number</label>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
class="form-control"
|
||||||
|
id="phoneNumber"
|
||||||
|
x-model="phoneNumber"
|
||||||
|
placeholder="Enter the recipient's number."
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="messageToSend" class="form-label">SMS Content</label>
|
||||||
|
<textarea
|
||||||
|
class="form-control"
|
||||||
|
id="messageToSend"
|
||||||
|
rows="3"
|
||||||
|
x-model="messageToSend"
|
||||||
|
placeholder="Enter SMS content."
|
||||||
|
></textarea>
|
||||||
|
</div>
|
||||||
|
<button class="btn btn-primary" @click="sendSMS()">
|
||||||
|
Send SMS
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</main>
|
||||||
|
<script src="js/dark-mode.js"></script>
|
||||||
|
<script>
|
||||||
|
function fetchSMS() {
|
||||||
|
return {
|
||||||
|
isLoading: false,
|
||||||
|
atCommandResponse: "",
|
||||||
|
messages: [],
|
||||||
|
senders: [],
|
||||||
|
dates: [],
|
||||||
|
selectedMessages: [],
|
||||||
|
phoneNumber: "",
|
||||||
|
messageToSend: "",
|
||||||
|
|
||||||
<!-- <div class="col-md-8 mb-3">
|
// 请求获取短信
|
||||||
|
// Request to get SMS
|
||||||
|
requestSMS() {
|
||||||
|
this.isLoading = true;
|
||||||
|
fetch("/cgi-bin/get_sms")
|
||||||
|
.then((response) => response.text())
|
||||||
|
.then((data) => {
|
||||||
|
this.atCommandResponse = data
|
||||||
|
.split("\n")
|
||||||
|
.filter((line) => line.trim() !== "OK" && line.trim() !== "")
|
||||||
|
.join("\n");
|
||||||
|
})
|
||||||
|
.finally(() => {
|
||||||
|
this.isLoading = false;
|
||||||
|
this.clearData();
|
||||||
|
this.parseSMSData(this.atCommandResponse);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
<textarea
|
// 清除现有数据
|
||||||
class="form-control"
|
// Clear existing data
|
||||||
id="smsInputBox"
|
clearData() {
|
||||||
rows="5"
|
this.messages = [];
|
||||||
placeholder="Enter SMS here (!!!CURRENTLY UNDER DEVELOPMENT!!!)"
|
this.senders = [];
|
||||||
x-model="messageToSend"
|
this.dates = [];
|
||||||
></textarea>
|
this.selectedMessages = [];
|
||||||
</div> -->
|
const selectAllCheckbox =
|
||||||
</form>
|
document.getElementById("selectAllCheckbox");
|
||||||
</div>
|
if (selectAllCheckbox) {
|
||||||
</div>
|
selectAllCheckbox.checked = false;
|
||||||
<div class="card-footer">
|
}
|
||||||
<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>
|
|
||||||
</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 =
|
// Parse SMS data
|
||||||
/^\s*\+CMGL:\s*(\d+),"[^"]*","([^"]*)"[^"]*,"([^"]*)"/gm;
|
parseSMSData(data) {
|
||||||
|
const cmglRegex =
|
||||||
|
/^\s*\+CMGL:\s*(\d+),"[^"]*","([^"]*)"[^"]*,"([^"]*)"/gm;
|
||||||
|
const messageGroups = {};
|
||||||
|
this.messageIndices = []; // 确保初始化messageIndices数组
|
||||||
|
// Ensure that the messageIndices array is initialized
|
||||||
|
|
||||||
let match;
|
let match;
|
||||||
while ((match = cmglRegex.exec(data)) !== null) {
|
while ((match = cmglRegex.exec(data)) !== null) {
|
||||||
const index = parseInt(match[1]);
|
const index = parseInt(match[1]);
|
||||||
const sender = match[2];
|
const sender = match[2];
|
||||||
let date = match[3];
|
const date = match[3].replace(/\+\d{2}$/, "");
|
||||||
|
|
||||||
// remove +32 from the date
|
const startIndex = cmglRegex.lastIndex;
|
||||||
date = date.replace("+32", "");
|
const endIndex =
|
||||||
|
data.indexOf("+CMGL:", startIndex) !== -1
|
||||||
|
? data.indexOf("+CMGL:", startIndex)
|
||||||
|
: data.length;
|
||||||
|
const messageHex = data.substring(startIndex, endIndex).trim();
|
||||||
|
|
||||||
// Find the start and end positions of the message
|
// 判断 messageHex 是否为 UCS2 格式
|
||||||
const startIndex = cmglRegex.lastIndex;
|
// Determine if messageHex is in UCS2 format
|
||||||
let endIndex = data.indexOf("+CMGL:", startIndex + 1);
|
const message = /^[0-9a-fA-F]+$/.test(messageHex)
|
||||||
if (endIndex === -1) {
|
? this.convertHexToText(messageHex)
|
||||||
// If no more +CMGL lines, set end index to end of string
|
: messageHex;
|
||||||
endIndex = data.length;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Extract the message from start to end index
|
if (!messageGroups[date]) {
|
||||||
const message = data.substring(startIndex, endIndex).trim();
|
messageGroups[date] = { sender, messages: [], indices: [] };
|
||||||
|
}
|
||||||
|
messageGroups[date].messages.push(message);
|
||||||
|
messageGroups[date].indices.push(index);
|
||||||
|
this.messageIndices.push(index); // 填充 messageIndices 数组
|
||||||
|
// Fill the messageIndices array
|
||||||
|
}
|
||||||
|
|
||||||
this.messages.push(message);
|
for (const date in messageGroups) {
|
||||||
this.senders.push(sender);
|
this.dates.push(date);
|
||||||
this.dates.push(date);
|
this.senders.push(messageGroups[date].sender);
|
||||||
}
|
this.messages.push(messageGroups[date].messages.join(" "));
|
||||||
},
|
}
|
||||||
|
},
|
||||||
|
|
||||||
deleteAllSMS() {
|
// 删除选中的短信
|
||||||
const atcmd = "AT+CMGD=,4";
|
// Delete selected SMS
|
||||||
fetch(
|
deleteSelectedSMS() {
|
||||||
"/cgi-bin/get_atcommand?" +
|
if (this.selectedMessages.length === 0) {
|
||||||
new URLSearchParams({
|
console.warn("No SMS selected");
|
||||||
atcmd: atcmd,
|
return;
|
||||||
})
|
}
|
||||||
)
|
|
||||||
.then((response) => response.text())
|
|
||||||
.then((data) => {
|
|
||||||
console.log(data);
|
|
||||||
})
|
|
||||||
.finally(() => {
|
|
||||||
this.requestSMS();
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
sendSMS() {
|
if (!this.messageIndices || this.messageIndices.length === 0) {
|
||||||
this.isLoading = true;
|
console.error("SMS index is not correctly initialized or is empty");
|
||||||
fetch(
|
return;
|
||||||
"/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
|
// Check if all are selected
|
||||||
const atcmd = "AT+CMGF=1";
|
const isAllSelected =
|
||||||
fetch(
|
this.selectedMessages.length === this.messages.length;
|
||||||
"/cgi-bin/get_atcommand?" +
|
|
||||||
new URLSearchParams({
|
if (isAllSelected) {
|
||||||
atcmd: atcmd,
|
// 如果全选,则调用删除所有短信的方法
|
||||||
})
|
// If all are selected, call the method to delete all SMS
|
||||||
)
|
this.deleteAllSMS();
|
||||||
.then((response) => response.text())
|
} else {
|
||||||
.then((data) => {
|
// 否则,删除选中的短信
|
||||||
console.log(data);
|
// Otherwise, delete the selected SMS
|
||||||
})
|
const deletePromises = this.selectedMessages.map((index) => {
|
||||||
.finally(() => {
|
if (index >= this.messageIndices.length) {
|
||||||
this.requestSMS();
|
console.error("SMS index out of range");
|
||||||
});
|
return Promise.resolve(); // 返回已解决的Promise,防止进一步错误
|
||||||
},
|
// Return a resolved Promise to prevent further errors
|
||||||
};
|
}
|
||||||
}
|
const actualIndex = this.messageIndices[index];
|
||||||
</script>
|
return fetch(
|
||||||
</body>
|
`/cgi-bin/get_atcommand?${new URLSearchParams({
|
||||||
|
atcmd: `AT+CMGD=${actualIndex}`,
|
||||||
|
})}`
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
Promise.all(deletePromises).finally(() => {
|
||||||
|
this.selectedMessages = [];
|
||||||
|
this.requestSMS();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
// 将十六进制转换为文本(假设使用 UTF-16BE 编码)
|
||||||
|
// Convert hexadecimal to text (assuming UTF-16BE encoding)
|
||||||
|
convertHexToText(hex) {
|
||||||
|
const bytes = new Uint8Array(
|
||||||
|
hex.match(/.{1,2}/g).map((byte) => parseInt(byte, 16))
|
||||||
|
);
|
||||||
|
return new TextDecoder("utf-16be").decode(bytes);
|
||||||
|
},
|
||||||
|
|
||||||
|
// 删除所有短信
|
||||||
|
// Delete all SMS
|
||||||
|
deleteAllSMS() {
|
||||||
|
fetch(
|
||||||
|
`/cgi-bin/get_atcommand?${new URLSearchParams({
|
||||||
|
atcmd: "AT+CMGD=,4",
|
||||||
|
})}`
|
||||||
|
).finally(() => {
|
||||||
|
this.init();
|
||||||
|
});
|
||||||
|
},
|
||||||
|
// 发送短信
|
||||||
|
// Send SMS
|
||||||
|
toUCS2(message) {
|
||||||
|
let ucs2Message = "";
|
||||||
|
for (let i = 0; i < message.length; i++) {
|
||||||
|
const code = message.charCodeAt(i).toString(16).toUpperCase();
|
||||||
|
ucs2Message += ("0000" + code).slice(-4); // Ensure each code is 4 digits
|
||||||
|
}
|
||||||
|
return ucs2Message;
|
||||||
|
},
|
||||||
|
|
||||||
|
sendSMS() {
|
||||||
|
const ucs2Message = this.toUCS2(this.messageToSend);
|
||||||
|
const encodedMessage = encodeURIComponent(ucs2Message);
|
||||||
|
const params = new URLSearchParams({
|
||||||
|
number: this.phoneNumber,
|
||||||
|
msg: encodedMessage,
|
||||||
|
});
|
||||||
|
fetch(`/cgi-bin/send_sms?${params.toString()}`)
|
||||||
|
.then((response) => response.text())
|
||||||
|
.then((data) => {
|
||||||
|
console.log("Response from server:", data);
|
||||||
|
// 检查返回的数据中是否包含 '+CMS ERROR'
|
||||||
|
// Check if the returned data contains '+CMS ERROR'
|
||||||
|
if (data.includes("+CMS ERROR")) {
|
||||||
|
// 解析错误代码,如果存在,获取更具体的错误信息
|
||||||
|
// Parse the error code, if it exists, get more specific error information
|
||||||
|
const errorCode = data.match(/\+CMS ERROR: (\d+)/)?.[1];
|
||||||
|
console.error("SMS send error:", data);
|
||||||
|
alert(`SMS sending failed!: ${errorCode}`);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
alert("SMS sent successfully!");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
// 初始化
|
||||||
|
// Initialize
|
||||||
|
init() {
|
||||||
|
this.clearData();
|
||||||
|
this.requestSMS();
|
||||||
|
},
|
||||||
|
|
||||||
|
// 全选/取消全选
|
||||||
|
// Select all/deselect all
|
||||||
|
toggleAll(event) {
|
||||||
|
this.selectedMessages = event.target.checked
|
||||||
|
? this.messages.map((_, index) => index)
|
||||||
|
: [];
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@@ -1,200 +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" />
|
|
||||||
|
|
||||||
<!-- Logo -->
|
|
||||||
<link rel="simpleadmin-logo" href="favicon.ico" />
|
|
||||||
|
|
||||||
<!-- Import BootStrap Javascript -->
|
|
||||||
<script src="js/bootstrap.bundle.min.js"></script>
|
|
||||||
<script src="js/alpinejs.min.js" defer></script>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<main>
|
|
||||||
<div class="container my-4" x-data="simpleWatchCat()">
|
|
||||||
<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 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
|
|
||||||
>
|
|
||||||
</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-3 mb-4">
|
|
||||||
<div class="col">
|
|
||||||
<div class="card">
|
|
||||||
<div class="card-header">Simple Watchcat</div>
|
|
||||||
<div class="card-body">
|
|
||||||
<div class="card-text">
|
|
||||||
<div>
|
|
||||||
<label
|
|
||||||
class="form-check-label m-lg-3"
|
|
||||||
for="flexSwitchCheckDefault"
|
|
||||||
>Select Watchcat Status</label
|
|
||||||
>
|
|
||||||
<!-- If wacthCatStatus is Enabled then make it checked -->
|
|
||||||
<input
|
|
||||||
type="radio"
|
|
||||||
class="btn-check"
|
|
||||||
name="Enable"
|
|
||||||
id="Enable"
|
|
||||||
autocomplete="off"
|
|
||||||
x-bind:checked="wacthCatStatus === 'Enable'"
|
|
||||||
x-bind:disabled="wacthCatStatus === 'Enable'"
|
|
||||||
x-model="wacthCatStatus"
|
|
||||||
/>
|
|
||||||
<label class="btn btn-primary" for="option1">Enable</label>
|
|
||||||
|
|
||||||
<input
|
|
||||||
type="radio"
|
|
||||||
class="btn-check"
|
|
||||||
name="Disable"
|
|
||||||
id="Disable"
|
|
||||||
autocomplete="off"
|
|
||||||
x-bind:checked="wacthCatStatus === 'Disable'"
|
|
||||||
x-bind:disabled="wacthCatStatus === 'Disable'"
|
|
||||||
x-model="wacthCatStatus"
|
|
||||||
/>
|
|
||||||
<label class="btn btn-danger" for="option2">Disable</label>
|
|
||||||
</div>
|
|
||||||
<div class="input-group mb-3 mt-3">
|
|
||||||
<span
|
|
||||||
class="input-group-text"
|
|
||||||
id="inputGroup-sizing-default"
|
|
||||||
>IP or DNS to Ping</span
|
|
||||||
>
|
|
||||||
<input
|
|
||||||
type="text"
|
|
||||||
class="form-control"
|
|
||||||
aria-label="Ping Timeout"
|
|
||||||
aria-describedby="inputGroup-sizing-default"
|
|
||||||
x-bind:placeholder="ipDNS"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="input-group mb-3 mt-3">
|
|
||||||
<span
|
|
||||||
class="input-group-text"
|
|
||||||
id="inputGroup-sizing-default"
|
|
||||||
>Ping Timeout in Seconds</span
|
|
||||||
>
|
|
||||||
<input
|
|
||||||
type="text"
|
|
||||||
class="form-control"
|
|
||||||
aria-label="Ping Failure Count"
|
|
||||||
aria-describedby="inputGroup-sizing-default"
|
|
||||||
x-bind:placeholder="pingTimeout + ' seconds'"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="input-group mb-3 mt-3">
|
|
||||||
<span
|
|
||||||
class="input-group-text"
|
|
||||||
id="inputGroup-sizing-default"
|
|
||||||
>Ping Failure Amount</span
|
|
||||||
>
|
|
||||||
<input
|
|
||||||
type="text"
|
|
||||||
class="form-control"
|
|
||||||
aria-label="Sizing example input"
|
|
||||||
aria-describedby="inputGroup-sizing-default"
|
|
||||||
x-bind:placeholder="pingFailures"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div>
|
|
||||||
<select
|
|
||||||
class="form-select"
|
|
||||||
aria-label="Default select example"
|
|
||||||
>
|
|
||||||
<option selected>Select Action</option>
|
|
||||||
<option value="1">None</option>
|
|
||||||
<option value="2">Reboot</option>
|
|
||||||
<option value="3">Switch Sim</option>
|
|
||||||
</select>
|
|
||||||
<label class="mt-1">
|
|
||||||
Current Action: <span x-text="action"></span>
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="card-footer">
|
|
||||||
Setting a low ping timeout and ping failure count may cause
|
|
||||||
intermittent disconnections due to high sensitivity. <br />
|
|
||||||
Select appropriate values for both based on your needs.
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</main>
|
|
||||||
<script src="js/dark-mode.js"></script>
|
|
||||||
<script>
|
|
||||||
function simpleWatchCat() {
|
|
||||||
return {
|
|
||||||
wacthCatStatus: "Enable",
|
|
||||||
ipDNS: "1.1.1.1",
|
|
||||||
pingTimeout: "30",
|
|
||||||
pingFailures: "5",
|
|
||||||
action: "Reboot",
|
|
||||||
};
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
363
simpleadmin/www/watchcat.html
Normal file
363
simpleadmin/www/watchcat.html
Normal file
@@ -0,0 +1,363 @@
|
|||||||
|
<!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" />
|
||||||
|
|
||||||
|
<!-- Logo -->
|
||||||
|
<link rel="simpleadmin-logo" href="favicon.ico" />
|
||||||
|
|
||||||
|
<!-- Import BootStrap Javascript -->
|
||||||
|
<script src="js/bootstrap.bundle.min.js"></script>
|
||||||
|
<script src="js/alpinejs.min.js" defer></script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.form-switch .form-check-input {
|
||||||
|
width: 3em;
|
||||||
|
height: 1.5em;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<main>
|
||||||
|
<div class="container my-4" x-data="simpleWatchCat()">
|
||||||
|
<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 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
|
||||||
|
>
|
||||||
|
</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-3 mb-4">
|
||||||
|
<div class="col">
|
||||||
|
<div class="card">
|
||||||
|
<div class="card-header">Simple Watchcat</div>
|
||||||
|
<div class="card-body">
|
||||||
|
<div class="card-text">
|
||||||
|
<div class="row mt-3 mb-5 align-content-center mx-4">
|
||||||
|
<div class="col">
|
||||||
|
<div class="mt-3">
|
||||||
|
<label> Enable Watchcat </label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-5">
|
||||||
|
<div class="mt-2">
|
||||||
|
<div class="form-check form-switch form-switch-lg">
|
||||||
|
<input
|
||||||
|
class="form-check-input"
|
||||||
|
type="checkbox"
|
||||||
|
role="switch"
|
||||||
|
id="watchCatSwitch"
|
||||||
|
x-model="watchCatStatus"
|
||||||
|
disabled
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row mt-3 mb-3 align-items-center mx-4">
|
||||||
|
<div class="col">
|
||||||
|
<div class="mt-3 mb-4">
|
||||||
|
<label> Track IP </label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="mt-3 mb-4">
|
||||||
|
<label> Ping Request Timeout </label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="mt-3 mb-4">
|
||||||
|
<label> Ping Failure Amount </label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-5">
|
||||||
|
<div class="mt-3 mb-4">
|
||||||
|
<select
|
||||||
|
class="form-select"
|
||||||
|
aria-label="Select Site to Ping"
|
||||||
|
x-model="trackIP"
|
||||||
|
>
|
||||||
|
<option selected>Select IP</option>
|
||||||
|
<option value="1.1.1.1">1.1.1.1</option>
|
||||||
|
<option value="8.8.8.8">8.8.8.8</option>
|
||||||
|
<option value="9.9.9.9">9.9.9.9</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="mt-3 mb-4">
|
||||||
|
<input
|
||||||
|
type="number"
|
||||||
|
class="form-control"
|
||||||
|
aria-label="Ping Timeout"
|
||||||
|
aria-describedby="inputGroup-sizing-default"
|
||||||
|
placeholder="Enter Ping Timeout in Seconds."
|
||||||
|
x-model="cooldown"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="mt-3 mb-4">
|
||||||
|
<input
|
||||||
|
type="number"
|
||||||
|
class="form-control"
|
||||||
|
aria-label="Sizing example input"
|
||||||
|
aria-describedby="inputGroup-sizing-default"
|
||||||
|
placeholder="Enter Ping Failure Amount."
|
||||||
|
x-model="failures"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row mt-3 mb-5 align-content-center mx-4">
|
||||||
|
<div class="col">
|
||||||
|
<div class="mt-3">
|
||||||
|
<label>Sim Auto Switch</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-5">
|
||||||
|
<div class="mt-2">
|
||||||
|
<div class="form-check form-switch form-switch-lg">
|
||||||
|
<input
|
||||||
|
class="form-check-input"
|
||||||
|
type="checkbox"
|
||||||
|
role="switch"
|
||||||
|
id="simAutoSwitch"
|
||||||
|
x-model="simAutoSwitchStatus"
|
||||||
|
disabled
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row mt-3 mb-3 align-items-center mx-4">
|
||||||
|
<div class="col">
|
||||||
|
<div class="mt-3 mb-4">
|
||||||
|
<label> Select Preferred SIM </label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="mt-3 mb-4">
|
||||||
|
<label> SIM 1 APN </label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="mt-3 mb-4">
|
||||||
|
<label> SIM 2 APN </label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="mt-3 mb-4">
|
||||||
|
<label> Failover Interval </label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="mt-3 mb-4">
|
||||||
|
<label> Scheduled SIM Hot Swap</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-5">
|
||||||
|
<div class="mt-3 mb-3">
|
||||||
|
<select
|
||||||
|
class="form-select"
|
||||||
|
aria-label="Select Sim"
|
||||||
|
x-model="preferredSim"
|
||||||
|
>
|
||||||
|
<option selected>Select SIM</option>
|
||||||
|
<option value="1">SIM 1</option>
|
||||||
|
<option value="2">SIM 2</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="mt-3 mb-3">
|
||||||
|
<input
|
||||||
|
type="number"
|
||||||
|
class="form-control"
|
||||||
|
aria-label="SIM 1 APN"
|
||||||
|
aria-describedby="inputGroup-sizing-default"
|
||||||
|
placeholder="Input APN for SIM 1. (Optional)"
|
||||||
|
x-model="sim1APN"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="mt-3 mb-3">
|
||||||
|
<input
|
||||||
|
type="number"
|
||||||
|
class="form-control"
|
||||||
|
aria-label="SIM 2 APN"
|
||||||
|
aria-describedby="inputGroup-sizing-default"
|
||||||
|
placeholder="Input APN for SIM 2. (Optional)"
|
||||||
|
x-model="sim2APN"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="mt-3 mb-3 d-flex align-items-center">
|
||||||
|
<select
|
||||||
|
class="form-select"
|
||||||
|
aria-label="Failover Interval"
|
||||||
|
>
|
||||||
|
<option selected>Failover Interval</option>
|
||||||
|
<option value="5">5</option>
|
||||||
|
<option value="10">10</option>
|
||||||
|
<option value="15">15</option>
|
||||||
|
<option value="20">20</option>
|
||||||
|
</select>
|
||||||
|
<label class="mx-3">Minutes</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="mt-3 mb-3">
|
||||||
|
<input
|
||||||
|
type="time"
|
||||||
|
class="form-control"
|
||||||
|
aria-label="Scheduled SIM Hot Swap"
|
||||||
|
aria-describedby="inputGroup-sizing-default"
|
||||||
|
x-model="scheduledSIMHotSwap"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="card-footer">
|
||||||
|
<!-- Setting a low ping timeout and ping failure count may cause
|
||||||
|
intermittent disconnections due to high sensitivity. <br />
|
||||||
|
Select appropriate values for both based on your needs.<br /> -->
|
||||||
|
Still under development. Coming soon...
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</main>
|
||||||
|
<script src="js/dark-mode.js"></script>
|
||||||
|
<script>
|
||||||
|
function simpleWatchCat() {
|
||||||
|
return {
|
||||||
|
watchCatStatus: "",
|
||||||
|
trackIP: "",
|
||||||
|
cooldown: "",
|
||||||
|
failures: "",
|
||||||
|
response: "",
|
||||||
|
formCompleted: false,
|
||||||
|
|
||||||
|
simAutoSwitchStatus: "",
|
||||||
|
scheduledSIMHotSwap: "",
|
||||||
|
sim1APN: "",
|
||||||
|
sim2APN: "",
|
||||||
|
preferredSim: "",
|
||||||
|
simFormCompleted: false,
|
||||||
|
|
||||||
|
modifyWatchCatScript() {
|
||||||
|
// If one of the params is empty then use their corresponding default values
|
||||||
|
if (this.IpDNS === "") {
|
||||||
|
this.IpDNS = "1.1.1.1";
|
||||||
|
} else if (this.cooldown === "") {
|
||||||
|
this.cooldown = "30";
|
||||||
|
} else if (this.failures === "") {
|
||||||
|
this.failures = "5";
|
||||||
|
} else if (this.action === "") {
|
||||||
|
this.action = "Reboot";
|
||||||
|
}
|
||||||
|
|
||||||
|
fetch(
|
||||||
|
"/cgi-bin/get_atcommand?" +
|
||||||
|
new URLSearchParams({
|
||||||
|
status: this.status,
|
||||||
|
IpDNS: this.IpDNS,
|
||||||
|
cooldown: this.cooldown,
|
||||||
|
failures: this.failures,
|
||||||
|
action: this.action,
|
||||||
|
})
|
||||||
|
)
|
||||||
|
.then((response) => {
|
||||||
|
return res.text();
|
||||||
|
})
|
||||||
|
.then((data) => {
|
||||||
|
this.response = data;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
formCompletedChecker() {
|
||||||
|
this.formCompleted =
|
||||||
|
this.watchCatStatus !== "" &&
|
||||||
|
this.trackIP !== "" &&
|
||||||
|
this.cooldown !== "" &&
|
||||||
|
this.failures !== "";
|
||||||
|
},
|
||||||
|
|
||||||
|
simFormCompletedChecker() {
|
||||||
|
if (
|
||||||
|
this.simAutoSwitchStatus !== "" &&
|
||||||
|
this.scheduledSIMHotSwap !== "" &&
|
||||||
|
this.preferredSim !== ""
|
||||||
|
) {
|
||||||
|
this.simFormCompleted = true;
|
||||||
|
} else {
|
||||||
|
this.simFormCompleted = false;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
init() {
|
||||||
|
this.$watch("watchCatStatus", this.formCompletedChecker.bind(this));
|
||||||
|
this.$watch("trackIP", this.formCompletedChecker.bind(this));
|
||||||
|
this.$watch("cooldown", this.formCompletedChecker.bind(this));
|
||||||
|
this.$watch("failures", this.formCompletedChecker.bind(this));
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -184,6 +184,8 @@ echo -e "\e[1;31m2) Installing simpleadmin from the $GITTREE branch\e[0m"
|
|||||||
wget https://raw.githubusercontent.com/$GITUSER/quectel-rgmii-toolkit/$GITTREE/simpleadmin/www/cgi-bin/set_ttl
|
wget https://raw.githubusercontent.com/$GITUSER/quectel-rgmii-toolkit/$GITTREE/simpleadmin/www/cgi-bin/set_ttl
|
||||||
wget https://raw.githubusercontent.com/$GITUSER/quectel-rgmii-toolkit/$GITTREE/simpleadmin/www/cgi-bin/send_sms
|
wget https://raw.githubusercontent.com/$GITUSER/quectel-rgmii-toolkit/$GITTREE/simpleadmin/www/cgi-bin/send_sms
|
||||||
wget https://raw.githubusercontent.com/$GITUSER/quectel-rgmii-toolkit/$GITTREE/simpleadmin/www/cgi-bin/get_uptime
|
wget https://raw.githubusercontent.com/$GITUSER/quectel-rgmii-toolkit/$GITTREE/simpleadmin/www/cgi-bin/get_uptime
|
||||||
|
wget https://raw.githubusercontent.com/$GITUSER/quectel-rgmii-toolkit/$GITTREE/simpleadmin/www/cgi-bin/get_watchcat_status
|
||||||
|
wget https://raw.githubusercontent.com/$GITUSER/quectel-rgmii-toolkit/$GITTREE/simpleadmin/www/cgi-bin/set_watchcat
|
||||||
sleep 1
|
sleep 1
|
||||||
cd /
|
cd /
|
||||||
chmod +x $SIMPLE_ADMIN_DIR/www/cgi-bin/*
|
chmod +x $SIMPLE_ADMIN_DIR/www/cgi-bin/*
|
||||||
|
|||||||
Reference in New Issue
Block a user