Compare commits
No commits in common. "development" and "main" have entirely different histories.
developmen
...
main
22
LICENSE
22
LICENSE
@ -1,22 +0,0 @@
|
||||
MIT License with Additional Stipulations
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
1. A clear and visible attribution to the original author (you) must be provided in an obvious place in any product, documentation, or interface where the software is utilized. This attribution should include your name and a reference to the original source repository.
|
||||
|
||||
2. The Software, or any modified version of it, must not be sold or charged for. However, selling physical products that include the Software is permitted, provided that a clear and visible attribution to the original author (you) is included in an obvious place in the product or accompanying documentation.
|
||||
|
||||
3. Any modifications made to the Software must be made available upon request by any party. This includes providing access to the modified source code, along with any accompanying documentation necessary for understanding the modifications.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
@ -1,962 +0,0 @@
|
||||
#!/bin/sh
|
||||
# Define toolkit paths
|
||||
export PATH=/bin:/sbin:/usr/bin:/usr/sbin:/opt/bin:/opt/sbin:/usrdata/root/bin
|
||||
GITUSER="iamromulan"
|
||||
GITTREE="development"
|
||||
GITMAINTREE="main"
|
||||
GITDEVTREE="development"
|
||||
TMP_DIR="/tmp"
|
||||
USRDATA_DIR="/usrdata"
|
||||
SOCAT_AT_DIR="/usrdata/socat-at-bridge"
|
||||
SOCAT_AT_SYSD_DIR="/usrdata/socat-at-bridge/systemd_units"
|
||||
SIMPLE_ADMIN_DIR="/usrdata/simpleadmin"
|
||||
SIMPLE_FIREWALL_DIR="/usrdata/simplefirewall"
|
||||
SIMPLE_FIREWALL_SCRIPT="$SIMPLE_FIREWALL_DIR/simplefirewall.sh"
|
||||
SIMPLE_FIREWALL_SYSTEMD_DIR="$SIMPLE_FIREWALL_DIR/systemd"
|
||||
TAILSCALE_DIR="/usrdata/tailscale"
|
||||
TAILSCALE_SYSD_DIR="/usrdata/tailscale/systemd"
|
||||
# AT Command Script Variables and Functions
|
||||
DEVICE_FILE="/dev/smd7"
|
||||
TIMEOUT=4 # Set a timeout for the response
|
||||
# Function to remount file system as read-write
|
||||
remount_rw() {
|
||||
mount -o remount,rw /
|
||||
}
|
||||
|
||||
# Function to remount file system as read-only
|
||||
remount_ro() {
|
||||
mount -o remount,ro /
|
||||
}
|
||||
|
||||
# Basic AT commands without socat bridge for fast responce commands only
|
||||
start_listening() {
|
||||
cat "$DEVICE_FILE" > /tmp/device_readout &
|
||||
CAT_PID=$!
|
||||
}
|
||||
|
||||
send_at_command() {
|
||||
echo -e "\e[1;31mThis only works for basic quick responding commands!\e[0m" # Red
|
||||
echo -e "\e[1;36mType 'install' to simply type atcmd in shell from now on\e[0m"
|
||||
echo -e "\e[1;36mThe installed version is much better than this portable version\e[0m"
|
||||
echo -e "\e[1;32mEnter AT command (or type 'exit' to quit): \e[0m"
|
||||
read at_command
|
||||
if [ "$at_command" = "exit" ]; then
|
||||
return 1
|
||||
fi
|
||||
|
||||
if [ "$at_command" = "install" ]; then
|
||||
install_update_at_socat
|
||||
echo -e "\e[1;32mInstalled. Type atcmd from adb shell or ssh to start an AT Command session\e[0m"
|
||||
return 1
|
||||
fi
|
||||
echo -e "${at_command}\r" > "$DEVICE_FILE"
|
||||
}
|
||||
|
||||
wait_for_response() {
|
||||
local start_time=$(date +%s)
|
||||
local current_time
|
||||
local elapsed_time
|
||||
|
||||
echo -e "\e[1;32mCommand sent, waiting for response...\e[0m"
|
||||
while true; do
|
||||
if grep -qe "OK" -e "ERROR" /tmp/device_readout; then
|
||||
echo -e "\e[1;32mResponse received:\e[0m"
|
||||
cat /tmp/device_readout
|
||||
return 0
|
||||
fi
|
||||
current_time=$(date +%s)
|
||||
elapsed_time=$((current_time - start_time))
|
||||
if [ "$elapsed_time" -ge "$TIMEOUT" ]; then
|
||||
echo -e "\e[1;31mError: Response timed out.\e[0m" # Red
|
||||
echo -e "\e[1;32mIf the responce takes longer than a second or 2 to respond this will not work\e[0m" # Green
|
||||
echo -e "\e[1;36mType install to install the better version of this that will work.\e[0m" # Cyan
|
||||
return 1
|
||||
fi
|
||||
sleep 1
|
||||
done
|
||||
}
|
||||
|
||||
cleanup() {
|
||||
kill "$CAT_PID"
|
||||
wait "$CAT_PID" 2>/dev/null
|
||||
rm -f /tmp/device_readout
|
||||
}
|
||||
|
||||
send_at_commands() {
|
||||
if [ -c "$DEVICE_FILE" ]; then
|
||||
while true; do
|
||||
start_listening
|
||||
send_at_command
|
||||
if [ $? -eq 1 ]; then
|
||||
cleanup
|
||||
break
|
||||
fi
|
||||
wait_for_response
|
||||
cleanup
|
||||
done
|
||||
else
|
||||
echo -e "\e[1;31mError: Device $DEVICE_FILE does not exist!\e[0m"
|
||||
fi
|
||||
}
|
||||
|
||||
# Check for existing Entware/opkg installation, install if not installed
|
||||
ensure_entware_installed() {
|
||||
remount_rw
|
||||
if [ ! -f "/opt/bin/opkg" ]; then
|
||||
echo -e "\e[1;32mInstalling Entware/OPKG\e[0m"
|
||||
cd /tmp && wget --no-check-certificate -O installentware.sh "http://gitea.hapyle.work:33000/taotao/webui/raw/development/installentware.sh" && chmod +x installentware.sh && ./installentware.sh
|
||||
if [ "$?" -ne 0 ]; then
|
||||
echo -e "\e[1;31mEntware/OPKG installation failed. Please check your internet connection or the repository URL.\e[0m"
|
||||
exit 1
|
||||
fi
|
||||
cd /
|
||||
else
|
||||
echo -e "\e[1;32mEntware/OPKG is already installed.\e[0m"
|
||||
if [ "$(readlink /bin/login)" != "/opt/bin/login" ]; then
|
||||
opkg update && opkg install shadow-login shadow-passwd shadow-useradd
|
||||
if [ "$?" -ne 0 ]; then
|
||||
echo -e "\e[1;31mPackage installation failed. Please check your internet connection and try again.\e[0m"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Replace the login and passwd binaries and set home for root to a writable directory
|
||||
rm /opt/etc/shadow
|
||||
rm /opt/etc/passwd
|
||||
cp /etc/shadow /opt/etc/
|
||||
cp /etc/passwd /opt/etc
|
||||
mkdir -p /usrdata/root/bin
|
||||
touch /usrdata/root/.profile
|
||||
echo "# Set PATH for all shells" > /usrdata/root/.profile
|
||||
echo "export PATH=/bin:/usr/sbin:/usr/bin:/sbin:/opt/sbin:/opt/bin:/usrdata/root/bin" >> /usrdata/root/.profile
|
||||
chmod +x /usrdata/root/.profile
|
||||
sed -i '1s|/home/root:/bin/sh|/usrdata/root:/bin/bash|' /opt/etc/passwd
|
||||
rm /bin/login /usr/bin/passwd
|
||||
ln -sf /opt/bin/login /bin
|
||||
ln -sf /opt/bin/passwd /usr/bin/
|
||||
ln -sf /opt/bin/useradd /usr/bin/
|
||||
echo -e "\e[1;31mPlease set the root password.\e[0m"
|
||||
/opt/bin/passwd
|
||||
|
||||
# Install basic and useful utilities
|
||||
opkg install mc htop dfc lsof
|
||||
ln -sf /opt/bin/mc /bin
|
||||
ln -sf /opt/bin/htop /bin
|
||||
ln -sf /opt/bin/dfc /bin
|
||||
ln -sf /opt/bin/lsof /bin
|
||||
fi
|
||||
|
||||
if [ ! -f "/usrdata/root/.profile" ]; then
|
||||
opkg update && opkg install shadow-useradd
|
||||
mkdir -p /usrdata/root/bin
|
||||
touch /usrdata/root/.profile
|
||||
echo "# Set PATH for all shells" > /usrdata/root/.profile
|
||||
echo "export PATH=/bin:/usr/sbin:/usr/bin:/sbin:/opt/sbin:/opt/bin:/usrdata/root/bin" >> /usrdata/root/.profile
|
||||
chmod +x /usrdata/root/.profile
|
||||
sed -i '1s|/home/root:/bin/sh|/usrdata/root:/bin/bash|' /opt/etc/passwd
|
||||
fi
|
||||
fi
|
||||
if [ ! -f "/opt/sbin/useradd" ]; then
|
||||
echo "useradd does not exist. Installing shadow-useradd..."
|
||||
opkg install shadow-useradd
|
||||
else
|
||||
echo "useradd already exists. Continuing..."
|
||||
fi
|
||||
|
||||
if [ ! -f "/usr/bin/curl" ] && [ ! -f "/opt/bin/curl" ]; then
|
||||
echo "curl does not exist. Installing curl..."
|
||||
opkg update && opkg install curl
|
||||
if [ "$?" -ne 0 ]; then
|
||||
echo -e "\e[1;31mFailed to install curl. Please check your internet connection and try again.\e[0m"
|
||||
exit 1
|
||||
fi
|
||||
else
|
||||
echo "curl already exists. Continuing..."
|
||||
fi
|
||||
}
|
||||
|
||||
#Uninstall Entware if the Users chooses
|
||||
uninstall_entware() {
|
||||
echo -e '\033[31mInfo: Starting Entware/OPKG uninstallation...\033[0m'
|
||||
|
||||
# Stop services
|
||||
systemctl stop rc.unslung.service
|
||||
/opt/etc/init.d/rc.unslung stop
|
||||
rm /lib/systemd/system/multi-user.target.wants/rc.unslung.service
|
||||
rm /lib/systemd/system/rc.unslung.service
|
||||
|
||||
systemctl stop opt.mount
|
||||
rm /lib/systemd/system/multi-user.target.wants/start-opt-mount.service
|
||||
rm /lib/systemd/system/opt.mount
|
||||
rm /lib/systemd/system/start-opt-mount.service
|
||||
|
||||
# Unmount /opt if mounted
|
||||
mountpoint -q /opt && umount /opt
|
||||
|
||||
# Remove Entware installation directory
|
||||
rm -rf /usrdata/opt
|
||||
rm -rf /opt
|
||||
|
||||
# Reload systemctl daemon
|
||||
systemctl daemon-reload
|
||||
|
||||
# Optionally, clean up any modifications to /etc/profile or other system files
|
||||
# Restore original link to login binary compiled by Quectel
|
||||
rm /bin/login
|
||||
ln /bin/login.shadow /bin/login
|
||||
|
||||
echo -e '\033[32mInfo: Entware/OPKG has been uninstalled successfully.\033[0m'
|
||||
}
|
||||
|
||||
# function to configure the fetures of simplefirewall
|
||||
configure_simple_firewall() {
|
||||
if [ ! -f "$SIMPLE_FIREWALL_SCRIPT" ]; then
|
||||
echo -e "\033[0;31mSimplefirewall is not installed, would you like to install it?\033[0m"
|
||||
echo -e "\033[0;32m1) Yes\033[0m"
|
||||
echo -e "\033[0;31m2) No\033[0m"
|
||||
read -p "Enter your choice (1-2): " install_choice
|
||||
|
||||
case $install_choice in
|
||||
1)
|
||||
install_simple_firewall
|
||||
;;
|
||||
2)
|
||||
return
|
||||
;;
|
||||
*)
|
||||
echo -e "\033[0;31mInvalid choice. Please select either 1 or 2.\033[0m"
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
|
||||
echo -e "\e[1;32mConfigure Simple Firewall:\e[0m"
|
||||
echo -e "\e[38;5;208m1) Configure incoming port block\e[0m"
|
||||
echo -e "\e[38;5;27m2) Configure TTL\e[0m"
|
||||
read -p "Enter your choice (1-2): " menu_choice
|
||||
|
||||
case $menu_choice in
|
||||
1)
|
||||
# Original ports configuration code with exit option
|
||||
current_ports_line=$(grep '^PORTS=' "$SIMPLE_FIREWALL_SCRIPT")
|
||||
ports=$(echo "$current_ports_line" | cut -d'=' -f2 | tr -d '()' | tr ' ' '\n' | grep -o '[0-9]\+')
|
||||
echo -e "\e[1;32mCurrent configured ports:\e[0m"
|
||||
echo "$ports" | awk '{print NR") "$0}'
|
||||
|
||||
while true; do
|
||||
echo -e "\e[1;32mEnter a port number to add/remove, or type 'done' or 'exit' to finish:\e[0m"
|
||||
read port
|
||||
if [ "$port" = "done" ] || [ "$port" = "exit" ]; then
|
||||
if [ "$port" = "exit" ]; then
|
||||
echo -e "\e[1;31mExiting without making changes...\e[0m"
|
||||
return
|
||||
fi
|
||||
break
|
||||
elif ! echo "$port" | grep -qE '^[0-9]+$'; then
|
||||
echo -e "\e[1;31mInvalid input: Please enter a numeric value.\e[0m"
|
||||
elif echo "$ports" | grep -q "^$port\$"; then
|
||||
ports=$(echo "$ports" | grep -v "^$port\$")
|
||||
echo -e "\e[1;32mPort $port removed.\e[0m"
|
||||
else
|
||||
ports=$(echo "$ports"; echo "$port" | grep -o '[0-9]\+')
|
||||
echo -e "\e[1;32mPort $port added.\e[0m"
|
||||
fi
|
||||
done
|
||||
|
||||
if [ "$port" != "exit" ]; then
|
||||
new_ports_line="PORTS=($(echo "$ports" | tr '\n' ' '))"
|
||||
sed -i "s/$current_ports_line/$new_ports_line/" "$SIMPLE_FIREWALL_SCRIPT"
|
||||
fi
|
||||
;;
|
||||
2)
|
||||
# TTL configuration code
|
||||
ttl_value=$(cat /usrdata/simplefirewall/ttlvalue)
|
||||
if [ "$ttl_value" -eq 0 ]; then
|
||||
echo -e "\e[1;31mTTL is not set.\e[0m"
|
||||
else
|
||||
echo -e "\e[1;32mTTL value is set to $ttl_value.\e[0m"
|
||||
fi
|
||||
|
||||
echo -e "\e[1;31mType 'exit' to cancel.\e[0m"
|
||||
read -p "What do you want the TTL value to be: " new_ttl_value
|
||||
if [ "$new_ttl_value" = "exit" ]; then
|
||||
echo -e "\e[1;31mExiting TTL configuration...\e[0m"
|
||||
return
|
||||
elif ! echo "$new_ttl_value" | grep -qE '^[0-9]+$'; then
|
||||
echo -e "\e[1;31mInvalid input: Please enter a numeric value.\e[0m"
|
||||
return
|
||||
else
|
||||
/usrdata/simplefirewall/ttl-override stop
|
||||
echo "$new_ttl_value" > /usrdata/simplefirewall/ttlvalue
|
||||
/usrdata/simplefirewall/ttl-override start
|
||||
echo -e "\033[0;32mTTL value updated to $new_ttl_value.\033[0m"
|
||||
fi
|
||||
;;
|
||||
*)
|
||||
echo -e "\e[1;31mInvalid choice. Please select either 1 or 2.\e[0m"
|
||||
;;
|
||||
esac
|
||||
|
||||
systemctl restart simplefirewall
|
||||
echo -e "\e[1;32mFirewall configuration updated.\e[0m"
|
||||
}
|
||||
|
||||
set_simpleadmin_passwd(){
|
||||
ensure_entware_installed
|
||||
opkg update
|
||||
opkg install libaprutil
|
||||
wget --no-check-certificate -O /usrdata/root/bin/htpasswd http://gitea.hapyle.work:33000/taotao/webui/raw/development/simpleadmin/htpasswd && chmod +x /usrdata/root/bin/htpasswd
|
||||
wget --no-check-certificate -O /usrdata/root/bin/simplepasswd http://gitea.hapyle.work:33000/taotao/webui/raw/development/simpleadmin/simplepasswd && chmod +x /usrdata/root/bin/simplepasswd
|
||||
echo -e "\e[1;32mTo change your simpleadmin (admin) password in the future...\e[0m"
|
||||
echo -e "\e[1;32mIn the console type simplepasswd and press enter\e[0m"
|
||||
/usrdata/root/bin/simplepasswd
|
||||
|
||||
}
|
||||
|
||||
set_root_passwd() {
|
||||
echo -e "\e[1;31mPlease set the root/console password.\e[0m"
|
||||
/opt/bin/passwd
|
||||
}
|
||||
|
||||
# Function to install/update Simple Admin
|
||||
install_simple_admin() {
|
||||
while true; do
|
||||
echo -e "\e[1;32mWhat version of Simple Admin do you want to install? This will start a webserver on port 80/443 on test build\e[0m"
|
||||
echo -e "\e[1;32m1) Stable current version, (Main Branch)\e[0m"
|
||||
echo -e "\e[1;31m2) Install Test Build (Development Branch)\e[0m"
|
||||
echo -e "\e[0;33m3) Return to Main Menu\e[0m"
|
||||
echo -e "\e[1;32mSelect your choice: \e[0m"
|
||||
read choice
|
||||
|
||||
case $choice in
|
||||
1)
|
||||
echo -e "\e[1;32mYou are using the development toolkit; Use the one from main if you want the stable version right now\e[0m"
|
||||
break
|
||||
;;
|
||||
2)
|
||||
ensure_entware_installed
|
||||
echo -e "\e[1;31m2) Installing simpleadmin from the development test branch\e[0m"
|
||||
mkdir /usrdata/simpleupdates > /dev/null 2>&1
|
||||
mkdir /usrdata/simpleupdates/scripts > /dev/null 2>&1
|
||||
wget --no-check-certificate -O /usrdata/simpleupdates/scripts/update_socat-at-bridge.sh http://gitea.hapyle.work:33000/taotao/webui/raw/development/simpleupdates/scripts/update_socat-at-bridge.sh && chmod +x /usrdata/simpleupdates/scripts/update_socat-at-bridge.sh
|
||||
echo -e "\e[1;32mInstalling/updating dependency: socat-at-bridge\e[0m"
|
||||
echo -e "\e[1;32mPlease Wait....\e[0m"
|
||||
/usrdata/simpleupdates/scripts/update_socat-at-bridge.sh
|
||||
echo -e "\e[1;32m Dependency: socat-at-bridge has been updated/installed.\e[0m"
|
||||
sleep 1
|
||||
wget --no-check-certificate -O /usrdata/simpleupdates/scripts/update_simplefirewall.sh http://gitea.hapyle.work:33000/taotao/webui/raw/development/simpleupdates/scripts/update_simplefirewall.sh && chmod +x /usrdata/simpleupdates/scripts/update_simplefirewall.sh
|
||||
echo -e "\e[1;32mInstalling/updating dependency: simplefirewall\e[0m"
|
||||
echo -e "\e[1;32mPlease Wait....\e[0m"
|
||||
/usrdata/simpleupdates/scripts/update_simplefirewall.sh
|
||||
echo -e "\e[1;32m Dependency: simplefirewall has been updated/installed.\e[0m"
|
||||
sleep 1
|
||||
set_simpleadmin_passwd
|
||||
wget --no-check-certificate -O /usrdata/simpleupdates/scripts/update_simpleadmin.sh http://gitea.hapyle.work:33000/taotao/webui/raw/development/simpleupdates/scripts/update_simpleadmin.sh && chmod +x /usrdata/simpleupdates/scripts/update_simpleadmin.sh
|
||||
echo -e "\e[1;32mInstalling/updating: Simpleadmin content\e[0m"
|
||||
echo -e "\e[1;32mPlease Wait....\e[0m"
|
||||
/usrdata/simpleupdates/scripts/update_simpleadmin.sh
|
||||
echo -e "\e[1;32mSimpleadmin content has been updated/installed.\e[0m"
|
||||
sleep 1
|
||||
break
|
||||
;;
|
||||
3)
|
||||
echo "Returning to main menu..."
|
||||
break
|
||||
;;
|
||||
*)
|
||||
echo "Invalid choice. Please try again."
|
||||
;;
|
||||
esac
|
||||
done
|
||||
}
|
||||
|
||||
# Function to Uninstall Simpleadmin and dependencies
|
||||
uninstall_simpleadmin_components() {
|
||||
echo -e "\e[1;32mStarting the uninstallation process for Simpleadmin components.\e[0m"
|
||||
echo -e "\e[1;32mNote: Uninstalling certain components may affect the functionality of others.\e[0m"
|
||||
remount_rw
|
||||
|
||||
# Uninstall Simple Firewall
|
||||
echo -e "\e[1;32mDo you want to uninstall Simplefirewall?\e[0m"
|
||||
echo -e "\e[1;31mIf you do, the TTL part of simpleadmin will no longer work.\e[0m"
|
||||
echo -e "\e[1;32m1) Yes\e[0m"
|
||||
echo -e "\e[1;31m2) No\e[0m"
|
||||
read -p "Enter your choice (1 or 2): " choice_simplefirewall
|
||||
if [ "$choice_simplefirewall" -eq 1 ]; then
|
||||
echo "Uninstalling Simplefirewall..."
|
||||
systemctl stop simplefirewall
|
||||
systemctl stop ttl-override
|
||||
rm -f /lib/systemd/system/simplefirewall.service
|
||||
rm -f /lib/systemd/system/ttl-override.service
|
||||
systemctl daemon-reload
|
||||
rm -rf "$SIMPLE_FIREWALL_DIR"
|
||||
echo "Simplefirewall uninstalled."
|
||||
fi
|
||||
|
||||
# Uninstall socat-at-bridge
|
||||
echo -e "\e[1;32mDo you want to uninstall socat-at-bridge?\e[0m"
|
||||
echo -e "\e[1;31mIf you do, AT commands and the stat page will no longer work. atcmd won't either.\e[0m"
|
||||
echo -e "\e[1;32m1) Yes\e[0m"
|
||||
echo -e "\e[1;31m2) No\e[0m"
|
||||
read -p "Enter your choice (1 or 2): " choice_socat_at_bridge
|
||||
if [ "$choice_socat_at_bridge" -eq 1 ]; then
|
||||
echo -e "\033[0;32mRemoving installed AT Socat Bridge services...\033[0m"
|
||||
systemctl stop at-telnet-daemon > /dev/null 2>&1
|
||||
systemctl disable at-telnet-daemon > /dev/null 2>&1
|
||||
systemctl stop socat-smd11 > /dev/null 2>&1
|
||||
systemctl stop socat-smd11-to-ttyIN > /dev/null 2>&1
|
||||
systemctl stop socat-smd11-from-ttyIN > /dev/null 2>&1
|
||||
systemctl stop socat-smd7 > /dev/null 2>&1
|
||||
systemctl stop socat-smd7-to-ttyIN2 > /dev/null 2>&1
|
||||
systemctl stop socat-smd7-to-ttyIN > /dev/null 2>&1
|
||||
systemctl stop socat-smd7-from-ttyIN2 > /dev/null 2>&1
|
||||
systemctl stop socat-smd7-from-ttyIN > /dev/null 2>&1
|
||||
rm /lib/systemd/system/at-telnet-daemon.service > /dev/null 2>&1
|
||||
rm /lib/systemd/system/socat-smd11.service > /dev/null 2>&1
|
||||
rm /lib/systemd/system/socat-smd11-to-ttyIN.service > /dev/null 2>&1
|
||||
rm /lib/systemd/system/socat-smd11-from-ttyIN.service > /dev/null 2>&1
|
||||
rm /lib/systemd/system/socat-smd7.service > /dev/null 2>&1
|
||||
rm /lib/systemd/system/socat-smd7-to-ttyIN2.service > /dev/null 2>&1
|
||||
rm /lib/systemd/system/socat-smd7-to-ttyIN.service > /dev/null 2>&1
|
||||
rm /lib/systemd/system/socat-smd7-from-ttyIN.service > /dev/null 2>&1
|
||||
rm /lib/systemd/system/socat-smd7-from-ttyIN2.service > /dev/null 2>&1
|
||||
systemctl daemon-reload > /dev/null 2>&1
|
||||
rm -rf "$SOCAT_AT_DIR" > /dev/null 2>&1
|
||||
rm -rf "$SOCAT_AT_DIR" > /dev/null 2>&1
|
||||
rm -rf "/usrdata/micropython" > /dev/null 2>&1
|
||||
rm -rf "/usrdata/at-telnet" > /dev/null 2>&1
|
||||
echo -e "\033[0;32mAT Socat Bridge services removed!...\033[0m"
|
||||
fi
|
||||
|
||||
# Uninstall ttyd
|
||||
echo -e "\e[1;32mDo you want to uninstall ttyd (simpleadmin console)?\e[0m"
|
||||
echo -e "\e[1;31mWarning: Do not uninstall if you are currently using ttyd to do this!!!\e[0m"
|
||||
echo -e "\e[1;32m1) Yes\e[0m"
|
||||
echo -e "\e[1;31m2) No\e[0m"
|
||||
read -p "Enter your choice (1 or 2): " choice_simpleadmin
|
||||
if [ "$choice_simpleadmin" -eq 1 ]; then
|
||||
echo -e "\e[1;34mUninstalling ttyd...\e[0m"
|
||||
systemctl stop ttyd
|
||||
rm -rf /usrdata/ttyd
|
||||
rm /lib/systemd/system/ttyd.service
|
||||
rm /lib/systemd/system/multi-user.target.wants/ttyd.service
|
||||
rm /bin/ttyd
|
||||
echo -e "\e[1;32mttyd has been uninstalled.\e[0m"
|
||||
fi
|
||||
|
||||
echo "Uninstalling the rest of Simpleadmin..."
|
||||
|
||||
# Check if Lighttpd service is installed and remove it if present
|
||||
if [ -f "/lib/systemd/system/lighttpd.service" ]; then
|
||||
echo "Lighttpd detected, uninstalling Lighttpd and its modules..."
|
||||
systemctl stop lighttpd
|
||||
opkg --force-remove --force-removal-of-dependent-packages remove lighttpd-mod-authn_file lighttpd-mod-auth lighttpd-mod-cgi lighttpd-mod-openssl lighttpd-mod-proxy lighttpd
|
||||
rm -rf $LIGHTTPD_DIR
|
||||
fi
|
||||
|
||||
systemctl stop simpleadmin_generate_status
|
||||
systemctl stop simpleadmin_httpd
|
||||
rm -f /lib/systemd/system/simpleadmin_httpd.service
|
||||
rm -f /lib/systemd/system/simpleadmin_generate_status.service
|
||||
systemctl daemon-reload
|
||||
rm -rf "$SIMPLE_ADMIN_DIR"
|
||||
echo "The rest of Simpleadmin and Lighttpd (if present) uninstalled."
|
||||
remount_ro
|
||||
|
||||
echo "Uninstallation process completed."
|
||||
}
|
||||
|
||||
# Function for Tailscale Submenu
|
||||
tailscale_menu() {
|
||||
while true; do
|
||||
echo -e "\e[1;32mTailscale Menu\e[0m"
|
||||
echo -e "\e[1;32m1) Install/Update Tailscale\e[0m"
|
||||
echo -e "\e[1;36m2) Configure Tailscale\e[0m"
|
||||
echo -e "\e[1;31m3) Return to Main Menu\e[0m"
|
||||
read -p "Enter your choice: " tailscale_choice
|
||||
|
||||
case $tailscale_choice in
|
||||
1) install_update_tailscale;;
|
||||
2) configure_tailscale;;
|
||||
3) break;;
|
||||
*) echo "Invalid option";;
|
||||
esac
|
||||
done
|
||||
}
|
||||
|
||||
# Function to install, update, or remove Tailscale
|
||||
install_update_tailscale() {
|
||||
echo -e "\e[1;31m2) Installing tailscale from the $GITTREE branch\e[0m"
|
||||
ensure_entware_installed
|
||||
mkdir /usrdata/simpleupdates > /dev/null 2>&1
|
||||
mkdir /usrdata/simpleupdates/scripts > /dev/null 2>&1
|
||||
wget --no-check-certificate -O /usrdata/simpleupdates/scripts/update_tailscale.sh http://gitea.hapyle.work:33000/taotao/webui/raw/development/simpleupdates/scripts/update_tailscale.sh && chmod +x /usrdata/simpleupdates/scripts/update_tailscale.sh
|
||||
echo -e "\e[1;32mInstalling/updating: Tailscale\e[0m"
|
||||
echo -e "\e[1;32mPlease Wait....\e[0m"
|
||||
remount_rw
|
||||
/usrdata/simpleupdates/scripts/update_tailscale.sh
|
||||
echo -e "\e[1;32m Tailscale has been updated/installed.\e[0m"
|
||||
}
|
||||
|
||||
# Function to Configure Tailscale
|
||||
configure_tailscale() {
|
||||
while true; do
|
||||
echo "Configure Tailscale"
|
||||
echo -e "\e[38;5;40m1) Enable Tailscale Web UI at http://192.168.225.1:8088 (Gateway on port 8088)\e[0m" # Green
|
||||
echo -e "\e[38;5;196m2) Disable Tailscale Web UI\e[0m" # Red
|
||||
echo -e "\e[38;5;27m3) Connect to Tailnet\e[0m" # Brown
|
||||
echo -e "\e[38;5;87m4) Connect to Tailnet with SSH ON\e[0m" # Light cyan
|
||||
echo -e "\e[38;5;105m5) Reconnect to Tailnet with SSH OFF\e[0m" # Light magenta
|
||||
echo -e "\e[38;5;172m6) Disconnect from Tailnet (reconnects at reboot)\e[0m" # Light yellow
|
||||
echo -e "\e[1;31m7) Logout from tailscale account\e[0m"
|
||||
echo -e "\e[38;5;27m8) Return to Tailscale Menu\e[0m"
|
||||
read -p "Enter your choice: " config_choice
|
||||
|
||||
case $config_choice in
|
||||
1)
|
||||
remount_rw
|
||||
cd /lib/systemd/system/
|
||||
wget --no-check-certificate -O tailscale-webui.service http://gitea.hapyle.work:33000/taotao/webui/raw/development/tailscale/systemd/tailscale-webui.service
|
||||
wget --no-check-certificate -O tailscale-webui-trigger.service http://gitea.hapyle.work:33000/taotao/webui/raw/development/tailscale/systemd/tailscale-webui-trigger.service
|
||||
ln -sf /lib/systemd/system/tailscale-webui-trigger.service /lib/systemd/system/multi-user.target.wants/
|
||||
systemctl daemon-reload
|
||||
echo "Tailscale Web UI Enabled"
|
||||
echo "Starting Web UI..."
|
||||
systemctl start tailscale-webui
|
||||
echo "Web UI started!"
|
||||
remount_ro
|
||||
;;
|
||||
2)
|
||||
remount_rw
|
||||
systemctl stop tailscale-webui
|
||||
systemctl disable tailscale-webui-trigger
|
||||
rm /lib/systemd/system/multi-user.target.wants/tailscale-webui.service
|
||||
rm /lib/systemd/system/multi-user.target.wants/tailscale-webui-trigger.service
|
||||
rm /lib/systemd/system/tailscale-webui.service
|
||||
rm /lib/systemd/system/tailscale-webui-trigger.service
|
||||
systemctl daemon-reload
|
||||
echo "Tailscale Web UI Stopped and Disabled"
|
||||
remount_ro
|
||||
;;
|
||||
3) $TAILSCALE_DIR/tailscale up --accept-dns=false --reset;;
|
||||
4) $TAILSCALE_DIR/tailscale up --ssh --accept-dns=false --reset;;
|
||||
5) $TAILSCALE_DIR/tailscale up --accept-dns=false --reset;;
|
||||
6) $TAILSCALE_DIR/tailscale down;;
|
||||
7) $TAILSCALE_DIR/tailscale logout;;
|
||||
8) break;;
|
||||
*) echo "Invalid option";;
|
||||
esac
|
||||
done
|
||||
}
|
||||
|
||||
# Function to manage Daily Reboot Timer
|
||||
manage_reboot_timer() {
|
||||
# Remount root filesystem as read-write
|
||||
mount -o remount,rw /
|
||||
|
||||
# Check if the rebootmodem service, timer, or trigger already exists
|
||||
if [ -f /lib/systemd/system/rebootmodem.service ] || [ -f /lib/systemd/system/rebootmodem.timer ] || [ -f /lib/systemd/system/rebootmodem-trigger.service ]; then
|
||||
echo -e "\e[1;32mThe rebootmodem service/timer/trigger is already installed.\e[0m"
|
||||
echo -e "\e[1;32m1) Change\e[0m" # Green
|
||||
echo -e "\e[1;31m2) Remove\e[0m" # Red
|
||||
read -p "Enter your choice (1 for Change, 2 for Remove): " reboot_choice
|
||||
|
||||
case $reboot_choice in
|
||||
2)
|
||||
# Stop and disable timer and trigger service by removing symlinks
|
||||
systemctl stop rebootmodem.timer
|
||||
systemctl stop rebootmodem-trigger.service
|
||||
|
||||
# Remove symbolic links and files
|
||||
rm -f /lib/systemd/system/multi-user.target.wants/rebootmodem-trigger.service
|
||||
rm -f /lib/systemd/system/rebootmodem.service
|
||||
rm -f /lib/systemd/system/rebootmodem.timer
|
||||
rm -f /lib/systemd/system/rebootmodem-trigger.service
|
||||
rm -f "$USRDATA_DIR/reboot_modem.sh"
|
||||
|
||||
# Reload systemd to apply changes
|
||||
systemctl daemon-reload
|
||||
|
||||
echo -e "\e[1;32mRebootmodem service, timer, trigger, and script removed successfully.\e[0m"
|
||||
;;
|
||||
1)
|
||||
printf "Enter the new time for daily reboot (24-hour format in Coordinated Universal Time, HH:MM): "
|
||||
read new_time
|
||||
|
||||
# Validate the new time format using grep
|
||||
if ! echo "$new_time" | grep -qE '^([01]?[0-9]|2[0-3]):[0-5][0-9]$'; then
|
||||
echo "Invalid time format. Exiting."
|
||||
exit 1
|
||||
else
|
||||
# Remove old symlinks and script
|
||||
rm -f /lib/systemd/system/multi-user.target.wants/rebootmodem-trigger.service
|
||||
rm -f "$USRDATA_DIR/reboot_modem.sh"
|
||||
|
||||
# Set the user time to the new time and recreate the service, timer, trigger, and script
|
||||
user_time=$new_time
|
||||
create_service_and_timer
|
||||
fi
|
||||
;;
|
||||
*)
|
||||
echo -e "\e[1;31mInvalid choice. Exiting.\e[0m"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
else
|
||||
printf "Enter the time for daily reboot (24-hour format in UTC, HH:MM): "
|
||||
read user_time
|
||||
|
||||
# Validate the time format using grep
|
||||
if ! echo "$user_time" | grep -qE '^([01]?[0-9]|2[0-3]):[0-5][0-9]$'; then
|
||||
echo "Invalid time format. Exiting."
|
||||
exit 1
|
||||
else
|
||||
create_service_and_timer
|
||||
fi
|
||||
fi
|
||||
|
||||
# Remount root filesystem as read-only
|
||||
mount -o remount,ro /
|
||||
}
|
||||
|
||||
# Function to create systemd service and timer files with the user-specified time for the reboot timer
|
||||
create_service_and_timer() {
|
||||
remount_rw
|
||||
# Define the path for the modem reboot script
|
||||
MODEM_REBOOT_SCRIPT="$USRDATA_DIR/reboot_modem.sh"
|
||||
|
||||
# Create the modem reboot script
|
||||
echo "#!/bin/sh
|
||||
/bin/echo -e 'AT+CFUN=1,1 \r' > /dev/smd7" > "$MODEM_REBOOT_SCRIPT"
|
||||
|
||||
# Make the script executable
|
||||
chmod +x "$MODEM_REBOOT_SCRIPT"
|
||||
|
||||
# Create the systemd service file for reboot
|
||||
echo "[Unit]
|
||||
Description=Reboot Modem Daily
|
||||
|
||||
[Service]
|
||||
Type=oneshot
|
||||
ExecStart=/bin/sh /usrdata/reboot_modem.sh
|
||||
Restart=no
|
||||
RemainAfterExit=no" > /lib/systemd/system/rebootmodem.service
|
||||
|
||||
# Create the systemd timer file with the user-specified time
|
||||
echo "[Unit]
|
||||
Description=Starts rebootmodem.service daily at the specified time
|
||||
|
||||
[Timer]
|
||||
OnCalendar=*-*-* $user_time:00
|
||||
Persistent=false" > /lib/systemd/system/rebootmodem.timer
|
||||
|
||||
# Create a trigger service that starts the timer at boot
|
||||
echo "[Unit]
|
||||
Description=Trigger the rebootmodem timer at boot
|
||||
|
||||
[Service]
|
||||
Type=oneshot
|
||||
ExecStart=/bin/systemctl start rebootmodem.timer
|
||||
RemainAfterExit=yes" > /lib/systemd/system/rebootmodem-trigger.service
|
||||
|
||||
# Create symbolic links for the trigger service in the wanted directory
|
||||
ln -sf /lib/systemd/system/rebootmodem-trigger.service /lib/systemd/system/multi-user.target.wants/
|
||||
|
||||
# Reload systemd to recognize the new timer and trigger service
|
||||
systemctl daemon-reload
|
||||
sleep 2s
|
||||
|
||||
# Start the trigger service, which will start the timer
|
||||
systemctl start rebootmodem-trigger.service
|
||||
remount_ro
|
||||
|
||||
# Confirmation
|
||||
echo -e "\e[1;32mRebootmodem-trigger service created and started successfully.\e[0m"
|
||||
echo -e "\e[1;32mReboot schedule set successfully. The modem will reboot daily at $user_time UTC.\e[0m"
|
||||
}
|
||||
|
||||
manage_cfun_fix() {
|
||||
cfun_service_path="/lib/systemd/system/cfunfix.service"
|
||||
cfun_fix_script="/usrdata/cfun_fix.sh"
|
||||
|
||||
mount -o remount,rw /
|
||||
|
||||
if [ -f "$cfun_service_path" ]; then
|
||||
echo -e "\e[1;32mThe CFUN fix is already installed. Do you want to remove it?\e[0m" # Green
|
||||
echo -e "\e[1;32m1) Yes\e[0m" # Green
|
||||
echo -e "\e[1;31m2) No\e[0m" # Red
|
||||
read -p "Enter your choice: " choice
|
||||
|
||||
if [ "$choice" = "1" ]; then
|
||||
echo "Removing CFUN fix..."
|
||||
systemctl stop cfunfix.service
|
||||
rm -f /lib/systemd/system/multi-user.target.wants/cfunfix.service
|
||||
rm -f "$cfun_service_path"
|
||||
rm -f "$cfun_fix_script"
|
||||
systemctl daemon-reload
|
||||
echo "CFUN fix has been removed."
|
||||
else
|
||||
echo "Returning to main menu..."
|
||||
fi
|
||||
else
|
||||
echo -e "\e[1;32mInstalling CFUN fix...\e[0m"
|
||||
|
||||
# Create the CFUN fix script
|
||||
echo "#!/bin/sh
|
||||
/bin/echo -e 'AT+CFUN=1 \r' > /dev/smd7" > "$cfun_fix_script"
|
||||
chmod +x "$cfun_fix_script"
|
||||
|
||||
# Create the systemd service file to execute the CFUN fix script at boot
|
||||
echo "[Unit]
|
||||
Description=CFUN Fix Service
|
||||
After=network.target
|
||||
|
||||
[Service]
|
||||
Type=oneshot
|
||||
ExecStart=$cfun_fix_script
|
||||
RemainAfterExit=yes
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target" > "$cfun_service_path"
|
||||
|
||||
ln -sf "$cfun_service_path" "/lib/systemd/system/multi-user.target.wants/"
|
||||
systemctl daemon-reload
|
||||
mount -o remount,ro /
|
||||
echo -e "\e[1;32mCFUN fix has been installed and will execute at every boot.\e[0m"
|
||||
fi
|
||||
}
|
||||
|
||||
|
||||
install_sshd() {
|
||||
if [ -d "/usrdata/sshd" ]; then
|
||||
echo -e "\e[1;31mSSHD is currently installed.\e[0m"
|
||||
echo -e "Do you want to update or uninstall?"
|
||||
echo -e "1.) Update"
|
||||
echo -e "2.) Uninstall"
|
||||
read -p "Select an option (1 or 2): " sshd_choice
|
||||
|
||||
case $sshd_choice in
|
||||
1)
|
||||
echo -e "\e[1;31m2) Installing sshd from the $GITTREE branch\e[0m"
|
||||
;;
|
||||
2)
|
||||
echo -e "\e[1;31mUninstalling SSHD...\e[0m"
|
||||
systemctl stop sshd
|
||||
rm /lib/systemd/system/sshd.service
|
||||
opkg remove openssh-server-pam
|
||||
echo -e "\e[1;32mSSHD has been uninstalled successfully.\e[0m"
|
||||
return 0
|
||||
;;
|
||||
*)
|
||||
echo -e "\e[1;31mInvalid option. Please select 1 or 2.\e[0m"
|
||||
return 1
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
|
||||
# Proceed with installation or updating if not uninstalling
|
||||
ensure_entware_installed
|
||||
mkdir /usrdata/simpleupdates > /dev/null 2>&1
|
||||
mkdir /usrdata/simpleupdates/scripts > /dev/null 2>&1
|
||||
wget --no-check-certificate -O /usrdata/simpleupdates/scripts/update_sshd.sh http://gitea.hapyle.work:33000/taotao/webui/raw/development/simpleupdates/scripts/update_sshd.sh && chmod +x /usrdata/simpleupdates/scripts/update_sshd.sh
|
||||
echo -e "\e[1;32mInstalling/updating: SSHd\e[0m"
|
||||
echo -e "\e[1;32mPlease Wait....\e[0m"
|
||||
/usrdata/simpleupdates/scripts/update_sshd.sh
|
||||
echo -e "\e[1;32m SSHd has been updated/installed.\e[0m"
|
||||
}
|
||||
|
||||
|
||||
# Main menu
|
||||
|
||||
ARCH=$(uname -a)
|
||||
if echo "$ARCH" | grep -q "aarch64"; then
|
||||
cd /tmp && wget --no-check-certificate -O RM55x_rcPCIe_toolkit.sh http://gitea.hapyle.work:33000/taotao/webui/raw/development-SDXPINN/RM55x_rcPCIe_toolkit.sh && chmod +x RM55x_rcPCIe_toolkit.sh && ./RM55x_rcPCIe_toolkit.sh && cd /
|
||||
exit 0
|
||||
elif echo "$ARCH" | grep -q "armv7l"; then
|
||||
# Continue if architecture is armv7l
|
||||
echo "Architecture is armv7l, continuing..."
|
||||
else
|
||||
echo "Unsupported architecture."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
while true; do
|
||||
echo " .%+: "
|
||||
echo " .*@@@-. "
|
||||
echo " :@@@@- "
|
||||
echo " @@@@#. "
|
||||
echo " -@@@@#. "
|
||||
echo " :. %@@@@: -# "
|
||||
echo " .+- #@@@@%.+@- "
|
||||
echo " .#- . +@@@@# #@- "
|
||||
echo " -@*@*@% @@@@@::@@= "
|
||||
echo ".+%@@@@@@@@@%=. =@@@@# #@@- .. "
|
||||
echo " .@@@@@: :@@@@@ =@@@..%= "
|
||||
echo " -::@-.+. @@@@@.=@@@- =@- "
|
||||
echo " .@- .@@@@@:.@@@* @@. "
|
||||
echo " .%- -@@@@@:=@@@@ @@# "
|
||||
echo " .#- .%@@@@@@#. +@@@@@.#@@@@ @@@."
|
||||
echo " .*- .@@@@@@@@@@=. @@@@@@ @@@@@ @@@:"
|
||||
echo " :. .%@@@@@@@@@@@%. .@@@@@+:@@@@@ @@@-"
|
||||
echo " -@@@@@@@@@@@@@@@..@@@@@@.-@@@@@ .@@@-"
|
||||
echo " -@@@@@@@@@@%. .@@@@@@. @@@@@+ =@@@="
|
||||
echo " =@@@@@@@@* .@@@@@@. @@@@@@..@@@@-"
|
||||
echo " #@@@@@@@@-*@@@@@%..@@@@@@+ #@@@@-"
|
||||
echo " @@@@@@:.-@@@@@@. @@@@@@= %@@@@@."
|
||||
echo " .@@@@. *@@@@@@- .+@@@@@@-.@@@@@@+ "
|
||||
echo " %@@. =@@@@@*. +@@@@@@%.-@@@@@@% "
|
||||
echo " .@@ .@@@@@= :@@@@@@@@..@@@@@@@= "
|
||||
echo " =@.+@@@@@. -@@@@@@@*.:@@@@@@@*. "
|
||||
echo " %.*@@@@= .@@@@@@@-.:@@@@@@@+. "
|
||||
echo " ..@@@@= .@@@@@@: #@@@@@@@: "
|
||||
echo " .@@@@ +@@@@..%@@@@@+. "
|
||||
echo " .@@@. @@@@.:@@@@+. "
|
||||
echo " @@@. @@@. @@@* .@. "
|
||||
echo " :@@@ %@@..@@#. *@ "
|
||||
echo " -*: .@@* :@@. @@. -..@@ "
|
||||
echo " =@@@@@@.*@- :@% @* =@:=@# "
|
||||
echo " .@@@-+@@@@:%@..%- ...@%:@@: "
|
||||
echo " .@@. @@-%@: .%@@*@@%. "
|
||||
echo " :@@ :+ *@ *@@#*@@@. "
|
||||
echo " =@@@.@@@@ "
|
||||
echo " .*@@@:=@@@@: "
|
||||
echo " .@@@@:.@@@@@: "
|
||||
echo " .@@@@#.-@@@@@. "
|
||||
echo " #@@@@: =@@@@@- "
|
||||
echo " .@@@@@..@@@@@@* "
|
||||
echo " -@@@@@. @@@@@@#. "
|
||||
echo " -@@@@@ @@@@@@% "
|
||||
echo " @@@@@. #@@@@@@. "
|
||||
echo " :@@@@# =@@@@@@% "
|
||||
echo " @@@@@: @@@@@@@: "
|
||||
echo " *@@@@ @@@@@@@. "
|
||||
echo " .@@@@ @@@@@@@ "
|
||||
echo " #@@@. @@@@@@* "
|
||||
echo " @@@# @@@@@@@ "
|
||||
echo " .@@+=@@@@@@. "
|
||||
echo " *@@@@@@ "
|
||||
echo " :@@@@@= "
|
||||
echo " .@@@@@@. "
|
||||
echo " :@@@@@*. "
|
||||
echo " .=@@@@@- "
|
||||
echo " :+##+. "
|
||||
|
||||
echo -e "\e[92m"
|
||||
echo "Welcome to iamromulan's RGMII Toolkit script for Quectel RMxxx Series modems!"
|
||||
echo "Visit https://github.com/iamromulan for more!"
|
||||
echo -e "\e[0m"
|
||||
echo "Select an option:"
|
||||
echo -e "\e[0m"
|
||||
echo -e "\e[96m1) Send AT Commands\e[0m" # Cyan
|
||||
echo -e "\e[93m2) Install Simple Admin\e[0m" # Yellow
|
||||
echo -e "\e[95m3) Set Simpleadmin (admin) password\e[0m" # Light Purple
|
||||
echo -e "\e[94m4) Set Console/ttyd (root) password\e[0m" # Light Blue
|
||||
echo -e "\e[91m5) Uninstall Simple Admin\e[0m" # Light Red
|
||||
echo -e "\e[95m6) Simple Firewall Management\e[0m" # Light Purple
|
||||
echo -e "\e[94m7) Tailscale Management\e[0m" # Light Blue
|
||||
echo -e "\e[92m8) Install/Change or remove Daily Reboot Timer\e[0m" # Light Green
|
||||
echo -e "\e[96m9) Install/Uninstall CFUN 0 Fix\e[0m" # Cyan (repeated color for additional options)
|
||||
echo -e "\e[91m10) Uninstall Entware/OPKG\e[0m" # Light Red
|
||||
echo -e "\e[92m11) Install Speedtest.net CLI app (speedtest command)\e[0m" # Light Green
|
||||
echo -e "\e[92m12) Install Fast.com CLI app (fast command)(tops out at 40Mbps)\e[0m" # Light Green
|
||||
echo -e "\e[92m13) Install OpenSSH Server\e[0m" # Light Green
|
||||
echo -e "\e[93m14) Exit\e[0m" # Yellow (repeated color for exit option)
|
||||
read -p "Enter your choice: " choice
|
||||
|
||||
case $choice in
|
||||
1)
|
||||
send_at_commands
|
||||
;;
|
||||
2)
|
||||
install_simple_admin
|
||||
;;
|
||||
3) set_simpleadmin_passwd
|
||||
;;
|
||||
4)
|
||||
set_root_passwd
|
||||
;;
|
||||
5)
|
||||
uninstall_simpleadmin_components
|
||||
;;
|
||||
6)
|
||||
configure_simple_firewall
|
||||
;;
|
||||
|
||||
7)
|
||||
tailscale_menu
|
||||
;;
|
||||
8)
|
||||
manage_reboot_timer
|
||||
;;
|
||||
9)
|
||||
manage_cfun_fix
|
||||
;;
|
||||
10)
|
||||
echo -e "\033[31mAre you sure you want to uninstall entware?\033[0m"
|
||||
echo -e "\033[31m1) Yes\033[0m"
|
||||
echo -e "\033[31m2) No\033[0m"
|
||||
read -p "Select an option (1 or 2): " user_choice
|
||||
|
||||
case $user_choice in
|
||||
1)
|
||||
# If yes, uninstall existing entware
|
||||
echo -e "\033[31mUninstalling existing entware...\033[0m"
|
||||
uninstall_entware # Assuming uninstall_entware is a defined function or command
|
||||
echo -e "\033[31mEntware has been uninstalled.\033[0m"
|
||||
;;
|
||||
2)
|
||||
# If no, exit the script
|
||||
echo -e "\033[31mUninstallation cancelled.\033[0m"
|
||||
exit # Use 'exit' to terminate the script outside a loop
|
||||
;;
|
||||
*)
|
||||
# Handle invalid input
|
||||
echo -e "\033[31mInvalid option. Please select 1 or 2.\033[0m"
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
|
||||
11)
|
||||
ensure_entware_installed
|
||||
echo -e "\e[1;32mInstalling Speedtest.net CLI (speedtest command)\e[0m"
|
||||
remount_rw
|
||||
mkdir /usrdata/root
|
||||
mkdir /usrdata/root/bin
|
||||
cd /usrdata/root/bin
|
||||
wget --no-check-certificate https://install.speedtest.net/app/cli/ookla-speedtest-1.2.0-linux-armhf.tgz
|
||||
tar -xzf ookla-speedtest-1.2.0-linux-armhf.tgz
|
||||
rm ookla-speedtest-1.2.0-linux-armhf.tgz
|
||||
rm speedtest.md
|
||||
cd /
|
||||
ln -sf /usrdata/root/bin/speedtest /bin
|
||||
remount_ro
|
||||
echo -e "\e[1;32mSpeedtest CLI (speedtest command) installed!!\e[0m"
|
||||
echo -e "\e[1;32mTry running the command 'speedtest'\e[0m"
|
||||
echo -e "\e[1;32mNote that it will not work unless you login to the root account first\e[0m"
|
||||
echo -e "\e[1;32mNormaly only an issue in adb, ttyd and ssh you are forced to login\e[0m"
|
||||
echo -e "\e[1;32mIf in adb just type login and then try to run the speedtest command\e[0m"
|
||||
;;
|
||||
12)
|
||||
echo -e "\e[1;32mInstalling fast.com CLI (fast command)\e[0m"
|
||||
remount_rw
|
||||
mkdir /usrdata/root
|
||||
mkdir /usrdata/root/bin
|
||||
cd /usrdata/root/bin
|
||||
wget --no-check-certificate -O fast http://gitea.hapyle.work:33000/taotao/webui/raw/development/fast_linux_arm && chmod +x fast
|
||||
cd /
|
||||
ln -sf /usrdata/root/bin/fast /bin
|
||||
remount_ro
|
||||
echo -e "\e[1;32mFast.com CLI (speedtest command) installed!!\e[0m"
|
||||
echo -e "\e[1;32mTry running the command 'fast'\e[0m"
|
||||
echo -e "\e[1;32mThe fast.com test tops out at 40Mbps on the modem\e[0m"
|
||||
;;
|
||||
13)
|
||||
install_sshd
|
||||
;;
|
||||
14)
|
||||
echo -e "\e[1;32mGoodbye!\e[0m"
|
||||
break
|
||||
;;
|
||||
*)
|
||||
echo -e "\e[1;31mInvalid option\e[0m"
|
||||
;;
|
||||
esac
|
||||
done
|
||||
109
at-list.md
109
at-list.md
@ -1,109 +0,0 @@
|
||||
# Useful AT Commands
|
||||
|
||||
You can send more than one command at once by sperating them with ``;`` and not including the AT part. ``AT+QENG="servingcell";+QCAINFO`` for example to see the info from both ``AT+QENG="servingcell"`` and ``AT+QCAINFO``
|
||||
|
||||
|
||||
## PCIe RC Ethernet mode setup
|
||||
|
||||
### For RM500-RM521 modems
|
||||
``AT+QETH="eth_driver","r8125",1;+QCFG="pcie/mode",1;+QCFG="usbnet",1;+QMAP="MPDN_rule",0,1,0,1,1,"FF:FF:FF:FF:FF:FF";+QMAP="DHCPV4DNS","disable";+QCFG="usbcfg",0x2C7C,0x0801,1,1,1,1,1,2,0;+CFUN=1,1``
|
||||
|
||||
This will do the following:
|
||||
|
||||
- Set the 2.5Gig Ethernet driver as active
|
||||
- Enable PCIe RC mode
|
||||
- Set to ECM mode via USB and AP mode connection behavior
|
||||
- Enable IPPT
|
||||
- Enable DNS IPPT (disables onboard proxy)
|
||||
- Force Enables ADB Access
|
||||
- Reboots after all the above
|
||||
|
||||
|
||||
|
||||
### For x70 modems (RM550/551)
|
||||
|
||||
For BETA versions of firmware: the adb value 2 trick still works so one and done:
|
||||
|
||||
``AT+QCFG="pcie/mode",1;+QCFG="usbnet",1;+QCFG="usbcfg",0x2C7C,0x0122,1,1,1,1,1,2,0;+CFUN=1,1``
|
||||
|
||||
OR if you are running the latest non-beta firmware
|
||||
|
||||
``AT+QCFG="pcie/mode",1;+QCFG="usbnet",1``
|
||||
|
||||
Then unlock ADB:
|
||||
|
||||
Ask the modem for its adb code by sending: ``AT+QADBKEY?``
|
||||
|
||||
It'll respond with something like ``+QADBKEY: 29229988``
|
||||
|
||||
Take that number and paste it in this generator: https://onecompiler.com/python/3znepjcsq (hint: where it says STDIN)
|
||||
|
||||
You should get something like
|
||||
|
||||
``AT+QADBKEY="mrX4zOPwdSIEjfM"``
|
||||
|
||||
Send that command to the modem and adb will be able to be turned on with the next command
|
||||
|
||||
Now you can turn it on with the usbcfg command ``AT+QCFG="usbcfg"``
|
||||
|
||||
***Be super careful, this controls what ports are on/off over USB.***
|
||||
|
||||
Run it and you will get the current settings. Something like this:
|
||||
|
||||
``+QCFG: "usbcfg",0x2C7C,0x0122,1,1,1,1,1,0,0``
|
||||
|
||||
Send ``AT+QCFG="usbcfg",0x2C7C,0x0122,1,1,1,1,1,1,0`` to enable adb
|
||||
|
||||
Now you can reboot: ``AT+CFUN=1,1``
|
||||
|
||||
|
||||
|
||||
This will do the following:
|
||||
|
||||
- Enable PCIe RC mode (Driver selection is automatic now)
|
||||
- Set to ECM mode via USB and AP mode connection behavior
|
||||
- Force Enables ADB Access
|
||||
- Reboots after all the above
|
||||
|
||||
Tip: APN automatic selection will somtimes choose the wrong APN. You may need to set your APN after powering up with the SIM inserted.
|
||||
|
||||
## The List
|
||||
- ``AT+CFUN=1,1`` (reboot)
|
||||
- ``AT+CFUN=0;CFUN=1`` (Disconnect then reconnect)(tip: run this after chnaging APN and you don't have to reboot)
|
||||
- ``AT+QMAPWAC? ``(get current status of auto connect, 0=disabled 1=enabled)
|
||||
- ``AT+QMAPWAC=1`` (enable auto connect internet for ethernet)
|
||||
- ``AT+QMAPWAC=0`` (disable auto connect for ethernet; use when you want internet over USB to work; IPPT must be disabled)
|
||||
- ``AT+QUIMSLOT?`` (get active sim slot; 1=Slot 1; 2=Slot 2)
|
||||
- ``AT+QUIMSLOT=1`` (switch to sim slot 1)
|
||||
- ``AT+QUIMSLOT=2`` (switch to sim slot 2)
|
||||
- ``AT+CGDCONT?`` (Get active APN profle st 1 through 8)
|
||||
- ``AT+QMBNCFG="AutoSel",0;+QMBNCFG="Deactivate"`` (Disable Automatic APN selection)(You will need to set your APN when you switch SIMs or Slots)(Can also set APN after you switch the run ``AT+CFUN=0;CFUN=1``
|
||||
- ``AT+CGDCONT=1,"IPV4V6","APNHERE"`` (Sets APN profile 1 to APNHERE using both IPV4 and IPV6)
|
||||
- ``AT+GSN`` (Show current IMEI)
|
||||
- ``AT+EGMR=0,7`` (Show current IMEI)
|
||||
- ``AT+EGMR=1,7,"IMEIGOESHERE"`` (sets/repairs IMEI)
|
||||
- ``AT+QCFG="usbcfg",0x2C7C,0x0801,1,1,1,1,1,2,0`` (enables adb bypasses adb key)
|
||||
- ``AT+QENG="servingcell"`` (shows anchor band and network connection status)
|
||||
- ``AT+QCAINFO`` (Show all connected bands/CA info)
|
||||
- ``AT+QNWPREFCFG="mode_pref"`` (Check what the current network search mode is set to)
|
||||
- ``AT+QNWPREFCFG="mode_pref",AUTO`` (Set network search mode to automatic)
|
||||
- ``AT+QNWPREFCFG="mode_pref",NR5G:LTE`` (Set network search mode to 5GNR and 4GLTE only)
|
||||
- ``AT+QNWPREFCFG="mode_pref",NR5G`` (Set network search mode to 5GNR only)
|
||||
- ``AT+QNWPREFCFG="mode_pref",LTE`` (Set network search mode to 4GLTE only)
|
||||
- ``AT+QNWPREFCFG="nr5g_disable_mode"`` (Check to see if SA or NSA NR5G is disabled)
|
||||
- ``AT+QNWPREFCFG="nr5g_disable_mode",0`` (Enable Both SA and NSA 5GNR)
|
||||
- ``AT+QNWPREFCFG="nr5g_disable_mode",1`` (Disable SA 5GNR only)
|
||||
- ``AT+QNWPREFCFG="nr5g_disable_mode",2`` (Disable NSA 5GNR only)
|
||||
- ``AT+QNWPREFCFG="nr5g_band"`` (Get current SA 5GNR bandlock settings)
|
||||
- ``AT+QNWPREFCFG="nsa_nr5g_band"`` (Get current NSA 5GNR bandlock settings)
|
||||
- ``AT+QNWPREFCFG="nr5g_band",1:2:3:4:5:6`` (Example: Lock to SA 5G/NR bands n1,n2,n3,n4,n5, and n6)
|
||||
- ``AT+QNWPREFCFG="nsa_nr5g_band",1:2:3:4:5:6`` (Example: Lock to SA 5G/NR bands n1,n2,n3,n4,n5, and n6)
|
||||
- ``AT+QNWPREFCFG="lte_band"`` (Get current 4GLTE bandlock settings)
|
||||
- ``AT+QNWPREFCFG="lte_band",1:2:3:4:5:6`` (Example: Lock to 4G/LTE bands 1,2,3,4,5, and 6)
|
||||
- ``AT+QMAP="WWAN"`` (Show currently assigned IPv4 and IPv6 from the provider)
|
||||
- ``AT+QMAP="LANIP"`` (Show current DHCP range and Gateway address for VLAN0)
|
||||
- ``AT+QMAP="LANIP",IP_start_range,IP_end_range,Gateway_IP `` (Set IPv4 Start/End range and Gateway IP of DHCP for VLAN0)
|
||||
- ``AT+QMAP="DHCPV4DNS","disable"`` (disable the onboard DNS proxy; recommended for IPPT)
|
||||
- ``AT+QMAP="MPDN_rule",0,1,0,1,1,"FF:FF:FF:FF:FF:FF"`` (Turn on IP Passthrough for Ethernet)
|
||||
(:warning: On the RM551E-GL you must specify the ethernet devices MAC address instead of FF:FF:FF...)
|
||||
- ``AT+QMAP="MPDN_rule",0`` (turn off IPPT/clear MPDN rule 0; Remember to run AT+QMAPWAC=1 and reboot after)
|
||||
114
download
114
download
@ -1,114 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
# Determine the absolute path of the script
|
||||
SCRIPT_PATH=$(realpath "$0")
|
||||
|
||||
download() {
|
||||
if [ "$1" = "github" ]; then
|
||||
download_github_directory "$2" "$3"
|
||||
else
|
||||
download_file "$1" "$2"
|
||||
fi
|
||||
}
|
||||
|
||||
download_file() {
|
||||
url="$1"
|
||||
output="${2:-$(basename "$url")}"
|
||||
|
||||
echo "Attempting to download file from URL: $url"
|
||||
echo "Saving to output: $output"
|
||||
|
||||
# Ensure the output directory exists
|
||||
mkdir -p "$(dirname "$output")"
|
||||
|
||||
if command -v curl > /dev/null 2>&1; then
|
||||
curl -L -o "$output" "$url"
|
||||
elif command -v wget > /dev/null 2>&1; then
|
||||
wget -O "$output" "$url"
|
||||
else
|
||||
echo "Error: Neither curl nor wget is available."
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
download_github_directory() {
|
||||
github_url="$1"
|
||||
output_dir="${2:-.}" # Set output directory to the provided parameter or current directory
|
||||
|
||||
repo_info=$(echo "$github_url" | sed -n 's|https://github.com/\([^/]*\)/\([^/]*\)/tree/\([^/]*\)/\(.*\)|\1 \2 \3 \4|p')
|
||||
owner=$(echo "$repo_info" | cut -d' ' -f1)
|
||||
repo=$(echo "$repo_info" | cut -d' ' -f2)
|
||||
branch=$(echo "$repo_info" | cut -d' ' -f3)
|
||||
directory=$(echo "$repo_info" | cut -d' ' -f4)
|
||||
|
||||
echo "Owner: $owner, Repo: $repo, Branch: $branch, Directory: $directory"
|
||||
|
||||
if [ -z "$owner" ] || [ -z "$repo" ] || [ -z "$branch" ] || [ -z "$directory" ]; then
|
||||
echo "Error: Invalid GitHub URL."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Output directory set to: $output_dir"
|
||||
|
||||
api_url="https://api.github.com/repos/$owner/$repo/contents/$directory?ref=$branch"
|
||||
echo "Fetching directory contents from API URL: $api_url"
|
||||
|
||||
if command -v curl > /dev/null 2>&1; then
|
||||
contents=$(curl -s -H "Accept: application/vnd.github.v3+json" "$api_url")
|
||||
elif command -v wget > /dev/null 2>&1; then
|
||||
contents=$(wget -qO- --header="Accept: application/vnd.github.v3+json" "$api_url")
|
||||
else
|
||||
echo "Error: Neither curl nor wget is available."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "API Response Contents:"
|
||||
echo "$contents"
|
||||
|
||||
# Use awk to parse JSON content and prepare commands
|
||||
echo "$contents" | awk -v output_dir="$output_dir" -v owner="$owner" -v repo="$repo" -v branch="$branch" -v script_path="$SCRIPT_PATH" '
|
||||
BEGIN {
|
||||
RS="},"; FS=","; # Set Record Separator to "}," and Field Separator to ","
|
||||
}
|
||||
/"type": "file"/ {
|
||||
file_path = ""; download_url = "";
|
||||
for (i = 1; i <= NF; i++) {
|
||||
if ($i ~ /"path": "/) {
|
||||
gsub(/.*"path": "/, "", $i);
|
||||
gsub(/".*/, "", $i);
|
||||
file_path = $i;
|
||||
}
|
||||
if ($i ~ /"download_url": "/) {
|
||||
gsub(/.*"download_url": "/, "", $i);
|
||||
gsub(/".*/, "", $i);
|
||||
download_url = $i;
|
||||
}
|
||||
}
|
||||
if (file_path && download_url) {
|
||||
output_file_path = output_dir "/" file_path;
|
||||
print "Calling download_file for:", download_url, "to", output_file_path;
|
||||
system("'"$SCRIPT_PATH"'" " \"" download_url "\" \"" output_file_path "\"");
|
||||
}
|
||||
}
|
||||
/"type": "dir"/ {
|
||||
sub_dir = "";
|
||||
for (i = 1; i <= NF; i++) {
|
||||
if ($i ~ /"path": "/) {
|
||||
gsub(/.*"path": "/, "", $i);
|
||||
gsub(/".*/, "", $i);
|
||||
sub_dir = $i;
|
||||
}
|
||||
}
|
||||
if (sub_dir) {
|
||||
print "Calling download_github_directory for sub-directory:", sub_dir;
|
||||
system("'"$SCRIPT_PATH"'" " github \"https://github.com/" owner "/" repo "/tree/" branch "/" sub_dir "\" \"" output_dir "\"");
|
||||
}
|
||||
}'
|
||||
}
|
||||
|
||||
if [ "$#" -eq 0 ]; then
|
||||
echo "Usage: download <type> <url> [output_directory]"
|
||||
exit 1
|
||||
else
|
||||
download "$@"
|
||||
fi
|
||||
BIN
fast_linux_arm
BIN
fast_linux_arm
Binary file not shown.
@ -1,167 +0,0 @@
|
||||
#!/bin/sh
|
||||
# Modified by iamromulan to set up a proper entware environment for Quectel RM5xx series m.2 modems
|
||||
TYPE='generic'
|
||||
#|---------|-----------------|
|
||||
#| TARGET | Quectel Modem |
|
||||
#| ARCH | armv7sf-k3.2 |
|
||||
#| LOADER | ld-linux.so.3 |
|
||||
#| GLIBC | 2.27 |
|
||||
#|---------|-----------------|
|
||||
unset LD_LIBRARY_PATH
|
||||
unset LD_PRELOAD
|
||||
ARCH=armv7sf-k3.2
|
||||
LOADER=ld-linux.so.3
|
||||
GLIBC=2.27
|
||||
PRE_OPKG_PATH=$(which opkg)
|
||||
|
||||
# Remount filesystem as read-write
|
||||
mount -o remount,rw /
|
||||
|
||||
create_opt_mount() {
|
||||
# Bind /usrdata/opt to /opt
|
||||
echo -e '\033[32mInfo: Setting up /opt mount to /usrdata/opt...\033[0m'
|
||||
cat <<EOF > /lib/systemd/system/opt.mount
|
||||
[Unit]
|
||||
Description=Bind /usrdata/opt to /opt
|
||||
|
||||
[Mount]
|
||||
What=/usrdata/opt
|
||||
Where=/opt
|
||||
Type=none
|
||||
Options=bind
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
EOF
|
||||
|
||||
systemctl daemon-reload
|
||||
systemctl start opt.mount
|
||||
|
||||
# Additional systemd service to ensure opt.mount starts at boot
|
||||
echo -e '\033[32mInfo: Creating service to start opt.mount at boot...\033[0m'
|
||||
cat <<EOF > /lib/systemd/system/start-opt-mount.service
|
||||
[Unit]
|
||||
Description=Ensure opt.mount is started at boot
|
||||
After=network.target
|
||||
|
||||
[Service]
|
||||
Type=oneshot
|
||||
ExecStart=/bin/systemctl start opt.mount
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
EOF
|
||||
|
||||
systemctl daemon-reload
|
||||
ln -s /lib/systemd/system/start-opt-mount.service /lib/systemd/system/multi-user.target.wants/start-opt-mount.service
|
||||
}
|
||||
|
||||
if [ -n "$PRE_OPKG_PATH" ]; then
|
||||
# Automatically rename the existing opkg binary
|
||||
mv "$PRE_OPKG_PATH" "${PRE_OPKG_PATH}_old"
|
||||
echo -e "\033[32mFactory/Already existing opkg has been renamed to opkg_old.\033[0m"
|
||||
else
|
||||
echo "Info: no existing opkg binary detected, proceeding with installation"
|
||||
fi
|
||||
|
||||
echo -e '\033[32mInfo: Creating /opt mount pointed to /usrdata/opt ...\033[0m'
|
||||
create_opt_mount
|
||||
echo -e '\033[32mInfo: Proceeding with main installation ...\033[0m'
|
||||
# no need to create many folders. entware-opt package creates most
|
||||
for folder in bin etc lib/opkg tmp var/lock
|
||||
do
|
||||
if [ -d "/opt/$folder" ]; then
|
||||
echo -e '\033[31mWarning: Folder /opt/$folder exists!\033[0m'
|
||||
echo -e '\033[31mWarning: If something goes wrong please clean /opt folder and try again.\033[0m'
|
||||
else
|
||||
mkdir -p /opt/$folder
|
||||
fi
|
||||
done
|
||||
|
||||
echo -e '\033[32mInfo: Opkg package manager deployment...\033[0m'
|
||||
URL=http://bin.entware.net/${ARCH}/installer
|
||||
wget --no-check-certificate $URL/opkg -O /opt/bin/opkg
|
||||
chmod 755 /opt/bin/opkg
|
||||
wget --no-check-certificate $URL/opkg.conf -O /opt/etc/opkg.conf
|
||||
|
||||
echo -e '\033[32mInfo: Basic packages installation...\033[0m'
|
||||
/opt/bin/opkg update
|
||||
/opt/bin/opkg install entware-opt
|
||||
|
||||
# Fix for multiuser environment
|
||||
chmod 777 /opt/tmp
|
||||
|
||||
for file in passwd group shells shadow gshadow; do
|
||||
if [ $TYPE = 'generic' ]; then
|
||||
if [ -f /etc/$file ]; then
|
||||
ln -sf /etc/$file /opt/etc/$file
|
||||
else
|
||||
[ -f /opt/etc/$file.1 ] && cp /opt/etc/$file.1 /opt/etc/$file
|
||||
fi
|
||||
else
|
||||
if [ -f /opt/etc/$file.1 ]; then
|
||||
cp /opt/etc/$file.1 /opt/etc/$file
|
||||
fi
|
||||
fi
|
||||
done
|
||||
|
||||
[ -f /etc/localtime ] && ln -sf /etc/localtime /opt/etc/localtime
|
||||
|
||||
# Create and enable rc.unslung service
|
||||
echo -e '\033[32mInfo: Creating rc.unslung (Entware init.d service)...\033[0m'
|
||||
cat <<EOF > /lib/systemd/system/rc.unslung.service
|
||||
[Unit]
|
||||
Description=Start Entware services
|
||||
|
||||
[Service]
|
||||
Type=oneshot
|
||||
# Add a delay to give /opt time to mount
|
||||
ExecStartPre=/bin/sleep 5
|
||||
ExecStart=/opt/etc/init.d/rc.unslung start
|
||||
RemainAfterExit=yes
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
EOF
|
||||
|
||||
systemctl daemon-reload
|
||||
ln -s /lib/systemd/system/rc.unslung.service /lib/systemd/system/multi-user.target.wants/rc.unslung.service
|
||||
systemctl start rc.unslung.service
|
||||
echo -e '\033[32mInfo: Congratulations!\033[0m'
|
||||
echo -e '\033[32mInfo: If there are no errors above then Entware was successfully initialized.\033[0m'
|
||||
echo -e '\033[32mInfo: Add /opt/bin & /opt/sbin to $PATH variable\033[0m'
|
||||
ln -sf /opt/bin/opkg /bin
|
||||
echo -e '\033[32mInfo: Patching Quectel Login Binary\033[0m'
|
||||
opkg update && opkg install shadow-login shadow-passwd shadow-useradd
|
||||
if [ "$?" -ne 0 ]; then
|
||||
echo -e "\e[1;31mPackage installation failed. Please check your internet connection and try again.\e[0m"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Replace the login and passwd binaries and set home for root to a writable directory
|
||||
rm /opt/etc/shadow
|
||||
rm /opt/etc/passwd
|
||||
cp /etc/shadow /opt/etc/
|
||||
cp /etc/passwd /opt/etc
|
||||
mkdir /usrdata/root
|
||||
mkdir /usrdata/root/bin
|
||||
touch /usrdata/root/.profile
|
||||
echo "# Set PATH for all shells" > /usrdata/root/.profile
|
||||
echo "export PATH=/bin:/usr/sbin:/usr/bin:/sbin:/opt/sbin:/opt/bin:/usrdata/root/bin" >> /usrdata/root/.profile
|
||||
chmod +x /usrdata/root/.profile
|
||||
sed -i '1s|/home/root:/bin/sh|/usrdata/root:/bin/bash|' /opt/etc/passwd
|
||||
rm /bin/login /usr/bin/passwd
|
||||
ln -sf /opt/bin/login /bin
|
||||
ln -sf /opt/bin/passwd /usr/bin/
|
||||
ln -sf /opt/bin/useradd /usr/bin/
|
||||
echo -e "\e[1;31mPlease set the root password.\e[0m"
|
||||
/usr/bin/passwd
|
||||
|
||||
# Install basic and useful utilites
|
||||
opkg install mc htop dfc lsof
|
||||
ln -sf /opt/bin/mc /bin
|
||||
ln -sf /opt/bin/htop /bin
|
||||
ln -sf /opt/bin/dfc /bin
|
||||
ln -sf /opt/bin/lsof /bin
|
||||
# Remount filesystem as read-only
|
||||
mount -o remount,ro /
|
||||
@ -1 +0,0 @@
|
||||
2
|
||||
@ -1,7 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
#Path
|
||||
export PATH=/bin:/sbin:/usr/bin:/usr/sbin:/opt/bin:/opt/sbin:/usrdata/root/bin
|
||||
|
||||
#Post-login execution
|
||||
/usrdata/simpleadmin/console/menu/start_menu.sh
|
||||
@ -1,150 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
CONFIG_FILE="/etc/data/mobileap_cfg.xml"
|
||||
|
||||
# Display Messages in Colors
|
||||
display_random_color() {
|
||||
local msg="$1"
|
||||
local colors=(33 34 35 36 37) # ANSI color codes for yellow, blue, magenta, cyan, white
|
||||
local num_colors=${#colors[@]}
|
||||
local random_color_index=$(($RANDOM % num_colors)) # Pick a random index from the colors array
|
||||
echo -e "\033[${colors[$random_color_index]}m$msg\033[0m"
|
||||
}
|
||||
|
||||
display_green() {
|
||||
echo -e "\033[0;32m$1\033[0m"
|
||||
}
|
||||
|
||||
display_red() {
|
||||
echo -e "\033[0;31m$1\033[0m"
|
||||
}
|
||||
|
||||
# Check and Install xml binary if not present
|
||||
check_and_install_xml() {
|
||||
if [ ! -f "/opt/bin/xml" ]; then
|
||||
echo "xml binary not found. Attempting to install xmlstarlet..."
|
||||
opkg update
|
||||
opkg install xmlstarlet
|
||||
# Verify installation
|
||||
if [ ! -f "/opt/bin/xml" ]; then
|
||||
echo "Failed to install xmlstarlet. Exiting..."
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
echo "xml binary is available."
|
||||
}
|
||||
|
||||
# Edit XML Value
|
||||
edit_xml_value() {
|
||||
local node="$1"
|
||||
local new_value="$2"
|
||||
/opt/bin/xml ed -L -u "$node" -v "$new_value" "$CONFIG_FILE"
|
||||
}
|
||||
|
||||
# Get Current XML Value
|
||||
get_current_value() {
|
||||
/opt/bin/xml sel -t -v "$1" "$CONFIG_FILE"
|
||||
}
|
||||
|
||||
# Enable/Disable Menu
|
||||
enable_disable_menu() {
|
||||
local node="$1"
|
||||
local current_value=$(get_current_value "$node")
|
||||
echo "Current status: $([ "$current_value" == "1" ] && echo "Enabled" || echo "Disabled")"
|
||||
echo "1. Enable"
|
||||
echo "2. Disable"
|
||||
read -p "Choose an option to toggle (1-2): " choice
|
||||
local new_value="$([ "$choice" == "1" ] && echo "1" || echo "0")"
|
||||
edit_xml_value "$node" "$new_value"
|
||||
display_green "After making changes, please reboot to have them take effect."
|
||||
}
|
||||
|
||||
# Edit Simple Value
|
||||
edit_simple_value() {
|
||||
local node="$1"
|
||||
local description="$2"
|
||||
local current=$(get_current_value "$node")
|
||||
echo "Current $description: $current"
|
||||
read -p "Enter new $description: " new_value
|
||||
edit_xml_value "$node" "$new_value"
|
||||
display_green "After making changes, please reboot to have them take effect."
|
||||
}
|
||||
|
||||
# Edit DHCP IP Range
|
||||
edit_dhcp_range() {
|
||||
local start_ip=$(get_current_value "//MobileAPLanCfg/DHCPCfg/StartIP")
|
||||
local end_ip=$(get_current_value "//MobileAPLanCfg/DHCPCfg/EndIP")
|
||||
echo "Current Start IP: $start_ip"
|
||||
echo "Current End IP: $end_ip"
|
||||
read -p "Enter new Start IP: " new_start_ip
|
||||
read -p "Enter new End IP: " new_end_ip
|
||||
edit_xml_value "//MobileAPLanCfg/DHCPCfg/StartIP" "$new_start_ip"
|
||||
edit_xml_value "//MobileAPLanCfg/DHCPCfg/EndIP" "$new_end_ip"
|
||||
display_green "After making changes, please reboot to have them take effect."
|
||||
}
|
||||
|
||||
# Reboot the system
|
||||
reboot_system() {
|
||||
echo "Rebooting system..."
|
||||
atcmd 'AT+CFUN=1,1' # Ensure this command is correct for your system
|
||||
echo "System reboot initiated. Good luck."
|
||||
}
|
||||
|
||||
# Main Menu
|
||||
main_menu() {
|
||||
while true; do
|
||||
clear
|
||||
display_red "Warning, these changes can break access over the network. Know what you are doing, and be prepared to use ADB to fix this just in case."
|
||||
echo "Configuration Menu"
|
||||
echo "------------------"
|
||||
display_green "1. Edit Gateway IPV4 Address"
|
||||
display_green "2. Edit Gateway URL"
|
||||
display_green "3. Edit LAN DHCP Start/End Range"
|
||||
display_green "4. Edit LAN Subnet Mask"
|
||||
display_green "5. Edit DHCPv6 Base address"
|
||||
display_green "6. Toggle IPv4 NAT"
|
||||
display_green "7. Toggle IPv6 NAT"
|
||||
display_green "8. Toggle DHCP Server"
|
||||
display_green "9. Toggle DHCPv4"
|
||||
display_green "10. Toggle DHCPv6"
|
||||
display_green "11. Toggle WAN Autoconnect"
|
||||
display_green "12. Toggle WAN AutoReconnect"
|
||||
display_green "13. Toggle Roaming"
|
||||
display_green "14. Toggle WAN DNSv4 Passthrough"
|
||||
display_green "15. Toggle WAN DNSv6 Passthrough"
|
||||
display_green "16. Toggle IPPT NAT/Ability to access gateway while in IPPT mode"
|
||||
display_green "17. Toggle UPnP"
|
||||
display_green "18. Reboot System"
|
||||
display_green "19. Exit"
|
||||
echo
|
||||
read -p "Select an option (1-19): " option
|
||||
|
||||
case "$option" in
|
||||
1) edit_simple_value "//MobileAPLanCfg/APIPAddr" "Gateway IPV4 Address";;
|
||||
2) edit_simple_value "//MobileAPLanCfg/GatewayURL" "Gateway URL";;
|
||||
3) edit_dhcp_range;;
|
||||
4) edit_simple_value "//MobileAPLanCfg/SubNetMask" "LAN Subnet Mask";;
|
||||
5) edit_simple_value "//MobileAPLanCfg/ULAIPv6BaseAddr" "DHCPv6 Base Address";;
|
||||
6) enable_disable_menu "//MobileAPNatCfg/IPv4NATDisable";;
|
||||
7) enable_disable_menu "//MobileAPNatv6Cfg/EnableIPv6NAT";;
|
||||
8) enable_disable_menu "//MobileAPLanCfg/EnableDHCPServer";;
|
||||
9) enable_disable_menu "//MobileAPLanCfg/EnableIPV4";;
|
||||
10) enable_disable_menu "//MobileAPLanCfg/EnableIPV6";;
|
||||
11) enable_disable_menu "//MobileAPWanCfg/AutoConnect";;
|
||||
12) enable_disable_menu "//MobileAPWanCfg/ReConnect";;
|
||||
13) enable_disable_menu "//MobileAPWanCfg/Roaming";;
|
||||
14) enable_disable_menu "//Dhcpv4Cfg/EnableDhcpv4Dns";;
|
||||
15) enable_disable_menu "//Dhcpv6Cfg/EnableDhcpv6Dns";;
|
||||
16) enable_disable_menu "//IPPassthroughFeatureWithNAT";;
|
||||
17) enable_disable_menu "//MobileAPSrvcCfg/UPnP";;
|
||||
18) reboot_system;;
|
||||
19) break;;
|
||||
*) echo "Invalid option. Please try again.";;
|
||||
esac
|
||||
done
|
||||
}
|
||||
|
||||
# Start by checking and installing xml if necessary, then mount filesystem as rw and run the menu
|
||||
mount -o remount,rw /
|
||||
check_and_install_xml
|
||||
main_menu
|
||||
@ -1,129 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
SIMPLE_FIREWALL_DIR="/usrdata/simplefirewall"
|
||||
SIMPLE_FIREWALL_SCRIPT="$SIMPLE_FIREWALL_DIR/simplefirewall.sh"
|
||||
SIMPLE_FIREWALL_SYSTEMD_DIR="$SIMPLE_FIREWALL_DIR/systemd"
|
||||
|
||||
# Display Messages in Colors
|
||||
display_random_color() {
|
||||
local msg="$1"
|
||||
local colors=(33 34 35 36 37) # ANSI color codes for yellow, blue, magenta, cyan, white
|
||||
local num_colors=${#colors[@]}
|
||||
local random_color_index=$(($RANDOM % num_colors)) # Pick a random index from the colors array
|
||||
echo -e "\033[${colors[$random_color_index]}m$msg\033[0m"
|
||||
}
|
||||
|
||||
display_green() {
|
||||
echo -e "\033[0;32m$1\033[0m"
|
||||
}
|
||||
|
||||
display_red() {
|
||||
echo -e "\033[0;31m$1\033[0m"
|
||||
}
|
||||
|
||||
set_portblocks() {
|
||||
current_ports_line=$(grep '^PORTS=' "$SIMPLE_FIREWALL_SCRIPT")
|
||||
ports=$(echo "$current_ports_line" | cut -d'=' -f2 | tr -d '()' | tr ' ' '\n' | grep -o '[0-9]\+')
|
||||
echo -e "\e[1;32mCurrent configured ports:\e[0m"
|
||||
echo "$ports" | awk '{print NR") "$0}'
|
||||
|
||||
while true; do
|
||||
echo -e "\e[1;32mEnter a port number to add/remove, or type 'done' or 'exit' to finish:\e[0m"
|
||||
read port
|
||||
if [ "$port" = "done" ] || [ "$port" = "exit" ]; then
|
||||
if [ "$port" = "exit" ]; then
|
||||
echo -e "\e[1;31mExiting without making changes...\e[0m"
|
||||
return
|
||||
fi
|
||||
break
|
||||
elif ! echo "$port" | grep -qE '^[0-9]+$'; then
|
||||
echo -e "\e[1;31mInvalid input: Please enter a numeric value.\e[0m"
|
||||
elif echo "$ports" | grep -q "^$port\$"; then
|
||||
ports=$(echo "$ports" | grep -v "^$port\$")
|
||||
echo -e "\e[1;32mPort $port removed.\e[0m"
|
||||
else
|
||||
ports=$(echo "$ports"; echo "$port" | grep -o '[0-9]\+')
|
||||
echo -e "\e[1;32mPort $port added.\e[0m"
|
||||
fi
|
||||
done
|
||||
|
||||
if [ "$port" != "exit" ]; then
|
||||
new_ports_line="PORTS=($(echo "$ports" | tr '\n' ' '))"
|
||||
sed -i "s/$current_ports_line/$new_ports_line/" "$SIMPLE_FIREWALL_SCRIPT"
|
||||
fi
|
||||
}
|
||||
|
||||
set_ttl(){
|
||||
# TTL configuration code
|
||||
ttl_value=$(cat /usrdata/simplefirewall/ttlvalue)
|
||||
if [ "$ttl_value" -eq 0 ]; then
|
||||
echo -e "\e[1;31mTTL is not set.\e[0m"
|
||||
else
|
||||
echo -e "\e[1;32mTTL value is set to $ttl_value.\e[0m"
|
||||
fi
|
||||
|
||||
echo -e "\e[1;31mType 'exit' to cancel.\e[0m"
|
||||
read -p "What do you want the TTL value to be: " new_ttl_value
|
||||
if [ "$new_ttl_value" = "exit" ]; then
|
||||
echo -e "\e[1;31mExiting TTL configuration...\e[0m"
|
||||
return
|
||||
elif ! echo "$new_ttl_value" | grep -qE '^[0-9]+$'; then
|
||||
echo -e "\e[1;31mInvalid input: Please enter a numeric value.\e[0m"
|
||||
return
|
||||
else
|
||||
/usrdata/simplefirewall/ttl-override stop
|
||||
echo "$new_ttl_value" > /usrdata/simplefirewall/ttlvalue
|
||||
/usrdata/simplefirewall/ttl-override start
|
||||
echo -e "\033[0;32mTTL value updated to $new_ttl_value.\033[0m"
|
||||
fi
|
||||
}
|
||||
|
||||
# function to configure the fetures of simplefirewall
|
||||
simple_firewall_menu() {
|
||||
if [ ! -f "$SIMPLE_FIREWALL_SCRIPT" ]; then
|
||||
display_random_color "Simplefirewall is not installed, would you like to install it?"
|
||||
display_green "1) Yes"
|
||||
display_red "2) No"
|
||||
read -p "Enter your choice (1-2): " install_choice
|
||||
|
||||
case $install_choice in
|
||||
1)
|
||||
install_simple_firewall
|
||||
;;
|
||||
2)
|
||||
return
|
||||
;;
|
||||
*)
|
||||
display_red "Invalid choice. Please select either 1 or 2."
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
|
||||
display_random_color "Configure Simple Firewall:"
|
||||
display_green "1) Configure incoming port block"
|
||||
display_green "2) Configure TTL"
|
||||
display_green "3) Exit to Main Menu"
|
||||
read -p "Enter your choice (1-2): " menu_choice
|
||||
|
||||
case $menu_choice in
|
||||
1)
|
||||
set_portblocks
|
||||
;;
|
||||
2)
|
||||
set_ttl
|
||||
;;
|
||||
3)
|
||||
return
|
||||
;;
|
||||
*)
|
||||
echo -e "\e[1;31mInvalid choice. Please select either 1 or 2.\e[0m"
|
||||
;;
|
||||
esac
|
||||
|
||||
systemctl restart simplefirewall
|
||||
echo -e "\e[1;32mFirewall configuration updated.\e[0m"
|
||||
}
|
||||
|
||||
# Main execution
|
||||
mount -o remount,rw /
|
||||
simple_firewall_menu
|
||||
@ -1,118 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Define executable files path
|
||||
MENU_SH=/usrdata/simpleadmin/console/menu
|
||||
|
||||
# Display Messages in Colors
|
||||
display_random_color() {
|
||||
local msg="$1"
|
||||
local colors=(33 34 35 36 37) # ANSI color codes for yellow, blue, magenta, cyan, white
|
||||
local num_colors=${#colors[@]}
|
||||
local random_color_index=$(($RANDOM % num_colors)) # Pick a random index from the colors array
|
||||
echo -e "\033[${colors[$random_color_index]}m$msg\033[0m"
|
||||
}
|
||||
|
||||
display_green() {
|
||||
echo -e "\033[0;32m$1\033[0m"
|
||||
}
|
||||
|
||||
display_red() {
|
||||
echo -e "\033[0;31m$1\033[0m"
|
||||
}
|
||||
|
||||
# Menus
|
||||
|
||||
toolkit_menu() {
|
||||
while true; do
|
||||
display_random_color "Run a Toolkit version"
|
||||
display_green "Select an option:"
|
||||
echo "------------------"
|
||||
display_green "1. Get and run the Toolkit"
|
||||
display_random_color "2. Get and run the Development/unstable Toolkit"
|
||||
display_random_color "3. Exit (Enter Root Shell)"
|
||||
echo
|
||||
read -p "Select an option (1-3): " option
|
||||
|
||||
case "$option" in
|
||||
1) cd /tmp && wget --no-check-certificate -O RMxxx_rgmii_toolkit.sh http://gitea.hapyle.work:33000/taotao/webui/raw/development/RMxxx_rgmii_toolkit.sh && chmod +x RMxxx_rgmii_toolkit.sh && ./RMxxx_rgmii_toolkit.sh && cd / ;;
|
||||
2) cd /tmp && wget --no-check-certificate -O RMxxx_rgmii_toolkit.sh http://gitea.hapyle.work:33000/taotao/webui/raw/development/RMxxx_rgmii_toolkit.sh && chmod +x RMxxx_rgmii_toolkit.sh && ./RMxxx_rgmii_toolkit.sh && cd / ;;
|
||||
3) break ;;
|
||||
*) echo "Invalid option. Please try again." ;;
|
||||
esac
|
||||
done
|
||||
}
|
||||
|
||||
apps_menu() {
|
||||
while true; do
|
||||
display_random_color "Run a modem App"
|
||||
display_green "Select an option:"
|
||||
echo "------------------"
|
||||
display_random_color "1. Open File Browser/Editor (mc)"
|
||||
display_random_color "2. View Used/Available space"
|
||||
display_random_color "3. Open Task Manager/View CPU Load"
|
||||
display_random_color "4. Run speedtest.net test"
|
||||
display_random_color "5. Run fast.com test (30Mbps max)"
|
||||
display_green "6. Go Back"
|
||||
echo
|
||||
read -p "Select an option (1-6): " option
|
||||
|
||||
case "$option" in
|
||||
1) mc ;;
|
||||
2) dfc ;;
|
||||
3) htop ;;
|
||||
4) speedtest ;;
|
||||
5) fast ;;
|
||||
6) break ;;
|
||||
*) echo "Invalid option. Please try again." ;;
|
||||
esac
|
||||
done
|
||||
}
|
||||
|
||||
settings_menu() {
|
||||
while true; do
|
||||
display_random_color "Welcome to" && display_green "iamromulan's" && display_random_color "Simple Console Menu"
|
||||
display_green "Select an option:"
|
||||
echo "------------------"
|
||||
display_green "1. LAN Settings"
|
||||
display_green "2. simplefirewall settings (TTL and Port Block)"
|
||||
display_green "3. Change simpleadmin (admin) password"
|
||||
display_green "4. Change root password (shell/ssh/console)"
|
||||
display_green "5. Go back"
|
||||
echo
|
||||
read -p "Select an option (1-5): " option
|
||||
|
||||
case "$option" in
|
||||
1) $MENU_SH/LAN_settings.sh ;;
|
||||
2) $MENU_SH/sfirewall_settings.sh ;;
|
||||
3) simplepasswd ;;
|
||||
4) passwd ;;
|
||||
5) break ;;
|
||||
*) echo "Invalid option. Please try again." ;;
|
||||
esac
|
||||
done
|
||||
}
|
||||
|
||||
main_menu() {
|
||||
while true; do
|
||||
display_green "Welcome to iamromulan's Simple Console Menu"
|
||||
display_green "To get back to this from the root shell, just type 'menu'"
|
||||
display_green "Select an option:"
|
||||
echo "------------------"
|
||||
display_random_color "1. Apps"
|
||||
display_random_color "2. Settings"
|
||||
display_random_color "3. Toolkit"
|
||||
display_random_color "4. Exit (Enter Root Shell)"
|
||||
echo
|
||||
read -p "Select an option (1-4): " option
|
||||
|
||||
case "$option" in
|
||||
1) apps_menu ;;
|
||||
2) settings_menu ;;
|
||||
3) toolkit_menu ;;
|
||||
4) break ;;
|
||||
*) echo "Invalid option. Please try again." ;;
|
||||
esac
|
||||
done
|
||||
}
|
||||
|
||||
main_menu
|
||||
@ -1,27 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Define the command to execute when the ethernet port breaks
|
||||
command_to_execute="/usrdata/socat-at-bridge/atcmd 'AT+CFUN=1,1'"
|
||||
|
||||
# Define the monitoring function
|
||||
watch() {
|
||||
while true; do
|
||||
# Extract the last 60 lines of dmesg and count the specific pattern occurrences
|
||||
count=$(dmesg | tail -60 | grep -e "eth0: cmd = 0xff, should be 0x47" -e "eth0: pci link is down" | grep -c "eth0")
|
||||
|
||||
# Check if the count of patterns is 4 or more
|
||||
if [ "$count" -ge 4 ]; then
|
||||
echo "Condition met, executing command..."
|
||||
eval "$command_to_execute"
|
||||
# Optionally, add a break here if you want the script to stop after executing the command
|
||||
# break
|
||||
fi
|
||||
|
||||
# Sleep for 3 seconds before checking again
|
||||
sleep 3
|
||||
done
|
||||
}
|
||||
|
||||
# Initial delay before starting monitoring
|
||||
sleep 30
|
||||
watch
|
||||
@ -1,28 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Define the hostname or IP address to ping
|
||||
HOSTNAME="google.com"
|
||||
|
||||
# Number of pings to attempt
|
||||
PING_COUNT=6
|
||||
|
||||
# Initialize a counter for successful pings
|
||||
success_count=0
|
||||
|
||||
# Attempt to ping the specified number of times
|
||||
for i in $(seq 1 $PING_COUNT); do
|
||||
# Ping the hostname with a timeout of 1 second per ping
|
||||
if ping -c 1 -W 1 $HOSTNAME &> /dev/null; then
|
||||
((success_count++))
|
||||
else
|
||||
echo "Ping attempt $i failed."
|
||||
fi
|
||||
done
|
||||
|
||||
# Check if all pings failed
|
||||
if [ $success_count -eq 0 ]; then
|
||||
echo "All $PING_COUNT ping attempts failed, executing AT command."
|
||||
/bin/atcmd 'AT+CFUN=1,1'
|
||||
else
|
||||
echo "$success_count out of $PING_COUNT ping attempts were successful."
|
||||
fi
|
||||
@ -1,14 +0,0 @@
|
||||
[Unit]
|
||||
Description=Ping Watchdog Service
|
||||
Wants=network.target
|
||||
After=network.target
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
ExecStartPre=/bin/sleep 60 # Sleep for 60 seconds to ensure the network is ready
|
||||
ExecStart=/usrdata/simpleadmin/console/services/ping_watchdog.sh
|
||||
Restart=on-failure
|
||||
RestartSec=30s
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
@ -1,15 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Check if /usrdata/socat-at-bridge/atcmd exists
|
||||
#if [ -f "/usrdata/socat-at-bridge/atcmd" ]; then
|
||||
# Read the serial number
|
||||
# serial_number=$(/usrdata/socat-at-bridge/atcmd 'AT+EGMR=0,5' | grep '+EGMR:' | cut -d '"' -f2)
|
||||
# Read the firmware revision
|
||||
# firmware_revision=$(/usrdata/socat-at-bridge/atcmd 'AT+QGMR' | grep -o 'RM[0-9A-Z].*')
|
||||
#else
|
||||
# serial_number="UNKNOWN"
|
||||
# firmware_revision="UNKNOWN"
|
||||
#fi
|
||||
#
|
||||
# Start a login session
|
||||
exec /bin/login
|
||||
Binary file not shown.
@ -1,47 +0,0 @@
|
||||
server.modules = (
|
||||
"mod_redirect",
|
||||
"mod_cgi",
|
||||
"mod_proxy",
|
||||
"mod_openssl",
|
||||
"mod_authn_file",
|
||||
)
|
||||
|
||||
server.username = "www-data"
|
||||
server.groupname = "dialout"
|
||||
|
||||
server.port = 80
|
||||
server.document-root = "/usrdata/simpleadmin/www"
|
||||
index-file.names = ( "index.html" )
|
||||
|
||||
auth.backend = "htpasswd"
|
||||
auth.backend.htpasswd.userfile = "/opt/etc/.htpasswd"
|
||||
|
||||
$SERVER["socket"] == "0.0.0.0:443" {
|
||||
ssl.engine = "enable"
|
||||
ssl.privkey= "/usrdata/simpleadmin/server.key"
|
||||
ssl.pemfile= "/usrdata/simpleadmin/server.crt"
|
||||
ssl.acme-tls-1 = "/etc/simpleadmin/dehydrated/tls-alpn-01"
|
||||
ssl.openssl.ssl-conf-cmd = ("MinProtocol" => "TLSv1.2") # (lighttpd 1.4.56 default; recommended to accept only TLSv1.2 and TLSv1.3)
|
||||
auth.require = ( "/" => (
|
||||
"method" => "basic",
|
||||
"realm" => "Authorized users only",
|
||||
"require" => "valid-user"
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
# Redirect everything to https
|
||||
$HTTP["scheme"] == "http" {
|
||||
url.redirect = ("" => "https://${url.authority}${url.path}${qsa}")
|
||||
}
|
||||
|
||||
# Anything in /cgi-bin will be run as a script
|
||||
$HTTP["url"] =~ "/cgi-bin/" {
|
||||
cgi.assign = ( "" => "" )
|
||||
}
|
||||
|
||||
# Handle proxy to ttyd if it's running
|
||||
$HTTP["url"] =~ "(^/console)" {
|
||||
proxy.header = ("map-urlpath" => ( "/console" => "/" ), "upgrade" => "enable" )
|
||||
proxy.server = ( "" => ("" => ( "host" => "127.0.0.1", "port" => 8080 )))
|
||||
}
|
||||
@ -1,60 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
# Function to create and run the Watchcat script
|
||||
create_and_run_watchcat_script() {
|
||||
local ip=$1
|
||||
local timeout=$2
|
||||
local failure_count=$3
|
||||
local script_path="/usrdata/simpleadmin/script/watchcat.sh"
|
||||
|
||||
# Create the script with the watchcat logic
|
||||
sudo cat << EOF > $script_path
|
||||
#!/bin/sh
|
||||
|
||||
failures=0
|
||||
|
||||
while :; do
|
||||
if ping -c 1 $ip > /dev/null 2>&1; then
|
||||
failures=0
|
||||
else
|
||||
failures=\$((failures + 1))
|
||||
if [ "\$failures" -ge "$failure_count" ]; then
|
||||
echo "Rebooting system due to \$failures consecutive ping failures."
|
||||
/sbin/reboot
|
||||
exit 0
|
||||
fi
|
||||
fi
|
||||
sleep $timeout
|
||||
done
|
||||
EOF
|
||||
|
||||
# Make the watchcat script executable
|
||||
chmod +x $script_path
|
||||
|
||||
# Create a JSON to be fetched later
|
||||
echo "{\"enabled\": true, \"track_ip\": \"$ip\", \"ping_timeout\": $timeout, \"ping_failure_count\": $failure_count}" > /usrdata/simpleadmin/script/watchcat.json
|
||||
|
||||
# Check if the script was created successfully
|
||||
if [ -f "$script_path" ]; then
|
||||
# Make the script executable
|
||||
chmod +x "$script_path"
|
||||
|
||||
# Run the script in the background
|
||||
# nohup /bin/sh "$script_path" &
|
||||
/bin/sh "$script_path" &
|
||||
|
||||
echo "Watchcat script created and running."
|
||||
else
|
||||
echo "Failed to create the Watchcat script."
|
||||
echo "Please check the script path: $script_path"
|
||||
fi
|
||||
}
|
||||
|
||||
# Check if the script is called with the required parameters
|
||||
if [ "$#" -ne 3 ]; then
|
||||
echo "Usage: $0 <IP> <timeout> <failure_count>"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Call the function with the provided arguments
|
||||
create_and_run_watchcat_script "$1" "$2" "$3"
|
||||
@ -1,32 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
# Function to remove the Watchcat script and JSON file
|
||||
remove_watchcat_script() {
|
||||
local script_path="/usrdata/simpleadmin/script/watchcat.sh"
|
||||
local json_path="/usrdata/simpleadmin/script/watchcat.json"
|
||||
|
||||
# Mount as read-write
|
||||
mount -o remount,rw /
|
||||
|
||||
# Remove the watchcat script if it exists
|
||||
if [ -f "$script_path" ]; then
|
||||
rm "$script_path"
|
||||
echo "Removed $script_path"
|
||||
else
|
||||
echo "$script_path does not exist"
|
||||
fi
|
||||
|
||||
# Remove the JSON file if it exists
|
||||
if [ -f "$json_path" ]; then
|
||||
rm "$json_path"
|
||||
echo "Removed $json_path"
|
||||
else
|
||||
echo "$json_path does not exist"
|
||||
fi
|
||||
|
||||
# Mount as read-only
|
||||
mount -o remount,ro /
|
||||
}
|
||||
|
||||
# Call the function to remove the scripts
|
||||
remove_watchcat_script
|
||||
@ -1,43 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
# Check if the required parameters are provided
|
||||
if [ "$#" -ne 2 ]; then
|
||||
echo "Usage: $0 <enable|disable> <ttl_value>"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Assign the provided parameters to variables
|
||||
mode="$1"
|
||||
ttl_value="$2"
|
||||
|
||||
# Check if iptables is still set
|
||||
ttlcheck=$(/opt/bin/sudo /usr/sbin/iptables -w 5 -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
|
||||
fi
|
||||
|
||||
# Handle the enable/disable mode
|
||||
case "${mode}" in
|
||||
enable)
|
||||
# Echo TTL to file
|
||||
echo "${ttl_value}" > /usrdata/simplefirewall/ttlvalue
|
||||
|
||||
# Set Start Service
|
||||
/opt/bin/sudo /usrdata/simplefirewall/ttl-override start
|
||||
;;
|
||||
disable)
|
||||
# Remove TTL value file
|
||||
rm -f /usrdata/simplefirewall/ttlvalue
|
||||
|
||||
# Stop the service
|
||||
/opt/bin/sudo /usrdata/simplefirewall/ttl-override stop
|
||||
;;
|
||||
*)
|
||||
echo "Invalid mode: ${mode}"
|
||||
echo "Usage: $0 <enable|disable> <ttl_value>"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
@ -1,5 +0,0 @@
|
||||
#/bin/bash
|
||||
|
||||
echo -e "\e[1;31mPlease set your simpleadmin (User: admin) web login password.\e[0m"
|
||||
/usrdata/root/bin/htpasswd -c /opt/etc/.htpasswd admin
|
||||
echo -e "\e[1;32mPassword set.\e[0m"
|
||||
@ -1,14 +0,0 @@
|
||||
[Unit]
|
||||
Description=Lighttpd Daemon
|
||||
After=network.target opt.mount
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
PIDFile=/opt/var/run/lighttpd.pid
|
||||
ExecStartPre=/opt/sbin/lighttpd -tt -f /usrdata/simpleadmin/lighttpd.conf
|
||||
ExecStart=/opt/sbin/lighttpd -D -f /usrdata/simpleadmin/lighttpd.conf
|
||||
ExecReload=/bin/kill -USR1 $MAINPID
|
||||
Restart=on-failure
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
@ -1,12 +0,0 @@
|
||||
[Unit]
|
||||
Description=TTYD Service
|
||||
After=network.target
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
ExecStartPre=/bin/sleep 5
|
||||
ExecStart=/usrdata/simpleadmin/console/ttyd -i 127.0.0.1 -p 8080 -t 'theme={"foreground":"white","background":"black"}' -t fontSize=25 --writable /usrdata/simpleadmin/console/ttyd.bash
|
||||
Restart=on-failure
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
@ -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
|
||||
|
||||
x=$(urldecode "$atcmd")
|
||||
MYATCMD=$(printf '%b\n' "${atcmd//%/\\x}")
|
||||
if [ -n "${MYATCMD}" ]; then
|
||||
# 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
|
||||
|
||||
# Check iptables for ttlvalue
|
||||
ttlvalue=$(/opt/bin/sudo /usr/sbin/iptables -w 5 -t mangle -vnL | grep TTL | awk '{print $13}' | head -n1)
|
||||
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,11 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Execute the uptime command and store the result
|
||||
uptime_output=$(uptime)
|
||||
|
||||
# Set header for plain text content
|
||||
echo "Content-Type: text/plain"
|
||||
echo ""
|
||||
|
||||
# Output the uptime result
|
||||
echo "$uptime_output"
|
||||
@ -1,17 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Content type header
|
||||
echo "Content-type: application/json"
|
||||
echo ""
|
||||
|
||||
# This script fetches the watchCat parameters from the /tmp/watchcat.json and returns it as JSON
|
||||
# Example content of /tmp/watchcat:
|
||||
# {"watchcat": {"enabled": true, "track_ip": "1.1.1.1", "ping_timeout": 30, "ping_failure_count": 10}}
|
||||
|
||||
# Check if the file exists
|
||||
if [ -f /tmp/watchcat.json ]; then
|
||||
cat /tmp/watchcat.json
|
||||
else
|
||||
# return an empty JSON object
|
||||
echo "{}"
|
||||
fi
|
||||
@ -1,31 +0,0 @@
|
||||
#!/bin/bash
|
||||
QUERY_STRING=$(echo "${QUERY_STRING}" | sed 's/;//g')
|
||||
urldecode() {
|
||||
local data
|
||||
data="${*//+/ }"
|
||||
echo -e "${data//%/\\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
|
||||
|
||||
phone_number="$number"
|
||||
message_encoded="$msg"
|
||||
|
||||
|
||||
send_at_command() {
|
||||
local cmd=$1
|
||||
echo -en "$cmd\r" | microcom -t 100 /dev/ttyOUT2
|
||||
}
|
||||
|
||||
send_at_command "AT+CMGS=\"$phone_number\","$Command""
|
||||
runcmd=$((echo -en "$message_encoded"; echo -en "\x1A") | microcom -t 500 /dev/ttyOUT2)
|
||||
echo "$runcmd"
|
||||
@ -1,64 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Debug log function
|
||||
log_debug() {
|
||||
local message="$1"
|
||||
debug_logs+=("$message")
|
||||
}
|
||||
|
||||
# Initialize debug logs array
|
||||
declare -a debug_logs=()
|
||||
|
||||
# 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
|
||||
log_debug "Received parameter: $key=$value"
|
||||
fi
|
||||
done
|
||||
fi
|
||||
|
||||
setTTL=$(printf '%b\n' "${ttlvalue//%/\\x}")
|
||||
if [ -n "${setTTL}" ]; then
|
||||
log_debug "Stopping service to remove rules"
|
||||
/usrdata/simplefirewall/ttl-override stop
|
||||
|
||||
# Convert ttlvalue to integer
|
||||
if [ "${ttlvalue}" ]; then
|
||||
ttlvalue_int=$(echo "${ttlvalue}" | sed 's/[^0-9]//g')
|
||||
log_debug "Converted ttlvalue to integer: $ttlvalue_int"
|
||||
fi
|
||||
|
||||
# Call the sh script with the appropriate parameters
|
||||
if [ "${ttlvalue_int}" != 0 ]; then
|
||||
log_debug "Enabling TTL with value: ${setTTL}"
|
||||
/usrdata/simpleadmin/script/ttl_script.sh enable "${setTTL}"
|
||||
commandRan="/usrdata/simpleadmin/script/ttl_script.sh enable ${setTTL}"
|
||||
ttlenabled=true
|
||||
ttlvalue=$ttlvalue_int
|
||||
elif [ "${ttlvalue_int}" = 0 ]; then
|
||||
log_debug "Disabling TTL"
|
||||
/usrdata/simpleadmin/script/ttl_script.sh disable 0
|
||||
commandRan="/usrdata/simpleadmin/script/ttl_script.sh disable 0"
|
||||
ttlenabled=false
|
||||
ttlvalue=0
|
||||
fi
|
||||
|
||||
log_debug "Starting service to apply rules"
|
||||
/usrdata/simplefirewall/ttl-override start
|
||||
fi
|
||||
|
||||
echo "Content-type: text/text"
|
||||
echo ""
|
||||
cat <<EOT
|
||||
{
|
||||
"debug_logs": [
|
||||
$(printf '"%s",' "${debug_logs[@]}")
|
||||
]
|
||||
}
|
||||
EOT
|
||||
@ -1,125 +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 [[ "$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"
|
||||
@ -1,26 +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
|
||||
|
||||
x=$(urldecode "$atcmd")
|
||||
MYATCMD=$(printf '%b\n' "${atcmd//%/\\x}")
|
||||
if [ -n "${MYATCMD}" ]; then
|
||||
# Capture the response and remove ANSI color codes using awk
|
||||
runcmd=$(atcmd '$x' | awk '{ gsub(/\x1B\[[0-9;]*[mG]/, "") }1')
|
||||
fi
|
||||
|
||||
echo "Content-type: text/plain"
|
||||
echo $x
|
||||
echo ""
|
||||
echo "$runcmd"
|
||||
@ -1,72 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Decode URL-encoded strings
|
||||
function urldecode() {
|
||||
local data=${1//+/ }
|
||||
printf '%b' "${data//%/\\x}"
|
||||
}
|
||||
|
||||
# Parse QUERY_STRING
|
||||
QUERY_STRING=$(echo "${QUERY_STRING}" | sed 's/;//g')
|
||||
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
|
||||
|
||||
# Set default values
|
||||
WATCHCAT_ENABLED=${WATCHCAT_ENABLED:-"disable"}
|
||||
TRACK_IP=${TRACK_IP:-"1.1.1.1"}
|
||||
PING_TIMEOUT=${PING_TIMEOUT:-30}
|
||||
PING_FAILURE_COUNT=${PING_FAILURE_COUNT:-3}
|
||||
|
||||
# Validate input
|
||||
if ! [[ "$WATCHCAT_ENABLED" =~ ^(enable|disable)$ ]]; then
|
||||
echo "Content-type: text/plain"
|
||||
echo ""
|
||||
echo "Invalid value for WATCHCAT_ENABLED. Use 'enable' or 'disable'."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if ! [[ "$TRACK_IP" =~ ^([0-9]{1,3}\.){3}[0-9]{1,3}$ ]]; then
|
||||
echo "Content-type: text/plain"
|
||||
echo ""
|
||||
echo "Invalid IP address format for TRACK_IP."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if ! [[ "$PING_TIMEOUT" =~ ^[0-9]+$ ]] || [ "$PING_TIMEOUT" -le 0 ]; then
|
||||
echo "Content-type: text/plain"
|
||||
echo ""
|
||||
echo "PING_TIMEOUT must be a positive integer."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if ! [[ "$PING_FAILURE_COUNT" =~ ^[0-9]+$ ]] || [ "$PING_FAILURE_COUNT" -le 0 ]; then
|
||||
echo "Content-type: text/plain"
|
||||
echo ""
|
||||
echo "PING_FAILURE_COUNT must be a positive integer."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Implement the Watchcat logic
|
||||
if [ "$WATCHCAT_ENABLED" == "enable" ]; then
|
||||
echo "Content-type: text/plain"
|
||||
echo ""
|
||||
echo "Watchcat is enabled. Tracking IP: $TRACK_IP, Ping timeout: $PING_TIMEOUT seconds, Ping failure count: $PING_FAILURE_COUNT"
|
||||
# Call the create script here and use the needed parameters
|
||||
sudo /usrdata/simpleadmin/script/create_watchcat.sh "$TRACK_IP" "$PING_TIMEOUT" "$PING_FAILURE_COUNT"
|
||||
else
|
||||
echo "Content-type: text/plain"
|
||||
echo ""
|
||||
echo "Watchcat is disabled."
|
||||
# Call the remove script here
|
||||
sudo /usrdata/simpleadmin/script/remove_watchcat.sh
|
||||
fi
|
||||
|
||||
exit 0
|
||||
6
simpleadmin/www/css/bootstrap.min.css
vendored
6
simpleadmin/www/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,520 +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>模块管理</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 fw-bold">模块管理</span></a>
|
||||
<button
|
||||
class="navbar-toggler"
|
||||
type="button"
|
||||
data-bs-toggle="collapse"
|
||||
data-bs-target="#navbarText"
|
||||
aria-controls="navbarText"
|
||||
aria-expanded="false"
|
||||
aria-label="Toggle navigation"
|
||||
>
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
<div class="collapse navbar-collapse" id="navbarText">
|
||||
<ul class="navbar-nav me-auto mb-2 mb-lg-0">
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="/">首页</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="/network.html">网络</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="/scanner.html">扫描</a>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="/settings.html">设置</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="/sms.html">短信</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="/console">控制台</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a
|
||||
class="nav-link active"
|
||||
href="/deviceinfo.html"
|
||||
aria-current="page"
|
||||
>设备信息</a
|
||||
>
|
||||
</li>
|
||||
</ul>
|
||||
<span class="navbar-text">
|
||||
<button class="btn btn-link text-reset" id="darkModeToggle">
|
||||
暗黑模式
|
||||
</button>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
<div class="row mt-5 gap-3">
|
||||
<div class="col">
|
||||
<div class="card">
|
||||
<div class="card-header">设备信息</div>
|
||||
<div class="card-body">
|
||||
<div class="card-text">
|
||||
<div class="table-responsive">
|
||||
<table class="table">
|
||||
<style>.table th,.table td { white-space: nowrap; /* 防止换行 */}</style>
|
||||
<tbody>
|
||||
<tr>
|
||||
<th scope="row">制造商</th>
|
||||
<td x-text="manufacturer"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">型号</th>
|
||||
<td x-text="modelName"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">固件版本</th>
|
||||
<td class="col-md-2" x-text="firmwareVersion"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">电话号码</th>
|
||||
<td class="col-md-2" x-text="phoneNumber"></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 === '-' ? '获取IMEI...' : imei"
|
||||
/>
|
||||
</td>
|
||||
<td>
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-primary"
|
||||
@click="openModal()"
|
||||
>
|
||||
更新
|
||||
</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">版本</th>
|
||||
<td class="col-md-2">SimpleAdminRev-Alpha-0.9</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>项目贡献者</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"
|
||||
>
|
||||
显示贡献者
|
||||
</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>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-footer">
|
||||
Visit our
|
||||
<a
|
||||
href="https://github.com/iamromulan/quectel-rgmii-toolkit/tree/development"
|
||||
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: "-",
|
||||
phoneNumber: "无",
|
||||
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";+CNUM';
|
||||
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.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, "");
|
||||
|
||||
try {
|
||||
this.imsi = lines[7].trim();
|
||||
this.iccid = lines[9].trim().replace("+ICCID: ", "");
|
||||
this.phoneNumber = lines[18]
|
||||
.trim()
|
||||
.split(",")[1]
|
||||
.replace(/"/g, "");
|
||||
|
||||
if (this.phoneNumber === "") {
|
||||
this.phoneNumber = "Unknown";
|
||||
}
|
||||
} catch (error) {
|
||||
this.phoneNumber = "No SIM Card Inserted or Detected";
|
||||
this.imsi = " ";
|
||||
this.iccid = " ";
|
||||
}
|
||||
|
||||
this.simpleAdminVersion = "SimpleAdminRev-Beta-1.0";
|
||||
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>
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 15 KiB |
File diff suppressed because it is too large
Load Diff
5
simpleadmin/www/js/alpinejs.min.js
vendored
5
simpleadmin/www/js/alpinejs.min.js
vendored
File diff suppressed because one or more lines are too long
7
simpleadmin/www/js/bootstrap.bundle.min.js
vendored
7
simpleadmin/www/js/bootstrap.bundle.min.js
vendored
File diff suppressed because one or more lines are too long
@ -1,37 +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 = '暗黑主题';
|
||||
localStorage.setItem('theme', 'light'); // Store the theme in localStorage
|
||||
} else {
|
||||
html.setAttribute('data-bs-theme', 'dark');
|
||||
darkModeToggle.textContent = '明亮主题';
|
||||
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');
|
||||
const html = document.querySelector('html');
|
||||
|
||||
if (storedTheme) {
|
||||
html.setAttribute('data-bs-theme', storedTheme);
|
||||
if (storedTheme === 'dark') {
|
||||
darkModeToggle.textContent = '明亮主题';
|
||||
} else {
|
||||
darkModeToggle.textContent = '暗黑主题';
|
||||
}
|
||||
} else {
|
||||
// If no preference is stored, default to dark mode
|
||||
html.setAttribute('data-bs-theme', 'dark');
|
||||
darkModeToggle.textContent = '明亮主题';
|
||||
localStorage.setItem('theme', 'dark');
|
||||
}
|
||||
|
||||
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,99 +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
|
||||
.find(
|
||||
(line) => line.includes("QUIMSLOT: 1") || line.includes("QUIMSLOT: 2")
|
||||
)
|
||||
.split(":")[1]
|
||||
// remove spaces
|
||||
.replace(/\s/g, "");
|
||||
// .replace(/\"/g, "");
|
||||
|
||||
try {
|
||||
this.apn = lines
|
||||
.find((line) => line.includes("+CGCONTRDP: 1"))
|
||||
.split(",")[2]
|
||||
.replace(/\"/g, "");
|
||||
} catch (error) {
|
||||
this.apn = "Failed fetching APN";
|
||||
}
|
||||
|
||||
this.cellLock4GStatus = lines
|
||||
.find((line) => line.includes('+QNWLOCK: "common/4g"'))
|
||||
.split(",")[1]
|
||||
.replace(/\"/g, "");
|
||||
|
||||
this.cellLock5GStatus = lines
|
||||
.find((line) => line.includes('+QNWLOCK: "common/5g"'))
|
||||
.split(",")[1]
|
||||
.replace(/\"/g, "");
|
||||
|
||||
this.prefNetwork = lines
|
||||
.find((line) => line.includes('+QNWPREFCFG: "mode_pref"'))
|
||||
.split(",")[1]
|
||||
.replace(/\"/g, "");
|
||||
|
||||
this.nrModeControlStatus = lines
|
||||
.find((line) => line.includes('+QNWPREFCFG: "nr5g_disable_mode"'))
|
||||
.split(",")[1]
|
||||
.replace(/\"/g, "");
|
||||
|
||||
this.apnIP = lines
|
||||
.find((line) => line.includes("+CGDCONT: 1"))
|
||||
.split(",")[1]
|
||||
.replace(/\"/g, "");
|
||||
|
||||
try {
|
||||
const PCCbands = lines
|
||||
.find((line) => line.includes('+QCAINFO: "PCC"'))
|
||||
.split(",")[3]
|
||||
.replace(/\"/g, "");
|
||||
|
||||
// Loop over all QCAINFO: "SCC" lines and get the bands
|
||||
try {
|
||||
const SCCbands = lines
|
||||
.filter((line) => line.includes('+QCAINFO: "SCC"'))
|
||||
.map((line) => line.split(",")[3].replace(/\"/g, ""))
|
||||
.join(", ");
|
||||
this.bands = `${PCCbands}, ${SCCbands}`;
|
||||
} catch (error) {
|
||||
this.bands = PCCbands;
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
this.bands = "Failed fetching 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,
|
||||
apnIP: apnIP,
|
||||
cellLockStatus: cellLockStatus,
|
||||
prefNetwork: prefNetwork,
|
||||
nrModeControl: nrModeControlStatus,
|
||||
bands: bands,
|
||||
};
|
||||
}
|
||||
@ -1,81 +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;
|
||||
var prefix;
|
||||
|
||||
// Determine bands and prefix based on selected network mode
|
||||
if (selectedMode === "LTE") {
|
||||
bands = lte_band;
|
||||
prefix = "B";
|
||||
} else if (selectedMode === "NSA") {
|
||||
bands = nsa_nr5g_band;
|
||||
prefix = "N";
|
||||
} else if (selectedMode === "SA") {
|
||||
bands = nr5g_band;
|
||||
prefix = "N";
|
||||
}
|
||||
|
||||
checkboxesForm.innerHTML = ""; // Clear existing checkboxes
|
||||
|
||||
// Store the locked bands in arrays
|
||||
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(":");
|
||||
|
||||
var isBandLocked = function(band) {
|
||||
if (selectedMode === "LTE" && locked_lte_bands_array.includes(band)) {
|
||||
return true;
|
||||
}
|
||||
if (selectedMode === "NSA" && locked_nsa_bands_array.includes(band)) {
|
||||
return true;
|
||||
}
|
||||
if (selectedMode === "SA" && locked_sa_bands_array.includes(band)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
var fragment = document.createDocumentFragment();
|
||||
|
||||
if (bands !== null && bands !== "0") {
|
||||
var bandsArray = bands.split(":");
|
||||
var currentRow;
|
||||
|
||||
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
|
||||
fragment.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";
|
||||
checkboxInput.checked = isBandLocked(band);
|
||||
|
||||
var checkboxLabel = document.createElement("label");
|
||||
checkboxLabel.className = "form-check-label";
|
||||
checkboxLabel.htmlFor = "inlineCheckbox" + band;
|
||||
checkboxLabel.innerText = prefix + band;
|
||||
|
||||
checkboxDiv.appendChild(checkboxInput);
|
||||
checkboxDiv.appendChild(checkboxLabel);
|
||||
currentRow.appendChild(checkboxDiv);
|
||||
});
|
||||
} else {
|
||||
// Create a text saying that no bands are available
|
||||
var noBandsText = document.createElement("p");
|
||||
noBandsText.className = "text-center";
|
||||
noBandsText.innerText = "No supported bands available";
|
||||
fragment.appendChild(noBandsText);
|
||||
}
|
||||
|
||||
checkboxesForm.appendChild(fragment);
|
||||
addCheckboxListeners(cellLock);
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -1,669 +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>模块管理</title>
|
||||
<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="simpleSettings()">
|
||||
<nav class="navbar navbar-expand-lg mt-2">
|
||||
<div class="container-fluid">
|
||||
<a class="navbar-brand" href="/"
|
||||
><span class="mb-0 h4 fw-bold">模块管理</span></a>
|
||||
<button
|
||||
class="navbar-toggler"
|
||||
type="button"
|
||||
data-bs-toggle="collapse"
|
||||
data-bs-target="#navbarText"
|
||||
aria-controls="navbarText"
|
||||
aria-expanded="false"
|
||||
aria-label="Toggle navigation"
|
||||
>
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
<div class="collapse navbar-collapse" id="navbarText">
|
||||
<ul class="navbar-nav me-auto mb-2 mb-lg-0">
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="/">首页</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="/network.html">网络</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="/scanner.html">扫描</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a
|
||||
class="nav-link active"
|
||||
href="/settings.html"
|
||||
aria-current="page"
|
||||
>设置</a
|
||||
>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="/sms.html">短信</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="/console">控制台</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="/deviceinfo.html"
|
||||
>设备信息</a
|
||||
>
|
||||
</li>
|
||||
</ul>
|
||||
<span class="navbar-text">
|
||||
<button class="btn btn-link text-reset" id="darkModeToggle">
|
||||
暗黑模式
|
||||
</button>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<div class="row mt-5 mb-4">
|
||||
<div class="col">
|
||||
<div class="card">
|
||||
<div class="card-header">AT 终端</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: 210px"
|
||||
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 命令</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">
|
||||
用逗号分隔多个命令.
|
||||
</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"
|
||||
>
|
||||
提交
|
||||
</button>
|
||||
<button
|
||||
class="btn btn-danger"
|
||||
type="button"
|
||||
@click="clearResponses()"
|
||||
:disabled="isClean"
|
||||
>
|
||||
清除
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<div class="card">
|
||||
<div class="card-header">一键工具</div>
|
||||
<div class="card-body">
|
||||
<div class="card-text table-responsive-sm">
|
||||
<div class="table-responsive">
|
||||
<table class="table">
|
||||
</style>
|
||||
<tbody>
|
||||
<tr>
|
||||
<th scope="row">重启</th>
|
||||
<td>
|
||||
<button
|
||||
type="submit"
|
||||
class="btn btn-danger"
|
||||
@click="showRebootModal()"
|
||||
:disabled="isLoading"
|
||||
>
|
||||
重启
|
||||
</button>
|
||||
</td>
|
||||
<tr>
|
||||
<tr>
|
||||
<th scope="row">重置AT命令设置</th>
|
||||
<td>
|
||||
<button
|
||||
type="submit"
|
||||
class="btn btn-danger"
|
||||
@click="resetATCommands()"
|
||||
:disabled="isLoading"
|
||||
>
|
||||
重置
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">IP 直通</th>
|
||||
<td style="display: flex; justify-content: flex-start;">
|
||||
<select
|
||||
class="form-select"
|
||||
id="ipPassModeSelect"
|
||||
x-model="ipPassMode"
|
||||
style="flex: 1; min-width: 100px;"
|
||||
>
|
||||
<option selected>直通模式</option>
|
||||
<option value="ETH">ETH</option>
|
||||
<option value="USB">USB(ECM/RNDIS)</option>
|
||||
</select>
|
||||
</td>
|
||||
<td>
|
||||
<button
|
||||
type="submit"
|
||||
class="btn btn-primary"
|
||||
@click="ipPassThroughEnable()"
|
||||
x-show="ipPassStatus === false"
|
||||
:disabled="isLoading"
|
||||
>
|
||||
启用
|
||||
</button>
|
||||
<button
|
||||
type="submit"
|
||||
class="btn btn-danger"
|
||||
@click="ipPassThroughDisable()"
|
||||
x-show="ipPassStatus === true"
|
||||
:disabled="isLoading"
|
||||
>
|
||||
禁用
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">USB调制解调器协议</th>
|
||||
<td>
|
||||
<select
|
||||
class="form-select"
|
||||
id="usbNetModeSelect"
|
||||
x-model="usbNetMode"
|
||||
>
|
||||
<option
|
||||
selected
|
||||
x-text="currentUsbNetMode"
|
||||
></option>
|
||||
<option value="RMNET">RMNET</option>
|
||||
<option value="ECM">ECM (推荐)</option>
|
||||
<option value="MBIM">MBIM</option>
|
||||
<option value="RNDIS">RNDIS</option>
|
||||
</select>
|
||||
</td>
|
||||
<td>
|
||||
<button
|
||||
type="submit"
|
||||
class="btn btn-primary"
|
||||
@click="usbNetModeChanger()"
|
||||
:disabled="isLoading"
|
||||
>
|
||||
更改
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">DNS 代理</th>
|
||||
<td>
|
||||
<button
|
||||
type="submit"
|
||||
class="btn btn-primary"
|
||||
@click="onBoardDNSProxyEnable()"
|
||||
x-show="DNSProxyStatus === false"
|
||||
:disabled="isLoading"
|
||||
>
|
||||
启用
|
||||
</button>
|
||||
<button
|
||||
type="submit"
|
||||
class="btn btn-danger"
|
||||
@click="onBoardDNSProxyDisable()"
|
||||
x-show="DNSProxyStatus === true"
|
||||
:disabled="isLoading"
|
||||
>
|
||||
禁用
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col">
|
||||
<div class="card mb-3">
|
||||
<div class="card-header">TTL和网络扫描设置</div>
|
||||
<div class="card-body">
|
||||
<style>.table th,.table td { white-space: nowrap; /* 防止换行 */}</style>
|
||||
<label for="TTLState" class="form-label"
|
||||
>TTL状态和数值</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激活
|
||||
</div>
|
||||
|
||||
<div
|
||||
class="p-3 text-danger-emphasis bg-danger-subtle border border-danger-subtle rounded-3"
|
||||
x-show="ttlStatus === false"
|
||||
>
|
||||
TTL不活动
|
||||
</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">
|
||||
将TTL值设置为0以禁用。
|
||||
</div>
|
||||
</div>
|
||||
<div class="d-grid gap-1">
|
||||
<button
|
||||
class="btn btn-primary"
|
||||
type="button"
|
||||
@click="setTTL()"
|
||||
>
|
||||
更新
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<!-- <div class="card-text">
|
||||
<div class="d-flex flex-row gap-4 w-full">
|
||||
<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>
|
||||
</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>模块将重启</h3>
|
||||
<p style="margin-top: 0.5rem">继续?</p>
|
||||
</div>
|
||||
<div class="d-grid gap-2 d-md-block">
|
||||
<button
|
||||
class="btn btn-primary"
|
||||
type="button"
|
||||
@click="rebootDevice()"
|
||||
>
|
||||
重启
|
||||
</button>
|
||||
<button
|
||||
class="btn btn-danger"
|
||||
type="button"
|
||||
@click="closeModal()"
|
||||
>
|
||||
取消
|
||||
</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>重启...</h3>
|
||||
<p style="margin-top: 0.5rem">
|
||||
请等待
|
||||
<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,
|
||||
ipPassMode: "Unspecified",
|
||||
ipPassStatus: false,
|
||||
usbNetMode: "Unspecified",
|
||||
currentUsbNetMode: "未知",
|
||||
DNSProxyStatus: true,
|
||||
|
||||
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;
|
||||
const encodedATCmd = encodeURIComponent(this.atcmd);
|
||||
const url = `/cgi-bin/get_atcommand?atcmd=${encodedATCmd}`;
|
||||
|
||||
fetch(url)
|
||||
.then((res) => {
|
||||
if (!res.ok) {
|
||||
throw new Error(`HTTP error! status: ${res.status}`);
|
||||
}
|
||||
return res.text();
|
||||
})
|
||||
.then((data) => {
|
||||
this.atCommandResponse = data;
|
||||
this.isLoading = false;
|
||||
this.isClean = false;
|
||||
this.fetchCurrentSettings();
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error("Error: ", error);
|
||||
this.showError = true;
|
||||
this.isLoading = false;
|
||||
});
|
||||
},
|
||||
|
||||
sendUserATCommand() {
|
||||
this.isLoading = true;
|
||||
const encodedATCmd = encodeURIComponent(this.atcmd);
|
||||
const url = `/cgi-bin/user_atcommand?atcmd=${encodedATCmd}`;
|
||||
|
||||
fetch(url)
|
||||
.then((res) => {
|
||||
if (!res.ok) {
|
||||
throw new Error(`HTTP error! status: ${res.status}`);
|
||||
}
|
||||
return res.text();
|
||||
})
|
||||
.then((data) => {
|
||||
this.atCommandResponse = data;
|
||||
this.isLoading = false;
|
||||
this.isClean = false;
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error("Error: ", error);
|
||||
this.showError = true;
|
||||
this.isLoading = false;
|
||||
});
|
||||
},
|
||||
|
||||
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();
|
||||
},
|
||||
|
||||
ipPassThroughEnable() {
|
||||
if (this.ipPassMode != "Unspecified") {
|
||||
if (this.ipPassMode == "ETH") {
|
||||
this.atcmd =
|
||||
// at+qmap="mpdn_rule",0,1,1,1,1,"FF:FF:FF:FF:FF:FF"
|
||||
'AT+QMAP="MPDN_RULE",0,1,0,1,1,"FF:FF:FF:FF:FF:FF"';
|
||||
this.sendATCommand();
|
||||
} else if (this.ipPassMode == "USB") {
|
||||
this.atcmd =
|
||||
'AT+QMAP="MPDN_RULE",0,1,0,3,1,"FF:FF:FF:FF:FF:FF"';
|
||||
this.sendATCommand();
|
||||
} else {
|
||||
console.error("Invalid IP Passthrough Mode");
|
||||
}
|
||||
} else {
|
||||
console.error("IP Passthrough Mode not specified");
|
||||
}
|
||||
},
|
||||
|
||||
ipPassThroughDisable() {
|
||||
this.atcmd = 'AT+QMAP="MPDN_RULE",0;+QMAPWAC=1';
|
||||
this.sendATCommand();
|
||||
},
|
||||
|
||||
onBoardDNSProxyEnable() {
|
||||
this.atcmd = 'AT+QMAP="DHCPV4DNS","enable"';
|
||||
this.sendATCommand().then(() => {
|
||||
this.fetchCurrentSettings();
|
||||
});
|
||||
},
|
||||
|
||||
onBoardDNSProxyDisable() {
|
||||
this.atcmd = 'AT+QMAP="DHCPV4DNS","disable"';
|
||||
this.sendATCommand().then(() => {
|
||||
this.fetchCurrentSettings();
|
||||
});
|
||||
},
|
||||
|
||||
usbNetModeChanger() {
|
||||
if (this.usbNetMode != "Unspecified") {
|
||||
if (this.usbNetMode == "RMNET") {
|
||||
this.atcmd = 'AT+QCFG="usbnet",0;';
|
||||
this.sendATCommand();
|
||||
} else if (this.usbNetMode == "ECM") {
|
||||
this.atcmd = 'AT+QCFG="usbnet",1;';
|
||||
this.sendATCommand();
|
||||
} else if (this.usbNetMode == "MBIM") {
|
||||
this.atcmd = 'AT+QCFG="usbnet",2;';
|
||||
this.sendATCommand();
|
||||
} else if (this.usbNetMode == "RNDIS") {
|
||||
this.atcmd = 'AT+QCFG="usbnet",3;';
|
||||
this.sendATCommand();
|
||||
} else {
|
||||
console.log("USB Net Mode Invalid");
|
||||
}
|
||||
} else {
|
||||
console.error("USB Net Mode not specified");
|
||||
}
|
||||
this.rebootDevice();
|
||||
},
|
||||
|
||||
fetchCurrentSettings() {
|
||||
this.fetchATCommand =
|
||||
'AT+QMAP="MPDN_RULE";+QMAP="DHCPV4DNS";+QCFG="usbnet"';
|
||||
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");
|
||||
console.log("Lines: ", currentData);
|
||||
|
||||
const testEthpass = currentData[1].match(
|
||||
/\+QMAP: "MPDN_rule",0,0,0,0,0/
|
||||
);
|
||||
|
||||
if (testEthpass) {
|
||||
this.ipPassStatus = false;
|
||||
} else {
|
||||
this.ipPassStatus = true;
|
||||
}
|
||||
|
||||
const testDNSProxy = currentData[6].match(
|
||||
/\+QMAP: "DHCPV4DNS","enable"/
|
||||
);
|
||||
|
||||
if (testDNSProxy) {
|
||||
this.DNSProxyStatus = true;
|
||||
} else {
|
||||
this.DNSProxyStatus = false;
|
||||
}
|
||||
|
||||
const testUSBNet = currentData[8].match(
|
||||
/\+QCFG: "usbnet",(\d)/
|
||||
);
|
||||
|
||||
if (testUSBNet[1] == "0") {
|
||||
this.currentUsbNetMode = "RMNET";
|
||||
} else if (testUSBNet[1] == "1") {
|
||||
this.currentUsbNetMode = "ECM";
|
||||
} else if (testUSBNet[1] == "2") {
|
||||
this.currentUsbNetMode = "MBIM";
|
||||
} else if (testUSBNet[1] == "3") {
|
||||
this.currentUsbNetMode = "RNDIS";
|
||||
} else {
|
||||
this.currentUsbNetMode = "未知";
|
||||
}
|
||||
|
||||
// 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
|
||||
const ttlval = this.newTTL;
|
||||
fetch(
|
||||
"/cgi-bin/set_ttl?" + new URLSearchParams({ ttlvalue: ttlval })
|
||||
)
|
||||
.then((res) => res.text()) // Use res.text() instead of res.json()
|
||||
.then((data) => {
|
||||
// Manually handle the response data
|
||||
console.log("Response from server:", data);
|
||||
// You can try to parse the JSON manually or handle the response as needed
|
||||
|
||||
// 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.fetchCurrentSettings();
|
||||
this.fetchTTL();
|
||||
},
|
||||
};
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@ -1,419 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en" data-bs-theme="dark">
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<title>模块管理</title>
|
||||
<!-- 导入自定义和Bootstrap样式 -->
|
||||
<link rel="stylesheet" href="css/styles.css" />
|
||||
<link rel="stylesheet" href="css/bootstrap.min.css" />
|
||||
<!-- 网站图标 -->
|
||||
<link rel="icon" href="favicon.ico" />
|
||||
<!-- 导入Bootstrap和Alpine.js脚本 -->
|
||||
<script src="js/bootstrap.bundle.min.js"></script>
|
||||
<script src="js/alpinejs.min.js" defer></script>
|
||||
|
||||
<!-- Contributed By: snjzb -->
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<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 fw-bold">模块管理</span></a>
|
||||
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarText"
|
||||
aria-controls="navbarText" aria-expanded="false" aria-label="切换导航">
|
||||
<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="/">首页</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="/network.html">网络</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="/scanner.html">扫描</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="/settings.html">设置</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link active" aria-current="page" href="/sms.html">短信</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="/console">控制台</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="/deviceinfo.html">设备信息</a>
|
||||
</li>
|
||||
</ul>
|
||||
<span class="navbar-text">
|
||||
<button class="btn btn-link text-reset" id="darkModeToggle">
|
||||
暗黑模式
|
||||
</button>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
<div class="row mt-5 mb-4">
|
||||
<div class="col">
|
||||
<div class="card">
|
||||
<div class="card-header">短信收件箱</div>
|
||||
<div class="card-body">
|
||||
<div class="card-text">
|
||||
<div class="col">
|
||||
<div style="
|
||||
max-height: 400px;
|
||||
overflow-y: scroll;
|
||||
overflow-x: hidden;
|
||||
">
|
||||
<div x-show="isLoading">
|
||||
<h4>正在获取短信...</h4>
|
||||
</div>
|
||||
<table class="table table-hover border-success" x-show="!isLoading">
|
||||
<tbody>
|
||||
<!-- 没有消息时显示 -->
|
||||
<!-- Display when there are no messages -->
|
||||
<template x-if="messages.length === 0 && !isLoading">
|
||||
<div>
|
||||
<p>收件箱为空</p>
|
||||
</div>
|
||||
</template>
|
||||
<!-- 循环显示短信消息 -->
|
||||
<!-- "Loop display SMS messages" -->
|
||||
<template x-for="(message, index) in messages" :key="index">
|
||||
<tr>
|
||||
<td>
|
||||
<div class="form-check">
|
||||
<input class="form-check-input" type="checkbox" :value="index"
|
||||
x-model="selectedMessages" />
|
||||
<div class="row column-gap-1 mb-2">
|
||||
<div class="col-md-3">
|
||||
<p x-text="'发件人: ' + senders[index]"></p>
|
||||
</div>
|
||||
<div class="col">
|
||||
<p x-text="'日期时间: ' + dates[index]"></p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-9">
|
||||
<p x-text="message.text"></p>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</template>
|
||||
</tbody>
|
||||
</table>
|
||||
</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">全选</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()">
|
||||
刷新
|
||||
</button>
|
||||
<!-- 删除选中短信按钮 -->
|
||||
<!-- Delete selected SMS button -->
|
||||
<button class="btn btn-danger" type="button" @click="deleteSelectedSMS()">
|
||||
删除选中的短信
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mt-5 mb-4">
|
||||
<div class="col">
|
||||
<div class="card">
|
||||
<div class="card-header">发送短信</div>
|
||||
<div class="card-body">
|
||||
<div class="mb-3">
|
||||
<label for="phoneNumber" class="form-label">收件人</label>
|
||||
<input type="text" class="form-control" id="phoneNumber" x-model="phoneNumber"
|
||||
placeholder="输入收件人号码" />
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="messageToSend" class="form-label">短信内容</label>
|
||||
<textarea class="form-control" id="messageToSend" rows="3" x-model="messageToSend"
|
||||
placeholder="输入短信内容"></textarea>
|
||||
</div>
|
||||
<div id="notification" class="alert" style="display: none;"></div>
|
||||
<button class="btn btn-primary" @click="sendSMS()">
|
||||
发送短信
|
||||
</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: '',
|
||||
messageIndices: [], // 确保初始化messageIndices数组
|
||||
|
||||
// 清除现有数据
|
||||
clearData() {
|
||||
this.messages = [];
|
||||
this.senders = [];
|
||||
this.dates = [];
|
||||
this.selectedMessages = [];
|
||||
this.messageIndices = [];
|
||||
const selectAllCheckbox = document.getElementById('selectAllCheckbox');
|
||||
if (selectAllCheckbox) {
|
||||
selectAllCheckbox.checked = false;
|
||||
}
|
||||
},
|
||||
|
||||
// 请求获取短信
|
||||
requestSMS() {
|
||||
this.isLoading = true;
|
||||
fetch(`/cgi-bin/get_atcommand?${new URLSearchParams({ atcmd: "AT+CSMS=1;+CSDH=0;+CNMI=2,1,0,0,0;+CMGF=1;+CSCA?;+CSMP=17,167,0,8;+CPMS=\"ME\",\"ME\",\"ME\";+CSCS=\"UCS2\";+CMGL=\"ALL\"" })}`)
|
||||
.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);
|
||||
});
|
||||
},
|
||||
|
||||
// 解析短信数据的方法
|
||||
parseSMSData(data) {
|
||||
const cmglRegex = /^\s*\+CMGL:\s*(\d+),"[^"]*","([^"]*)"[^"]*,"([^"]*)"/gm;
|
||||
const cscaRegex = /^\s*\+CSCA:\s*"([^"]*)"/gm;
|
||||
this.messageIndices = [];
|
||||
this.serviceCenters = [];
|
||||
this.dates = [];
|
||||
this.senders = [];
|
||||
this.messages = [];
|
||||
let match;
|
||||
let lastIndex = null;
|
||||
while ((match = cmglRegex.exec(data)) !== null) {
|
||||
const index = parseInt(match[1]);
|
||||
const senderHex = match[2];
|
||||
const sender = senderHex.startsWith("003") ? this.convertHexToText(senderHex) : senderHex;
|
||||
const dateStr = match[3].replace(/\+\d{2}$/, "");
|
||||
const date = this.parseCustomDate(dateStr);
|
||||
if (isNaN(date)) {
|
||||
console.error(`Invalid Date: ${dateStr}`);
|
||||
continue;
|
||||
}
|
||||
const startIndex = cmglRegex.lastIndex;
|
||||
const endIndex = data.indexOf("+CMGL:", startIndex) !== -1 ? data.indexOf("+CMGL:", startIndex) : data.length;
|
||||
const messageHex = data.substring(startIndex, endIndex).trim();
|
||||
const message = /^[0-9a-fA-F]+$/.test(messageHex) ? this.convertHexToText(messageHex) : messageHex;
|
||||
if (lastIndex !== null && this.messages[lastIndex].sender === sender && (date - this.messages[lastIndex].date) / 1000 <= 1) {
|
||||
this.messages[lastIndex].text += " " + message;
|
||||
this.messages[lastIndex].indices.push(index);
|
||||
this.dates[lastIndex] = this.formatDate(date);
|
||||
} else {
|
||||
this.messageIndices.push([index]);
|
||||
this.senders.push(sender);
|
||||
this.dates.push(this.formatDate(date));
|
||||
this.messages.push({ text: message, sender: sender, date: date, indices: [index] });
|
||||
lastIndex = this.messages.length - 1;
|
||||
}
|
||||
}
|
||||
while ((match = cscaRegex.exec(data)) !== null) {
|
||||
const serviceCenterHex = match[1];
|
||||
const serviceCenter = this.convertHexToText(serviceCenterHex);
|
||||
this.serviceCenters.push(serviceCenter);
|
||||
}
|
||||
},
|
||||
|
||||
// 将十六进制转换为文本(假设使用 UTF-16BE 编码)
|
||||
convertHexToText(hex) {
|
||||
const bytes = new Uint8Array(hex.match(/.{1,2}/g).map(byte => parseInt(byte, 16)));
|
||||
return new TextDecoder('utf-16be').decode(bytes);
|
||||
},
|
||||
|
||||
// 自定义解析日期函数
|
||||
parseCustomDate(dateStr) {
|
||||
const [datePart, timePart] = dateStr.split(',');
|
||||
const [day, month, year] = datePart.split('/').map(part => parseInt(part, 10));
|
||||
const [hour, minute, second] = timePart.split(':').map(part => parseInt(part, 10));
|
||||
|
||||
// 将日期转换为标准格式的日期对象
|
||||
return new Date(Date.UTC(2000 + year, month - 1, day, hour, minute, second));
|
||||
},
|
||||
|
||||
// 自定义格式化日期函数
|
||||
formatDate(date) {
|
||||
const year = date.getUTCFullYear() - 2000;
|
||||
const month = (date.getUTCMonth() + 1).toString().padStart(2, '0');
|
||||
const day = date.getUTCDate().toString().padStart(2, '0');
|
||||
const hour = date.getUTCHours().toString().padStart(2, '0');
|
||||
const minute = date.getUTCMinutes().toString().padStart(2, '0');
|
||||
const second = date.getUTCSeconds().toString().padStart(2, '0');
|
||||
return `${day}/${month}/${year},${hour}:${minute}:${second}`;
|
||||
},
|
||||
|
||||
// 删除选中的短信
|
||||
deleteSelectedSMS() {
|
||||
if (this.selectedMessages.length === 0) {
|
||||
console.warn("没有选中的短信");
|
||||
return;
|
||||
}
|
||||
if (!this.messageIndices || this.messageIndices.length === 0) {
|
||||
console.error("短信索引未正确初始化或为空");
|
||||
return;
|
||||
}
|
||||
|
||||
// 检查是否全选
|
||||
const isAllSelected = this.selectedMessages.length === this.messages.length;
|
||||
|
||||
if (isAllSelected) {
|
||||
// 如果全选,则调用删除所有短信的方法
|
||||
this.deleteAllSMS();
|
||||
} else {
|
||||
// 否则,删除选中的短信
|
||||
const indicesToDelete = [];
|
||||
this.selectedMessages.forEach(index => {
|
||||
indicesToDelete.push(...this.messages[index].indices);
|
||||
});
|
||||
if (indicesToDelete.length === 0) {
|
||||
console.warn("没有有效的短信索引");
|
||||
return;
|
||||
}
|
||||
|
||||
// 拼接 AT 命令
|
||||
const atCommands = indicesToDelete.map((index, i) => i === 0 ? `AT+CMGD=${index}` : `+CMGD=${index}`).join(';');
|
||||
fetch(`/cgi-bin/get_atcommand?${new URLSearchParams({ atcmd: atCommands })}`)
|
||||
.finally(() => {
|
||||
this.selectedMessages = [];
|
||||
this.requestSMS();
|
||||
});
|
||||
}
|
||||
},
|
||||
// 删除所有短信
|
||||
deleteAllSMS() {
|
||||
fetch(`/cgi-bin/get_atcommand?${new URLSearchParams({ atcmd: "AT+CMGD=,4" })}`)
|
||||
.finally(() => {
|
||||
this.init();
|
||||
});
|
||||
},
|
||||
// 发送短信
|
||||
encodeUCS2(input) {
|
||||
let output = '';
|
||||
for (let i = 0; i < input.length; i++) {
|
||||
const hex = input.charCodeAt(i).toString(16).toUpperCase().padStart(4, '0');
|
||||
output += hex;
|
||||
}
|
||||
return output;
|
||||
},
|
||||
|
||||
async sendSMS() {
|
||||
let phoneNumberWithCountryCode;
|
||||
if (this.phoneNumber.length < 11) {
|
||||
phoneNumberWithCountryCode = this.phoneNumber;
|
||||
} else {
|
||||
const serviceCenterPrefix = this.serviceCenters[0].substring(0, 3);
|
||||
phoneNumberWithCountryCode = `${serviceCenterPrefix}${this.phoneNumber}`;
|
||||
}
|
||||
const encodedPhoneNumber = this.encodeUCS2(phoneNumberWithCountryCode);
|
||||
const messageSegments = this.splitMessage(this.messageToSend, 70); // 将消息分段
|
||||
const uid = Math.floor(Math.random() * 256); // 生成随机的UID
|
||||
const totalSegments = messageSegments.length;
|
||||
let allSegmentsSent = true;
|
||||
let errorCode = null;
|
||||
for (let i = 0; i < totalSegments; i++) {
|
||||
const segment = messageSegments[i];
|
||||
const encodedMessage = this.encodeUCS2(segment);
|
||||
const currentSegment = i + 1;
|
||||
const Command = `${uid},${currentSegment},${totalSegments}`;
|
||||
const params = new URLSearchParams({
|
||||
number: encodedPhoneNumber,
|
||||
msg: encodedMessage,
|
||||
Command: Command
|
||||
});
|
||||
try {
|
||||
const response = await fetch(`/cgi-bin/send_sms?${params.toString()}`);
|
||||
const data = await response.text();
|
||||
console.log("Response from server:", data);
|
||||
|
||||
// 检查返回的数据中是否包含 '+CMS ERROR'
|
||||
if (data.includes('+CMS ERROR')) {
|
||||
errorCode = data.match(/\+CMS ERROR: (\d+)/)?.[1];
|
||||
console.error("SMS send error:", data);
|
||||
allSegmentsSent = false;
|
||||
break; // 停止发送剩余的段
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Fetch error:", error);
|
||||
allSegmentsSent = false;
|
||||
break; // 停止发送剩余的段
|
||||
}
|
||||
}
|
||||
if (allSegmentsSent) {
|
||||
this.showNotification("SMS sent successfully!");
|
||||
} else {
|
||||
this.showNotification(`SMS sending failed!: ${errorCode}`);
|
||||
}
|
||||
},
|
||||
|
||||
splitMessage(message, length) {
|
||||
const segments = [];
|
||||
for (let i = 0; i < message.length; i += length) {
|
||||
segments.push(message.substring(i, i + length));
|
||||
}
|
||||
return segments;
|
||||
},
|
||||
|
||||
showNotification(message, type) {
|
||||
const notification = document.getElementById('notification');
|
||||
notification.innerText = message;
|
||||
notification.className = `alert alert-${type}`;
|
||||
notification.style.display = 'block';
|
||||
setTimeout(() => {
|
||||
notification.style.display = 'none';
|
||||
}, 3000); // 3秒后自动关闭
|
||||
},
|
||||
|
||||
// 初始化
|
||||
// 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>
|
||||
@ -1,276 +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>
|
||||
<!-- 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: 2.4em;
|
||||
height: 1.2em;
|
||||
}
|
||||
</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" href="/scanner.html">Simple Scan</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="!isFormComplete"
|
||||
x-on:change="setWatchCatSettings"
|
||||
/>
|
||||
</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="223.5.5.5">223.5.5.5</option>
|
||||
<option value="114.114.114.114">114.114.114.114</option>
|
||||
<option value="119.29.29.29">119.29.29.29</option>
|
||||
<option value="180.76.76.76">180.76.76.76</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="pingTimeout"
|
||||
/>
|
||||
</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="pingFailureCount"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-footer">
|
||||
Still under development. Coming soon...
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mt-3 mb-3">
|
||||
<div class="col">
|
||||
<div class="card">
|
||||
<div class="card-header">Simple Watchcat Logs</div>
|
||||
<div class="card-body">
|
||||
<div class="card-text">
|
||||
<div class="form-floating">
|
||||
<textarea
|
||||
class="form-control"
|
||||
placeholder="Leave a comment here"
|
||||
id="floatingTextarea2"
|
||||
style="height: 100px"
|
||||
x-text="response"
|
||||
readonly
|
||||
></textarea>
|
||||
<label for="floatingTextarea2">Logs</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-footer">
|
||||
No log is provided when successfully enabling the watchcat.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
<script src="js/dark-mode.js"></script>
|
||||
<script>
|
||||
function simpleWatchCat() {
|
||||
return {
|
||||
watchCatStatus: false, // Initialize as false (not enabled)
|
||||
trackIP: "",
|
||||
pingTimeout: "",
|
||||
pingFailureCount: "",
|
||||
response: "",
|
||||
|
||||
setWatchCatSettings() {
|
||||
fetch(
|
||||
"/cgi-bin/watchcat_maker?" +
|
||||
new URLSearchParams({
|
||||
WATCHCAT_ENABLED: this.watchCatStatus ? "enable" : "disable",
|
||||
TRACK_IP: this.trackIP,
|
||||
PING_TIMEOUT: this.pingTimeout,
|
||||
PING_FAILURE_COUNT: this.pingFailureCount,
|
||||
})
|
||||
)
|
||||
.then((response) => response.text()) // Convert response to text
|
||||
.then((data) => {
|
||||
this.response = data; // Store the response data
|
||||
console.log(data); // Log the response for debugging
|
||||
})
|
||||
.then(() => {
|
||||
this.fetchWatchCatSettings();
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error("Error:", error); // Handle any errors
|
||||
this.response = "An error occurred.";
|
||||
});
|
||||
},
|
||||
|
||||
// Computed property to check if the form is complete
|
||||
get isFormComplete() {
|
||||
return (
|
||||
this.trackIP !== "" &&
|
||||
this.pingTimeout !== "" &&
|
||||
this.pingFailureCount !== ""
|
||||
);
|
||||
},
|
||||
|
||||
// Fetch the current watchcat settings
|
||||
fetchWatchCatSettings() {
|
||||
fetch("/cgi-bin/get_watchcat_status")
|
||||
.then((response) => {
|
||||
if (!response.ok) {
|
||||
throw new Error("Network response was not ok");
|
||||
}
|
||||
return response.json(); // Parse response as JSON
|
||||
})
|
||||
.then((data) => {
|
||||
console.log(data); // Log the parsed data for debugging
|
||||
|
||||
// Check if the JSON is not empty
|
||||
if (data) {
|
||||
this.watchCatStatus = data.enabled === true;
|
||||
this.trackIP = data.track_ip;
|
||||
this.pingTimeout = data.ping_timeout;
|
||||
this.pingFailureCount = data.ping_failure_count;
|
||||
}
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error("Error:", error); // Handle any errors
|
||||
this.response = "An error occurred.";
|
||||
});
|
||||
},
|
||||
|
||||
init() {
|
||||
this.fetchWatchCatSettings();
|
||||
},
|
||||
};
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@ -1,351 +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>
|
||||
|
||||
<style>
|
||||
.form-switch .form-check-input {
|
||||
width: 2.4em;
|
||||
height: 1.2em;
|
||||
}
|
||||
</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="!isFormComplete"
|
||||
x:onchange="setWatchCatSettings"
|
||||
/>
|
||||
</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="pingTimeout"
|
||||
/>
|
||||
</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="pingFailureCount"
|
||||
/>
|
||||
</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 class="row mt-3 mb-3">
|
||||
<div class="col">
|
||||
<div class="card">
|
||||
<div class="card-header">Simple Watchcat Logs</div>
|
||||
<div class="card-body">
|
||||
<div class="card-text">
|
||||
<div class="form-floating">
|
||||
<textarea
|
||||
class="form-control"
|
||||
placeholder="Leave a comment here"
|
||||
id="floatingTextarea2"
|
||||
style="height: 100px"
|
||||
x-text="response"
|
||||
readonly
|
||||
></textarea>
|
||||
<label for="floatingTextarea2">Logs Here</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
<script src="js/dark-mode.js"></script>
|
||||
<script>
|
||||
function simpleWatchCat() {
|
||||
return {
|
||||
watchCatStatus: false,
|
||||
trackIP: "",
|
||||
pingTimeout: "",
|
||||
pingFailureCount: "",
|
||||
response: "",
|
||||
|
||||
setWatchCatSettings() {
|
||||
fetch(
|
||||
"/cgi-bin/watchcat_maker?" +
|
||||
new URLSearchParams({
|
||||
WATCHCAT_ENABLED: this.watchCatStatus,
|
||||
TRACK_IP: this.trackIP,
|
||||
PING_TIMEOUT: this.pingTimeout,
|
||||
PING_FAILURE_COUNT: this.pingFailureCount,
|
||||
})
|
||||
)
|
||||
.then((response) => response.text()) // Convert response to text
|
||||
.then((data) => {
|
||||
this.response = data; // Store the response data
|
||||
console.log(data); // Log the response for debugging
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error("Error:", error); // Handle any errors
|
||||
this.response = "An error occurred.";
|
||||
});
|
||||
},
|
||||
|
||||
// Computed property to check if the form is complete
|
||||
get isFormComplete() {
|
||||
return (
|
||||
this.trackIP !== "" &&
|
||||
this.pingTimeout !== "" &&
|
||||
this.pingFailureCount !== ""
|
||||
);
|
||||
},
|
||||
};
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@ -1 +0,0 @@
|
||||
2
|
||||
@ -1,16 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Define the ports you want to block
|
||||
PORTS=("80" "443") # Default ports, will be modified by the install script
|
||||
|
||||
# First, allow specified ports on bridge0, eth0, and tailscale0
|
||||
for port in "${PORTS[@]}"; do
|
||||
iptables -A INPUT -i bridge0 -p tcp --dport $port -j ACCEPT
|
||||
iptables -A INPUT -i eth0 -p tcp --dport $port -j ACCEPT
|
||||
iptables -A INPUT -i tailscale0 -p tcp --dport $port -j ACCEPT
|
||||
done
|
||||
|
||||
# Then, block specified ports on all other interfaces
|
||||
for port in "${PORTS[@]}"; do
|
||||
iptables -A INPUT -p tcp --dport $port -j DROP
|
||||
done
|
||||
@ -1,11 +0,0 @@
|
||||
[Unit]
|
||||
Description=Simple Firewall Setup
|
||||
After=network.target
|
||||
|
||||
[Service]
|
||||
Type=oneshot
|
||||
ExecStart=/bin/bash /usrdata/simplefirewall/simplefirewall.sh
|
||||
RemainAfterExit=yes
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
@ -1,12 +0,0 @@
|
||||
[Unit]
|
||||
Description=TTL Override
|
||||
After=ql-netd.service
|
||||
DefaultDependencies=no
|
||||
|
||||
[Service]
|
||||
Type=oneshot
|
||||
ExecStart=/usrdata/simplefirewall/ttl-override start
|
||||
User=root
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
@ -1,53 +0,0 @@
|
||||
#! /bin/bash
|
||||
|
||||
# Adapted from https://github.com/natecarlson/quectel-rgmii-configuration-notes/blob/main/files/ttl-override
|
||||
# Uses ttlvalue file to read what ttl should be set to
|
||||
|
||||
|
||||
if [ -f /usrdata/simplefirewall/ttlvalue ];
|
||||
then
|
||||
ttlfile=$(</usrdata/simplefirewall/ttlvalue)
|
||||
TTLVALUE=$(echo $ttlfile | grep -o "[0-9]\{1,3\}")
|
||||
|
||||
if [ -z "${TTLVALUE}" ]; then
|
||||
echo "Couldnt get proper ttl value from file" >&2
|
||||
exit 1
|
||||
fi
|
||||
else
|
||||
# Couldnt find ttlvalue file, lets generate one with 0 ttlvalue (0 = disabled)
|
||||
touch /usrdata/simplefirewall/ttlvalue && echo '0' > /usrdata/simplefirewall/ttlvalue
|
||||
exit 1
|
||||
fi
|
||||
|
||||
case "$1" in
|
||||
start)
|
||||
if (( $TTLVALUE > 0 )); then
|
||||
echo "Adding TTL override rules: "
|
||||
iptables -t mangle -I POSTROUTING -o rmnet+ -j TTL --ttl-set ${TTLVALUE}
|
||||
ip6tables -t mangle -I POSTROUTING -o rmnet+ -j HL --hl-set ${TTLVALUE}
|
||||
else
|
||||
echo "TTLVALUE set to 0, nothing to do..."
|
||||
fi
|
||||
echo "done"
|
||||
;;
|
||||
stop)
|
||||
if (( $TTLVALUE > 0 )); then
|
||||
echo "Removing TTL override rules: "
|
||||
iptables -t mangle -D POSTROUTING -o rmnet+ -j TTL --ttl-set ${TTLVALUE} &>/dev/null || true
|
||||
ip6tables -t mangle -D POSTROUTING -o rmnet+ -j HL --hl-set ${TTLVALUE} &>/dev/null || true
|
||||
else
|
||||
echo "TTLVALUE set to 0, nothing to do..."
|
||||
fi
|
||||
echo "done"
|
||||
;;
|
||||
restart)
|
||||
$0 stop
|
||||
$0 start
|
||||
;;
|
||||
*)
|
||||
echo "Usage ttl-override { start | stop | restart }" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
exit 0
|
||||
@ -1 +0,0 @@
|
||||
0
|
||||
@ -1 +0,0 @@
|
||||
2
|
||||
@ -1,240 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Define constants
|
||||
GITUSER="iamromulan"
|
||||
GITTREE="development"
|
||||
DIR_NAME="simpleadmin"
|
||||
SERVICE_FILE="/lib/systemd/system/install_simpleadmin.service"
|
||||
SERVICE_NAME="install_simpleadmin"
|
||||
TMP_SCRIPT="/tmp/install_simpleadmin.sh"
|
||||
LOG_FILE="/tmp/install_simpleadmin.log"
|
||||
export PATH=/bin:/sbin:/usr/bin:/usr/sbin:/opt/bin:/opt/sbin:/usrdata/root/bin
|
||||
|
||||
# Tmp Script dependent constants
|
||||
SIMPLE_ADMIN_DIR="/usrdata/simpleadmin"
|
||||
# Function to remount file system as read-write
|
||||
remount_rw() {
|
||||
mount -o remount,rw /
|
||||
}
|
||||
|
||||
# Function to remount file system as read-only
|
||||
remount_ro() {
|
||||
mount -o remount,ro /
|
||||
}
|
||||
|
||||
# Installation Prep
|
||||
remount_rw
|
||||
systemctl daemon-reload
|
||||
rm $SERVICE_FILE > /dev/null 2>&1
|
||||
rm $SERVICE_NAME > /dev/null 2>&1
|
||||
|
||||
# Create the systemd service file
|
||||
cat <<EOF > "$SERVICE_FILE"
|
||||
[Unit]
|
||||
Description=Update $DIR_NAME temporary service
|
||||
|
||||
[Service]
|
||||
Type=oneshot
|
||||
ExecStart=/bin/bash $TMP_SCRIPT > $LOG_FILE 2>&1
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
EOF
|
||||
|
||||
# Create and populate the temporary shell script for installation
|
||||
cat <<EOF > "$TMP_SCRIPT"
|
||||
#!/bin/bash
|
||||
|
||||
GITUSER="iamromulan"
|
||||
GITTREE="development"
|
||||
SIMPLE_ADMIN_DIR="/usrdata/simpleadmin"
|
||||
export HOME=/usrdata/root
|
||||
export PATH=/bin:/sbin:/usr/bin:/usr/sbin:/opt/bin:/opt/sbin:/usrdata/root/bin
|
||||
|
||||
# Function to remount file system as read-write
|
||||
remount_rw() {
|
||||
mount -o remount,rw /
|
||||
}
|
||||
|
||||
# Function to remount file system as read-only
|
||||
remount_ro() {
|
||||
mount -o remount,ro /
|
||||
}
|
||||
remount_rw
|
||||
uninstall_simpleadmin() {
|
||||
echo "Uninstalling Simpleadmin..."
|
||||
|
||||
# Check if Lighttpd service is installed and remove it if present
|
||||
if [ -f "/lib/systemd/system/lighttpd.service" ]; then
|
||||
echo "Lighttpd detected, uninstalling Lighttpd webserver and its modules..."
|
||||
systemctl stop lighttpd
|
||||
rm -f /lib/systemd/system/lighttpd.service
|
||||
opkg --force-remove --force-removal-of-dependent-packages remove lighttpd-mod-authn_file lighttpd-mod-auth lighttpd-mod-cgi lighttpd-mod-openssl lighttpd-mod-proxy lighttpd
|
||||
fi
|
||||
echo -e "\e[1;34mUninstalling simpleadmin content...\e[0m"
|
||||
systemctl stop simpleadmin_generate_status
|
||||
systemctl stop simpleadmin_httpd
|
||||
rm -f /lib/systemd/system/simpleadmin_httpd.service
|
||||
rm -f /lib/systemd/system/simpleadmin_generate_status.service
|
||||
systemctl daemon-reload
|
||||
|
||||
echo -e "\e[1;34mUninstalling ttyd...\e[0m"
|
||||
systemctl stop ttyd
|
||||
rm -rf /usrdata/ttyd
|
||||
rm -rf "$SIMPLE_ADMIN_DIR"
|
||||
rm -f /lib/systemd/system/ttyd.service
|
||||
rm -f /lib/systemd/system/multi-user.target.wants/ttyd.service
|
||||
rm -f /bin/ttyd
|
||||
echo -e "\e[1;32mttyd has been uninstalled.\e[0m"
|
||||
|
||||
echo "Uninstallation process completed."
|
||||
}
|
||||
|
||||
install_lighttpd() {
|
||||
# Check for simpleadmin_httpd service and remove if exists
|
||||
if [ -f "/lib/systemd/system/simpleadmin_httpd.service" ]; then
|
||||
systemctl stop simpleadmin_httpd
|
||||
rm /lib/systemd/system/simpleadmin_httpd.service
|
||||
rm /lib/systemd/system/multi-user.target.wants/simpleadmin_httpd.service
|
||||
fi
|
||||
|
||||
/opt/bin/opkg install sudo lighttpd lighttpd-mod-auth lighttpd-mod-authn_file lighttpd-mod-cgi lighttpd-mod-openssl lighttpd-mod-proxy
|
||||
# Ensure rc.unslung doesn't try to start it
|
||||
# Dynamically find and remove any Lighttpd-related init script
|
||||
for script in /opt/etc/init.d/*lighttpd*; do
|
||||
if [ -f "$script" ]; then
|
||||
echo "Removing existing Lighttpd init script: $script"
|
||||
rm "$script" # Remove the script if it contains 'lighttpd' in its name
|
||||
fi
|
||||
done
|
||||
systemctl stop lighttpd
|
||||
echo -e "\033[0;32mInstalling/Updating Lighttpd...\033[0m"
|
||||
mkdir -p "$SIMPLE_ADMIN_DIR"
|
||||
wget --no-check-certificate -O "$SIMPLE_ADMIN_DIR/lighttpd.conf" http://gitea.hapyle.work:33000/taotao/webui/raw/development/simpleadmin/lighttpd.conf
|
||||
wget --no-check-certificate -O "/lib/systemd/system/lighttpd.service" http://gitea.hapyle.work:33000/taotao/webui/raw/development/simpleadmin/systemd/lighttpd.service
|
||||
ln -sf "/lib/systemd/system/lighttpd.service" "/lib/systemd/system/multi-user.target.wants/"
|
||||
echo "www-data ALL = (root) NOPASSWD: /usr/sbin/iptables, /usr/sbin/ip6tables, /usrdata/simplefirewall/ttl-override, /bin/echo, /bin/cat" > /opt/etc/sudoers.d/www-data
|
||||
|
||||
openssl req -new -newkey rsa:2048 -days 3650 -nodes -x509 \
|
||||
-subj "/C=US/ST=MI/L=Romulus/O=RMIITools/CN=localhost" \
|
||||
-keyout $SIMPLE_ADMIN_DIR/server.key -out $SIMPLE_ADMIN_DIR/server.crt
|
||||
systemctl daemon-reload
|
||||
systemctl start lighttpd
|
||||
|
||||
echo -e "\033[0;32mLighttpd installation/update complete.\033[0m"
|
||||
}
|
||||
|
||||
install_simpleadmin() {
|
||||
remount_rw
|
||||
echo -e "\e[1;31m2) Installing simpleadmin from the $GITTREE branch\e[0m"
|
||||
mkdir $SIMPLE_ADMIN_DIR
|
||||
mkdir $SIMPLE_ADMIN_DIR/systemd
|
||||
mkdir $SIMPLE_ADMIN_DIR/script
|
||||
mkdir $SIMPLE_ADMIN_DIR/console
|
||||
mkdir $SIMPLE_ADMIN_DIR/console/menu
|
||||
mkdir $SIMPLE_ADMIN_DIR/console/services
|
||||
mkdir $SIMPLE_ADMIN_DIR/console/services/systemd
|
||||
mkdir $SIMPLE_ADMIN_DIR/www
|
||||
mkdir $SIMPLE_ADMIN_DIR/www/cgi-bin
|
||||
mkdir $SIMPLE_ADMIN_DIR/www/css
|
||||
mkdir $SIMPLE_ADMIN_DIR/www/js
|
||||
cd $SIMPLE_ADMIN_DIR/systemd
|
||||
wget --no-check-certificate http://gitea.hapyle.work:33000/taotao/webui/raw/development/simpleadmin/systemd/lighttpd.service
|
||||
sleep 1
|
||||
cd $SIMPLE_ADMIN_DIR/script
|
||||
wget --no-check-certificate http://gitea.hapyle.work:33000/taotao/webui/raw/development/simpleadmin/script/ttl_script.sh
|
||||
wget --no-check-certificate http://gitea.hapyle.work:33000/taotao/webui/raw/development/simpleadmin/script/remove_watchcat.sh
|
||||
wget --no-check-certificate http://gitea.hapyle.work:33000/taotao/webui/raw/development/simpleadmin/script/create_watchcat.sh
|
||||
sleep 1
|
||||
cd $SIMPLE_ADMIN_DIR/console
|
||||
wget --no-check-certificate http://gitea.hapyle.work:33000/taotao/webui/raw/development/simpleadmin/console/.profile
|
||||
sleep 1
|
||||
cd $SIMPLE_ADMIN_DIR/console/menu
|
||||
wget --no-check-certificate http://gitea.hapyle.work:33000/taotao/webui/raw/development/simpleadmin/console/menu/start_menu.sh
|
||||
ln -f $SIMPLE_ADMIN_DIR/console/menu/start_menu.sh /usrdata/root/bin/menu
|
||||
wget --no-check-certificate http://gitea.hapyle.work:33000/taotao/webui/raw/development/simpleadmin/console/menu/sfirewall_settings.sh
|
||||
wget --no-check-certificate http://gitea.hapyle.work:33000/taotao/webui/raw/development/simpleadmin/console/menu/start_menu.sh
|
||||
wget --no-check-certificate http://gitea.hapyle.work:33000/taotao/webui/raw/development/simpleadmin/console/menu/LAN_settings.sh
|
||||
sleep 1
|
||||
cd $SIMPLE_ADMIN_DIR/www
|
||||
wget --no-check-certificate http://gitea.hapyle.work:33000/taotao/webui/raw/development/simpleadmin/www/deviceinfo.html
|
||||
wget --no-check-certificate http://gitea.hapyle.work:33000/taotao/webui/raw/development/simpleadmin/www/favicon.ico
|
||||
wget --no-check-certificate http://gitea.hapyle.work:33000/taotao/webui/raw/development/simpleadmin/www/index.html
|
||||
wget --no-check-certificate http://gitea.hapyle.work:33000/taotao/webui/raw/development/simpleadmin/www/network.html
|
||||
wget --no-check-certificate http://gitea.hapyle.work:33000/taotao/webui/raw/development/simpleadmin/www/settings.html
|
||||
wget --no-check-certificate http://gitea.hapyle.work:33000/taotao/webui/raw/development/simpleadmin/www/sms.html
|
||||
wget --no-check-certificate http://gitea.hapyle.work:33000/taotao/webui/raw/development/simpleadmin/www/scanner.html
|
||||
wget --no-check-certificate http://gitea.hapyle.work:33000/taotao/webui/raw/development/simpleadmin/www/watchcat.html
|
||||
sleep 1
|
||||
cd $SIMPLE_ADMIN_DIR/www/js
|
||||
wget --no-check-certificate http://gitea.hapyle.work:33000/taotao/webui/raw/development/simpleadmin/www/js/alpinejs.min.js
|
||||
wget --no-check-certificate http://gitea.hapyle.work:33000/taotao/webui/raw/development/simpleadmin/www/js/bootstrap.bundle.min.js
|
||||
wget --no-check-certificate http://gitea.hapyle.work:33000/taotao/webui/raw/development/simpleadmin/www/js/dark-mode.js
|
||||
wget --no-check-certificate http://gitea.hapyle.work:33000/taotao/webui/raw/development/simpleadmin/www/js/generate-freq-box.js
|
||||
wget --no-check-certificate http://gitea.hapyle.work:33000/taotao/webui/raw/development/simpleadmin/www/js/parse-settings.js
|
||||
wget --no-check-certificate http://gitea.hapyle.work:33000/taotao/webui/raw/development/simpleadmin/www/js/populate-checkbox.js
|
||||
sleep 1
|
||||
cd $SIMPLE_ADMIN_DIR/www/css
|
||||
wget --no-check-certificate http://gitea.hapyle.work:33000/taotao/webui/raw/development/simpleadmin/www/css/bootstrap.min.css
|
||||
wget --no-check-certificate http://gitea.hapyle.work:33000/taotao/webui/raw/development/simpleadmin/www/css/styles.css
|
||||
sleep 1
|
||||
cd $SIMPLE_ADMIN_DIR/www/cgi-bin
|
||||
wget --no-check-certificate http://gitea.hapyle.work:33000/taotao/webui/raw/development/simpleadmin/www/cgi-bin/get_atcommand
|
||||
wget --no-check-certificate http://gitea.hapyle.work:33000/taotao/webui/raw/development/simpleadmin/www/cgi-bin/user_atcommand
|
||||
wget --no-check-certificate http://gitea.hapyle.work:33000/taotao/webui/raw/development/simpleadmin/www/cgi-bin/get_ping
|
||||
wget --no-check-certificate http://gitea.hapyle.work:33000/taotao/webui/raw/development/simpleadmin/www/cgi-bin/get_sms
|
||||
wget --no-check-certificate http://gitea.hapyle.work:33000/taotao/webui/raw/development/simpleadmin/www/cgi-bin/get_ttl_status
|
||||
wget --no-check-certificate http://gitea.hapyle.work:33000/taotao/webui/raw/development/simpleadmin/www/cgi-bin/set_ttl
|
||||
wget --no-check-certificate http://gitea.hapyle.work:33000/taotao/webui/raw/development/simpleadmin/www/cgi-bin/send_sms
|
||||
wget --no-check-certificate http://gitea.hapyle.work:33000/taotao/webui/raw/development/simpleadmin/www/cgi-bin/get_uptime
|
||||
wget --no-check-certificate http://gitea.hapyle.work:33000/taotao/webui/raw/development/simpleadmin/www/cgi-bin/get_watchcat_status
|
||||
wget --no-check-certificate http://gitea.hapyle.work:33000/taotao/webui/raw/development/simpleadmin/www/cgi-bin/set_watchcat
|
||||
wget --no-check-certificate http://gitea.hapyle.work:33000/taotao/webui/raw/development/simpleadmin/www/cgi-bin/watchcat_maker
|
||||
sleep 1
|
||||
cd /
|
||||
chmod +x $SIMPLE_ADMIN_DIR/www/cgi-bin/*
|
||||
chmod +x $SIMPLE_ADMIN_DIR/script/*
|
||||
chmod +x $SIMPLE_ADMIN_DIR/console/menu/*
|
||||
chmod +x $SIMPLE_ADMIN_DIR/console/.profile
|
||||
cp -f $SIMPLE_ADMIN_DIR/console/.profile /usrdata/root/.profile
|
||||
chmod +x /usrdata/root/.profile
|
||||
cp -rf $SIMPLE_ADMIN_DIR/systemd/* /lib/systemd/system
|
||||
sleep 1
|
||||
systemctl daemon-reload
|
||||
sleep 1
|
||||
}
|
||||
install_ttyd() {
|
||||
echo -e "\e[1;34mStarting ttyd installation process...\e[0m"
|
||||
cd $SIMPLE_ADMIN_DIR/console
|
||||
curl -L -o ttyd http://gitea.hapyle.work:33000/taotao/webui/raw/development/ttyd.armhf && chmod +x ttyd
|
||||
wget --no-check-certificate "http://gitea.hapyle.work:33000/taotao/webui/raw/development/simpleadmin/console/ttyd.bash" && chmod +x ttyd.bash
|
||||
cd $SIMPLE_ADMIN_DIR/systemd/
|
||||
wget --no-check-certificate "http://gitea.hapyle.work:33000/taotao/webui/raw/development/simpleadmin/systemd/ttyd.service"
|
||||
cp -f $SIMPLE_ADMIN_DIR/systemd/ttyd.service /lib/systemd/system/
|
||||
ln -sf /usrdata/simpleadmin/ttyd /bin
|
||||
|
||||
# Enabling and starting ttyd service
|
||||
systemctl daemon-reload
|
||||
ln -sf /lib/systemd/system/ttyd.service /lib/systemd/system/multi-user.target.wants/
|
||||
systemctl start ttyd
|
||||
if [ "$?" -ne 0 ]; then
|
||||
echo -e "\e[1;31mFailed to start ttyd service. Please check the systemd service file and ttyd binary.\e[0m"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo -e "\e[1;32mInstallation Complete! ttyd server is up.\e[0m"
|
||||
}
|
||||
uninstall_simpleadmin
|
||||
install_lighttpd
|
||||
install_simpleadmin
|
||||
install_ttyd
|
||||
remount_ro
|
||||
exit 0
|
||||
EOF
|
||||
|
||||
# Make the temporary script executable
|
||||
chmod +x "$TMP_SCRIPT"
|
||||
|
||||
# Reload systemd to recognize the new service and start the update
|
||||
systemctl daemon-reload
|
||||
systemctl start $SERVICE_NAME
|
||||
@ -1,106 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Define constants
|
||||
GITUSER="iamromulan"
|
||||
GITTREE="development"
|
||||
DIR_NAME="simplefirewall"
|
||||
SERVICE_FILE="/lib/systemd/system/install_simplefirewall.service"
|
||||
SERVICE_NAME="install_simplefirewall"
|
||||
TMP_SCRIPT="/tmp/install_simple_firewall.sh"
|
||||
LOG_FILE="/tmp/install_simplefirewall.log"
|
||||
|
||||
# Tmp Script dependent constants
|
||||
SIMPLE_FIREWALL_DIR="/usrdata/simplefirewall"
|
||||
SIMPLE_FIREWALL_SCRIPT="$SIMPLE_FIREWALL_DIR/simplefirewall.sh"
|
||||
SIMPLE_FIREWALL_SYSTEMD_DIR="$SIMPLE_FIREWALL_DIR/systemd"
|
||||
|
||||
# Function to remount file system as read-write
|
||||
remount_rw() {
|
||||
mount -o remount,rw /
|
||||
}
|
||||
|
||||
# Function to remount file system as read-only
|
||||
remount_ro() {
|
||||
mount -o remount,ro /
|
||||
}
|
||||
remount_rw
|
||||
# Create the systemd service file
|
||||
cat <<EOF > "$SERVICE_FILE"
|
||||
[Unit]
|
||||
Description=Update $DIR_NAME temporary service
|
||||
|
||||
[Service]
|
||||
Type=oneshot
|
||||
ExecStart=/bin/bash $TMP_SCRIPT > $LOG_FILE 2>&1
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
EOF
|
||||
|
||||
# Create and populate the temporary shell script for installation
|
||||
cat <<EOF > "$TMP_SCRIPT"
|
||||
#!/bin/bash
|
||||
|
||||
GITUSER="iamromulan"
|
||||
GITTREE="development"
|
||||
SIMPLE_FIREWALL_DIR="/usrdata/simplefirewall"
|
||||
SIMPLE_FIREWALL_SCRIPT="$SIMPLE_FIREWALL_DIR/simplefirewall.sh"
|
||||
SIMPLE_FIREWALL_SYSTEMD_DIR="$SIMPLE_FIREWALL_DIR/systemd"
|
||||
|
||||
# Function to remount file system as read-write
|
||||
remount_rw() {
|
||||
mount -o remount,rw /
|
||||
}
|
||||
|
||||
# Function to remount file system as read-only
|
||||
remount_ro() {
|
||||
mount -o remount,ro /
|
||||
}
|
||||
remount_rw
|
||||
# Function to remove Simple Firewall
|
||||
uninstall_simple_firewall() {
|
||||
echo "Uninstalling Simplefirewall..."
|
||||
systemctl stop simplefirewall
|
||||
systemctl stop ttl-override
|
||||
rm -f /lib/systemd/system/simplefirewall.service
|
||||
rm -f /lib/systemd/system/ttl-override.service
|
||||
systemctl daemon-reload
|
||||
rm -rf "$SIMPLE_FIREWALL_DIR"
|
||||
echo "Simplefirewall uninstalled."
|
||||
}
|
||||
# Function to install Simple Firewall
|
||||
install_simple_firewall() {
|
||||
systemctl stop simplefirewall
|
||||
systemctl stop ttl-override
|
||||
echo -e "\033[0;32mInstalling/Updating Simple Firewall...\033[0m"
|
||||
mount -o remount,rw /
|
||||
mkdir -p "$SIMPLE_FIREWALL_DIR"
|
||||
mkdir -p "$SIMPLE_FIREWALL_SYSTEMD_DIR"
|
||||
wget --no-check-certificate -O "$SIMPLE_FIREWALL_DIR/simplefirewall.sh" http://gitea.hapyle.work:33000/taotao/webui/raw/development/simplefirewall/simplefirewall.sh
|
||||
wget --no-check-certificate -O "$SIMPLE_FIREWALL_DIR/ttl-override" http://gitea.hapyle.work:33000/taotao/webui/raw/development/simplefirewall/ttl-override
|
||||
wget --no-check-certificate -O "$SIMPLE_FIREWALL_DIR/ttlvalue" http://gitea.hapyle.work:33000/taotao/webui/raw/development/simplefirewall/ttlvalue
|
||||
chmod 666 $SIMPLE_FIREWALL_DIR/ttlvalue
|
||||
chmod +x "$SIMPLE_FIREWALL_DIR/simplefirewall.sh"
|
||||
chmod +x "$SIMPLE_FIREWALL_DIR/ttl-override"
|
||||
wget --no-check-certificate -O "$SIMPLE_FIREWALL_SYSTEMD_DIR/simplefirewall.service" http://gitea.hapyle.work:33000/taotao/webui/raw/development/simplefirewall/systemd/simplefirewall.service
|
||||
wget --no-check-certificate -O "$SIMPLE_FIREWALL_SYSTEMD_DIR/ttl-override.service" http://gitea.hapyle.work:33000/taotao/webui/raw/development/simplefirewall/systemd/ttl-override.service
|
||||
cp -rf $SIMPLE_FIREWALL_SYSTEMD_DIR/* /lib/systemd/system
|
||||
ln -sf "/lib/systemd/system/simplefirewall.service" "/lib/systemd/system/multi-user.target.wants/"
|
||||
ln -sf "/lib/systemd/system/ttl-override.service" "/lib/systemd/system/multi-user.target.wants/"
|
||||
systemctl daemon-reload
|
||||
systemctl start simplefirewall
|
||||
systemctl start ttl-override
|
||||
echo -e "\033[0;32mSimple Firewall installation/update complete.\033[0m"
|
||||
}
|
||||
uninstall_simple_firewall
|
||||
install_simple_firewall
|
||||
remount_ro
|
||||
exit 0
|
||||
EOF
|
||||
|
||||
# Make the temporary script executable
|
||||
chmod +x "$TMP_SCRIPT"
|
||||
|
||||
# Reload systemd to recognize the new service and start the update
|
||||
systemctl daemon-reload
|
||||
systemctl start $SERVICE_NAME
|
||||
@ -1,46 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
# WORK IN PROGRESS
|
||||
|
||||
# Define constants
|
||||
GITUSER="iamromulan"
|
||||
GITTREE="development"
|
||||
DIR_NAME="simpleupdates"
|
||||
SERVICE_FILE="/lib/systemd/system/install_simpleupdates.service"
|
||||
SERVICE_NAME="install_simpleupdates"
|
||||
TMP_SCRIPT="/tmp/install_simpleupdates.sh"
|
||||
LOG_FILE="/tmp/install_simpleupdates.log"
|
||||
|
||||
# Tmp Script dependent constants
|
||||
|
||||
|
||||
# Create the systemd service file
|
||||
cat <<EOF > "$SERVICE_FILE"
|
||||
[Unit]
|
||||
Description=Update $DIR_NAME temporary service
|
||||
|
||||
[Service]
|
||||
Type=oneshot
|
||||
ExecStart=/bin/bash $TMP_SCRIPT > $LOG_FILE 2>&1
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
EOF
|
||||
|
||||
# Create and populate the temporary shell script for installation
|
||||
cat <<EOF > "$TMP_SCRIPT"
|
||||
#!/bin/bash
|
||||
|
||||
install_simpleupdates() {
|
||||
# CONTENT
|
||||
}
|
||||
install_simpleupdates
|
||||
exit 0
|
||||
EOF
|
||||
|
||||
# Make the temporary script executable
|
||||
chmod +x "$TMP_SCRIPT"
|
||||
|
||||
# Reload systemd to recognize the new service and start the update
|
||||
systemctl daemon-reload
|
||||
systemctl start $SERVICE_NAME
|
||||
@ -1,150 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Define constants
|
||||
GITUSER="iamromulan"
|
||||
GITTREE="development"
|
||||
DIR_NAME="socat-at-bridge"
|
||||
SERVICE_FILE="/lib/systemd/system/install_socat-at-bridge.service"
|
||||
SERVICE_NAME="install_socat-at-bridge"
|
||||
TMP_SCRIPT="/tmp/install_socat-at-bridge.sh"
|
||||
LOG_FILE="/tmp/install_socat-at-bridge.log"
|
||||
|
||||
# Tmp Script dependent constants
|
||||
SOCAT_AT_DIR="/usrdata/socat-at-bridge"
|
||||
SOCAT_AT_SYSD_DIR="/usrdata/socat-at-bridge/systemd_units"
|
||||
# Function to remount file system as read-write
|
||||
remount_rw() {
|
||||
mount -o remount,rw /
|
||||
}
|
||||
|
||||
# Function to remount file system as read-only
|
||||
remount_ro() {
|
||||
mount -o remount,ro /
|
||||
}
|
||||
remount_rw
|
||||
# Create the systemd service file
|
||||
cat <<EOF > "$SERVICE_FILE"
|
||||
[Unit]
|
||||
Description=Update $DIR_NAME temporary service
|
||||
|
||||
[Service]
|
||||
Type=oneshot
|
||||
ExecStart=/bin/bash $TMP_SCRIPT > $LOG_FILE 2>&1
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
EOF
|
||||
|
||||
# Create and populate the temporary shell script for installation
|
||||
cat <<EOF > "$TMP_SCRIPT"
|
||||
#!/bin/bash
|
||||
|
||||
GITUSER="iamromulan"
|
||||
GITTREE="development"
|
||||
SOCAT_AT_DIR="/usrdata/socat-at-bridge"
|
||||
SOCAT_AT_SYSD_DIR="/usrdata/socat-at-bridge/systemd_units"
|
||||
|
||||
# Function to remount file system as read-write
|
||||
remount_rw() {
|
||||
mount -o remount,rw /
|
||||
}
|
||||
|
||||
# Function to remount file system as read-only
|
||||
remount_ro() {
|
||||
mount -o remount,ro /
|
||||
}
|
||||
remount_rw
|
||||
uninstall_at_socat() {
|
||||
echo -e "\033[0;32mRemoving installed AT Socat Bridge services...\033[0m"
|
||||
systemctl stop at-telnet-daemon > /dev/null 2>&1
|
||||
systemctl disable at-telnet-daemon > /dev/null 2>&1
|
||||
systemctl stop socat-smd11 > /dev/null 2>&1
|
||||
systemctl stop socat-smd11-to-ttyIN > /dev/null 2>&1
|
||||
systemctl stop socat-smd11-from-ttyIN > /dev/null 2>&1
|
||||
systemctl stop socat-smd7 > /dev/null 2>&1
|
||||
systemctl stop socat-smd7-to-ttyIN2 > /dev/null 2>&1
|
||||
systemctl stop socat-smd7-to-ttyIN > /dev/null 2>&1
|
||||
systemctl stop socat-smd7-from-ttyIN2 > /dev/null 2>&1
|
||||
systemctl stop socat-smd7-from-ttyIN > /dev/null 2>&1
|
||||
rm /lib/systemd/system/at-telnet-daemon.service > /dev/null 2>&1
|
||||
rm /lib/systemd/system/socat-smd11.service > /dev/null 2>&1
|
||||
rm /lib/systemd/system/socat-smd11-to-ttyIN.service > /dev/null 2>&1
|
||||
rm /lib/systemd/system/socat-smd11-from-ttyIN.service > /dev/null 2>&1
|
||||
rm /lib/systemd/system/socat-smd7.service > /dev/null 2>&1
|
||||
rm /lib/systemd/system/socat-smd7-to-ttyIN2.service > /dev/null 2>&1
|
||||
rm /lib/systemd/system/socat-smd7-to-ttyIN.service > /dev/null 2>&1
|
||||
rm /lib/systemd/system/socat-smd7-from-ttyIN.service > /dev/null 2>&1
|
||||
rm /lib/systemd/system/socat-smd7-from-ttyIN2.service > /dev/null 2>&1
|
||||
systemctl daemon-reload > /dev/null 2>&1
|
||||
rm -rf "$SOCAT_AT_DIR" > /dev/null 2>&1
|
||||
}
|
||||
|
||||
install_at_socat() {
|
||||
# Install service units
|
||||
echo -e "\033[0;32mInstalling AT Socat Bridge services...\033[0m"
|
||||
mkdir $SOCAT_AT_DIR
|
||||
cd $SOCAT_AT_DIR
|
||||
mkdir $SOCAT_AT_SYSD_DIR
|
||||
wget --no-check-certificate http://gitea.hapyle.work:33000/taotao/webui/raw/development/socat-at-bridge/socat-armel-static
|
||||
wget --no-check-certificate http://gitea.hapyle.work:33000/taotao/webui/raw/development/socat-at-bridge/killsmd7bridge
|
||||
wget --no-check-certificate http://gitea.hapyle.work:33000/taotao/webui/raw/development/socat-at-bridge/atcmd
|
||||
wget --no-check-certificate http://gitea.hapyle.work:33000/taotao/webui/raw/development/socat-at-bridge/atcmd11
|
||||
cd $SOCAT_AT_SYSD_DIR
|
||||
wget --no-check-certificate http://gitea.hapyle.work:33000/taotao/webui/raw/development/socat-at-bridge/systemd_units/socat-smd11.service
|
||||
wget --no-check-certificate http://gitea.hapyle.work:33000/taotao/webui/raw/development/socat-at-bridge/systemd_units/socat-smd11-from-ttyIN.service
|
||||
wget --no-check-certificate http://gitea.hapyle.work:33000/taotao/webui/raw/development/socat-at-bridge/systemd_units/socat-smd11-to-ttyIN.service
|
||||
wget --no-check-certificate http://gitea.hapyle.work:33000/taotao/webui/raw/development/socat-at-bridge/systemd_units/socat-killsmd7bridge.service
|
||||
wget --no-check-certificate http://gitea.hapyle.work:33000/taotao/webui/raw/development/socat-at-bridge/systemd_units/socat-smd7-from-ttyIN2.service
|
||||
wget --no-check-certificate http://gitea.hapyle.work:33000/taotao/webui/raw/development/socat-at-bridge/systemd_units/socat-smd7-to-ttyIN2.service
|
||||
wget --no-check-certificate http://gitea.hapyle.work:33000/taotao/webui/raw/development/socat-at-bridge/systemd_units/socat-smd7.service
|
||||
|
||||
# Set execute permissions
|
||||
cd $SOCAT_AT_DIR
|
||||
chmod +x socat-armel-static
|
||||
chmod +x killsmd7bridge
|
||||
chmod +x atcmd
|
||||
chmod +x atcmd11
|
||||
|
||||
# Link new command for AT Commands from the shell
|
||||
ln -sf $SOCAT_AT_DIR/atcmd /bin
|
||||
ln -sf $SOCAT_AT_DIR/atcmd11 /bin
|
||||
|
||||
# Install service units
|
||||
echo -e "\033[0;32mAdding AT Socat Bridge systemd service units...\033[0m"
|
||||
cp -rf $SOCAT_AT_SYSD_DIR/*.service /lib/systemd/system
|
||||
ln -sf /lib/systemd/system/socat-killsmd7bridge.service /lib/systemd/system/multi-user.target.wants/
|
||||
ln -sf /lib/systemd/system/socat-smd11.service /lib/systemd/system/multi-user.target.wants/
|
||||
ln -sf /lib/systemd/system/socat-smd11-to-ttyIN.service /lib/systemd/system/multi-user.target.wants/
|
||||
ln -sf /lib/systemd/system/socat-smd11-from-ttyIN.service /lib/systemd/system/multi-user.target.wants/
|
||||
ln -sf /lib/systemd/system/socat-smd7.service /lib/systemd/system/multi-user.target.wants/
|
||||
ln -sf /lib/systemd/system/socat-smd7-to-ttyIN2.service /lib/systemd/system/multi-user.target.wants/
|
||||
ln -sf /lib/systemd/system/socat-smd7-from-ttyIN2.service /lib/systemd/system/multi-user.target.wants/
|
||||
systemctl daemon-reload
|
||||
systemctl start socat-smd11
|
||||
sleep 2s
|
||||
systemctl start socat-smd11-to-ttyIN
|
||||
systemctl start socat-smd11-from-ttyIN
|
||||
echo -e "\033[0;32mAT Socat Bridge service online: smd11 to ttyOUT\033[0m"
|
||||
systemctl start socat-killsmd7bridge
|
||||
sleep 1s
|
||||
systemctl start socat-smd7
|
||||
sleep 2s
|
||||
systemctl start socat-smd7-to-ttyIN2
|
||||
systemctl start socat-smd7-from-ttyIN2
|
||||
echo -e "\033[0;32mAT Socat Bridge service online: smd7 to ttyOUT2\033[0m"
|
||||
remount_ro
|
||||
cd /
|
||||
echo -e "\033[0;32mAT Socat Bridge services Installed!\033[0m"
|
||||
}
|
||||
uninstall_at_socat
|
||||
install_at_socat
|
||||
remount_ro
|
||||
exit 0
|
||||
EOF
|
||||
|
||||
# Make the temporary script executable
|
||||
chmod +x "$TMP_SCRIPT"
|
||||
|
||||
# Reload systemd to recognize the new service and start the update
|
||||
systemctl daemon-reload
|
||||
systemctl start $SERVICE_NAME
|
||||
@ -1,73 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Define constants
|
||||
GITUSER="iamromulan"
|
||||
GITTREE="development"
|
||||
DIR_NAME="simpleupdates"
|
||||
SERVICE_FILE="/lib/systemd/system/install_sshd.service"
|
||||
SERVICE_NAME="install_sshd"
|
||||
TMP_SCRIPT="/tmp/install_sshd.sh"
|
||||
LOG_FILE="/tmp/install_sshd.log"
|
||||
|
||||
# Tmp Script dependent constants
|
||||
|
||||
|
||||
# Create the systemd service file
|
||||
cat <<EOF > "$SERVICE_FILE"
|
||||
[Unit]
|
||||
Description=Update $DIR_NAME temporary service
|
||||
|
||||
[Service]
|
||||
Type=oneshot
|
||||
ExecStart=/bin/bash $TMP_SCRIPT > $LOG_FILE 2>&1
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
EOF
|
||||
|
||||
# Create and populate the temporary shell script for installation
|
||||
cat <<EOF > "$TMP_SCRIPT"
|
||||
#!/bin/bash
|
||||
|
||||
GITUSER="iamromulan"
|
||||
GITTREE="development"
|
||||
|
||||
install_sshd() {
|
||||
echo -e "\e[1;32mOpenSSH Server\e[0m"
|
||||
remount_rw
|
||||
|
||||
mkdir /usrdata/sshd
|
||||
wget --no-check-certificate -O /lib/systemd/system/sshd.service "http://gitea.hapyle.work:33000/taotao/webui/blob/development/sshd/sshd.service"
|
||||
ln -sf "/lib/systemd/system/sshd.service" "/lib/systemd/system/multi-user.target.wants/"
|
||||
|
||||
opkg install openssh-server-pam
|
||||
for script in /opt/etc/init.d/*sshd*; do
|
||||
if [ -f "$script" ]; then
|
||||
echo "Removing existing sshd init script: $script"
|
||||
rm "$script" # Remove the script if it contains 'sshd' in its name
|
||||
fi
|
||||
done
|
||||
/opt/bin/ssh-keygen -A
|
||||
systemctl daemon-reload
|
||||
systemctl enable sshd
|
||||
|
||||
# Enable PAM and PermitRootLogin
|
||||
sed -i "s/^.*UsePAM .*/UsePAM yes/" "/opt/etc/ssh/sshd_config"
|
||||
sed -i "s/^.*PermitRootLogin .*/PermitRootLogin yes/" "/opt/etc/ssh/sshd_config"
|
||||
|
||||
# Ensure the sshd user exists in the /opt/etc/passwd file
|
||||
grep "sshd:x:106" /opt/etc/passwd || echo "sshd:x:106:65534:Linux User,,,:/opt/run/sshd:/bin/nologin" >> /opt/etc/passwd
|
||||
systemctl start sshd
|
||||
|
||||
echo -e "\e[1;32mOpenSSH installed!!\e[0m"
|
||||
}
|
||||
install_sshd
|
||||
exit 0
|
||||
EOF
|
||||
|
||||
# Make the temporary script executable
|
||||
chmod +x "$TMP_SCRIPT"
|
||||
|
||||
# Reload systemd to recognize the new service and start the update
|
||||
systemctl daemon-reload
|
||||
systemctl start $SERVICE_NAME
|
||||
@ -1,116 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Define constants
|
||||
GITUSER="iamromulan"
|
||||
GITTREE="development"
|
||||
DIR_NAME="tailscale"
|
||||
SERVICE_FILE="/lib/systemd/system/install_tailscale.service"
|
||||
SERVICE_NAME="install_tailscale"
|
||||
TMP_SCRIPT="/tmp/install_tailscale.sh"
|
||||
LOG_FILE="/tmp/install_sshd.log"
|
||||
export PATH=/bin:/sbin:/usr/bin:/usr/sbin:/opt/bin:/opt/sbin:/usrdata/root/bin
|
||||
|
||||
# Tmp Script dependent constants
|
||||
TAILSCALE_DIR="/usrdata/tailscale/"
|
||||
TAILSCALE_SYSD_DIR="/usrdata/tailscale/systemd"
|
||||
# Function to remount file system as read-write
|
||||
remount_rw() {
|
||||
mount -o remount,rw /
|
||||
}
|
||||
|
||||
# Function to remount file system as read-only
|
||||
remount_ro() {
|
||||
mount -o remount,ro /
|
||||
}
|
||||
|
||||
# Installation Prep
|
||||
remount_rw
|
||||
systemctl daemon-reload
|
||||
rm $SERVICE_FILE > /dev/null 2>&1
|
||||
rm $SERVICE_NAME > /dev/null 2>&1
|
||||
|
||||
# Create the systemd service file
|
||||
cat <<EOF > "$SERVICE_FILE"
|
||||
[Unit]
|
||||
Description=Update $DIR_NAME temporary service
|
||||
|
||||
[Service]
|
||||
Type=oneshot
|
||||
ExecStart=/bin/bash $TMP_SCRIPT > $LOG_FILE 2>&1
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
EOF
|
||||
|
||||
# Create and populate the temporary shell script for installation
|
||||
cat <<EOF > "$TMP_SCRIPT"
|
||||
#!/bin/bash
|
||||
|
||||
export HOME=/usrdata/root
|
||||
export PATH=/bin:/sbin:/usr/bin:/usr/sbin:/opt/bin:/opt/sbin:/usrdata/root/bin
|
||||
GITUSER="iamromulan"
|
||||
GITTREE="development"
|
||||
TAILSCALE_DIR="/usrdata/tailscale/"
|
||||
TAILSCALE_SYSD_DIR="/usrdata/tailscale/systemd"
|
||||
|
||||
# Function to remount file system as read-write
|
||||
remount_rw() {
|
||||
mount -o remount,rw /
|
||||
}
|
||||
|
||||
# Function to remount file system as read-only
|
||||
remount_ro() {
|
||||
mount -o remount,ro /
|
||||
}
|
||||
|
||||
install_update_tailscale() {
|
||||
echo "Checking if Tailscale is already installed..."
|
||||
if [ -f "$TAILSCALE_DIR/tailscale" ]; then
|
||||
echo "Tailscale binary found. Updating Tailscale..."
|
||||
ln -sf "$TAILSCALE_DIR/tailscale" "/usrdata/root/bin/tailscale"
|
||||
echo y | $TAILSCALE_DIR/tailscale update
|
||||
echo -e "\e[32mTailscale updated!\e[0m"
|
||||
remount_ro
|
||||
exit 0
|
||||
else
|
||||
echo "Installing Tailscale..."
|
||||
mkdir -p "$TAILSCALE_DIR" "$TAILSCALE_SYSD_DIR"
|
||||
echo "Downloading binary files..."
|
||||
cd /usrdata
|
||||
curl -O https://pkgs.tailscale.com/stable/tailscale_1.70.0_arm.tgz
|
||||
tar -xzf tailscale_1.70.0_arm.tgz
|
||||
rm tailscale_1.70.0_arm.tgz
|
||||
cd /usrdata/tailscale_1.70.0_arm
|
||||
mv tailscale tailscaled "$TAILSCALE_DIR/"
|
||||
rm -rf /usrdata/tailscale_1.70.0_arm
|
||||
echo "Downloading systemd files..."
|
||||
cd "$TAILSCALE_SYSD_DIR"
|
||||
wget --no-check-certificate http://gitea.hapyle.work:33000/taotao/webui/blob/development/tailscale/systemd/tailscaled.service
|
||||
wget --no-check-certificate http://gitea.hapyle.work:33000/taotao/webui/blob/development/tailscale/systemd/tailscaled.defaults
|
||||
sleep 2s
|
||||
echo "Setting Permissions..."
|
||||
chmod +x "$TAILSCALE_DIR/tailscaled" "$TAILSCALE_DIR/tailscale"
|
||||
echo "Copying systemd units..."
|
||||
cp -rf "$TAILSCALE_SYSD_DIR"/* /lib/systemd/system/
|
||||
ln -sf /lib/systemd/system/tailscaled.service /lib/systemd/system/multi-user.target.wants/
|
||||
systemctl daemon-reload
|
||||
echo "Starting Tailscaled..."
|
||||
systemctl start tailscaled
|
||||
cd /
|
||||
remount_ro
|
||||
echo -e "\e[32mTailscale installed successfully.\e[0m"
|
||||
exit 0
|
||||
fi
|
||||
}
|
||||
|
||||
# Execute the function
|
||||
install_update_tailscale
|
||||
exit 0
|
||||
EOF
|
||||
|
||||
# Make the temporary script executable
|
||||
chmod +x "$TMP_SCRIPT"
|
||||
|
||||
# Reload systemd to recognize the new service and start the update
|
||||
systemctl daemon-reload
|
||||
systemctl start $SERVICE_NAME
|
||||
@ -1,12 +0,0 @@
|
||||
# Enable or disable update checks
|
||||
CONF_ENABLED=no
|
||||
# Check for updates at boot
|
||||
CHECK_AT_BOOT=no
|
||||
# Update frequency: daily, weekly, monthly, or none
|
||||
UPDATE_FREQUENCY=none
|
||||
# Scheduled time for updates (24-hour UTC format)
|
||||
SCHEDULED_TIME=00:00
|
||||
# Day for weekly updates (e.g., Mon, Tues, Wed, Thurs, Fri)
|
||||
WEEKLY_DAY=
|
||||
# Date for monthly updates (e.g., 15 for the 15th of the month)
|
||||
MONTHLY_DATE=
|
||||
@ -1,255 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Configuration and directories
|
||||
CONFIG_FILE="/usrdata/simpleupdates/simpleupdate.conf"
|
||||
GITUSER="iamromulan"
|
||||
GITTREE="main"
|
||||
DIRECTORIES=("simpleadmin" "socat-at-bridge" "simplefirewall" "tailscale" "ttyd")
|
||||
BASE_URL="https://raw.githubusercontent.com/$GITUSER/quectel-rgmii-toolkit/$GITTREE"
|
||||
LOG_FILE="/tmp/simpleupdate.log"
|
||||
|
||||
# Load configuration
|
||||
load_config() {
|
||||
if [[ -f "$CONFIG_FILE" ]]; then
|
||||
source "$CONFIG_FILE"
|
||||
else
|
||||
echo "Configuration file ($CONFIG_FILE) not found."
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Function to trim the log file to the last 100 lines
|
||||
trim_log_file() {
|
||||
tail -n 100 "$LOG_FILE" > "$LOG_FILE.tmp" && mv "$LOG_FILE.tmp" "$LOG_FILE"
|
||||
}
|
||||
|
||||
# Function to check for updates
|
||||
check_for_updates() {
|
||||
echo "$(date): Checking for updates..."
|
||||
for dir in "${DIRECTORIES[@]}"; do
|
||||
local remote_rev=$(wget -qO- "$BASE_URL/$dir/.rev")
|
||||
local local_rev_file="/usrdata/$dir/.rev"
|
||||
|
||||
if [[ ! -f "$local_rev_file" ]]; then
|
||||
echo "No local revision file found for $dir, skipping."
|
||||
continue
|
||||
fi
|
||||
|
||||
local local_rev=$(cat "$local_rev_file")
|
||||
|
||||
if [[ "$remote_rev" -gt "$local_rev" ]]; then
|
||||
echo "Update available for $dir, updating..."
|
||||
wget -qO "/tmp/update_${dir}.sh" "$BASE_URL/simpleupdates/scripts/update_${dir}.sh"
|
||||
chmod +x "/tmp/update_${dir}.sh"
|
||||
"/tmp/update_${dir}.sh"
|
||||
else
|
||||
echo "$dir is up to date."
|
||||
fi
|
||||
done
|
||||
trim_log_file
|
||||
wait_to_update
|
||||
}
|
||||
|
||||
# Function to wait and trigger updates based on scheduling
|
||||
wait_to_update() {
|
||||
echo "Waiting for the next update check according to schedule..."
|
||||
while true; do
|
||||
local current_time=$(date "+%H:%M")
|
||||
local current_day=$(date "+%a")
|
||||
local current_date=$(date "+%d")
|
||||
|
||||
case $UPDATE_FREQUENCY in
|
||||
daily)
|
||||
if [[ "$current_time" == "$SCHEDULED_TIME" ]]; then
|
||||
check_for_updates
|
||||
fi
|
||||
;;
|
||||
weekly)
|
||||
if [[ "$current_day" == "$WEEKLY_DAY" && "$current_time" == "$SCHEDULED_TIME" ]]; then
|
||||
check_for_updates
|
||||
fi
|
||||
;;
|
||||
monthly)
|
||||
if [[ "$current_date" == "$MONTHLY_DATE" && "$current_time" == "$SCHEDULED_TIME" ]]; then
|
||||
check_for_updates
|
||||
fi
|
||||
;;
|
||||
none)
|
||||
echo "Update checking is disabled by frequency setting."
|
||||
exit 0
|
||||
;;
|
||||
esac
|
||||
sleep 30 # Sleep for 30 seconds for more granular checks
|
||||
trim_log_file
|
||||
done
|
||||
}
|
||||
|
||||
# Daemon mode to wait and trigger updates based on scheduling
|
||||
daemon_mode() {
|
||||
load_config
|
||||
exec > >(tee -a "$LOG_FILE") 2>&1
|
||||
echo "Daemon mode started."
|
||||
# Validate only one update frequency is defined
|
||||
frequency_count=0
|
||||
[[ "$UPDATE_FREQUENCY" == "daily" ]] && ((frequency_count++))
|
||||
[[ "$UPDATE_FREQUENCY" == "weekly" ]] && ((frequency_count++))
|
||||
[[ "$UPDATE_FREQUENCY" == "monthly" ]] && ((frequency_count++))
|
||||
|
||||
if [[ $frequency_count -gt 1 ]]; then
|
||||
echo "Error: More than one update frequency is defined. Exiting."
|
||||
exit 1
|
||||
elif [[ $frequency_count -eq 0 && "$UPDATE_FREQUENCY" != "none" ]]; then
|
||||
echo "Error: No valid update frequency defined. Exiting."
|
||||
exit 1
|
||||
fi
|
||||
if [[ "$CONF_ENABLED" == "no" ]]; then
|
||||
echo "Updates are disabled in the configuration."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [[ "$CHECK_AT_BOOT" == "yes" ]]; then
|
||||
check_for_updates
|
||||
else
|
||||
wait_to_update
|
||||
fi
|
||||
}
|
||||
|
||||
# Function to check for updates
|
||||
force_check_for_updates() {
|
||||
echo "$(date): Checking for updates..."
|
||||
for dir in "${DIRECTORIES[@]}"; do
|
||||
local remote_rev=$(wget -qO- "$BASE_URL/$dir/.rev")
|
||||
local local_rev_file="/usrdata/$dir/.rev"
|
||||
|
||||
if [[ ! -f "$local_rev_file" ]]; then
|
||||
echo "No local revision file found for $dir, skipping."
|
||||
continue
|
||||
fi
|
||||
|
||||
local local_rev=$(cat "$local_rev_file")
|
||||
|
||||
if [[ "$remote_rev" -gt "$local_rev" ]]; then
|
||||
echo "Update available for $dir, updating..."
|
||||
wget -qO "/tmp/update_${dir}.sh" "$BASE_URL/simpleupdates/scripts/update_${dir}.sh"
|
||||
chmod +x "/tmp/update_${dir}.sh"
|
||||
"/tmp/update_${dir}.sh"
|
||||
else
|
||||
echo "$dir is up to date."
|
||||
fi
|
||||
done
|
||||
exit 0
|
||||
}
|
||||
|
||||
# Helper function to load and update the configuration
|
||||
update_config() {
|
||||
local key="$1"
|
||||
local value="$2"
|
||||
if grep -q "^$key=" "$CONFIG_FILE"; then
|
||||
sed -i "s|^$key=.*|$key=$value|" "$CONFIG_FILE"
|
||||
else
|
||||
echo "$key=$value" >> "$CONFIG_FILE"
|
||||
fi
|
||||
}
|
||||
|
||||
# Display the current configuration status
|
||||
status() {
|
||||
echo "Current Configuration Status:"
|
||||
if [[ -f "$CONFIG_FILE" ]]; then
|
||||
while IFS= read -r line; do
|
||||
echo "$line"
|
||||
done < "$CONFIG_FILE"
|
||||
else
|
||||
echo "Configuration file not found."
|
||||
fi
|
||||
}
|
||||
|
||||
# Enable automatic updates
|
||||
enable_updates() {
|
||||
update_config "CONF_ENABLED" "yes"
|
||||
echo "Automatic updates have been enabled."
|
||||
}
|
||||
|
||||
# Disable automatic updates
|
||||
disable_updates() {
|
||||
update_config "CONF_ENABLED" "no"
|
||||
echo "Automatic updates have been disabled."
|
||||
}
|
||||
|
||||
# Interactive setup for the update configuration
|
||||
setup() {
|
||||
read -p "Enable automatic updates? [yes/no]: " enable_updates
|
||||
if [[ "$enable_updates" == "yes" ]]; then
|
||||
enable_updates
|
||||
else
|
||||
disable_updates
|
||||
fi
|
||||
|
||||
read -p "Check for updates at boot? [yes/no]: " check_boot
|
||||
update_config "CHECK_AT_BOOT" "$check_boot"
|
||||
|
||||
read -p "Update frequency (none, daily, weekly, monthly): " frequency
|
||||
update_config "UPDATE_FREQUENCY" "$frequency"
|
||||
|
||||
case $frequency in
|
||||
daily)
|
||||
read -p "Scheduled time (HH:MM in 24-hour format): " time
|
||||
update_config "SCHEDULED_TIME" "$time"
|
||||
;;
|
||||
weekly)
|
||||
echo "Please enter the day of the week."
|
||||
read -p "Day (full name or abbreviation, e.g., Monday or Mon): " day_input
|
||||
# Normalize input to abbreviated form
|
||||
day_abbr=$(date -d "$day_input" +%a 2>/dev/null)
|
||||
if [[ $? -ne 0 ]]; then
|
||||
echo "Invalid day of the week. Please try again."
|
||||
return 1
|
||||
fi
|
||||
update_config "WEEKLY_DAY" "$day_abbr"
|
||||
read -p "Scheduled time (HH:MM in 24-hour format): " time
|
||||
update_config "SCHEDULED_TIME" "$time"
|
||||
;;
|
||||
monthly)
|
||||
read -p "Date of the month (1-31): " date
|
||||
update_config "MONTHLY_DATE" "$date"
|
||||
read -p "Scheduled time (HH:MM in 24-hour format): " time
|
||||
update_config "SCHEDULED_TIME" "$time"
|
||||
;;
|
||||
*)
|
||||
echo "No scheduling will be set."
|
||||
;;
|
||||
esac
|
||||
|
||||
echo "Update configuration has been set."
|
||||
}
|
||||
|
||||
# Command operations: status, enable, disable, update, setup
|
||||
case "$1" in
|
||||
d)
|
||||
daemon_mode
|
||||
;;
|
||||
update)
|
||||
load_config
|
||||
force_check_for_updates
|
||||
;;
|
||||
status)
|
||||
status
|
||||
;;
|
||||
enable)
|
||||
enable_updates
|
||||
;;
|
||||
disable)
|
||||
disable_updates
|
||||
;;
|
||||
setup)
|
||||
setup
|
||||
;;
|
||||
*)
|
||||
echo "Usage:"
|
||||
echo "d: Run as a background check daemon"
|
||||
echo "update: Force check for and install updates"
|
||||
echo "status: Display current set update schedule"
|
||||
echo "enable: Enable automatic updates"
|
||||
echo "disable: Disable automatic updates"
|
||||
echo "setup: Set up an automatic update schedule"
|
||||
;;
|
||||
esac
|
||||
@ -1,10 +0,0 @@
|
||||
[Unit]
|
||||
Description=Simple Update Daemon
|
||||
After=network.target
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
ExecStart=/usrdata/simpleupdates/simpleupdate d
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
@ -1 +0,0 @@
|
||||
2
|
||||
@ -1,69 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
DEVICE=/dev/ttyOUT2
|
||||
BAUD=115200
|
||||
|
||||
# Function to setup device communication parameters
|
||||
setup_device() {
|
||||
stty -F $DEVICE cs8 $BAUD ignbrk -brkint -icrnl -imaxbel \
|
||||
-opost -onlcr -isig -icanon -iexten -echo -echoe -echok \
|
||||
-echoctl -echoke noflsh -ixon -crtscts
|
||||
}
|
||||
|
||||
# Function to send AT command and capture the output
|
||||
send_at_command() {
|
||||
local command="$1"
|
||||
|
||||
# Clear the device buffer before sending a new command
|
||||
echo -n > $DEVICE
|
||||
|
||||
# Send the AT command, preserving the integrity of the input
|
||||
echo -e "$command\r" > $DEVICE
|
||||
|
||||
# Use a temporary file to capture the command output
|
||||
tmpfile=$(mktemp)
|
||||
|
||||
# Start reading the device output to the temporary file
|
||||
cat $DEVICE > "$tmpfile" &
|
||||
CAT_PID=$!
|
||||
|
||||
# Monitor the output file for "OK" or "ERROR"
|
||||
while ! grep -qe "OK" -e "ERROR" "$tmpfile"; do
|
||||
sleep 1
|
||||
done
|
||||
|
||||
# Kill the `cat` process after capturing the response
|
||||
kill $CAT_PID
|
||||
wait $CAT_PID 2>/dev/null
|
||||
|
||||
# Display the response
|
||||
cat "$tmpfile" | while IFS= read -r line; do
|
||||
echo -e "\033[0;32m$line\033[0m"
|
||||
done
|
||||
|
||||
# Clean up
|
||||
rm "$tmpfile"
|
||||
}
|
||||
|
||||
# Prepare the device for communication
|
||||
setup_device
|
||||
|
||||
# Check if an AT command is provided as an argument
|
||||
if [ $# -gt 0 ]; then
|
||||
# Concatenate all arguments to handle commands with spaces and/or quotes correctly
|
||||
FULL_CMD="$*"
|
||||
send_at_command "$FULL_CMD"
|
||||
else
|
||||
echo -e "\033[0;36mType 'exit' to end the session.\033[0m"
|
||||
while true; do
|
||||
echo -en "\033[0;36mEnter AT Command: \033[0m"
|
||||
read user_input
|
||||
|
||||
if [[ "$user_input" == "exit" ]]; then
|
||||
echo -e "\033[0;32mExiting...\033[0m"
|
||||
break
|
||||
fi
|
||||
|
||||
send_at_command "$user_input"
|
||||
done
|
||||
fi
|
||||
@ -1,69 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
DEVICE=/dev/ttyOUT
|
||||
BAUD=115200
|
||||
|
||||
# Function to setup device communication parameters
|
||||
setup_device() {
|
||||
stty -F $DEVICE cs8 $BAUD ignbrk -brkint -icrnl -imaxbel \
|
||||
-opost -onlcr -isig -icanon -iexten -echo -echoe -echok \
|
||||
-echoctl -echoke noflsh -ixon -crtscts
|
||||
}
|
||||
|
||||
# Function to send AT command and capture the output
|
||||
send_at_command() {
|
||||
local command="$1"
|
||||
|
||||
# Clear the device buffer before sending a new command
|
||||
echo -n > $DEVICE
|
||||
|
||||
# Send the AT command, preserving the integrity of the input
|
||||
echo -e "$command\r" > $DEVICE
|
||||
|
||||
# Use a temporary file to capture the command output
|
||||
tmpfile=$(mktemp)
|
||||
|
||||
# Start reading the device output to the temporary file
|
||||
cat $DEVICE > "$tmpfile" &
|
||||
CAT_PID=$!
|
||||
|
||||
# Monitor the output file for "OK" or "ERROR"
|
||||
while ! grep -qe "OK" -e "ERROR" "$tmpfile"; do
|
||||
sleep 1
|
||||
done
|
||||
|
||||
# Kill the `cat` process after capturing the response
|
||||
kill $CAT_PID
|
||||
wait $CAT_PID 2>/dev/null
|
||||
|
||||
# Display the response
|
||||
cat "$tmpfile" | while IFS= read -r line; do
|
||||
echo -e "\033[0;32m$line\033[0m"
|
||||
done
|
||||
|
||||
# Clean up
|
||||
rm "$tmpfile"
|
||||
}
|
||||
|
||||
# Prepare the device for communication
|
||||
setup_device
|
||||
|
||||
# Check if an AT command is provided as an argument
|
||||
if [ $# -gt 0 ]; then
|
||||
# Concatenate all arguments to handle commands with spaces and/or quotes correctly
|
||||
FULL_CMD="$*"
|
||||
send_at_command "$FULL_CMD"
|
||||
else
|
||||
echo -e "\033[0;36mType 'exit' to end the session.\033[0m"
|
||||
while true; do
|
||||
echo -en "\033[0;36mEnter AT Command: \033[0m"
|
||||
read user_input
|
||||
|
||||
if [[ "$user_input" == "exit" ]]; then
|
||||
echo -e "\033[0;32mExiting...\033[0m"
|
||||
break
|
||||
fi
|
||||
|
||||
send_at_command "$user_input"
|
||||
done
|
||||
fi
|
||||
@ -1,4 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Look for the process by its command and kill it so socat can have smd7 instead
|
||||
pkill -f "/usr/bin/port_bridge smd7 at_usb2 1"
|
||||
Binary file not shown.
@ -1,9 +0,0 @@
|
||||
[Unit]
|
||||
Description=Kill port_bridge process on boot
|
||||
|
||||
[Service]
|
||||
Type=oneshot
|
||||
ExecStart=/usrdata/socat-at-bridge/killsmd7bridge
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
@ -1,14 +0,0 @@
|
||||
[Unit]
|
||||
Description=Read from /dev/ttyIN and write to smd11
|
||||
BindsTo=socat-smd11.service
|
||||
After=socat-smd11.service
|
||||
|
||||
[Service]
|
||||
ExecStart=/bin/bash -c "/bin/cat /dev/ttyIN > /dev/smd11"
|
||||
ExecStartPost=/bin/sleep 2s
|
||||
StandardInput=tty-force
|
||||
Restart=always
|
||||
RestartSec=1s
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
@ -1,14 +0,0 @@
|
||||
[Unit]
|
||||
Description=Read from /dev/smd11 and write to ttyIN
|
||||
BindsTo=socat-smd11.service
|
||||
After=socat-smd11.service
|
||||
|
||||
[Service]
|
||||
ExecStart=/bin/bash -c "/bin/cat /dev/smd11 > /dev/ttyIN"
|
||||
ExecStartPost=/bin/sleep 2s
|
||||
StandardInput=tty-force
|
||||
Restart=always
|
||||
RestartSec=1s
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
@ -1,13 +0,0 @@
|
||||
[Unit]
|
||||
Description=Socat Serial Emulation for smd11
|
||||
After=ql-netd.service
|
||||
|
||||
[Service]
|
||||
ExecStart=/usrdata/socat-at-bridge/socat-armel-static -d -d pty,link=/dev/ttyIN,raw,echo=0,group=20,perm=660 pty,link=/dev/ttyOUT,raw,echo=1,group=20,perm=660
|
||||
# Add a delay to prevent the clients from starting too early
|
||||
ExecStartPost=/bin/sleep 2s
|
||||
Restart=always
|
||||
RestartSec=1s
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
@ -1,14 +0,0 @@
|
||||
[Unit]
|
||||
Description=Read from /dev/ttyIN2 and write to smd7
|
||||
BindsTo=socat-smd7.service
|
||||
After=socat-smd7.service
|
||||
|
||||
[Service]
|
||||
ExecStart=/bin/bash -c "/bin/cat /dev/ttyIN2 > /dev/smd7"
|
||||
ExecStartPost=/bin/sleep 2s
|
||||
StandardInput=tty-force
|
||||
Restart=always
|
||||
RestartSec=1s
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
@ -1,14 +0,0 @@
|
||||
[Unit]
|
||||
Description=Read from /dev/smd7 and write to ttyIN2
|
||||
BindsTo=socat-smd7.service
|
||||
After=socat-smd7.service
|
||||
|
||||
[Service]
|
||||
ExecStart=/bin/bash -c "/bin/cat /dev/smd7 > /dev/ttyIN2"
|
||||
ExecStartPost=/bin/sleep 2s
|
||||
StandardInput=tty-force
|
||||
Restart=always
|
||||
RestartSec=1s
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
@ -1,13 +0,0 @@
|
||||
[Unit]
|
||||
Description=Socat Serial Emulation for smd7
|
||||
After=ql-netd.service
|
||||
|
||||
[Service]
|
||||
ExecStart=/usrdata/socat-at-bridge/socat-armel-static -d -d pty,link=/dev/ttyIN2,raw,echo=0,group=20,perm=660 pty,link=/dev/ttyOUT2,raw,echo=1,group=20,perm=660
|
||||
# Add a delay to prevent the clients from starting too early
|
||||
ExecStartPost=/bin/sleep 2s
|
||||
Restart=always
|
||||
RestartSec=1s
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
@ -1,17 +0,0 @@
|
||||
[Unit]
|
||||
Description=OpenBSD Secure Shell server
|
||||
Documentation=man:sshd(8) man:sshd_config(5)
|
||||
After=network.target
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
PIDFile=/opt/var/run/sshd.pid
|
||||
ExecStartPre=/opt/sbin/sshd -t
|
||||
ExecStart=/opt/sbin/sshd -D
|
||||
ExecReload=/bin/kill -HUP $MAINPID
|
||||
KillMode=process
|
||||
Restart=on-failure
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
Alias=sshd.service
|
||||
@ -1 +0,0 @@
|
||||
2
|
||||
@ -1,8 +0,0 @@
|
||||
[Unit]
|
||||
Description=Trigger the Tailscale Web UI
|
||||
After=tailscaled.service
|
||||
|
||||
[Service]
|
||||
Type=oneshot
|
||||
ExecStart=/bin/systemctl start tailscale-webui
|
||||
RemainAfterExit=yes
|
||||
@ -1,12 +0,0 @@
|
||||
Description=Tailscale Web Interface
|
||||
After=tailscaled.service
|
||||
Requires=tailscaled.service
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
ExecStartPre=/bin/sleep 5
|
||||
ExecStart=/usrdata/tailscale/tailscale web --listen 0.0.0.0:8088
|
||||
RemainAfterExit=yes
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
@ -1,8 +0,0 @@
|
||||
# Set the port to listen on for incoming VPN packets.
|
||||
# Remote nodes will automatically be informed about the new port number,
|
||||
# but you might want to configure this in order to set external firewall
|
||||
# settings.
|
||||
PORT="41641"
|
||||
|
||||
# Extra flags you might want to pass to tailscaled.
|
||||
FLAGS=""
|
||||
@ -1,16 +0,0 @@
|
||||
[Unit]
|
||||
Description=Tailscale node agent
|
||||
Documentation=https://tailscale.com/kb/
|
||||
Wants=network-pre.target
|
||||
After=network-pre.target NetworkManager.service systemd-resolved.service
|
||||
|
||||
[Service]
|
||||
EnvironmentFile=/usrdata/tailscale/systemd/tailscaled.defaults
|
||||
ExecStartPre=/usrdata/tailscale/tailscaled --cleanup
|
||||
ExecStart=/usrdata/tailscale/tailscaled --statedir=/usrdata/tailscale/ --port=${PORT} $FLAGS
|
||||
ExecStopPost=/usrdata/tailscale/tailscaled --cleanup
|
||||
Restart=on-failure
|
||||
Type=notify
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
BIN
ttyd.armhf
BIN
ttyd.armhf
Binary file not shown.
Loading…
Reference in New Issue
Block a user