Merge pull request #1 from iamromulan/development
Merge with Development
This commit is contained in:
@@ -3,6 +3,8 @@
|
||||
# Define toolkit paths
|
||||
GITUSER="iamromulan"
|
||||
GITTREE="development"
|
||||
GITMAINTREE="main"
|
||||
GITDEVTREE="development"
|
||||
TMP_DIR="/tmp"
|
||||
USRDATA_DIR="/usrdata"
|
||||
SOCAT_AT_DIR="/usrdata/socat-at-bridge"
|
||||
@@ -11,12 +13,6 @@ 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"
|
||||
SIMPLE_FIREWALL_SERVICE="/lib/systemd/system/simplefirewall.service"
|
||||
GITHUB_URL="https://github.com/$GITUSER/quectel-rgmii-toolkit/archive/refs/heads/$GITTREE.zip"
|
||||
GITHUB_SIMPADMIN_FULL_URL="https://github.com/$GITUSER/quectel-rgmii-toolkit/archive/refs/heads/simpleadminfull.zip"
|
||||
GITHUB_SIMPADMIN_NOCMD_URL="https://github.com/$GITUSER/quectel-rgmii-toolkit/archive/refs/heads/simpleadminnoatcmds.zip"
|
||||
GITHUB_SIMPADMIN_TTL_URL="https://github.com/$GITUSER/quectel-rgmii-toolkit/archive/refs/heads/simpleadminttlonly.zip"
|
||||
GITHUB_SIMPADMIN_TEST_URL="https://github.com/$GITUSER/quectel-rgmii-toolkit/archive/refs/heads/simpleadmintest.zip"
|
||||
TAILSCALE_DIR="/usrdata/tailscale/"
|
||||
TAILSCALE_SYSD_DIR="/usrdata/tailscale/systemd"
|
||||
# AT Command Script Variables and Functions
|
||||
@@ -103,118 +99,105 @@ send_at_commands() {
|
||||
fi
|
||||
}
|
||||
|
||||
# Check if Simple Admin is installed
|
||||
is_simple_admin_installed() {
|
||||
[ -d "$SIMPLE_ADMIN_DIR" ] && return 0 || return 1
|
||||
# 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 -O installentware.sh "https://raw.githubusercontent.com/$GITUSER/quectel-rgmii-toolkit/$GITTREE/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
|
||||
|
||||
}
|
||||
|
||||
# Function to install/update AT Socat Bridge
|
||||
install_update_at_socat() {
|
||||
remount_rw
|
||||
#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
|
||||
|
||||
# Stop and disable existing services/files before installing new ones
|
||||
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 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 https://raw.githubusercontent.com/$GITUSER/quectel-rgmii-toolkit/$GITTREE/socat-at-bridge/socat-armel-static
|
||||
wget https://raw.githubusercontent.com/$GITUSER/quectel-rgmii-toolkit/$GITTREE/socat-at-bridge/killsmd7bridge
|
||||
wget https://raw.githubusercontent.com/$GITUSER/quectel-rgmii-toolkit/$GITTREE/socat-at-bridge/atcmd
|
||||
cd $SOCAT_AT_SYSD_DIR
|
||||
wget https://raw.githubusercontent.com/$GITUSER/quectel-rgmii-toolkit/$GITTREE/socat-at-bridge/systemd_units/socat-smd11.service
|
||||
wget https://raw.githubusercontent.com/$GITUSER/quectel-rgmii-toolkit/$GITTREE/socat-at-bridge/systemd_units/socat-smd11-from-ttyIN.service
|
||||
wget https://raw.githubusercontent.com/$GITUSER/quectel-rgmii-toolkit/$GITTREE/socat-at-bridge/systemd_units/socat-smd11-to-ttyIN.service
|
||||
wget https://raw.githubusercontent.com/$GITUSER/quectel-rgmii-toolkit/$GITTREE/socat-at-bridge/systemd_units/socat-killsmd7bridge.service
|
||||
wget https://raw.githubusercontent.com/$GITUSER/quectel-rgmii-toolkit/$GITTREE/socat-at-bridge/systemd_units/socat-smd7-from-ttyIN2.service
|
||||
wget https://raw.githubusercontent.com/$GITUSER/quectel-rgmii-toolkit/$GITTREE/socat-at-bridge/systemd_units/socat-smd7-to-ttyIN2.service
|
||||
wget https://raw.githubusercontent.com/$GITUSER/quectel-rgmii-toolkit/$GITTREE/socat-at-bridge/systemd_units/socat-smd7.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
|
||||
|
||||
# Set execute permissions
|
||||
cd $SOCAT_AT_DIR
|
||||
chmod +x socat-armel-static
|
||||
chmod +x killsmd7bridge
|
||||
chmod +x atcmd
|
||||
|
||||
# Link new command for AT Commands from the shell
|
||||
ln -sf $SOCAT_AT_DIR/atcmd /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/
|
||||
# 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
|
||||
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"
|
||||
}
|
||||
|
||||
# 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 -O "$SIMPLE_FIREWALL_DIR/simplefirewall.sh" https://raw.githubusercontent.com/$GITUSER/quectel-rgmii-toolkit/$GITTREE/simplefirewall/simplefirewall.sh
|
||||
wget -O "$SIMPLE_FIREWALL_DIR/ttl-override" https://raw.githubusercontent.com/$GITUSER/quectel-rgmii-toolkit/$GITTREE/simplefirewall/ttl-override
|
||||
wget -O "$SIMPLE_FIREWALL_DIR/ttlvalue" https://raw.githubusercontent.com/$GITUSER/quectel-rgmii-toolkit/$GITTREE/simplefirewall/ttlvalue
|
||||
chmod +x "$SIMPLE_FIREWALL_DIR/simplefirewall.sh"
|
||||
chmod +x "$SIMPLE_FIREWALL_DIR/ttl-override"
|
||||
wget -O "$SIMPLE_FIREWALL_SYSTEMD_DIR/simplefirewall.service" https://raw.githubusercontent.com/$GITUSER/quectel-rgmii-toolkit/$GITTREE/simplefirewall/systemd/simplefirewall.service
|
||||
wget -O "$SIMPLE_FIREWALL_SYSTEMD_DIR/ttl-override.service" https://raw.githubusercontent.com/$GITUSER/quectel-rgmii-toolkit/$GITTREE/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
|
||||
remount_ro
|
||||
echo -e "\033[0;32mSimple Firewall installation/update complete.\033[0m"
|
||||
|
||||
# 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"
|
||||
@@ -306,101 +289,65 @@ configure_simple_firewall() {
|
||||
echo -e "\e[1;32mFirewall configuration updated.\e[0m"
|
||||
}
|
||||
|
||||
set_simpleadmin_passwd(){
|
||||
ensure_entware_installed
|
||||
opkg update
|
||||
opkg install libaprutil
|
||||
wget -O /usrdata/root/bin/htpasswd https://raw.githubusercontent.com/$GITUSER/quectel-rgmii-toolkit/$GITTREE/simpleadmin/htpasswd && chmod +x /usrdata/root/bin/htpasswd
|
||||
wget -O /usrdata/root/bin/simplepasswd https://raw.githubusercontent.com/$GITUSER/quectel-rgmii-toolkit/$GITTREE/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 8080\e[0m"
|
||||
echo -e "\e[1;32m1) Full Install\e[0m"
|
||||
echo -e "\e[1;34m2) No AT Commands, List only\e[0m"
|
||||
echo -e "\e[1;33m3) TTL Only\e[0m"
|
||||
echo -e "\e[1;31m4) Install Test Build (work in progress/not ready yet)\e[0m"
|
||||
echo -e "\e[0;33m5) Return to Main Menu\e[0m"
|
||||
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)
|
||||
install_update_at_socat
|
||||
install_simple_firewall
|
||||
remount_rw
|
||||
cd $TMP_DIR
|
||||
wget $GITHUB_SIMPADMIN_FULL_URL -O simpleadminfull.zip
|
||||
unzip -o simpleadminfull.zip
|
||||
cp -Rf quectel-rgmii-toolkit-simpleadminfull/simpleadmin/ $USRDATA_DIR
|
||||
chmod +x $SIMPLE_ADMIN_DIR/scripts/*
|
||||
chmod +x $SIMPLE_ADMIN_DIR/www/cgi-bin/*
|
||||
cp -rf $SIMPLE_ADMIN_DIR/systemd/* /lib/systemd/system
|
||||
systemctl daemon-reload
|
||||
ln -sf /lib/systemd/system/simpleadmin_httpd.service /lib/systemd/system/multi-user.target.wants/
|
||||
ln -sf /lib/systemd/system/simpleadmin_generate_status.service /lib/systemd/system/multi-user.target.wants/
|
||||
systemctl start simpleadmin_generate_status
|
||||
systemctl start simpleadmin_httpd
|
||||
remount_ro
|
||||
echo "Cleaning up..."
|
||||
rm /tmp/simpleadminfull.zip
|
||||
rm -rf /tmp/quectel-rgmii-toolkit-simpleadminfull/
|
||||
break
|
||||
;;
|
||||
2)
|
||||
install_update_at_socat
|
||||
install_simple_firewall
|
||||
remount_rw
|
||||
cd $TMP_DIR
|
||||
wget $GITHUB_SIMPADMIN_NOCMD_URL -O simpleadminnoatcmds.zip
|
||||
unzip -o simpleadminnoatcmds.zip
|
||||
cp -Rf quectel-rgmii-toolkit-simpleadminnoatcmds/simpleadmin/ $USRDATA_DIR
|
||||
chmod +x $SIMPLE_ADMIN_DIR/scripts/*
|
||||
chmod +x $SIMPLE_ADMIN_DIR/www/cgi-bin/*
|
||||
cp -rf $SIMPLE_ADMIN_DIR/systemd/* /lib/systemd/system
|
||||
systemctl daemon-reload
|
||||
ln -sf /lib/systemd/system/simpleadmin_httpd.service /lib/systemd/system/multi-user.target.wants/
|
||||
ln -sf /lib/systemd/system/simpleadmin_generate_status.service /lib/systemd/system/multi-user.target.wants/
|
||||
systemctl start simpleadmin_generate_status
|
||||
systemctl start simpleadmin_httpd
|
||||
remount_ro
|
||||
echo "Cleaning up..."
|
||||
rm /tmp/simpleadminnoatcmds.zip
|
||||
rm -rf /tmp/quectel-rgmii-toolkit-simpleadminnoatcmds/
|
||||
break
|
||||
;;
|
||||
3)
|
||||
install_simple_firewall
|
||||
remount_rw
|
||||
cd $TMP_DIR
|
||||
wget $GITHUB_SIMPADMIN_TTL_URL -O simpleadminttlonly.zip
|
||||
unzip -o simpleadminttlonly.zip
|
||||
cp -Rf quectel-rgmii-toolkit-simpleadminttlonly/simpleadmin/ $USRDATA_DIR
|
||||
chmod +x $SIMPLE_ADMIN_DIR/www/cgi-bin/*
|
||||
cp -rf $SIMPLE_ADMIN_DIR/systemd/* /lib/systemd/system
|
||||
systemctl daemon-reload
|
||||
ln -sf /lib/systemd/system/simpleadmin_httpd.service /lib/systemd/system/multi-user.target.wants/
|
||||
systemctl start simpleadmin_httpd
|
||||
remount_ro
|
||||
echo "Cleaning up..."
|
||||
rm /tmp/simpleadminttlonly.zip
|
||||
rm -rf /tmp/quectel-rgmii-toolkit-simpleadminttlonly/
|
||||
break
|
||||
;;
|
||||
4)
|
||||
install_update_at_socat
|
||||
install_simple_firewall
|
||||
remount_rw
|
||||
cd $TMP_DIR
|
||||
wget $GITHUB_SIMPADMIN_TEST_URL -O simpleadmintest.zip
|
||||
unzip -o simpleadmintest.zip
|
||||
cp -Rf quectel-rgmii-toolkit-simpleadmintest/simpleadmin/ $USRDATA_DIR
|
||||
chmod +x $SIMPLE_ADMIN_DIR/scripts/*
|
||||
chmod +x $SIMPLE_ADMIN_DIR/www/cgi-bin/*
|
||||
cp -rf $SIMPLE_ADMIN_DIR/systemd/* /lib/systemd/system
|
||||
systemctl daemon-reload
|
||||
ln -sf /lib/systemd/system/simpleadmin_httpd.service /lib/systemd/system/multi-user.target.wants/
|
||||
ln -sf /lib/systemd/system/simpleadmin_generate_status.service /lib/systemd/system/multi-user.target.wants/
|
||||
systemctl start simpleadmin_generate_status
|
||||
systemctl start simpleadmin_httpd
|
||||
remount_ro
|
||||
break
|
||||
;;
|
||||
5)
|
||||
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 -O /usrdata/simpleupdates/scripts/update_socat-at-bridge.sh https://raw.githubusercontent.com/$GITUSER/quectel-rgmii-toolkit/$GITTREE/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 -O /usrdata/simpleupdates/scripts/update_simplefirewall.sh https://raw.githubusercontent.com/$GITUSER/quectel-rgmii-toolkit/$GITTREE/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 -O /usrdata/simpleupdates/scripts/update_simpleadmin.sh https://raw.githubusercontent.com/$GITUSER/quectel-rgmii-toolkit/$GITTREE/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
|
||||
;;
|
||||
@@ -415,7 +362,6 @@ install_simple_admin() {
|
||||
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"
|
||||
echo -e "\e[1;36mIf you are upgrading from an older version of the toolkit uninstall/say yes to all everything.\e[0m"
|
||||
remount_rw
|
||||
|
||||
# Uninstall Simple Firewall
|
||||
@@ -443,49 +389,67 @@ uninstall_simpleadmin_components() {
|
||||
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"
|
||||
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 the rest of Simpleadmin
|
||||
echo -e "\e[1;32mDo you want to uninstall the rest of Simpleadmin?\e[0m"
|
||||
# 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 "Uninstalling the rest of Simpleadmin..."
|
||||
systemctl stop simpleadmin_httpd
|
||||
systemctl stop simpleadmin_generate_status
|
||||
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 uninstalled."
|
||||
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
|
||||
fi
|
||||
|
||||
echo "Uninstallation process completed."
|
||||
}
|
||||
@@ -494,13 +458,13 @@ uninstall_simpleadmin_components() {
|
||||
tailscale_menu() {
|
||||
while true; do
|
||||
echo -e "\e[1;32mTailscale Menu\e[0m"
|
||||
echo -e "\e[1;32m1) Install/Update/Remove Tailscale\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_remove_tailscale;;
|
||||
1) install_update_tailscale;;
|
||||
2) configure_tailscale;;
|
||||
3) break;;
|
||||
*) echo "Invalid option";;
|
||||
@@ -509,62 +473,16 @@ tailscale_menu() {
|
||||
}
|
||||
|
||||
# Function to install, update, or remove Tailscale
|
||||
install_update_remove_tailscale() {
|
||||
if [ -d "$TAILSCALE_DIR" ]; then
|
||||
echo "Tailscale is already installed."
|
||||
echo "1) Update Tailscale"
|
||||
echo "2) Remove Tailscale"
|
||||
read -p "Enter your choice: " tailscale_update_remove_choice
|
||||
|
||||
case $tailscale_update_remove_choice in
|
||||
1)
|
||||
echo "Updating Tailscale..."
|
||||
/usrdata/tailscale/tailscale update
|
||||
;;
|
||||
2)
|
||||
echo "Removing Tailscale..."
|
||||
remount_rw
|
||||
$TAILSCALE_DIR/tailscale down
|
||||
$TAILSCALE_DIR/tailscale logout
|
||||
systemctl stop tailscaled
|
||||
rm -f /lib/systemd/system/tailscaled.service
|
||||
systemctl daemon-reload
|
||||
rm -rf $TAILSCALE_DIR
|
||||
remount_ro
|
||||
echo "Tailscale removed successfully."
|
||||
;;
|
||||
*)
|
||||
echo "Invalid option";;
|
||||
esac
|
||||
else
|
||||
echo "Installing Tailscale..."
|
||||
remount_rw
|
||||
echo "Creating /usrdata/tailscale/"
|
||||
mkdir $TAILSCALE_DIR
|
||||
mkdir $TAILSCALE_SYSD_DIR
|
||||
cd $TAILSCALE_DIR
|
||||
echo "Downloading binary: /usrdata/tailscale/tailscaled"
|
||||
wget https://raw.githubusercontent.com/$GITUSER/quectel-rgmii-toolkit/main/tailscale/tailscaled
|
||||
echo "Downloading binary: /usrdata/tailscale/tailscale"
|
||||
wget https://raw.githubusercontent.com/$GITUSER/quectel-rgmii-toolkit/main/tailscale/tailscale
|
||||
echo "Downloading systemd files..."
|
||||
cd $TAILSCALE_SYSD_DIR
|
||||
wget https://raw.githubusercontent.com/$GITUSER/quectel-rgmii-toolkit/main/tailscale/systemd/tailscaled.service
|
||||
wget https://raw.githubusercontent.com/$GITUSER/quectel-rgmii-toolkit/main/tailscale/systemd/tailscaled.defaults
|
||||
sleep 2s
|
||||
echo "Setting Permissions..."
|
||||
chmod +x /usrdata/tailscale/tailscaled
|
||||
chmod +x /usrdata/tailscale/tailscale
|
||||
echo "Copy systemd units..."
|
||||
cp -rf /usrdata/tailscale/systemd/* /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 "Tailscale installed successfully."
|
||||
fi
|
||||
install_update_tailscale() {
|
||||
echo -e "\e[1;31m2) Installing tailscale from the $GITTREE branch\e[0m"
|
||||
mkdir /usrdata/simpleupdates > /dev/null 2>&1
|
||||
mkdir /usrdata/simpleupdates/scripts > /dev/null 2>&1
|
||||
wget -O /usrdata/simpleupdates/scripts/update_tailscale.sh https://raw.githubusercontent.com/$GITUSER/quectel-rgmii-toolkit/$GITTREE/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
|
||||
@@ -795,57 +713,43 @@ WantedBy=multi-user.target" > "$cfun_service_path"
|
||||
fi
|
||||
}
|
||||
|
||||
# Function for TTYd install
|
||||
install_ttyd() {
|
||||
echo -e "\e[1;34mStarting ttyd installation process...\e[0m"
|
||||
|
||||
if [ ! -f "/opt/bin/opkg" ]; then
|
||||
echo -e "\e[1;32mInstalling Entware/OPKG\e[0m"
|
||||
cd /tmp && wget -O installentware.sh "https://raw.githubusercontent.com/$GITUSER/quectel-rgmii-toolkit/$GITTREE/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"
|
||||
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
|
||||
|
||||
mount -o remount,rw /
|
||||
opkg update && opkg install shadow-login shadow-passwd
|
||||
if [ "$?" -ne 0 ]; then
|
||||
echo -e "\e[1;31mPackage installation failed. Please check your internet connection and try again.\e[0m"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Replacing the login and passwd binaries
|
||||
rm /opt/etc/shadow
|
||||
cp /etc/shadow /opt/etc/
|
||||
rm /bin/login /usr/bin/passwd
|
||||
ln -sf /opt/bin/login /bin
|
||||
ln -sf /opt/bin/passwd /usr/bin/
|
||||
echo -e "\e[1;31mPlease set your system login password.\e[0m"
|
||||
/usr/bin/passwd
|
||||
|
||||
# Setting up ttyd
|
||||
mkdir -p /usrdata/ttyd/scripts /usrdata/ttyd/systemd
|
||||
cd /usrdata/ttyd/
|
||||
wget -O ttyd "https://raw.githubusercontent.com/$GITUSER/quectel-rgmii-toolkit/$GITTREE/ttyd/ttyd" && chmod +x ttyd
|
||||
wget -O scripts/ttyd.bash "https://raw.githubusercontent.com/$GITUSER/quectel-rgmii-toolkit/$GITTREE/ttyd/scripts/ttyd.bash" && chmod +x scripts/ttyd.bash
|
||||
wget -O systemd/ttyd.service "https://raw.githubusercontent.com/$GITUSER/quectel-rgmii-toolkit/$GITTREE/ttyd/systemd/ttyd.service"
|
||||
cp systemd/ttyd.service /lib/systemd/system/
|
||||
ln -sf /lib/systemd/system/ttyd.service /etc/systemd/system/multi-user.target.wants/
|
||||
|
||||
# Enabling and starting ttyd service
|
||||
systemctl daemon-reload
|
||||
systemctl enable ttyd
|
||||
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;32mInstall Complete! ttyd server is up on port 443. Note: No TLS/SSL enabled yet.\e[0m"
|
||||
# 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 -O /usrdata/simpleupdates/scripts/update_sshd.sh https://raw.githubusercontent.com/$GITUSER/quectel-rgmii-toolkit/$GITTREE/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"
|
||||
}
|
||||
|
||||
|
||||
@@ -918,14 +822,19 @@ echo " :+##+. "
|
||||
echo "Select an option:"
|
||||
echo -e "\e[0m"
|
||||
echo -e "\e[96m1) Send AT Commands\e[0m" # Cyan
|
||||
echo -e "\e[93m2) Install/Update/Uninstall Simple Admin\e[0m" # Yellow
|
||||
echo -e "\e[95m3) Simple Firewall Management\e[0m" # Light Purple
|
||||
echo -e "\e[94m4) Tailscale Management\e[0m" # Light Blue
|
||||
echo -e "\e[92m5) Install/Change or remove Daily Reboot Timer\e[0m" # Light Green
|
||||
echo -e "\e[91m6) Install/Uninstall CFUN 0 Fix\e[0m" # Light Red
|
||||
echo -e "\e[96m7) Install Entware/OPKG (BETA/Advanced)\e[0m" # Cyan (repeated color for additional options)
|
||||
echo -e "\e[96m8) Install TTYd (BETA,443,No TLS/SSL)\e[0m" # Cyan
|
||||
echo -e "\e[93m9) Exit\e[0m" # Yellow (repeated color for exit option)
|
||||
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
|
||||
@@ -933,48 +842,97 @@ echo " :+##+. "
|
||||
send_at_commands
|
||||
;;
|
||||
2)
|
||||
if is_simple_admin_installed; then
|
||||
echo -e "\e[1;31mSimple Admin is already installed. It must be removed first\e[0m"
|
||||
echo -e "\e[1;32m1) Remove\e[0m" # Green
|
||||
echo -e "\e[0;33m2) Return to main menu\e[0m"
|
||||
read -p "Enter your choice: " simple_admin_choice
|
||||
case $simple_admin_choice in
|
||||
1) uninstall_simpleadmin_components;;
|
||||
2) break;;
|
||||
*) echo -e "\e[1;31mInvalid option\e[0m";;
|
||||
esac
|
||||
else
|
||||
echo -e "\e[1;32mInstalling Simple Admin...\e[0m"
|
||||
install_simple_admin
|
||||
fi
|
||||
install_simple_admin
|
||||
;;
|
||||
3)
|
||||
configure_simple_firewall
|
||||
3) set_simpleadmin_passwd
|
||||
;;
|
||||
4)
|
||||
set_root_passwd
|
||||
;;
|
||||
5)
|
||||
uninstall_simpleadmin_components
|
||||
;;
|
||||
6)
|
||||
configure_simple_firewall
|
||||
;;
|
||||
|
||||
4)
|
||||
tailscale_menu
|
||||
;;
|
||||
5)
|
||||
manage_reboot_timer
|
||||
7)
|
||||
tailscale_menu
|
||||
;;
|
||||
8)
|
||||
manage_reboot_timer
|
||||
;;
|
||||
6)
|
||||
manage_cfun_fix
|
||||
9)
|
||||
manage_cfun_fix
|
||||
;;
|
||||
7)
|
||||
echo -e "\e[1;32mInstalling Entware/OPKG\e[0m"
|
||||
cd /tmp && wget -O installentware.sh https://raw.githubusercontent.com/$GITUSER/quectel-rgmii-toolkit/$GITTREE/installentware.sh && chmod +x installentware.sh && ./installentware.sh
|
||||
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 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"
|
||||
;;
|
||||
8)
|
||||
install_ttyd
|
||||
;;
|
||||
9)
|
||||
echo -e "\e[1;32mGoodbye!\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 -O fast https://github.com/ddo/fast/releases/download/v0.0.4/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"
|
||||
*)
|
||||
echo -e "\e[1;31mInvalid option\e[0m"
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
#!/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 |
|
||||
@@ -16,64 +17,6 @@ PRE_OPKG_PATH=$(which opkg)
|
||||
# Remount filesystem as read-write
|
||||
mount -o remount,rw /
|
||||
|
||||
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
|
||||
# This step depends on the specific changes made by the user or the installation script
|
||||
|
||||
echo -e '\033[32mInfo: Entware/OPKG has been uninstalled successfully.\033[0m'
|
||||
}
|
||||
|
||||
# Check if /opt exists
|
||||
if [ -d /opt ]; then
|
||||
echo -e "\033[32mDo you want to uninstall Entware/OPKG first? It is already installed.\033[0m"
|
||||
echo -e "\033[32m1) Yes\033[0m"
|
||||
echo -e "\033[32m2) No\033[0m"
|
||||
echo -e "\033[32m3) Cancel\033[0m"
|
||||
read -p "Select an option: " choice
|
||||
|
||||
case $choice in
|
||||
1)
|
||||
# Call the uninstall function
|
||||
uninstall_entware
|
||||
exit 0
|
||||
;;
|
||||
2)
|
||||
# Continue with the script
|
||||
echo "Continuing with the script..."
|
||||
;;
|
||||
3)
|
||||
echo "Canceling. Exiting script."
|
||||
exit 0
|
||||
;;
|
||||
*)
|
||||
echo "Invalid option. Please select 1, 2, or 3."
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
|
||||
create_opt_mount() {
|
||||
# Bind /usrdata/opt to /opt
|
||||
echo -e '\033[32mInfo: Setting up /opt mount to /usrdata/opt...\033[0m'
|
||||
@@ -114,32 +57,13 @@ EOF
|
||||
}
|
||||
|
||||
if [ -n "$PRE_OPKG_PATH" ]; then
|
||||
while true; do
|
||||
echo -e "\033[32mopkg already exists at: $PRE_OPKG_PATH\033[0m"
|
||||
echo -e "\033[32mDo you want to rename it to opkg_old?\033[0m"
|
||||
echo -e "\033[32m1) Yes (Highly Recommended)\033[0m"
|
||||
echo -e "\033[32m2) No (The opkg command may not work)\033[0m"
|
||||
read -p "Select an option (1 or 2): " user_choice
|
||||
|
||||
|
||||
case $user_choice in
|
||||
1)
|
||||
mv "$PRE_OPKG_PATH" "${PRE_OPKG_PATH}_old"
|
||||
echo "Factory/Already existing opkg has been renamed to opkg_old."
|
||||
break
|
||||
;;
|
||||
2)
|
||||
echo "Proceeding without renaming opkg."
|
||||
break
|
||||
;;
|
||||
*)
|
||||
echo "Invalid option. Please select 1 or 2."
|
||||
;;
|
||||
esac
|
||||
done
|
||||
# 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'
|
||||
@@ -206,9 +130,38 @@ 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'
|
||||
echo -e '\033[32mInfo: Run export PATH=/opt/bin:/opt/sbin:$PATH to do it for this session only\033[0m'
|
||||
echo -e '\033[32mInfo: opkg at /opt/bin will be linked to /bin but any package you install with opkg will not be automatically.\033[0m'
|
||||
ln -sf /opt/bin/opkg /bin
|
||||
opkg update
|
||||
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
simpleadmin/.rev
Normal file
1
simpleadmin/.rev
Normal file
@@ -0,0 +1 @@
|
||||
2
|
||||
7
simpleadmin/console/.profile
Normal file
7
simpleadmin/console/.profile
Normal file
@@ -0,0 +1,7 @@
|
||||
#!/bin/bash
|
||||
|
||||
#Path
|
||||
export PATH=/bin:/sbin:/usr/bin:/usr/sbin:opt/bin:/opt/sbin:/usrdata/root/bin
|
||||
|
||||
#Post-login execution
|
||||
start_menu.sh
|
||||
150
simpleadmin/console/menu/LAN_settings.sh
Normal file
150
simpleadmin/console/menu/LAN_settings.sh
Normal file
@@ -0,0 +1,150 @@
|
||||
#!/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
|
||||
125
simpleadmin/console/menu/sfirewall_settings.sh
Normal file
125
simpleadmin/console/menu/sfirewall_settings.sh
Normal file
@@ -0,0 +1,125 @@
|
||||
#!/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
|
||||
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)
|
||||
set_portblocks
|
||||
;;
|
||||
2)
|
||||
set_ttl
|
||||
;;
|
||||
*)
|
||||
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"
|
||||
}
|
||||
|
||||
# Start by checking and installing xml if necessary, then mount filesystem as rw and run the menu
|
||||
mount -o remount,rw /
|
||||
simple_firewall_menu
|
||||
143
simpleadmin/console/menu/start_menu.sh
Normal file
143
simpleadmin/console/menu/start_menu.sh
Normal file
@@ -0,0 +1,143 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Define executable files path
|
||||
EXE=/usrdata/root/bin
|
||||
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() {
|
||||
while true; do
|
||||
display_green "Welcome to iamromulan's Simple Console Menu"
|
||||
display_green "Select an option:"
|
||||
echo "------------------"
|
||||
display_green "1. LAN Settings"
|
||||
display_green "2. Change simpleadmin (admin) password"
|
||||
display_green "3. Change root password (shell/ssh/console)"
|
||||
display_green "4. Open File Browser/Editor (mc)"
|
||||
display_green "5. View Used/Available space"
|
||||
display_green "6. Open Task Manager/View CPU Load"
|
||||
display_green "7. Run speedtest.net test"
|
||||
display_green "8. Run fast.com test (30Mbps max)"
|
||||
display_green "9. Get and run the Toolkit"
|
||||
display_green "10. Get and run the Development/unstable Toolkit"
|
||||
display_green "11. Exit (Enter Root Shell)"
|
||||
echo
|
||||
read -p "Select an option (1-11): " option
|
||||
|
||||
case "$option" in
|
||||
1) $MEU/LAN_settings ;;
|
||||
2) $EXE/simplepasswd ;;
|
||||
3) passwd ;;
|
||||
4) mc ;;
|
||||
5) dfc ;;
|
||||
6) htop ;;
|
||||
7) $EXE/speedtest ;;
|
||||
8) $EXE/fast ;;
|
||||
9) cd /tmp && wget -O RMxxx_rgmii_toolkit.sh https://raw.githubusercontent.com/iamromulan/quectel-rgmii-toolkit/main/RMxxx_rgmii_toolkit.sh && chmod +x RMxxx_rgmii_toolkit.sh && ./RMxxx_rgmii_toolkit.sh && cd / ;;
|
||||
10) cd /tmp && wget -O RMxxx_rgmii_toolkit.sh https://raw.githubusercontent.com/iamromulan/quectel-rgmii-toolkit/development/RMxxx_rgmii_toolkit.sh && chmod +x RMxxx_rgmii_toolkit.sh && ./RMxxx_rgmii_toolkit.sh && cd / ;;
|
||||
11) break ;;
|
||||
*) echo "Invalid option. Please try again." ;;
|
||||
esac
|
||||
done
|
||||
}
|
||||
|
||||
apps() {
|
||||
while true; do
|
||||
display_green "Welcome to iamromulan's Simple Console Menu"
|
||||
display_green "Select an option:"
|
||||
echo "------------------"
|
||||
display_green "1. LAN Settings"
|
||||
display_green "2. Change simpleadmin (admin) password"
|
||||
display_green "3. Change root password (shell/ssh/console)"
|
||||
display_green "4. Open File Browser/Editor (mc)"
|
||||
display_green "5. View Used/Available space"
|
||||
display_green "6. Open Task Manager/View CPU Load"
|
||||
display_green "7. Run speedtest.net test"
|
||||
display_green "8. Run fast.com test (30Mbps max)"
|
||||
display_green "9. Get and run the Toolkit"
|
||||
display_green "10. Get and run the Development/unstable Toolkit"
|
||||
display_green "11. Exit (Enter Root Shell)"
|
||||
echo
|
||||
read -p "Select an option (1-11): " option
|
||||
|
||||
case "$option" in
|
||||
1) $menu_sh/LAN_settings ;;
|
||||
2) $EXE/simplepasswd ;;
|
||||
3) passwd ;;
|
||||
4) mc ;;
|
||||
5) dfc ;;
|
||||
6) htop ;;
|
||||
7) $EXE/speedtest ;;
|
||||
8) $EXE/fast ;;
|
||||
9) cd /tmp && wget -O RMxxx_rgmii_toolkit.sh https://raw.githubusercontent.com/iamromulan/quectel-rgmii-toolkit/main/RMxxx_rgmii_toolkit.sh && chmod +x RMxxx_rgmii_toolkit.sh && ./RMxxx_rgmii_toolkit.sh && cd / ;;
|
||||
10) cd /tmp && wget -O RMxxx_rgmii_toolkit.sh https://raw.githubusercontent.com/iamromulan/quectel-rgmii-toolkit/development/RMxxx_rgmii_toolkit.sh && chmod +x RMxxx_rgmii_toolkit.sh && ./RMxxx_rgmii_toolkit.sh && cd / ;;
|
||||
11) break ;;
|
||||
*) echo "Invalid option. Please try again." ;;
|
||||
esac
|
||||
done
|
||||
}
|
||||
|
||||
settings() {
|
||||
while true; do
|
||||
display_green "Welcome to iamromulan's Simple Console Menu"
|
||||
display_green "Select an option:"
|
||||
echo "------------------"
|
||||
display_green "1. LAN Settings"
|
||||
display_green "2. Change simpleadmin (admin) password"
|
||||
display_green "3. Change root password (shell/ssh/console)"
|
||||
display_green "4. Go back"
|
||||
echo
|
||||
read -p "Select an option (1-11): " option
|
||||
|
||||
case "$option" in
|
||||
1) $MENU_SH/LAN_settings ;;
|
||||
2) $EXE/simplepasswd ;;
|
||||
3) passwd ;;
|
||||
4) 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-11): " option
|
||||
|
||||
case "$option" in
|
||||
1) apps ;;
|
||||
2) settings ;;
|
||||
3) toolkit ;;
|
||||
4) break ;;
|
||||
*) echo "Invalid option. Please try again." ;;
|
||||
esac
|
||||
done
|
||||
}
|
||||
|
||||
main_menu
|
||||
27
simpleadmin/console/services/ethernet_watchdog.sh
Normal file
27
simpleadmin/console/services/ethernet_watchdog.sh
Normal file
@@ -0,0 +1,27 @@
|
||||
#!/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
|
||||
28
simpleadmin/console/services/ping_watchdog.sh
Normal file
28
simpleadmin/console/services/ping_watchdog.sh
Normal file
@@ -0,0 +1,28 @@
|
||||
#!/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
|
||||
14
simpleadmin/console/services/systemd/ping_watchdog.service
Normal file
14
simpleadmin/console/services/systemd/ping_watchdog.service
Normal file
@@ -0,0 +1,14 @@
|
||||
[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,7 +1,15 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Read the serial number and remove the last two digits
|
||||
serial_number=$(cat /sys/devices/soc0/serial_number | sed 's/..$//')
|
||||
# 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+CGMR' | grep -o 'RM[0-9A-Z]*' | head -1)
|
||||
else
|
||||
serial_number="UNKNOWN"
|
||||
firmware_revision="UNKNOWN"
|
||||
fi
|
||||
|
||||
echo "=============================================================="
|
||||
echo "=============================================================="
|
||||
@@ -82,9 +90,10 @@ echo " :@@@@@*. "
|
||||
echo " .=@@@@@- "
|
||||
echo " :+##+. "
|
||||
echo "=============================================================="
|
||||
echo "Test ttyd startup file by iamromulan V0.1"
|
||||
echo "quectel-ID: $serial_number"
|
||||
echo "TTYd session file by iamromulan v1.1"
|
||||
echo "Firmware Revision: $firmware_revision"
|
||||
echo "Serial Number: $serial_number"
|
||||
echo "=============================================================="
|
||||
|
||||
# Start a login session
|
||||
exec /bin/login
|
||||
exec /bin/login
|
||||
BIN
simpleadmin/htpasswd
Normal file
BIN
simpleadmin/htpasswd
Normal file
Binary file not shown.
47
simpleadmin/lighttpd.conf
Normal file
47
simpleadmin/lighttpd.conf
Normal file
@@ -0,0 +1,47 @@
|
||||
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,28 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
while true; do
|
||||
# Run AT+CGMM to get the modem model
|
||||
echo -en "AT+CGMM\r\n" | microcom -t 1000 /dev/ttyOUT > /tmp/modemmodel.txt
|
||||
sleep 2
|
||||
|
||||
# Run AT+CGCONTRDP once then proceed to while loop
|
||||
echo -en "AT+CGCONTRDP=1\r\n" | microcom -t 1000 /dev/ttyOUT > /tmp/apn.txt
|
||||
sleep 2
|
||||
|
||||
# Run AT+QUIMSLOT? to get the current sim slot
|
||||
echo -en "AT+QUIMSLOT?\r\n" | microcom -t 1000 /dev/ttyOUT > /tmp/simslot.txt
|
||||
sleep 2
|
||||
|
||||
# Send request to modem and wait 3 seconds for data
|
||||
echo -en "AT+QSPN;+CEREG=2;+CEREG?;+CEREG=0;+C5GREG=2;+C5GREG?;+C5GREG=0;+CSQ;+QENG=\"servingcell\";+QRSRP;+QCAINFO;+QNWPREFCFG=\"mode_pref\";+QTEMP\r\n" \
|
||||
| microcom -t 3000 /dev/ttyOUT > /tmp/modemstatus.txt
|
||||
if [ $? -eq 0 ]
|
||||
then
|
||||
# Parse
|
||||
if [ -f /tmp/modemstatus.txt ]
|
||||
then
|
||||
/usrdata/simpleadmin/scripts/modemstatus_parse.sh
|
||||
fi
|
||||
fi
|
||||
sleep 25 # Add a sleep to avoid CPU overload
|
||||
done
|
||||
@@ -1,522 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Adapted to work with RJ45 / Quectel Board Dev
|
||||
# Quectel AT Parsing Original source ROOter2203
|
||||
# https://github.com/ofmodemsandmen/ROOterSource2203/blob/6636758b945ff16b6c5b54494de04b74b011c204/package/rooter/ext-rooter-basic/files/usr/lib/rooter/common/quecteldata.sh
|
||||
#
|
||||
|
||||
|
||||
rspr2rssi() {
|
||||
echo ${RSCP} ${BW_N} | awk '{printf "%.0f\n", (($1+10*log(12*$2)/log(10)))}'
|
||||
}
|
||||
|
||||
lte_bw() {
|
||||
BW=$(echo $BW | grep -o "[0-5]\{1\}")
|
||||
case $BW in
|
||||
"0")
|
||||
BW="1.4" ;;
|
||||
"1")
|
||||
BW="3" ;;
|
||||
"2"|"3"|"4"|"5")
|
||||
BW=$((($(echo $BW) - 1) * 5)) ;;
|
||||
esac
|
||||
}
|
||||
|
||||
nr_bw() {
|
||||
BW=$(echo $BW | grep -o "[0-9]\{1,2\}")
|
||||
case $BW in
|
||||
"0"|"1"|"2"|"3"|"4"|"5")
|
||||
BW=$((($(echo $BW) + 1) * 5)) ;;
|
||||
"6"|"7"|"8"|"9"|"10"|"11"|"12")
|
||||
BW=$((($(echo $BW) - 2) * 10)) ;;
|
||||
"13")
|
||||
BW="200" ;;
|
||||
"14")
|
||||
BW="400" ;;
|
||||
esac
|
||||
}
|
||||
|
||||
# Function to get the secondary LTE & NR5G bands
|
||||
# Now conditionally calls the functions to get the secondary bands
|
||||
# Only apply | sed '1d' to NR_BAND when network mode is SA
|
||||
get_secondary_bands() {
|
||||
# Extract LTE BANDs from SCC lines
|
||||
SCC_BANDS=$(echo "$OX" | grep '+QCAINFO: "SCC"' | grep -o '"LTE BAND [0-9]\+"' | tr -d '"' | sed '1d')
|
||||
|
||||
# Extract NR5G BANDs from SCC lines
|
||||
NR_BAND=$(echo "$OX" | grep '+QCAINFO: "SCC"' | grep -o '"NR5G BAND [0-9]\+"' | tr -d '"')
|
||||
|
||||
# Check if both SCC and NR bands are non-empty
|
||||
if [ -n "$SCC_BANDS" ] && [ -n "$NR_BAND" ]; then
|
||||
# Concatenate LTE BANDs with NR5G BANDs
|
||||
SC_BANDS="$SCC_BANDS<br />$NR_BAND"
|
||||
else
|
||||
# Set SC_BANDS to the non-empty variable or empty if both are empty
|
||||
SC_BANDS="${SCC_BANDS}${NR_BAND}"
|
||||
fi
|
||||
}
|
||||
|
||||
# Get the modem model from /tmp/modemmodel.txt and parse it
|
||||
MODEM_MODEL=$(</tmp/modemmodel.txt)
|
||||
# Get the model name from the modem model (they either start with RG or RM)
|
||||
MODEM_MODEL=$(echo "$MODEM_MODEL" | grep -o "RG[^ ]\+\|RM[^ ]\+")
|
||||
|
||||
# Get the APN from /tmp/apn.txt and parse it
|
||||
APN=$(grep "^+CGCONTRDP" /tmp/apn.txt | awk -F',' '{gsub(/"/, "", $3); print $3}')
|
||||
|
||||
# Get the SIM slot from /tmp/simslot.txt and parse it
|
||||
# simslot.txt looks like this: +QUIMSLOT: 1
|
||||
SIMSLOT=$(</tmp/simslot.txt)
|
||||
SIMSLOT=$(echo "$SIMSLOT" | grep -o "[0-9]")
|
||||
# Append SIM before the SIM slot number
|
||||
SIMSLOT="SIM "$SIMSLOT
|
||||
|
||||
# Read File
|
||||
OX=$(</tmp/modemstatus.txt)
|
||||
|
||||
OX=$(echo $OX | tr 'a-z' 'A-Z')
|
||||
|
||||
RSRP=""
|
||||
RSRQ=""
|
||||
CHANNEL="-"
|
||||
ECIO="-"
|
||||
RSCP="-"
|
||||
ECIO1=" "
|
||||
RSCP1=" "
|
||||
MODE="-"
|
||||
MODTYPE="-"
|
||||
NETMODE="-"
|
||||
LBAND="-"
|
||||
PCI="-"
|
||||
CTEMP="-"
|
||||
SINR="-"
|
||||
COPS="-"
|
||||
COPS_MCC="-"
|
||||
COPS_MNC="-"
|
||||
CID=""
|
||||
CID5=""
|
||||
RAT=""
|
||||
QSPN=$(echo $OX | grep -o '+QSPN: "[^"]*","[^"]*","[^"]*",[^"]*,"[^"]*"' | cut -c 8-)
|
||||
# GET MCCMNC from the last field of QSPN
|
||||
MCCMNC=$(echo $QSPN | cut -d, -f5 | tr -d '"')
|
||||
PROVIDER=$(echo $QSPN | cut -d, -f1 | tr -d '"')
|
||||
PROVIDER_ID=$(echo $QSPN | cut -d, -f5 | tr -d '"')
|
||||
CSQ=$(echo $OX | grep -o "+CSQ: [0-9]\{1,2\}" | grep -o "[0-9]\{1,2\}")
|
||||
if [ "$CSQ" = "99" ]; then
|
||||
CSQ=""
|
||||
fi
|
||||
if [ -n "$CSQ" ]; then
|
||||
CSQ_PER=$(($CSQ * 100/31))"%"
|
||||
CSQ_RSSI=$((2 * CSQ - 113))" dBm"
|
||||
else
|
||||
CSQ="-"
|
||||
CSQ_PER="-"
|
||||
CSQ_RSSI="-"
|
||||
fi
|
||||
|
||||
NR_NSA=$(echo $OX | grep -o "+QENG:[ ]\?\"NR5G-NSA\",")
|
||||
NR_SA=$(echo $OX | grep -o "+QENG: \"SERVINGCELL\",[^,]\+,\"NR5G-SA\",\"[DFT]\{3\}\",")
|
||||
if [ -n "$NR_NSA" ]; then
|
||||
QENG=",,"$(echo $OX" " | grep -o "+QENG: \"LTE\".\+\"NR5G-NSA\"," | tr " " ",")
|
||||
if [ -z "$QENG5" ]; then
|
||||
# Fixed an issue where the last 2 digits were not included in the regex
|
||||
QENG5=$(echo $OX | grep -o "+QENG:[ ]\?\"NR5G-NSA\",[0-9]\{3\},[0-9]\{2,3\},[0-9]\{1,5\},-[0-9]\{2,3\},[-0-9]\{1,3\},-[0-9]\{2,3\},[0-9]\{1,6\},[0-9]\{1,3\},[0-9]\{1,3\},[0-9]\{1,3\}")
|
||||
if [ -n "$QENG5" ]; then
|
||||
QENG5=$QENG5",,"
|
||||
fi
|
||||
fi
|
||||
elif [ -n "$NR_SA" ]; then
|
||||
QENG=$(echo $NR_SA | tr " " ",")
|
||||
QENG5=$(echo $OX | grep -o "+QENG: \"SERVINGCELL\",[^,]\+,\"NR5G-SA\",\"[DFT]\{3\}\",[ 0-9]\{3,4\},[0-9]\{2,3\},[0-9A-F]\{1,10\},[0-9]\{1,5\},[0-9A-F]\{2,6\},[0-9]\{6,7\},[0-9]\{1,3\},[0-9]\{1,2\},-[0-9]\{2,5\},-[0-9]\{2,3\},[-0-9]\{1,3\}")
|
||||
else
|
||||
QENG=$(echo $OX" " | grep -o "+QENG: [^ ]\+ " | tr " " ",")
|
||||
fi
|
||||
QCA=$(echo $OX" " | grep -o "+QCAINFO: \"S[CS]\{2\}\".\+NWSCANMODE" | tr " " ",")
|
||||
QNSM=$(echo $OX | grep -o "+QCFG: \"NWSCANMODE\",[0-9]")
|
||||
QNWP=$(echo $OX | grep -o "+QNWPREFCFG: \"MODE_PREF\",[A-Z5:]\+" | cut -d, -f2)
|
||||
QTEMP=$(echo $OX | grep -o "+QTEMP: [0-9]\{1,3\}")
|
||||
if [ -z "$QTEMP" ]; then
|
||||
QTEMP=$(echo $OX | grep -o "+QTEMP:[ ]\?\"XO[_-]THERM[_-][^,]\+,[\"]\?[0-9]\{1,3\}" | grep -o "[0-9]\{1,3\}")
|
||||
fi
|
||||
if [ -z "$QTEMP" ]; then
|
||||
QTEMP=$(echo $OX | grep -o "+QTEMP:[ ]\?\"MDM-CORE-USR.\+[0-9]\{1,3\}\"" | cut -d\" -f4)
|
||||
fi
|
||||
if [ -z "$QTEMP" ]; then
|
||||
QTEMP=$(echo $OX | grep -o "+QTEMP:[ ]\?\"MDMSS.\+[0-9]\{1,3\}\"" | cut -d\" -f4)
|
||||
fi
|
||||
if [ -n "$QTEMP" ]; then
|
||||
CTEMP=$(echo $QTEMP | grep -o "[0-9]\{1,3\}")$(printf "\xc2\xb0")"C"
|
||||
fi
|
||||
RAT=$(echo $QENG | cut -d, -f4 | grep -o "[-A-Z5]\{3,7\}")
|
||||
|
||||
|
||||
rm -f /tmp/modnetwork
|
||||
case $RAT in
|
||||
"GSM")
|
||||
MODE="GSM"
|
||||
;;
|
||||
"WCDMA")
|
||||
MODE="WCDMA"
|
||||
CHANNEL=$(echo $QENG | cut -d, -f9)
|
||||
RSCP=$(echo $QENG | cut -d, -f12)
|
||||
RSCP="-"$(echo $RSCP | grep -o "[0-9]\{1,3\}")
|
||||
ECIO=$(echo $QENG | cut -d, -f13)
|
||||
ECIO="-"$(echo $ECIO | grep -o "[0-9]\{1,3\}")
|
||||
;;
|
||||
"LTE"|"CAT-M"|"CAT-NB")
|
||||
MODE=$(echo $QENG | cut -d, -f5 | grep -o "[DFT]\{3\}")
|
||||
if [ -n "$MODE" ]; then
|
||||
MODE="$RAT $MODE"
|
||||
else
|
||||
MODE="$RAT"
|
||||
fi
|
||||
get_secondary_bands
|
||||
PCI=$(echo $QENG | cut -d, -f9)
|
||||
CHANNEL=$(echo $QENG | cut -d, -f10)
|
||||
LBAND=$(echo $QENG | cut -d, -f11 | grep -o "[0-9]\{1,3\}")
|
||||
BW=$(echo $QENG | cut -d, -f12)
|
||||
lte_bw
|
||||
BWU=$BW
|
||||
BW=$(echo $QENG | cut -d, -f13)
|
||||
lte_bw
|
||||
BWD=$BW
|
||||
if [ -z "$BWD" ]; then
|
||||
BWD="unknown"
|
||||
fi
|
||||
if [ -z "$BWU" ]; then
|
||||
BWU="unknown"
|
||||
fi
|
||||
if [ -n "$LBAND" ]; then
|
||||
PC_BAND="LTE BAND "$LBAND
|
||||
LBAND="B"$LBAND" (Bandwidth $BWD MHz Down | $BWU MHz Up)"
|
||||
fi
|
||||
RSRP=$(echo $QENG | cut -d, -f15 | grep -o "[0-9]\{1,3\}")
|
||||
if [ -n "$RSRP" ]; then
|
||||
RSCP="-"$RSRP
|
||||
RSRPLTE=$RSCP
|
||||
fi
|
||||
RSRQ=$(echo $QENG | cut -d, -f16 | grep -o "[0-9]\{1,3\}")
|
||||
if [ -n "$RSRQ" ]; then
|
||||
ECIO="-"$RSRQ
|
||||
fi
|
||||
RSSI=$(echo $QENG | cut -d, -f17 | grep -o "\-[0-9]\{1,3\}")
|
||||
if [ -n "$RSSI" ]; then
|
||||
CSQ_RSSI=$RSSI" dBm"
|
||||
fi
|
||||
SINRR=$(echo $QENG | cut -d, -f18 | grep -o "[0-9]\{1,3\}")
|
||||
if [ -n "$SINRR" ]; then
|
||||
if [ $SINRR -le 25 ]; then
|
||||
SINR=$((($(echo $SINRR) * 2) -20))" dB"
|
||||
fi
|
||||
fi
|
||||
if [ -n "$(echo $QENG | cut -d, -f21)" ]; then
|
||||
CQI=$(echo $QENG | cut -d, -f19 | grep "^[0-9]\+$")
|
||||
if [ -n "$SINR" -a -n "$CQI" -a "$CQI" != "0" ]; then
|
||||
SINR=$SINR" (CQI $CQI)"
|
||||
fi
|
||||
fi
|
||||
if [ -n "$NR_NSA" ]; then
|
||||
# Changed network mode to NR5G NSA for easy identification
|
||||
MODE="NR5G NSA"
|
||||
echo "0" > /tmp/modnetwork
|
||||
if [ -n "$QENG5" ]; then
|
||||
QENG5=$QENG5",,"
|
||||
# Append the initial PCI value rather than overwriting it
|
||||
get_secondary_bands
|
||||
PCI="$PCI, "$(echo $QENG5 | cut -d, -f4)
|
||||
SCHV=$(echo $QENG5 | cut -d, -f8)
|
||||
SLBV=$(echo $QENG5 | cut -d, -f9) # Now correctly captures the NR band
|
||||
BW=$(echo $QENG5 | cut -d, -f10) # Now gets the correct BW
|
||||
if [ -n "$SLBV" ]; then
|
||||
LBAND=$LBAND"<br />n"$SLBV
|
||||
if [ -n "$BW" ]; then
|
||||
nr_bw
|
||||
LBAND=$LBAND" (Bandwidth $BW MHz)"
|
||||
fi
|
||||
if [ "$SCHV" -ge 123400 ]; then
|
||||
CHANNEL=$CHANNEL", "$SCHV
|
||||
else
|
||||
CHANNEL=$CHANNEL", -"
|
||||
fi
|
||||
else
|
||||
# removed the (unknown NR5G BAND) and replaced with No NR5G Band to avoid confusion
|
||||
LBAND=$LBAND"<br />No NR5G Band Detected"
|
||||
CHANNEL=$CHANNEL", -"
|
||||
fi
|
||||
RSCP=$RSCP" dBm<br />"$(echo $QENG5 | cut -d, -f5)
|
||||
SINRR=$(echo $QENG5 | cut -d, -f6 | grep -o "[0-9]\{1,3\}")
|
||||
if [ -n "$SINRR" ]; then
|
||||
if [ $SINRR -le 30 ]; then
|
||||
SINR=$SINR"<br />"$((($(echo $SINRR) * 2) -20))" dB"
|
||||
fi
|
||||
fi
|
||||
ECIO=$ECIO" (4G) dB<br />"$(echo $QENG5 | cut -d, -f7)" (5G) "
|
||||
fi
|
||||
fi
|
||||
if [ -z "$LBAND" ]; then
|
||||
LBAND="-"
|
||||
else
|
||||
if [ -n "$QCA" ]; then
|
||||
QCA=$(echo $QCA | grep -o "\"S[CS]\{2\}\"[-0-9A-Z,\"]\+")
|
||||
for QCAL in $(echo "$QCA"); do
|
||||
if [ $(echo "$QCAL" | cut -d, -f7) = "2" ]; then
|
||||
SCHV=$(echo $QCAL | cut -d, -f2 | grep -o "[0-9]\+")
|
||||
SRATP="B"
|
||||
if [ -n "$SCHV" ]; then
|
||||
CHANNEL="$CHANNEL, $SCHV"
|
||||
if [ "$SCHV" -gt 123400 ]; then
|
||||
SRATP="n"
|
||||
fi
|
||||
fi
|
||||
SLBV=$(echo $QCAL | cut -d, -f6 | grep -o "[0-9]\{1,2\}")
|
||||
if [ -n "$SLBV" ]; then
|
||||
LBAND=$LBAND"<br />"$SRATP$SLBV
|
||||
BWD=$(echo $QCAL | cut -d, -f3 | grep -o "[0-9]\{1,3\}")
|
||||
if [ -n "$BWD" ]; then
|
||||
UPDOWN=$(echo $QCAL | cut -d, -f13)
|
||||
case "$UPDOWN" in
|
||||
"UL" )
|
||||
CATYPE="CA"$(printf "\xe2\x86\x91") ;;
|
||||
"DL" )
|
||||
CATYPE="CA"$(printf "\xe2\x86\x93") ;;
|
||||
* )
|
||||
CATYPE="CA" ;;
|
||||
esac
|
||||
if [ $BWD -gt 14 ]; then
|
||||
LBAND=$LBAND" ("$CATYPE", Bandwidth "$(($(echo $BWD) / 5))" MHz)"
|
||||
else
|
||||
LBAND=$LBAND" ("$CATYPE", Bandwidth 1.4 MHz)"
|
||||
fi
|
||||
fi
|
||||
LBAND=$LBAND
|
||||
fi
|
||||
PCI="$PCI, "$(echo $QCAL | cut -d, -f8)
|
||||
fi
|
||||
done
|
||||
fi
|
||||
fi
|
||||
if [ $RAT = "CAT-M" ] || [ $RAT = "CAT-NB" ]; then
|
||||
LBAND="B$(echo $QENG | cut -d, -f11) ($RAT)"
|
||||
fi
|
||||
;;
|
||||
"NR5G-SA")
|
||||
MODE="NR5G-SA"
|
||||
echo "0" > /tmp/modnetwork
|
||||
if [ -n "$QENG5" ]; then
|
||||
MODE="$RAT $(echo $QENG5 | cut -d, -f4)"
|
||||
PCI=$(echo $QENG5 | cut -d, -f8)
|
||||
get_secondary_bands
|
||||
# Apply | sed '1d' to NR_BAND
|
||||
NR_BAND=$(echo $NR_BAND | sed '1d')
|
||||
CHANNEL=$(echo $QENG5 | cut -d, -f10)
|
||||
LBAND=$(echo $QENG5 | cut -d, -f11)
|
||||
PC_BAND="NR5G BAND "$LBAND
|
||||
BW=$(echo $QENG5 | cut -d, -f12)
|
||||
nr_bw
|
||||
LBAND="n"$LBAND" (Bandwidth $BW MHz)"
|
||||
RSCP=$(echo $QENG5 | cut -d, -f13)
|
||||
ECIO=$(echo $QENG5 | cut -d, -f14)
|
||||
if [ "$CSQ_PER" = "-" ]; then
|
||||
BW_N=($BW * 5)
|
||||
RSSI=$(rspr2rssi)
|
||||
CSQ_PER=$((100 - (($RSSI + 51) * 100/-62)))"%"
|
||||
CSQ=$((($RSSI + 113) / 2))
|
||||
CSQ_RSSI=$RSSI" dBm"
|
||||
fi
|
||||
SINRR=$(echo $QENG5 | cut -d, -f15 | grep -o "[0-9]\{1,3\}")
|
||||
if [ -n "$SINRR" ]; then
|
||||
if [ $SINRR -le 30 ]; then
|
||||
SINR=$((($(echo $SINRR) * 2) -20))" dB"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
|
||||
QRSRP=$(echo "$OX" | grep -o "+QRSRP:[^,]\+,-[0-9]\{1,5\},-[0-9]\{1,5\},-[0-9]\{1,5\}[^ ]*")
|
||||
if [ -n "$QRSRP" ] && [ "$RAT" != "WCDMA" ]; then
|
||||
QRSRP1=$(echo $QRSRP | cut -d, -f1 | grep -o "[-0-9]\+")
|
||||
QRSRP2=$(echo $QRSRP | cut -d, -f2)
|
||||
QRSRP3=$(echo $QRSRP | cut -d, -f3)
|
||||
QRSRP4=$(echo $QRSRP | cut -d, -f4)
|
||||
QRSRPtype=$(echo $QRSRP | cut -d, -f5)
|
||||
if [ "$QRSRPtype" == "NR5G" ]; then
|
||||
if [ -n "$NR_SA" ]; then
|
||||
RSCP=$QRSRP1
|
||||
if [ -n "$QRSRP2" -a "$QRSRP2" != "-32768" ]; then
|
||||
RSCP1="RxD "$QRSRP2
|
||||
fi
|
||||
if [ -n "$QRSRP3" -a "$QRSRP3" != "-32768" -a "$QRSRP3" != "-44" ]; then
|
||||
RSCP=$RSCP" dBm<br />"$QRSRP3
|
||||
fi
|
||||
if [ -n "$QRSRP4" -a "$QRSRP4" != "-32768" -a "$QRSRP4" != "-44" ]; then
|
||||
RSCP1="RxD "$QRSRP4
|
||||
fi
|
||||
else
|
||||
RSCP=$RSRPLTE
|
||||
if [ -n "$QRSRP1" -a "$QRSRP1" != "-32768" -a "$QRSRP1" != "-44" ]; then
|
||||
RSCP=$RSCP" (4G) dBm<br />"$QRSRP1
|
||||
if [ -n "$QRSRP2" -a "$QRSRP2" != "-32768" -a "$QRSRP2" != "-44" ]; then
|
||||
RSCP="$RSCP, $QRSRP2"
|
||||
if [ -n "$QRSRP3" -a "$QRSRP3" != "-32768" -a "$QRSRP3" != "-44" ]; then
|
||||
RSCP="$RSCP, $QRSRP3"
|
||||
if [ -n "$QRSRP4" -a "$QRSRP4" != "-32768" -a "$QRSRP4" != "-44" ]; then
|
||||
RSCP="$RSCP, $QRSRP4"
|
||||
fi
|
||||
fi
|
||||
RSCP=$RSCP" (5G) "
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
elif [ "$QRSRP2$QRSRP3$QRSRP4" != "-44-44-44" -a -z "$QENG5" ]; then
|
||||
RSCP=$QRSRP1
|
||||
if [ "$QRSRP3$QRSRP4" == "-140-140" -o "$QRSRP3$QRSRP4" == "-44-44" -o "$QRSRP3$QRSRP4" == "-32768-32768" ]; then
|
||||
RSCP1="RxD "$(echo $QRSRP | cut -d, -f2)
|
||||
else
|
||||
RSCP=$RSCP" dBm (RxD "$QRSRP2" dBm)<br />"$QRSRP3
|
||||
RSCP1="RxD "$QRSRP4
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
QNSM=$(echo "$QNSM" | grep -o "[0-9]")
|
||||
if [ -n "$QNSM" ]; then
|
||||
MODTYPE="6"
|
||||
case $QNSM in
|
||||
"0" )
|
||||
NETMODE="1" ;;
|
||||
"1" )
|
||||
NETMODE="3" ;;
|
||||
"2"|"5" )
|
||||
NETMODE="5" ;;
|
||||
"3" )
|
||||
NETMODE="7" ;;
|
||||
esac
|
||||
fi
|
||||
if [ -n "$QNWP" ]; then
|
||||
MODTYPE="6"
|
||||
case $QNWP in
|
||||
"AUTO" )
|
||||
NETMODE="1" ;;
|
||||
"WCDMA" )
|
||||
NETMODE="5" ;;
|
||||
"LTE" )
|
||||
NETMODE="7" ;;
|
||||
"LTE:NR5G" )
|
||||
NETMODE="8" ;;
|
||||
"NR5G" )
|
||||
NETMODE="9" ;;
|
||||
esac
|
||||
fi
|
||||
|
||||
OX=$(echo "${OX//[ \"]/}")
|
||||
|
||||
REGV=$(echo "$OX" | grep -o "+C5GREG:2,[0-9],[A-F0-9]\{2,6\},[A-F0-9]\{5,10\},[0-9]\{1,2\}")
|
||||
if [ -n "$REGV" ]; then
|
||||
LAC5=$(echo "$REGV" | cut -d, -f3)
|
||||
LAC5=$LAC5" ($(printf "%d" 0x$LAC5))"
|
||||
CID5=$(echo "$REGV" | cut -d, -f4)
|
||||
CID5L=$(printf "%010X" 0x$CID5)
|
||||
RNC5=${CID5L:1:6}
|
||||
RNC5=$RNC5" ($(printf "%d" 0x$RNC5))"
|
||||
CID5=${CID5L:7:3}
|
||||
CID5="Short $(printf "%X" 0x$CID5) ($(printf "%d" 0x$CID5)), Long $(printf "%X" 0x$CID5L) ($(printf "%d" 0x$CID5L))"
|
||||
RAT=$(echo "$REGV" | cut -d, -f5)
|
||||
fi
|
||||
REGV=$(echo "$OX" | grep -o "+CEREG:2,[0-9],[A-F0-9]\{2,4\},[A-F0-9]\{5,8\}")
|
||||
REGFMT="3GPP"
|
||||
if [ -z "$REGV" ]; then
|
||||
REGV=$(echo "$OX" | grep -o "+CEREG:2,[0-9],[A-F0-9]\{2,4\},[A-F0-9]\{1,3\},[A-F0-9]\{5,8\}")
|
||||
REGFMT="SW"
|
||||
fi
|
||||
if [ -n "$REGV" ]; then
|
||||
LAC=$(echo "$REGV" | cut -d, -f3)
|
||||
LAC=$(printf "%04X" 0x$LAC)" ($(printf "%d" 0x$LAC))"
|
||||
if [ $REGFMT = "3GPP" ]; then
|
||||
CID=$(echo "$REGV" | cut -d, -f4)
|
||||
else
|
||||
CID=$(echo "$REGV" | cut -d, -f5)
|
||||
fi
|
||||
CIDL=$(printf "%08X" 0x$CID)
|
||||
RNC=${CIDL:1:5}
|
||||
RNC=$RNC" ($(printf "%d" 0x$RNC))"
|
||||
CID=${CIDL:6:2}
|
||||
CID="Short $(printf "%X" 0x$CID) ($(printf "%d" 0x$CID)), Long $(printf "%X" 0x$CIDL) ($(printf "%d" 0x$CIDL))"
|
||||
|
||||
else
|
||||
REGV=$(echo "$OX" | grep -o "+CREG:2,[0-9],[A-F0-9]\{2,4\},[A-F0-9]\{2,8\}")
|
||||
if [ -n "$REGV" ]; then
|
||||
LAC=$(echo "$REGV" | cut -d, -f3)
|
||||
CID=$(echo "$REGV" | cut -d, -f4)
|
||||
if [ ${#CID} -gt 4 ]; then
|
||||
LAC=$(printf "%04X" 0x$LAC)" ($(printf "%d" 0x$LAC))"
|
||||
CIDL=$(printf "%08X" 0x$CID)
|
||||
RNC=${CIDL:1:3}
|
||||
CID=${CIDL:4:4}
|
||||
CID="Short $(printf "%X" 0x$CID) ($(printf "%d" 0x$CID)), Long $(printf "%X" 0x$CIDL) ($(printf "%d" 0x$CIDL))"
|
||||
else
|
||||
LAC=""
|
||||
fi
|
||||
else
|
||||
LAC=""
|
||||
fi
|
||||
fi
|
||||
REGSTAT=$(echo "$REGV" | cut -d, -f2)
|
||||
if [ "$REGSTAT" == "5" -a "$COPS" != "-" ]; then
|
||||
COPS_MNC=$COPS_MNC" (Roaming)"
|
||||
fi
|
||||
if [ -n "$CID" -a -n "$CID5" ] && [ "$RAT" == "13" -o "$RAT" == "10" ]; then
|
||||
LAC="4G $LAC, 5G $LAC5"
|
||||
CID="4G $CID<br />5G $CID5"
|
||||
RNC="4G $RNC, 5G $RNC5"
|
||||
elif [ -n "$CID5" ]; then
|
||||
LAC=$LAC5
|
||||
CID=$CID5
|
||||
RNC=$RNC5
|
||||
fi
|
||||
if [ -z "$LAC" ]; then
|
||||
LAC="-"
|
||||
CID="-"
|
||||
RNC="-"
|
||||
fi
|
||||
|
||||
LUPDATE=$(date +%s)
|
||||
rm -fR /tmp/signal.txt
|
||||
MODEZ=$(echo $MODE | tr -d '"')
|
||||
{
|
||||
echo 'PROVIDER="'"$PROVIDER"'"'
|
||||
echo 'CSQ="'"$CSQ"'"'
|
||||
echo 'CSQ_PER="'"$CSQ_PER"'"'
|
||||
echo 'CSQ_RSSI="'"$CSQ_RSSI"'"'
|
||||
echo 'ECIO="'"$ECIO"'"'
|
||||
echo 'RSCP="'"$RSCP"'"'
|
||||
echo 'ECIO1="'"$ECIO1"'"'
|
||||
echo 'RSCP1="'"$RSCP1"'"'
|
||||
echo 'MODE="'"$MODEZ"'"'
|
||||
echo 'MODTYPE="'"$MODTYPE"'"'
|
||||
echo 'NETMODE="'"$NETMODE"'"'
|
||||
echo 'CHANNEL="'"$CHANNEL"'"'
|
||||
echo 'LBAND="'"$LBAND"'"'
|
||||
echo 'PC_BAND="'"$PC_BAND"'"'
|
||||
echo 'SC_BANDS="'"$SC_BANDS"'"'
|
||||
echo 'APN="'"$APN"'"'
|
||||
echo 'MODEM_MODEL="'"$MODEM_MODEL"'"'
|
||||
echo 'SIMSLOT="'"$SIMSLOT"'"'
|
||||
echo 'PCI="'"$PCI"'"'
|
||||
echo 'TEMP="'"$CTEMP"'"'
|
||||
echo 'SINR="'"$SINR"'"'
|
||||
echo 'LASTUPDATE="'"$LUPDATE"'"'
|
||||
echo 'COPS="'"$COPS"'"'
|
||||
echo 'COPS_MCC="'"$COPS_MCC"'"'
|
||||
echo 'COPS_MNC="'"$COPS_MNC"'"'
|
||||
echo 'MCCMNC="'"$MCCMNC"'"'
|
||||
echo 'LAC="'"$LAC"'"'
|
||||
echo 'LAC_NUM="'""'"'
|
||||
echo 'CID="'"$CID"'"'
|
||||
echo 'CID_NUM="'""'"'
|
||||
echo 'RNC="'"$RNC"'"'
|
||||
echo 'RNC_NUM="'""'"'
|
||||
} > /tmp/signal.txt
|
||||
|
||||
# Pregenerate JSON File
|
||||
/usrdata/simpleadmin/scripts/tojson.sh /tmp/signal.txt > /tmp/modemstatus.json
|
||||
@@ -1,48 +0,0 @@
|
||||
#!/bin/bash
|
||||
# sarav (hello@grity.com)
|
||||
# convert key=value to json
|
||||
# Created at Gritfy ( Devops Junction )
|
||||
# Updated by: dr-dolomite to make it more robust since it was failing on some casess
|
||||
|
||||
file_name="$1"
|
||||
|
||||
echo "{"
|
||||
last_line=$(wc -l < "$file_name")
|
||||
first_line=true
|
||||
|
||||
while IFS='=' read -r key value || [[ -n "$key" ]]; do
|
||||
# Skip empty lines and comments
|
||||
if [[ -z "$key" || "$key" == \#* ]]; then
|
||||
continue
|
||||
fi
|
||||
|
||||
# Trim leading and trailing whitespace from key and value
|
||||
key=$(echo "$key" | awk '{$1=$1};1')
|
||||
value=$(echo "$value" | awk '{$1=$1};1')
|
||||
|
||||
# Check if value includes double quotes inside it like: "value,"value"". If there is, remove the inner double quotes.
|
||||
if [[ "$value" == *\"* ]]; then
|
||||
value=$(echo "$value" | sed 's/\"//g')
|
||||
# enclose the value in double quotes again
|
||||
value="\"$value\""
|
||||
fi
|
||||
|
||||
# Check if value is empty, if so, skip printing this key-value pair
|
||||
if [[ -z "$value" ]]; then
|
||||
continue
|
||||
fi
|
||||
|
||||
# Print comma before each pair except for the first one
|
||||
if $first_line; then
|
||||
first_line=false
|
||||
else
|
||||
printf ','
|
||||
fi
|
||||
|
||||
# Print key-value pair in JSON format without surrounding double quotes on value
|
||||
printf ' "%s" : %s' "$key" "$value"
|
||||
|
||||
printf '\n'
|
||||
done < "$file_name"
|
||||
|
||||
echo "}"
|
||||
5
simpleadmin/simplepasswd
Normal file
5
simpleadmin/simplepasswd
Normal file
@@ -0,0 +1,5 @@
|
||||
#/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"
|
||||
14
simpleadmin/systemd/lighttpd.service
Normal file
14
simpleadmin/systemd/lighttpd.service
Normal file
@@ -0,0 +1,14 @@
|
||||
[Unit]
|
||||
Description=Lighttpd Daemon
|
||||
After=network.target
|
||||
|
||||
[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,9 +0,0 @@
|
||||
[Unit]
|
||||
Description=Simpleadmin service to generate status from modem
|
||||
|
||||
[Service]
|
||||
ExecStart=/usrdata/simpleadmin/scripts/build_modem_status
|
||||
Restart=always
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
@@ -1,11 +0,0 @@
|
||||
[Unit]
|
||||
Description=SimpleAdmin httpd service
|
||||
After=network.target
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
ExecStart=/usr/sbin/httpd -f -h /usrdata/simpleadmin/www -p 8080
|
||||
ExecStop=/bin/kill -WINCH ${MAINPID}
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
12
simpleadmin/systemd/ttyd.service
Normal file
12
simpleadmin/systemd/ttyd.service
Normal file
@@ -0,0 +1,12 @@
|
||||
[Unit]
|
||||
Description=TTYD Service
|
||||
After=network.target
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
ExecStartPre=/bin/sleep 5
|
||||
ExecStart=/usrdata/simpleadmin/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,303 +0,0 @@
|
||||
<!-- !Font Awesome Free 6.5.1 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2024 Fonticons, Inc. -->
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<title>RM5xxx AT Commands</title>
|
||||
|
||||
<script src="/js/alpinejs.min.js" defer></script>
|
||||
<link rel="stylesheet" href="/css/bulma.css" />
|
||||
<link rel="stylesheet" type="text/css" href="/css/admin.css" />
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<!-- START NAV -->
|
||||
<nav class="navbar is-black" x-data="{ isOpen: false }">
|
||||
<div class="container">
|
||||
<div class="navbar-brand">
|
||||
<a class="navbar-item brand-text" href="/"> Simple Admin </a>
|
||||
<a
|
||||
role="button"
|
||||
class="navbar-burger burger"
|
||||
@click="isOpen = !isOpen"
|
||||
>
|
||||
<span aria-hidden="true"></span>
|
||||
<span aria-hidden="true"></span>
|
||||
<span aria-hidden="true"></span>
|
||||
</a>
|
||||
</div>
|
||||
<div
|
||||
id="navMenu"
|
||||
class="navbar-menu"
|
||||
:class="isOpen ? 'is-active' : ''"
|
||||
>
|
||||
<div class="navbar-start">
|
||||
<a class="navbar-item" href="/"> Connection Info </a>
|
||||
<a class="navbar-item" href="/atcommander.html"> AT Commands </a>
|
||||
<a class="navbar-item" href="/sms.html"> SMS </a>
|
||||
<a class="navbar-item" href="/ttl.html"> TTL Changer </a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
<!-- END NAV -->
|
||||
<div class="container" x-data="atCommands()">
|
||||
<div class="columns">
|
||||
<div class="column is-12">
|
||||
<div class="columns">
|
||||
<div class="column is-4">
|
||||
<div class="card">
|
||||
<header class="card-header">
|
||||
<p class="card-header-title">AT Command</p>
|
||||
</header>
|
||||
<div class="card-content">
|
||||
<div class="content">
|
||||
<div class="field">
|
||||
<label class="label">AT Command</label>
|
||||
<div class="control">
|
||||
<input
|
||||
class="input"
|
||||
type="text"
|
||||
placeholder="ATI"
|
||||
x-model="atcmd"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="field">
|
||||
<p class="control">
|
||||
<button
|
||||
class="button is-success"
|
||||
@click="sendAtCommand()"
|
||||
:disabled="isLoading"
|
||||
>
|
||||
Send AT Command
|
||||
</button>
|
||||
|
||||
<button
|
||||
class="button is-danger"
|
||||
@click="clearResponses()"
|
||||
:disabled="atCommandResponse === ''"
|
||||
>
|
||||
Clear
|
||||
</button>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="column is-8">
|
||||
<div class="card">
|
||||
<header class="card-header">
|
||||
<p class="card-header-title">ATI Response</p>
|
||||
</header>
|
||||
<div class="card-content">
|
||||
<div class="content">
|
||||
<textarea
|
||||
class="textarea"
|
||||
placeholder="Please send only 1 AT command at a time"
|
||||
rows="10"
|
||||
x-text="isLoading ? 'Fetching response, please wait...' : atCommandResponse"
|
||||
></textarea>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- START Useful Commands Section -->
|
||||
<div class="container">
|
||||
<div class="columns">
|
||||
<div class="column is-12">
|
||||
<div class="card">
|
||||
<header class="card-header">
|
||||
<p class="card-header-title">Useful Commands</p>
|
||||
</header>
|
||||
<div class="card-content">
|
||||
<div class="content">
|
||||
<!-- <div class="field" style="margin-bottom: 1rem">
|
||||
<p class="control">
|
||||
<button
|
||||
class="button is-danger"
|
||||
click="sendRebootCommand()"
|
||||
:disabled="isRebootClicked"
|
||||
|
||||
>
|
||||
Reboot
|
||||
</button>
|
||||
</p>
|
||||
</div> -->
|
||||
<!-- Add your useful commands content here -->
|
||||
<p>Here are some useful commands:</p>
|
||||
<ul>
|
||||
<li>
|
||||
See https://github.com/iamromulan/RM520N-GL#at-commands for
|
||||
more
|
||||
</li>
|
||||
<li>AT+CFUN=1,1 (reboot)</li>
|
||||
<li>
|
||||
AT+QMAPWAC? (get current status of auto connect, 0=disabled
|
||||
1=enabled)
|
||||
</li>
|
||||
<li>
|
||||
AT+QMAPWAC=1 (enable auto connect internet for ethernet)
|
||||
</li>
|
||||
<li>
|
||||
AT+QMAPWAC=0 (disable auto connect for ethernet; use when
|
||||
you want internet over usb to work; IPPT must be disabled)
|
||||
</li>
|
||||
<li>
|
||||
AT+QUIMSLOT? (get active sim slot; 1=Slot 1; 2=Slot 2)
|
||||
</li>
|
||||
<li>AT+QUIMSLOT=1 (switch to sim slot 1)</li>
|
||||
<li>AT+QUIMSLOT=2 (switch to sim slot 2)</li>
|
||||
<li>AT+CGDCONT? (Get active APN profle list 1 through 8)</li>
|
||||
<li>
|
||||
AT+CGDCONT=1,"IPV4V6","APNHERE" (Sets APN profle 1 to
|
||||
APNHERE using both IPV4 and IPV6)
|
||||
</li>
|
||||
<li>AT+GSN (Show current IMEI)</li>
|
||||
<li>AT+EGMR=1,7,"IMEIGOESHERE" (sets/repairs IMEI)</li>
|
||||
<li>AT+QCAINFO (Show all connected bands/CA info)</li>
|
||||
<li>
|
||||
AT+QNWPREFCFG="mode_pref" (Check what the current network
|
||||
search mode is set to)
|
||||
</li>
|
||||
<li>
|
||||
AT+QNWPREFCFG="mode_pref",AUTO (Set network search mode to
|
||||
automatic)
|
||||
</li>
|
||||
<li>
|
||||
AT+QNWPREFCFG="mode_pref",NR5G:LTE (Set network search mode
|
||||
to 5G/NR and 4G/LTE only)
|
||||
</li>
|
||||
<li>
|
||||
AT+QNWPREFCFG="mode_pref",NR5G (Set network search mode to
|
||||
5G/NR only)
|
||||
</li>
|
||||
<li>
|
||||
AT+QNWPREFCFG="mode_pref",LTE (Set network search mode to
|
||||
4G/LTE only)
|
||||
</li>
|
||||
<li>
|
||||
AT+QNWPREFCFG="nr5g_disable_mode" (Check to see if SA or NSA
|
||||
NR5G is disabled)
|
||||
</li>
|
||||
<li>
|
||||
AT+QNWPREFCFG="nr5g_disable_mode",0 (Enable Both SA and NSA
|
||||
5G/NR)
|
||||
</li>
|
||||
<li>
|
||||
AT+QNWPREFCFG="nr5g_disable_mode",1 (Disable SA 5G/NR only)
|
||||
</li>
|
||||
<li>
|
||||
AT+QNWPREFCFG="nr5g_disable_mode",2 (Disable NSA 5G/NR only)
|
||||
</li>
|
||||
<li>
|
||||
AT+QNWPREFCFG="nr5g_band" (Get current 5G/NR bandlock
|
||||
settings)
|
||||
</li>
|
||||
<li>
|
||||
AT+QNWPREFCFG="nr5g_band",1:2:3:4:5:6 (Example: Lock to
|
||||
5G/NR bands n1,n2,n3,n4,n5, and n6)
|
||||
</li>
|
||||
<li>
|
||||
AT+QNWPREFCFG="lte_band" (Get current 4G/LTE bandlock
|
||||
settings)
|
||||
</li>
|
||||
<li>
|
||||
AT+QNWPREFCFG="lte_band",1:2:3:4:5:6 (Example: Lock to
|
||||
4G/LTE bands 1,2,3,4,5, and 6)
|
||||
</li>
|
||||
<li>
|
||||
AT+QMAP="WWAN" (Show currently assigned IPv4 and IPv6 from
|
||||
the provider)
|
||||
</li>
|
||||
<li>
|
||||
AT+QMAP="LANIP" (Show current DHCP range and Gateway address
|
||||
for VLAN0)
|
||||
</li>
|
||||
<li>
|
||||
AT+QMAP="LANIP",IP_start_range,IP_end_range,Gateway_IP (Set
|
||||
IPv4 Start/End range and Gateway IP of DHCP for VLAN0)
|
||||
</li>
|
||||
<li>
|
||||
AT+QMAP="DHCPV4DNS","disable" (disable the onboard DNS
|
||||
proxy; recommended for IPPT)
|
||||
</li>
|
||||
<li>
|
||||
AT+QMAP="MPDN_rule",0,1,0,1,1,"FF:FF:FF:FF:FF:FF" (Turn on
|
||||
IP Passthrough for Ethernet)
|
||||
</li>
|
||||
<li>
|
||||
AT+QMAP="MPDN_rule",0 (turn off IPPT/clear MPDN rule 0;
|
||||
Remember to run AT+QMAPWAC=1 and reboot after)
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- END Useful Commands Section -->
|
||||
|
||||
<script>
|
||||
function atCommands() {
|
||||
return {
|
||||
isLoading: false,
|
||||
atcmd: null,
|
||||
atCommandResponse: "",
|
||||
sendAtCommand() {
|
||||
this.isLoading = true;
|
||||
fetch(
|
||||
"/cgi-bin/get_atcommand?" +
|
||||
new URLSearchParams({
|
||||
atcmd: this.atcmd,
|
||||
})
|
||||
)
|
||||
.then((res) => {
|
||||
return res.text();
|
||||
})
|
||||
.then((data) => {
|
||||
this.atCommandResponse = data;
|
||||
this.isLoading = false;
|
||||
})
|
||||
.finally(() => {
|
||||
this.isLoading = false;
|
||||
});
|
||||
},
|
||||
clearResponses() {
|
||||
this.atCommandResponse = "";
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
function sendRebootCommand() {
|
||||
var isRebootClicked = true;
|
||||
console.log("Reboot command triggered");
|
||||
var atcmd = "AT+CFUN=1,1";
|
||||
fetch(
|
||||
"/cgi-bin/get_atcommand?" +
|
||||
new URLSearchParams({
|
||||
atcmd: atcmd,
|
||||
})
|
||||
)
|
||||
.then((res) => {
|
||||
return res.text();
|
||||
})
|
||||
.then((data) => {
|
||||
console.log(data); // Logging the response for debugging purposes
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error("Error:", error);
|
||||
});
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -16,8 +16,8 @@ fi
|
||||
MYATCMD=$(printf '%b\n' "${atcmd//%/\\x}")
|
||||
if [ -n "${MYATCMD}" ]; then
|
||||
x=$(urldecode "$atcmd")
|
||||
# Initialize wait time to 2 seconds
|
||||
wait_time=2
|
||||
# Initialize wait time to 1 second
|
||||
wait_time=1000
|
||||
while true; do
|
||||
runcmd=$(echo -en "$x\r\n" | microcom -t $wait_time /dev/ttyOUT2)
|
||||
# Check if "OK" or "ERROR" is present in the response
|
||||
|
||||
@@ -1,13 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
if [ ! -f /tmp/modemstatus.json ]
|
||||
then
|
||||
/usrdata/simpleadmin/scripts/modemstatus_parse.sh > /dev/null
|
||||
fi
|
||||
|
||||
runcmd=$(</tmp/modemstatus.json)
|
||||
|
||||
echo "Content-type: text/json"
|
||||
echo ""
|
||||
cat <<EOT
|
||||
$runcmd
|
||||
19
simpleadmin/www/cgi-bin/get_ping
Normal file
19
simpleadmin/www/cgi-bin/get_ping
Normal file
@@ -0,0 +1,19 @@
|
||||
#!/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
|
||||
20
simpleadmin/www/cgi-bin/get_sms
Normal file
20
simpleadmin/www/cgi-bin/get_sms
Normal file
@@ -0,0 +1,20 @@
|
||||
#!/bin/bash
|
||||
|
||||
# This is a simple scrip that fetches the SMS messages from the device
|
||||
SMS_MESSAGE_INDICATION="AT+CNMI=2,1"
|
||||
SMS_FORMAT="AT+CMGF=1"
|
||||
SMS_LIST="AT+CMGL=\"ALL\""
|
||||
|
||||
while true; do
|
||||
runcmd=$(echo -en "$SMS_LIST\r\n" | microcom -t 2000 /dev/ttyOUT2)
|
||||
if [[ $runcmd =~ "OK" ]] || [[ $runcmd =~ "ERROR" ]]; then
|
||||
break
|
||||
fi
|
||||
((wait_time++))
|
||||
done
|
||||
|
||||
|
||||
# Print the list of SMS messages as JSON plain text
|
||||
echo "Content-type: text/plain"
|
||||
echo ""
|
||||
echo $runcmd
|
||||
@@ -1,7 +1,7 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Check iptables for ttlvalue
|
||||
ttlvalue=$(iptables -t mangle -vnL | grep TTL | awk '{print $13}')
|
||||
ttlvalue=$(/opt/bin/sudo /usr/sbin/iptables -w 5 -t mangle -vnL | grep TTL | awk '{print $13}' | head -n1)
|
||||
ttlenabled=true;
|
||||
|
||||
# Set Variables
|
||||
@@ -16,4 +16,5 @@ cat <<EOT
|
||||
{
|
||||
"isEnabled": $ttlenabled,
|
||||
"ttl": $ttlvalue
|
||||
}
|
||||
}
|
||||
EOT
|
||||
|
||||
44
simpleadmin/www/cgi-bin/send_sms
Normal file
44
simpleadmin/www/cgi-bin/send_sms
Normal file
@@ -0,0 +1,44 @@
|
||||
#!/bin/bash
|
||||
QUERY_STRING=$(echo "${QUERY_STRING}" | sed 's/;//g')
|
||||
function urldecode() { : "${*//+/ }"; echo -e "${_//%/\\x}"; }
|
||||
|
||||
if [ "${QUERY_STRING}" ]; then
|
||||
export IFS="&"
|
||||
for cmd in ${QUERY_STRING}; do
|
||||
if [ "$(echo $cmd | grep '=')" ]; then
|
||||
key=$(echo $cmd | awk -F '=' '{print $1}')
|
||||
value=$(echo $cmd | awk -F '=' '{print $2}')
|
||||
eval $key=$value
|
||||
fi
|
||||
done
|
||||
fi
|
||||
|
||||
# Extract phone number and message from inputs
|
||||
phone_number="$number"
|
||||
message="$msg"
|
||||
|
||||
# Prepare AT command with phone number and message
|
||||
ATCMD="AT+CMGS=\"$phone_number\""
|
||||
|
||||
MYATCMD=$(printf '%b\n' "${ATCMD//%/\\x}")
|
||||
if [ -n "${MYATCMD}" ]; then
|
||||
x=$(urldecode "$ATCMD")
|
||||
# Send the AT command to initiate message sending
|
||||
echo -en "$x\r\n" | microcom /dev/ttyOUT2
|
||||
# Wait for a brief moment (assuming the message sending is instantaneous)
|
||||
sleep 1
|
||||
fi
|
||||
|
||||
# Send the message
|
||||
echo -en "$message\c"
|
||||
|
||||
# Send Ctrl+Z to terminate the message
|
||||
echo -en "\032"
|
||||
|
||||
# Ensure microcom reads the response (assuming microcom will show response instantly)
|
||||
sleep 1
|
||||
|
||||
# Capture and output the response
|
||||
runcmd=$(microcom /dev/ttyOUT2)
|
||||
echo "Content-type: text/plain"
|
||||
echo "$runcmd"
|
||||
@@ -1,5 +1,5 @@
|
||||
#!/bin/bash
|
||||
|
||||
PATH=/bin:/usr/sbin:/usr/bin:/sbin:/opt/sbin:/opt/bin:/usrdata/root/bin
|
||||
# Get query
|
||||
QUERY_STRING=$(echo "${QUERY_STRING}" | sed 's/;//g')
|
||||
|
||||
@@ -22,28 +22,28 @@ setTTL=$(printf '%b\n' "${ttlvalue//%/\\x}")
|
||||
|
||||
if [ -n "${setTTL}" ]; then
|
||||
# Stop Service To Remove Rules
|
||||
/usrdata/simplefirewall/ttl-override stop
|
||||
/opt/bin/sudo /usrdata/simplefirewall/ttl-override stop
|
||||
|
||||
# Check iptables is still set
|
||||
ttlcheck=$(iptables -t mangle -vnL | grep TTL | awk '{print $13}')
|
||||
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
|
||||
iptables -t mangle -D POSTROUTING -o rmnet+ -j TTL --ttl-set ${ttlcheck} &>/dev/null || true
|
||||
ip6tables -t mangle -D POSTROUTING -o rmnet+ -j HL --hl-set ${ttlcheck} &>/dev/null || true
|
||||
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
|
||||
|
||||
# Echo TTL to file
|
||||
echo $setTTL > /usrdata/simplefirewall/ttlvalue
|
||||
|
||||
# Set Start Service
|
||||
/usrdata/simplefirewall/ttl-override start
|
||||
/opt/bin/sudo /usrdata/simplefirewall/ttl-override start
|
||||
fi
|
||||
|
||||
|
||||
|
||||
# Check iptables for ttlvalue
|
||||
ttlvalue=$(iptables -t mangle -vnL | grep TTL | awk '{print $13}')
|
||||
ttlvalue=$(/opt/bin/sudo /usr/sbin/iptables -w 5 -t mangle -vnL | grep TTL | awk '{print $13}')
|
||||
ttlenabled=true;
|
||||
|
||||
# Set Variables
|
||||
@@ -58,4 +58,5 @@ cat <<EOT
|
||||
{
|
||||
"isEnabled": $ttlenabled,
|
||||
"ttl": $ttlvalue
|
||||
}
|
||||
}
|
||||
EOT
|
||||
|
||||
@@ -1,86 +0,0 @@
|
||||
:root{
|
||||
::-webkit-scrollbar{height:10px;width:10px}::-webkit-scrollbar-track{background:#efefef;border-radius:6px}::-webkit-scrollbar-thumb{background:#d5d5d5;border-radius:6px}::-webkit-scrollbar-thumb:hover{background:#c4c4c4}
|
||||
}
|
||||
html, body {
|
||||
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif;
|
||||
font-size: 16px;
|
||||
line-height: 1.5;
|
||||
height: 100%;
|
||||
background: #ECF0F3;
|
||||
}
|
||||
nav.navbar {
|
||||
border-top: 4px solid #276cda;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
.navbar-item.brand-text {
|
||||
font-weight: 300;
|
||||
}
|
||||
.navbar-item, .navbar-link {
|
||||
font-size: 14px;
|
||||
font-weight: 700;
|
||||
}
|
||||
.columns {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
margin-left: 0;
|
||||
}
|
||||
.menu-label {
|
||||
color: #8F99A3;
|
||||
letter-spacing: 1.3;
|
||||
font-weight: 700;
|
||||
}
|
||||
.menu-list a {
|
||||
color: #0F1D38;
|
||||
font-size: 14px;
|
||||
font-weight: 700;
|
||||
}
|
||||
.menu-list a:hover {
|
||||
background-color: transparent;
|
||||
color: #276cda;
|
||||
}
|
||||
.menu-list a.is-active {
|
||||
background-color: transparent;
|
||||
color: #276cda;
|
||||
font-weight: 700;
|
||||
}
|
||||
.card {
|
||||
box-shadow: 0px 2px 4px rgba(0, 0, 0, 0.18);
|
||||
margin-bottom: 2rem;
|
||||
}
|
||||
.card-header-title {
|
||||
color: #8F99A3;
|
||||
font-weight: 400;
|
||||
}
|
||||
.info-tiles {
|
||||
margin: 1rem 0;
|
||||
}
|
||||
.info-tiles .subtitle {
|
||||
font-weight: 300;
|
||||
color: #8F99A3;
|
||||
}
|
||||
.hero.welcome.is-info {
|
||||
background: #36D1DC;
|
||||
background: -webkit-linear-gradient(to right, #5B86E5, #36D1DC);
|
||||
background: linear-gradient(to right, #5B86E5, #36D1DC);
|
||||
}
|
||||
.hero.welcome .title, .hero.welcome .subtitle {
|
||||
color: hsl(192, 17%, 99%);
|
||||
}
|
||||
.card .content {
|
||||
font-size: 14px;
|
||||
}
|
||||
.card-footer-item {
|
||||
font-size: 14px;
|
||||
font-weight: 700;
|
||||
color: #8F99A3;
|
||||
}
|
||||
.card-footer-item:hover {
|
||||
}
|
||||
.card-table .table {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
.events-card .card-table {
|
||||
height: 330px;
|
||||
overflow-y: scroll;
|
||||
}
|
||||
|
||||
6
simpleadmin/www/css/bootstrap.min.css
vendored
Normal file
6
simpleadmin/www/css/bootstrap.min.css
vendored
Normal file
File diff suppressed because one or more lines are too long
1
simpleadmin/www/css/bulma.css
vendored
1
simpleadmin/www/css/bulma.css
vendored
File diff suppressed because one or more lines are too long
95
simpleadmin/www/css/styles.css
Normal file
95
simpleadmin/www/css/styles.css
Normal file
@@ -0,0 +1,95 @@
|
||||
/* 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;
|
||||
}
|
||||
357
simpleadmin/www/deviceinfo.html
Normal file
357
simpleadmin/www/deviceinfo.html
Normal file
@@ -0,0 +1,357 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en" data-bs-theme="light">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<title>Simple Admin</title>
|
||||
<!-- <link
|
||||
href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css"
|
||||
rel="stylesheet"
|
||||
integrity="sha384-QWTKZyjpPEjISv5WaRU9OFeRpok6YctnYmDr5pNlyT2bRjXh0JMhjY6hW+ALEwIH"
|
||||
crossorigin="anonymous"
|
||||
/> -->
|
||||
<!-- Import all the bootstrap css files from css folder -->
|
||||
<link rel="stylesheet" href="/css/styles.css" />
|
||||
<link rel="stylesheet" href="/css/bootstrap.min.css" />
|
||||
|
||||
<!-- Import BootStrap Javascript -->
|
||||
<script src="/js/bootstrap.bundle.min.js"></script>
|
||||
<script src="/js/alpinejs.min.js" defer></script>
|
||||
</head>
|
||||
<body>
|
||||
<main>
|
||||
<div class="container my-4" x-data="fetchDeviceInfo()">
|
||||
<nav class="navbar navbar-expand-lg mt-2">
|
||||
<div class="container-fluid">
|
||||
<a class="navbar-brand" href="/"
|
||||
><span class="mb-0 h4">Simple Admin</span></a
|
||||
>
|
||||
<button
|
||||
class="navbar-toggler"
|
||||
type="button"
|
||||
data-bs-toggle="collapse"
|
||||
data-bs-target="#navbarText"
|
||||
aria-controls="navbarText"
|
||||
aria-expanded="false"
|
||||
aria-label="Toggle navigation"
|
||||
>
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
<div class="collapse navbar-collapse" id="navbarText">
|
||||
<ul class="navbar-nav me-auto mb-2 mb-lg-0">
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="/">Home</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="/network.html">Simple Network</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="/settings.html">Simple Settings</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="/sms.html">SMS</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="/console">Console</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link active" href="/deviceinfo.html" aria-current="page" >Device Information</a>
|
||||
</li>
|
||||
</ul>
|
||||
<span class="navbar-text">
|
||||
<button class="btn btn-link text-reset" id="darkModeToggle">Dark Mode</button>
|
||||
</span>
|
||||
<span class="navbar-text">
|
||||
<button class="btn btn-link" href="logout.html">Log Out</button>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<div class="row mt-5 gap-3">
|
||||
<div class="col">
|
||||
<div class="card">
|
||||
<div class="card-header">Device Information</div>
|
||||
<div class="card-body">
|
||||
<div class="card-text">
|
||||
<div class="table-responsive">
|
||||
<table class="table">
|
||||
<tbody>
|
||||
<tr>
|
||||
<th scope="row">Manufacturer</th>
|
||||
<td x-text="manufacturer"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">Model Name</th>
|
||||
<td x-text="modelName"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">Firmware version</th>
|
||||
<td class="col-md-2" x-text="firmwareVersion"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">IMSI</th>
|
||||
<td class="col-md-2" x-text="imsi"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">ICCID</th>
|
||||
<td class="col-md-2" x-text="iccid"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">IMEI</th>
|
||||
<td class="col-md-2">
|
||||
<input
|
||||
class="form-control"
|
||||
type="text"
|
||||
x-model="newImei"
|
||||
x-bind:placeholder="imei === '-' ? 'Fetching IMEI...' : imei"
|
||||
/>
|
||||
</td>
|
||||
<td>
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-primary"
|
||||
@click="openModal()"
|
||||
>
|
||||
Update
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<th scope="row">LAN IP</th>
|
||||
<td class="col-md-2" x-text="lanIp"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">WWAN IPv<sup>4</sup></th>
|
||||
<td class="col-md-2" x-text="wwanIpv4"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">WWAN IPv<sup>6</sup></th>
|
||||
<td class="col-md-2" x-text="wwanIpv6"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">Simple Admin Version</th>
|
||||
<td class="col-md-2">SimpleAdminRev-Alpha-0.3</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-footer">
|
||||
Visit our
|
||||
<a
|
||||
href="https://github.com/iamromulan/quectel-rgmii-toolkit.gits"
|
||||
target="_blank"
|
||||
class="text-reset"
|
||||
>repository</a
|
||||
>
|
||||
or
|
||||
<a
|
||||
href="https://github.com/iamromulan/quectel-rgmii-configuration-notes.git"
|
||||
target="_blank"
|
||||
class="text-reset"
|
||||
>documentation</a
|
||||
>
|
||||
for more information. All rights reserved. 2024
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Loading Modal for Reboot -->
|
||||
<div class="modal-overlay" x-show="showModal">
|
||||
<div class="loading-modal">
|
||||
<div
|
||||
class="loading-text"
|
||||
style="display: flex; flex-direction: column"
|
||||
>
|
||||
<h3>This will reboot the modem.</h3>
|
||||
<p style="margin-top: 0.5rem">Continue?</p>
|
||||
</div>
|
||||
<div class="d-grid gap-2 d-md-block">
|
||||
<button
|
||||
class="btn btn-primary"
|
||||
type="button"
|
||||
@click="updateIMEI()"
|
||||
>
|
||||
Reboot
|
||||
</button>
|
||||
<button
|
||||
class="btn btn-danger"
|
||||
type="button"
|
||||
@click="closeModal()"
|
||||
>
|
||||
Cancel
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Reboot Modal Countdown -->
|
||||
<div class="modal-overlay" x-show="isRebooting">
|
||||
<div class="loading-modal">
|
||||
<div class="loader"></div>
|
||||
<div
|
||||
class="loading-text"
|
||||
style="display: flex; flex-direction: column"
|
||||
>
|
||||
<h3>Rebooting...</h3>
|
||||
<p style="margin-top: 0.5rem">
|
||||
Please wait for
|
||||
<span x-text="countdown" style="font-weight: 500"></span>
|
||||
seconds.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
<script src="/js/dark-mode.js"></script>
|
||||
<script>
|
||||
function fetchDeviceInfo() {
|
||||
return {
|
||||
manufacturer: "-",
|
||||
modelName: "-",
|
||||
firmwareVersion: "-",
|
||||
imsi: "-",
|
||||
iccid: "-",
|
||||
imei: "-",
|
||||
newImei: null,
|
||||
lanIp: "-",
|
||||
wwanIpv4: "-",
|
||||
wwanIpv6: "-",
|
||||
simpleAdminVersion: "-",
|
||||
atcmd: null,
|
||||
atCommandResponse: "",
|
||||
showModal: false,
|
||||
isLoading: false,
|
||||
isRebooting: false,
|
||||
countdown: 3,
|
||||
|
||||
sendATCommand() {
|
||||
if (!this.atcmd) {
|
||||
// Use ATI as default command
|
||||
console.log(
|
||||
"AT Command is empty, using ATI as default command: "
|
||||
);
|
||||
}
|
||||
|
||||
this.isLoading = true;
|
||||
fetch(
|
||||
"/cgi-bin/get_atcommand?" +
|
||||
new URLSearchParams({
|
||||
atcmd: this.atcmd,
|
||||
})
|
||||
)
|
||||
.then((res) => {
|
||||
return res.text();
|
||||
})
|
||||
.then((data) => {
|
||||
this.atCommandResponse = data;
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error("Error: ", error);
|
||||
this.showError = true;
|
||||
});
|
||||
},
|
||||
|
||||
fetchATCommand() {
|
||||
this.atcmd =
|
||||
'AT+CGMI;+CGMM;+QGMR;+CIMI;+ICCID;+CGSN;+QMAP="LANIP";+QMAP="WWAN"';
|
||||
this.isLoading = true;
|
||||
fetch(
|
||||
"/cgi-bin/get_atcommand?" +
|
||||
new URLSearchParams({
|
||||
atcmd: this.atcmd,
|
||||
})
|
||||
)
|
||||
.then((res) => {
|
||||
return res.text();
|
||||
})
|
||||
.then((data) => {
|
||||
this.atCommandResponse = data;
|
||||
this.parseFetchedData();
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error("Error: ", error);
|
||||
this.showError = true;
|
||||
});
|
||||
},
|
||||
|
||||
parseFetchedData() {
|
||||
const lines = this.atCommandResponse.split("\n");
|
||||
|
||||
console.log("AT Command Response: ", lines);
|
||||
|
||||
this.manufacturer = lines[1].trim();
|
||||
this.modelName = lines[3].trim();
|
||||
this.firmwareVersion = lines[5].trim();
|
||||
this.imsi = lines[7].trim();
|
||||
this.iccid = lines[9].trim().replace("+ICCID: ", "");
|
||||
this.imei = lines[11].trim();
|
||||
this.lanIp = lines[13].trim().split(",")[3];
|
||||
this.wwanIpv4 = lines[15].trim().split(",")[4].replace(/"/g, "");
|
||||
this.wwanIpv6 = lines[16].trim().split(",")[4].replace(/"/g, "");
|
||||
this.simpleAdminVersion = "SimpleAdminRev-Alpha-0.5";
|
||||
this.isLoading = false;
|
||||
},
|
||||
|
||||
updateIMEI() {
|
||||
this.atcmd = `AT+EGMR=1,7,"${this.newImei}"`;
|
||||
this.sendATCommand();
|
||||
this.rebootDevice();
|
||||
},
|
||||
|
||||
rebootDevice() {
|
||||
this.atcmd = "AT+CFUN=1,1";
|
||||
this.sendATCommand();
|
||||
|
||||
this.isLoading = true;
|
||||
this.showModal = false;
|
||||
this.isRebooting = true;
|
||||
this.countdown = 40;
|
||||
const interval = setInterval(() => {
|
||||
this.countdown--;
|
||||
if (this.countdown === 0) {
|
||||
clearInterval(interval);
|
||||
this.isLoading = false;
|
||||
this.showModal = false;
|
||||
this.isRebooting = false;
|
||||
this.init();
|
||||
}
|
||||
}, 1000);
|
||||
},
|
||||
|
||||
openModal() {
|
||||
if (!this.newImei) {
|
||||
alert("No new IMEI provided.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.newImei.length !== 15) {
|
||||
alert("IMEI is invalid");
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.newImei === this.imei) {
|
||||
alert("IMEI is the same as the current IMEI");
|
||||
return;
|
||||
}
|
||||
|
||||
this.showModal = true;
|
||||
},
|
||||
|
||||
closeModal() {
|
||||
this.showModal = false;
|
||||
},
|
||||
|
||||
init() {
|
||||
this.fetchATCommand();
|
||||
},
|
||||
};
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
File diff suppressed because it is too large
Load Diff
7
simpleadmin/www/js/bootstrap.bundle.min.js
vendored
Normal file
7
simpleadmin/www/js/bootstrap.bundle.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
29
simpleadmin/www/js/dark-mode.js
Normal file
29
simpleadmin/www/js/dark-mode.js
Normal file
@@ -0,0 +1,29 @@
|
||||
// Function to toggle dark mode
|
||||
const toggleDarkMode = () => {
|
||||
const html = document.querySelector('html');
|
||||
const currentTheme = html.getAttribute('data-bs-theme');
|
||||
|
||||
if (currentTheme === 'dark') {
|
||||
html.removeAttribute('data-bs-theme');
|
||||
darkModeToggle.textContent = 'Dark Mode';
|
||||
localStorage.setItem('theme', 'light'); // Store the theme in localStorage
|
||||
} else {
|
||||
html.setAttribute('data-bs-theme', 'dark');
|
||||
darkModeToggle.textContent = 'Light Mode';
|
||||
localStorage.setItem('theme', 'dark'); // Store the theme in localStorage
|
||||
}
|
||||
};
|
||||
|
||||
const darkModeToggle = document.getElementById('darkModeToggle');
|
||||
|
||||
// Check if theme preference is stored in localStorage
|
||||
const storedTheme = localStorage.getItem('theme');
|
||||
if (storedTheme) {
|
||||
const html = document.querySelector('html');
|
||||
html.setAttribute('data-bs-theme', storedTheme);
|
||||
if (storedTheme === 'dark') {
|
||||
darkModeToggle.textContent = 'Light Mode';
|
||||
}
|
||||
}
|
||||
|
||||
darkModeToggle.addEventListener('click', toggleDarkMode);
|
||||
37
simpleadmin/www/js/generate-freq-box.js
Normal file
37
simpleadmin/www/js/generate-freq-box.js
Normal file
@@ -0,0 +1,37 @@
|
||||
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);
|
||||
});
|
||||
});
|
||||
58
simpleadmin/www/js/parse-settings.js
Normal file
58
simpleadmin/www/js/parse-settings.js
Normal file
@@ -0,0 +1,58 @@
|
||||
function parseCurrentSettings(rawdata) {
|
||||
const data = rawdata;
|
||||
|
||||
const lines = data.split("\n");
|
||||
console.log(lines);
|
||||
|
||||
// Remove QUIMSLOT and only take 1 or 2
|
||||
this.sim = lines[1].split(":")[1].trim();
|
||||
this.apn = lines[3].split(",")[2].replace(/\"/g, "");
|
||||
this.cellLock4GStatus = lines[5].split(",")[1].replace(/\"/g, "");
|
||||
this.cellLock5GStatus = lines[7].split(",")[1].replace(/\"/g, "");
|
||||
this.prefNetwork = lines[9].split(",")[1].replace(/\"/g, "");
|
||||
this.nrModeControlStatus = lines[11].split(",")[1].replace(/\"/g, "");
|
||||
|
||||
|
||||
let bands = [];
|
||||
|
||||
// Append the values if there is separated by comma
|
||||
for (let i = 13; i < 17; i++) {
|
||||
if (lines[i].split(",").length > 1) {
|
||||
bands.push(lines[i].split(",")[3].replace(/\"/g, ""));
|
||||
}
|
||||
}
|
||||
|
||||
this.bands = bands;
|
||||
|
||||
if (this.cellLock4GStatus == 1 && this.cellLock5GStatus == 1) {
|
||||
this.cellLockStatus = "Locked to 4G and 5G";
|
||||
} else if (this.cellLock4GStatus == 1) {
|
||||
this.cellLockStatus = "Locked to 4G";
|
||||
}
|
||||
else if (this.cellLock5GStatus == 1) {
|
||||
this.cellLockStatus = "Locked to 5G";
|
||||
}
|
||||
else {
|
||||
this.cellLockStatus = "Not Locked";
|
||||
}
|
||||
|
||||
if (this.nrModeControlStatus == 0) {
|
||||
this.nrModeControlStatus = "Not Disabled";
|
||||
}
|
||||
else if (this.nrModeControlStatus == 1) {
|
||||
this.nrModeControlStatus = "SA Disabled";
|
||||
}
|
||||
else {
|
||||
this.nrModeControlStatus = "NSA Disabled";
|
||||
}
|
||||
|
||||
return {
|
||||
sim: sim,
|
||||
apn: apn,
|
||||
cellLockStatus: cellLockStatus,
|
||||
prefNetwork: prefNetwork,
|
||||
nrModeControl: nrModeControlStatus,
|
||||
bands: bands
|
||||
};
|
||||
}
|
||||
|
||||
76
simpleadmin/www/js/populate-checkbox.js
Normal file
76
simpleadmin/www/js/populate-checkbox.js
Normal file
@@ -0,0 +1,76 @@
|
||||
function populateCheckboxes(lte_band, nsa_nr5g_band, nr5g_band, locked_lte_bands, locked_nsa_bands, locked_sa_bands, cellLock) {
|
||||
var checkboxesForm = document.getElementById("checkboxForm");
|
||||
var selectedMode = document.getElementById("networkModeBand").value;
|
||||
var bands;
|
||||
|
||||
// Determine bands based on selected network mode
|
||||
if (selectedMode === "LTE") {
|
||||
bands = lte_band;
|
||||
} else if (selectedMode === "NSA") {
|
||||
bands = nsa_nr5g_band;
|
||||
} else if (selectedMode === "SA") {
|
||||
bands = nr5g_band;
|
||||
}
|
||||
|
||||
checkboxesForm.innerHTML = ""; // Clear existing checkboxes
|
||||
|
||||
var bandsArray;
|
||||
if (bands !== null) {
|
||||
bandsArray = bands.split(":");
|
||||
bandsArray.forEach(function(band, index) {
|
||||
if (index % 5 === 0) {
|
||||
currentRow = document.createElement("div");
|
||||
currentRow.className = "row mb-2 mx-auto"; // Add margin bottom for spacing
|
||||
checkboxesForm.appendChild(currentRow);
|
||||
}
|
||||
|
||||
var checkboxDiv = document.createElement("div");
|
||||
checkboxDiv.className = "form-check form-check-reverse col-2"; // Each checkbox takes a column
|
||||
var checkboxInput = document.createElement("input");
|
||||
checkboxInput.className = "form-check-input";
|
||||
checkboxInput.type = "checkbox";
|
||||
checkboxInput.id = "inlineCheckbox" + band;
|
||||
checkboxInput.value = band;
|
||||
checkboxInput.autocomplete = "off";
|
||||
|
||||
// Store the locked bands in an array
|
||||
var locked_lte_bands_array = locked_lte_bands.split(":");
|
||||
var locked_nsa_bands_array = locked_nsa_bands.split(":");
|
||||
var locked_sa_bands_array = locked_sa_bands.split(":");
|
||||
|
||||
// Check if the current band is locked
|
||||
var isLocked = false;
|
||||
if (selectedMode === "LTE") {
|
||||
if (locked_lte_bands_array.includes(band)) {
|
||||
isLocked = true;
|
||||
}
|
||||
} else if (selectedMode === "NSA") {
|
||||
if (locked_nsa_bands_array.includes(band)) {
|
||||
isLocked = true;
|
||||
}
|
||||
} else if (selectedMode === "SA") {
|
||||
if (locked_sa_bands_array.includes(band)) {
|
||||
isLocked = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (isLocked) {
|
||||
checkboxInput.checked = true;
|
||||
}
|
||||
|
||||
var checkboxLabel = document.createElement("label");
|
||||
checkboxLabel.className = "form-check-label";
|
||||
checkboxLabel.htmlFor = "inlineCheckbox" + band;
|
||||
checkboxLabel.innerText = "B" + band;
|
||||
|
||||
checkboxDiv.appendChild(checkboxInput);
|
||||
checkboxDiv.appendChild(checkboxLabel);
|
||||
currentRow.appendChild(checkboxDiv);
|
||||
});
|
||||
} else {
|
||||
// Do nothing
|
||||
}
|
||||
|
||||
var currentRow;
|
||||
addCheckboxListeners(cellLock);
|
||||
}
|
||||
47
simpleadmin/www/logout.html
Normal file
47
simpleadmin/www/logout.html
Normal file
@@ -0,0 +1,47 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<!-- change to a much simpler tab title -->
|
||||
<title>Simple Admin</title>
|
||||
|
||||
<link rel="stylesheet" href="/css/bulma.css" />
|
||||
<link rel="stylesheet" type="text/css" href="/css/admin.css" />
|
||||
<link rel="stylesheet" href="styles.css" />
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<!-- START NAV -->
|
||||
<nav class="navbar is-black" x-data="{ isOpen: false }">
|
||||
<div class="container">
|
||||
<div class="navbar-brand">
|
||||
<a class="navbar-item brand-text" href="/"> Simple Admin </a>
|
||||
<a
|
||||
role="button"
|
||||
class="navbar-burger burger"
|
||||
@click="isOpen = !isOpen"
|
||||
>
|
||||
<span aria-hidden="true"></span>
|
||||
<span aria-hidden="true"></span>
|
||||
<span aria-hidden="true"></span>
|
||||
</a>
|
||||
</div>
|
||||
<div
|
||||
id="navMenu"
|
||||
class="navbar-menu"
|
||||
:class="isOpen ? 'is-active' : ''"
|
||||
>
|
||||
<div class="navbar-start">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
<!-- END NAV -->
|
||||
|
||||
<script>
|
||||
window.location=window.location.href.replace(/:\/\//, '://log:out@');
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
930
simpleadmin/www/network.html
Normal file
930
simpleadmin/www/network.html
Normal file
@@ -0,0 +1,930 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en" data-bs-theme="light">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<title>Simple Admin</title>
|
||||
<!-- <link
|
||||
href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css"
|
||||
rel="stylesheet"
|
||||
integrity="sha384-QWTKZyjpPEjISv5WaRU9OFeRpok6YctnYmDr5pNlyT2bRjXh0JMhjY6hW+ALEwIH"
|
||||
crossorigin="anonymous"
|
||||
/> -->
|
||||
<!-- Import all the bootstrap css files from css folder -->
|
||||
<link rel="stylesheet" href="css/styles.css" />
|
||||
<link rel="stylesheet" href="css/bootstrap.min.css" />
|
||||
|
||||
<!-- Import BootStrap Javascript -->
|
||||
<script src="js/bootstrap.bundle.min.js"></script>
|
||||
<script src="js/alpinejs.min.js" defer></script>
|
||||
</head>
|
||||
<body>
|
||||
<main>
|
||||
<div class="container my-4" x-data="cellLocking()">
|
||||
<nav class="navbar navbar-expand-lg mt-2">
|
||||
<div class="container-fluid">
|
||||
<a class="navbar-brand" href="/"
|
||||
><span class="mb-0 h4">Simple Admin</span></a
|
||||
>
|
||||
<button
|
||||
class="navbar-toggler"
|
||||
type="button"
|
||||
data-bs-toggle="collapse"
|
||||
data-bs-target="#navbarText"
|
||||
aria-controls="navbarText"
|
||||
aria-expanded="false"
|
||||
aria-label="Toggle navigation"
|
||||
>
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
<div class="collapse navbar-collapse" id="navbarText">
|
||||
<ul class="navbar-nav me-auto mb-2 mb-lg-0">
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="/">Home</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link active" href="network.html" aria-current="page">Simple Network</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="/settings.html">Simple Settings</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="/sms.html">SMS</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="/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>
|
||||
<span class="navbar-text">
|
||||
<button class="btn btn-link" href="logout.html">Log Out</button>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<div class="row mt-5 gap-3">
|
||||
<div class="col">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<div class="row align-items-center">
|
||||
<div class="col">Band Locking</div>
|
||||
<div class="col-md-3">
|
||||
<select
|
||||
class="form-select"
|
||||
id="networkModeBand"
|
||||
aria-label="LTE"
|
||||
>
|
||||
<option selected value="LTE">LTE</option>
|
||||
<option value="NSA">NR5G-NSA</option>
|
||||
<option value="SA">NR5G-SA</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<h5 class="card-subtitle" x-show="isLoading">
|
||||
Fetching supported bands...
|
||||
</h5>
|
||||
<form id="checkboxForm" x-show="isLoading === false">
|
||||
<!-- Checkboxes will be populated here -->
|
||||
</form>
|
||||
</div>
|
||||
<div class="card-footer">
|
||||
<div class="d-flex align-items-center">
|
||||
<div class="col">
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-primary m-2"
|
||||
@click="lockSelectedBands()"
|
||||
>
|
||||
Lock Bands
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-info m-2"
|
||||
id="uncheckAll"
|
||||
>
|
||||
Uncheck All
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-danger m-2"
|
||||
@click="resetBandLocking()"
|
||||
>
|
||||
Reset
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-footer">
|
||||
<p x-text="'Active bands: ' + bands"></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row gap-3 mt-4">
|
||||
<div class="col">
|
||||
<form>
|
||||
<div class="card">
|
||||
<div class="card-header">Network Utilities</div>
|
||||
<div class="card-body row">
|
||||
<div class="col">
|
||||
<div class="mb-4">
|
||||
<label for="APN" class="form-label">APN</label>
|
||||
<input
|
||||
type="text"
|
||||
class="form-control"
|
||||
id="APN"
|
||||
x-model="newApn"
|
||||
aria-describedby="APN"
|
||||
x-bind:placeholder="apn === '-' ? 'Fetching...' : apn"
|
||||
/>
|
||||
</div>
|
||||
<div class="mb-4 input-group grid gap-3">
|
||||
<label for="SIM1" class="form-label"> Change SIM</label>
|
||||
<div class="form-check form-check-inline">
|
||||
<input
|
||||
class="form-check-input"
|
||||
type="radio"
|
||||
name="inlineRadioOptions"
|
||||
aria-describedby="SIM1"
|
||||
id="SIM1"
|
||||
value="option1"
|
||||
x-bind:checked="sim === '1'"
|
||||
x-on:click="newSim = '1'"
|
||||
/>
|
||||
<label class="form-check-label" for="inlineRadio1"
|
||||
>1</label
|
||||
>
|
||||
</div>
|
||||
<div class="form-check form-check-inline">
|
||||
<input
|
||||
class="form-check-input"
|
||||
type="radio"
|
||||
name="inlineRadioOptions"
|
||||
aria-describedby="SIM2"
|
||||
id="SIM2"
|
||||
value="option2"
|
||||
x-bind:checked="sim === '2'"
|
||||
x-on:click="newSim = '2'"
|
||||
/>
|
||||
<label class="form-check-label" for="inlineRadio2"
|
||||
>2</label
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col">
|
||||
<div class="mb-4">
|
||||
<label for="nrModeControl" class="form-label"
|
||||
>Select Preferred Network</label
|
||||
>
|
||||
<select
|
||||
class="form-select"
|
||||
id="prefNetworkMode"
|
||||
x-model="prefNetworkMode"
|
||||
aria-label="prefNetworkMode"
|
||||
>
|
||||
<option
|
||||
selected
|
||||
x-text="prefNetwork === '-' ? 'Fetching...' : 'Current: ' + prefNetwork"
|
||||
></option>
|
||||
<option value="AUTO">AUTO</option>
|
||||
<option value="LTE">LTE Only</option>
|
||||
<option value="LTE:NR5G">NR5G-NSA</option>
|
||||
<option value="NR5G">NR5G-SA</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="mb-4">
|
||||
<label for="prefNetwork" class="form-label"
|
||||
>NR5G Mode Control</label
|
||||
>
|
||||
<select
|
||||
class="form-select"
|
||||
id="nrModeControl"
|
||||
x-model="nrModeControl"
|
||||
aria-label="nrModeControl"
|
||||
>
|
||||
<option
|
||||
selected
|
||||
x-text="nrModeControl === '-' ? 'Fetching...' : 'Current: ' + nrModeControl"
|
||||
></option>
|
||||
<option value="0">Enable All</option>
|
||||
<option value="2">Disable NR5G-NSA</option>
|
||||
<option value="1">Disable NR5G-SA</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-footer">
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-primary"
|
||||
@click="saveChanges()"
|
||||
>
|
||||
Save Changes
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div class="col-md-4">
|
||||
<div class="card">
|
||||
<div class="card-header">Cell Locking</div>
|
||||
<div class="card-body">
|
||||
<select
|
||||
class="form-select"
|
||||
id="networkModeCell"
|
||||
x-model="networkModeCell"
|
||||
aria-label="LTE"
|
||||
>
|
||||
<option
|
||||
selected
|
||||
x-text="'Cell Lock: ' + cellLockStatus"
|
||||
></option>
|
||||
<option>LTE</option>
|
||||
<option>NR5G-SA</option>
|
||||
<option>Unlock LTE</option>
|
||||
<option>Unlock NR5G-SA</option>
|
||||
</select>
|
||||
|
||||
<div class="my-4">
|
||||
<!-- For LTE -->
|
||||
<div id="lteElementsCell" x-show="networkModeCell == 'LTE'">
|
||||
<div class="input-group mb-3">
|
||||
<span class="input-group-text" id="basic-addon1"
|
||||
>Num Cells</span
|
||||
>
|
||||
<input
|
||||
type="number"
|
||||
class="form-control"
|
||||
placeholder="1-10"
|
||||
min="1"
|
||||
max="10"
|
||||
aria-label="NumCells"
|
||||
aria-describedby="basic-addon1"
|
||||
x-model="cellNum"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="freqNumbersContainer">
|
||||
<!-- Generate EARFCN and PCI here -->
|
||||
</div>
|
||||
|
||||
<!-- For SA -->
|
||||
<div
|
||||
id="saElementsCell"
|
||||
x-show="networkModeCell == 'NR5G-SA'"
|
||||
>
|
||||
<div
|
||||
class="input-group mb-3"
|
||||
x-show="networkModeCell == 'NR5G-SA'"
|
||||
>
|
||||
<input
|
||||
type="text"
|
||||
aria-label="EARFCN"
|
||||
placeholder="EARFCN"
|
||||
class="form-control"
|
||||
x-model="earfcn1"
|
||||
/>
|
||||
<input
|
||||
type="text"
|
||||
aria-label="PCI"
|
||||
placeholder="PCI"
|
||||
class="form-control"
|
||||
x-model="pci1"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div
|
||||
class="input-group mb-3"
|
||||
x-show="networkModeCell == 'NR5G-SA'"
|
||||
>
|
||||
<select
|
||||
class="form-select"
|
||||
x-model="scs"
|
||||
aria-label="SCS"
|
||||
>
|
||||
<option selected>SCS</option>
|
||||
<option>15</option>
|
||||
<option>30</option>
|
||||
<option>60</option>
|
||||
<option>120</option>
|
||||
<option>240</option>
|
||||
</select>
|
||||
<input
|
||||
type="text"
|
||||
aria-label="band"
|
||||
placeholder="Band"
|
||||
class="form-control"
|
||||
x-model="band"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-primary"
|
||||
x-show="networkModeCell == 'LTE'"
|
||||
@click="cellLockEnableLTE()"
|
||||
>
|
||||
Lock LTE Cells
|
||||
</button>
|
||||
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-primary"
|
||||
x-show="networkModeCell == 'NR5G-SA'"
|
||||
@click="cellLockEnableNR()"
|
||||
>
|
||||
Lock NR5G-SA Cells
|
||||
</button>
|
||||
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-danger"
|
||||
x-show="networkModeCell == 'Unlock LTE'"
|
||||
@click="cellLockDisableLTE()"
|
||||
>
|
||||
Unlock LTE Cells
|
||||
</button>
|
||||
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-danger"
|
||||
x-show="networkModeCell == 'Unlock NR5G-SA'"
|
||||
@click="cellLockDisableNR()"
|
||||
>
|
||||
Unlock NR5G-SA Cells
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Loading Modal for Locking Band -->
|
||||
<div class="modal-overlay" x-show="showModal">
|
||||
<div class="loading-modal">
|
||||
<div class="loader"></div>
|
||||
<div
|
||||
class="loading-text"
|
||||
style="display: flex; flex-direction: column"
|
||||
>
|
||||
<h3>Initializing Network...</h3>
|
||||
<p style="margin-top: 0.5rem">
|
||||
Please wait for
|
||||
<span x-text="countdown" style="font-weight: 500"></span>
|
||||
seconds.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<!-- Import Band Locking GUI JS -->
|
||||
<!-- <script src="js/band-locking.js"></script> -->
|
||||
<script src="js/generate-freq-box.js"></script>
|
||||
<script src="js/populate-checkbox.js"></script>
|
||||
<script src="js/parse-settings.js"></script>
|
||||
<script>
|
||||
function requestATInfo(atcmd) {
|
||||
return fetch(
|
||||
"/cgi-bin/get_atcommand?" +
|
||||
new URLSearchParams({
|
||||
atcmd: atcmd,
|
||||
})
|
||||
)
|
||||
.then((response) => response.text())
|
||||
.then((data) => {
|
||||
return data;
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error("Error:", error);
|
||||
// Throw the error again to ensure it's propagated
|
||||
throw error;
|
||||
});
|
||||
}
|
||||
|
||||
function getSupportedBands() {
|
||||
const atcmd = 'AT+QNWPREFCFG="policy_band"';
|
||||
return requestATInfo(atcmd).then((rawdata) => {
|
||||
let { lte_bands, nsa_bands, sa_bands } = parseSupportedBands(rawdata);
|
||||
|
||||
return {
|
||||
lte_bands: lte_bands,
|
||||
nsa_bands: nsa_bands,
|
||||
sa_bands: sa_bands,
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
function parseSupportedBands(rawdata) {
|
||||
const data = rawdata;
|
||||
const regex = /"([^"]+)",([0-9:]+)/g;
|
||||
|
||||
// Object to store the results
|
||||
const bands = {};
|
||||
|
||||
let match;
|
||||
while ((match = regex.exec(data)) !== null) {
|
||||
const bandType = match[1];
|
||||
const numbers = match[2].split(":").map(Number);
|
||||
bands[bandType] = numbers;
|
||||
}
|
||||
|
||||
// Seperate the bands for each network mode
|
||||
const lte_bands = bands.lte_band.join(":");
|
||||
const nsa_bands = bands.nsa_nr5g_band.join(":");
|
||||
const sa_bands = bands.nr5g_band.join(":");
|
||||
|
||||
return {
|
||||
lte_bands,
|
||||
nsa_bands,
|
||||
sa_bands,
|
||||
};
|
||||
}
|
||||
|
||||
function parseLockedBands(rawdata) {
|
||||
const data = rawdata;
|
||||
const regex = /"([^"]+)",([0-9:]+)/g;
|
||||
|
||||
// Object to store the results
|
||||
const bands = {};
|
||||
|
||||
let match;
|
||||
while ((match = regex.exec(data)) !== null) {
|
||||
const bandType = match[1];
|
||||
const numbers = match[2].split(":").map(Number);
|
||||
bands[bandType] = numbers;
|
||||
}
|
||||
|
||||
// Seperate the bands for each network mode
|
||||
const locked_lte_bands = bands.lte_band.join(":");
|
||||
const locked_nsa_bands = bands.nsa_nr5g_band.join(":");
|
||||
const locked_sa_bands = bands.nr5g_band.join(":");
|
||||
|
||||
return {
|
||||
locked_lte_bands,
|
||||
locked_nsa_bands,
|
||||
locked_sa_bands,
|
||||
};
|
||||
}
|
||||
|
||||
function getLockedBands() {
|
||||
const atcmd =
|
||||
'AT+QNWPREFCFG="lte_band";+QNWPREFCFG= "nsa_nr5g_band";+QNWPREFCFG= "nr5g_band"';
|
||||
|
||||
return requestATInfo(atcmd).then((rawdata) => {
|
||||
const lockedBandsData = parseLockedBands(rawdata);
|
||||
return lockedBandsData;
|
||||
});
|
||||
}
|
||||
|
||||
function getCurrentSettings() {
|
||||
const atcmd =
|
||||
'AT+QUIMSLOT?;+CGCONTRDP=1;+QNWLOCK="common/4g";+QNWLOCK="common/5g";+QNWPREFCFG="mode_pref";+QNWPREFCFG="nr5g_disable_mode";+QCAINFO';
|
||||
|
||||
return requestATInfo(atcmd).then((rawdata) => {
|
||||
const settings = parseCurrentSettings(rawdata);
|
||||
return {
|
||||
sim: settings.sim,
|
||||
apn: settings.apn,
|
||||
cellLockStatus: settings.cellLockStatus,
|
||||
prefNetwork: settings.prefNetwork,
|
||||
nrModeControl: settings.nrModeControl,
|
||||
bands: settings.bands,
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
function cellLocking() {
|
||||
return {
|
||||
isLoading: false,
|
||||
showModal: false,
|
||||
countdown: 0,
|
||||
networkModeCell: "-",
|
||||
earfcn1: null,
|
||||
pci1: null,
|
||||
earfcn2: null,
|
||||
pci2: null,
|
||||
earfcn3: null,
|
||||
pci3: null,
|
||||
earfcn4: null,
|
||||
pci4: null,
|
||||
earfcn5: null,
|
||||
pci5: null,
|
||||
earfcn6: null,
|
||||
pci6: null,
|
||||
earfcn7: null,
|
||||
pci7: null,
|
||||
earfcn8: null,
|
||||
pci8: null,
|
||||
earfcn9: null,
|
||||
pci9: null,
|
||||
earfcn10: null,
|
||||
pci10: null,
|
||||
scs: null,
|
||||
band: null,
|
||||
apn: "-",
|
||||
newApn: null,
|
||||
prefNetwork: "-",
|
||||
prefNetworkMode: null,
|
||||
nrModeControl: "-",
|
||||
cellNum: null,
|
||||
lte_bands: null,
|
||||
nsa_bands: null,
|
||||
sa_bands: null,
|
||||
locked_lte_bands: null,
|
||||
locked_nsa_bands: null,
|
||||
locked_sa_bands: null,
|
||||
currentNetworkMode: "-",
|
||||
updatedLockedBands: null,
|
||||
sim: "-",
|
||||
newSim: null,
|
||||
cellLockStatus: null,
|
||||
bands: "Fetching Bands...",
|
||||
init() {
|
||||
// Function to populate checkboxes
|
||||
const showPopulateCheckboxes = () => {
|
||||
this.isLoading = true;
|
||||
Promise.all([getSupportedBands(), getLockedBands()])
|
||||
.then(([supportedBandsData, lockedBandsData]) => {
|
||||
this.lte_bands = supportedBandsData.lte_bands;
|
||||
this.nsa_bands = supportedBandsData.nsa_bands;
|
||||
this.sa_bands = supportedBandsData.sa_bands;
|
||||
this.locked_lte_bands = lockedBandsData.locked_lte_bands;
|
||||
this.locked_nsa_bands = lockedBandsData.locked_nsa_bands;
|
||||
this.locked_sa_bands = lockedBandsData.locked_sa_bands;
|
||||
|
||||
// Once both promises are resolved, call populateCheckboxes
|
||||
populateCheckboxes(
|
||||
this.lte_bands,
|
||||
this.nsa_bands,
|
||||
this.sa_bands,
|
||||
this.locked_lte_bands,
|
||||
this.locked_nsa_bands,
|
||||
this.locked_sa_bands,
|
||||
this
|
||||
);
|
||||
|
||||
// Set isLoading to false after populating checkboxes
|
||||
this.isLoading = false;
|
||||
|
||||
// Add event listeners to checkboxes after populating them
|
||||
addCheckboxListeners(this);
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error("Error:", error);
|
||||
// Handle errors if any
|
||||
});
|
||||
};
|
||||
|
||||
// Function to track checkbox changes
|
||||
this.trackCheckboxChanges = () => {
|
||||
var selectedMode =
|
||||
document.getElementById("networkModeBand").value;
|
||||
var checkboxes = document.querySelectorAll(
|
||||
'input[type="checkbox"]'
|
||||
);
|
||||
var newCheckedValues = [];
|
||||
|
||||
checkboxes.forEach(function (checkbox) {
|
||||
if (checkbox.checked) {
|
||||
newCheckedValues.push(checkbox.value);
|
||||
}
|
||||
});
|
||||
|
||||
// Update currentNetworkMode and updatedLockedBands
|
||||
this.currentNetworkMode = selectedMode;
|
||||
this.updatedLockedBands = newCheckedValues;
|
||||
};
|
||||
|
||||
// Function to get the current settings
|
||||
const getCurrentSettingsData = () => {
|
||||
getCurrentSettings().then((settings) => {
|
||||
this.sim = settings.sim;
|
||||
this.apn = settings.apn;
|
||||
this.cellLockStatus = settings.cellLockStatus;
|
||||
this.prefNetwork = settings.prefNetwork;
|
||||
this.nrModeControl = settings.nrModeControl;
|
||||
this.bands = settings.bands;
|
||||
});
|
||||
};
|
||||
|
||||
// Function to add event listener to network mode dropdown
|
||||
const addNetworkModeListener = () => {
|
||||
document
|
||||
.getElementById("networkModeBand")
|
||||
.addEventListener("change", function () {
|
||||
showPopulateCheckboxes(); // Update checkboxes when network mode changes
|
||||
});
|
||||
};
|
||||
|
||||
// Execute necessary functions on initialization
|
||||
showPopulateCheckboxes();
|
||||
addNetworkModeListener();
|
||||
getCurrentSettingsData();
|
||||
},
|
||||
lockSelectedBands() {
|
||||
// Get the updated this.currentNetworkMode = selectedMode; and this.updatedLockedBands = newCheckedValues;
|
||||
const selectedMode = this.currentNetworkMode;
|
||||
const newCheckedValues = this.updatedLockedBands;
|
||||
let atcmd;
|
||||
|
||||
// Check if both values are null then show the error message
|
||||
if (selectedMode === null || newCheckedValues === null) {
|
||||
} else {
|
||||
if (selectedMode === "LTE") {
|
||||
atcmd = `AT+QNWPREFCFG="lte_band",${newCheckedValues.join(
|
||||
":"
|
||||
)}`;
|
||||
this.sendATcommand(atcmd);
|
||||
} else if (selectedMode === "NSA") {
|
||||
atcmd = `AT+QNWPREFCFG="nsa_nr5g_band",${newCheckedValues.join(
|
||||
":"
|
||||
)}`;
|
||||
this.sendATcommand(atcmd);
|
||||
} else if (selectedMode === "SA") {
|
||||
atcmd = `AT+QNWPREFCFG="nr5g_band",${newCheckedValues.join(
|
||||
":"
|
||||
)}`;
|
||||
this.sendATcommand(atcmd);
|
||||
} else {
|
||||
alert("Invalid network mode selected");
|
||||
}
|
||||
|
||||
// Do a 5 second countdown
|
||||
this.showModal = true;
|
||||
this.countdown = 5;
|
||||
const interval = setInterval(() => {
|
||||
this.countdown--;
|
||||
if (this.countdown === 0) {
|
||||
clearInterval(interval);
|
||||
this.showModal = false;
|
||||
|
||||
// Refresh the page to show the updated bands
|
||||
this.init();
|
||||
}
|
||||
}, 1000);
|
||||
}
|
||||
},
|
||||
resetBandLocking() {
|
||||
// Send the atcmd command to reset the locked bands
|
||||
const atcmd = 'AT+QNWPREFCFG="restore_band"';
|
||||
|
||||
this.showModal = true;
|
||||
|
||||
this.sendATcommand(atcmd);
|
||||
|
||||
this.countdown = 5;
|
||||
const interval = setInterval(() => {
|
||||
this.countdown--;
|
||||
if (this.countdown === 0) {
|
||||
clearInterval(interval);
|
||||
this.showModal = false;
|
||||
|
||||
// Refresh the page to show the updated bands
|
||||
this.init();
|
||||
}
|
||||
}, 1000);
|
||||
|
||||
// Run init function to repopulate the checkboxes
|
||||
this.init();
|
||||
},
|
||||
saveChanges() {
|
||||
const newApn = this.newApn;
|
||||
const newSim = this.newSim;
|
||||
const prefNetworkMode = this.prefNetworkMode;
|
||||
const nrModeControl = this.nrModeControl;
|
||||
|
||||
let atAPN, atSIM, ATNetwork, ATNRMode, atcmd;
|
||||
atAPN = "";
|
||||
atSIM = "";
|
||||
ATNetwork = "";
|
||||
ATNRMode = "";
|
||||
|
||||
if (newApn !== null) {
|
||||
atAPN = `+CGDCONT=1,"IP","${newApn}";`;
|
||||
}
|
||||
|
||||
if (newSim !== null) {
|
||||
atSIM = `+QUIMSLOT=${newSim};`;
|
||||
}
|
||||
|
||||
if (prefNetworkMode !== null) {
|
||||
ATNetwork = `+QNWPREFCFG="mode_pref",${prefNetworkMode};`;
|
||||
}
|
||||
|
||||
if (nrModeControl !== this.nrModeControl) {
|
||||
ATNRMode = `+QNWPREFCFG="nr5g_disable_mode",${nrModeControl}`;
|
||||
}
|
||||
|
||||
atcmd = `AT+${atAPN}${atSIM}${ATNetwork}${ATNRMode}`;
|
||||
// If there is double + (++), remove 1 + from the command
|
||||
atcmd = atcmd.replace("++", "+");
|
||||
if (atcmd !== "AT+") {
|
||||
this.showModal = true;
|
||||
console.log(atcmd);
|
||||
|
||||
this.sendATcommand(atcmd);
|
||||
|
||||
// Do a 15 second countdown
|
||||
this.countdown = 15;
|
||||
|
||||
const interval = setInterval(() => {
|
||||
this.countdown--;
|
||||
if (this.countdown === 0) {
|
||||
clearInterval(interval);
|
||||
this.showModal = false;
|
||||
this.init();
|
||||
}
|
||||
}, 1000);
|
||||
} else {
|
||||
alert("No changes made");
|
||||
}
|
||||
},
|
||||
cellLockEnableLTE() {
|
||||
const cellNum = this.cellNum;
|
||||
|
||||
if (cellNum === null) {
|
||||
alert("Please enter the number of cells to lock");
|
||||
return; // Exit the function early if cellNum is null
|
||||
}
|
||||
|
||||
// Create an array to hold earfcn and pci pairs
|
||||
const earfcnPciPairs = [
|
||||
{ earfcn: this.earfcn1, pci: this.pci1 },
|
||||
{ earfcn: this.earfcn2, pci: this.pci2 },
|
||||
{ earfcn: this.earfcn3, pci: this.pci3 },
|
||||
{ earfcn: this.earfcn4, pci: this.pci4 },
|
||||
{ earfcn: this.earfcn5, pci: this.pci5 },
|
||||
{ earfcn: this.earfcn6, pci: this.pci6 },
|
||||
{ earfcn: this.earfcn7, pci: this.pci7 },
|
||||
{ earfcn: this.earfcn8, pci: this.pci8 },
|
||||
{ earfcn: this.earfcn9, pci: this.pci9 },
|
||||
{ earfcn: this.earfcn10, pci: this.pci10 },
|
||||
];
|
||||
|
||||
// Filter out pairs where either earfcn or pci is null
|
||||
const validPairs = earfcnPciPairs.filter(
|
||||
(pair) => pair.earfcn !== null && pair.pci !== null
|
||||
);
|
||||
|
||||
if (validPairs.length === 0) {
|
||||
alert("Please enter at least one valid earfcn and pci pair");
|
||||
return; // Exit the function early if no valid pairs are found
|
||||
}
|
||||
|
||||
// Construct the AT command using the valid pairs
|
||||
let atcmd = `+QNWLOCK="common/4g",${cellNum},${validPairs
|
||||
.map((pair) => `${pair.earfcn},${pair.pci}`)
|
||||
.join(",")}`;
|
||||
atcmd = "AT+CFUN=0;" + atcmd + ";+CFUN=1";
|
||||
|
||||
// Mock data
|
||||
this.showModal = true;
|
||||
|
||||
this.sendATcommand(atcmd);
|
||||
|
||||
// Do a 15 second countdown
|
||||
this.countdown = 15;
|
||||
const interval = setInterval(() => {
|
||||
this.countdown--;
|
||||
if (this.countdown === 0) {
|
||||
clearInterval(interval);
|
||||
this.showModal = false;
|
||||
}
|
||||
}, 1000);
|
||||
},
|
||||
cellLockEnableNR() {
|
||||
const earfcn = this.earfcn1;
|
||||
const pci = this.pci1;
|
||||
const scs = this.scs;
|
||||
const band = this.band;
|
||||
|
||||
if (
|
||||
earfcn === null ||
|
||||
pci === null ||
|
||||
scs === null ||
|
||||
band === null
|
||||
) {
|
||||
alert("Please enter all the required fields");
|
||||
return; // Exit the function early if any of the fields are null
|
||||
}
|
||||
|
||||
// Construct the AT command using the valid pairs
|
||||
let atcmd = `+QNWLOCK="common/5g",${earfcn},${pci},${scs},${band}`;
|
||||
atcmd = "AT+CFUN=0;" + atcmd + ";+CFUN=1";
|
||||
|
||||
// Mock data
|
||||
this.showModal = true;
|
||||
|
||||
this.sendATcommand(atcmd);
|
||||
|
||||
// Do a 15 second countdown
|
||||
this.countdown = 15;
|
||||
const interval = setInterval(() => {
|
||||
this.countdown--;
|
||||
if (this.countdown === 0) {
|
||||
clearInterval(interval);
|
||||
this.showModal = false;
|
||||
}
|
||||
}, 1000);
|
||||
},
|
||||
cellLockDisableLTE() {
|
||||
// Send the atcmd command to reset the locked bands
|
||||
const atcmd = 'AT+CFUN=0;+QNWLOCK="common/4g,0;+CFUN=1"';
|
||||
this.showModal = true;
|
||||
|
||||
this.sendATcommand(atcmd);
|
||||
|
||||
this.countdown = 15;
|
||||
const interval = setInterval(() => {
|
||||
this.countdown--;
|
||||
if (this.countdown === 0) {
|
||||
clearInterval(interval);
|
||||
this.showModal = false;
|
||||
}
|
||||
}, 1000);
|
||||
},
|
||||
cellLockDisableNR() {
|
||||
// Send the atcmd command to reset the locked bands
|
||||
const atcmd = 'AT+CFUN=0;+QNWLOCK="common/5g,0;+CFUN=1"';
|
||||
|
||||
this.showModal = true;
|
||||
|
||||
this.sendATcommand(atcmd);
|
||||
|
||||
this.countdown = 15;
|
||||
const interval = setInterval(() => {
|
||||
this.countdown--;
|
||||
if (this.countdown === 0) {
|
||||
clearInterval(interval);
|
||||
this.showModal = false;
|
||||
}
|
||||
}, 1000);
|
||||
},
|
||||
sendATcommand(atcmd) {
|
||||
return fetch(
|
||||
"/cgi-bin/get_atcommand?" +
|
||||
new URLSearchParams({
|
||||
atcmd: atcmd,
|
||||
})
|
||||
)
|
||||
.then((response) => response.text())
|
||||
.then((data) => {
|
||||
return data;
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error("Error:", error);
|
||||
// Throw the error again to ensure it's propagated
|
||||
throw error;
|
||||
});
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
function addCheckboxListeners(cellLock) {
|
||||
// Remove existing event listeners
|
||||
document
|
||||
.querySelectorAll('input[type="checkbox"]')
|
||||
.forEach(function (checkbox) {
|
||||
checkbox.removeEventListener(
|
||||
"change",
|
||||
cellLock.trackCheckboxChanges
|
||||
);
|
||||
});
|
||||
|
||||
// Add new event listeners
|
||||
document
|
||||
.querySelectorAll('input[type="checkbox"]')
|
||||
.forEach(function (checkbox) {
|
||||
checkbox.addEventListener("change", cellLock.trackCheckboxChanges);
|
||||
});
|
||||
}
|
||||
|
||||
// Function for unchecking all checkboxes
|
||||
document
|
||||
.getElementById("uncheckAll")
|
||||
.addEventListener("click", function () {
|
||||
document
|
||||
.querySelectorAll('input[type="checkbox"]')
|
||||
.forEach(function (checkbox) {
|
||||
checkbox.checked = false;
|
||||
});
|
||||
});
|
||||
</script>
|
||||
<script src="/js/dark-mode.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
666
simpleadmin/www/settings.html
Normal file
666
simpleadmin/www/settings.html
Normal file
@@ -0,0 +1,666 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en" data-bs-theme="light">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<title>Simple Admin</title>
|
||||
<link rel="stylesheet" href="/css/styles.css" />
|
||||
<link rel="stylesheet" href="/css/bootstrap.min.css" />
|
||||
|
||||
<!-- Import BootStrap Javascript -->
|
||||
<script src="/js/bootstrap.bundle.min.js"></script>
|
||||
<script src="/js/alpinejs.min.js" defer></script>
|
||||
</head>
|
||||
<body>
|
||||
<main>
|
||||
<div class="container my-4" x-data="simpleSettings()">
|
||||
<nav class="navbar navbar-expand-lg mt-2">
|
||||
<div class="container-fluid">
|
||||
<a class="navbar-brand" href="/"
|
||||
><span class="mb-0 h4">Simple Admin</span></a
|
||||
>
|
||||
<button
|
||||
class="navbar-toggler"
|
||||
type="button"
|
||||
data-bs-toggle="collapse"
|
||||
data-bs-target="#navbarText"
|
||||
aria-controls="navbarText"
|
||||
aria-expanded="false"
|
||||
aria-label="Toggle navigation"
|
||||
>
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
<div class="collapse navbar-collapse" id="navbarText">
|
||||
<ul class="navbar-nav me-auto mb-2 mb-lg-0">
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="/">Home</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="/network.html">Simple Network</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link active" href="/settings.html" aria-current="page">Simple Settings</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="/sms.html">SMS</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="/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>
|
||||
<span class="navbar-text">
|
||||
<button class="btn btn-link" href="logout.html">Log Out</button>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<div class="row mt-5 mb-4">
|
||||
<div class="col">
|
||||
<div class="card">
|
||||
<div class="card-header">AT Terminal</div>
|
||||
<div class="card-body">
|
||||
<div class="card-text">
|
||||
<div class="form-floating mb-4">
|
||||
<!-- At commands output here -->
|
||||
<textarea
|
||||
class="form-control"
|
||||
placeholder="ATI"
|
||||
id="atOutputBox"
|
||||
style="height: 220px"
|
||||
x-text="atCommandResponse"
|
||||
readonly
|
||||
>
|
||||
<label for="floatingTextarea">ATI</label>
|
||||
</textarea>
|
||||
</div>
|
||||
<div>
|
||||
<div class="col-md-4 mb-3">
|
||||
<label for="exampleInputEmail1" class="form-label"
|
||||
>AT Command</label
|
||||
>
|
||||
<input
|
||||
type="text"
|
||||
class="form-control"
|
||||
id="atCommandInput"
|
||||
placeholder="ATI"
|
||||
aria-describedby="atCommandInput"
|
||||
x-model="atcmd"
|
||||
@keydown.enter = "sendATCommand()"
|
||||
/>
|
||||
<div id="atCommandInputHelper" class="form-text">
|
||||
Seperate multiple commands with comma (,).
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="d-grid gap-2 d-md-flex justify-content-md-start"
|
||||
>
|
||||
<button
|
||||
class="btn btn-primary me-md-2"
|
||||
type="button"
|
||||
@click="sendATCommand()"
|
||||
:disabled="isLoading"
|
||||
>
|
||||
Submit
|
||||
</button>
|
||||
<button
|
||||
class="btn btn-danger"
|
||||
type="button"
|
||||
@click="clearResponses()"
|
||||
:disabled="isClean"
|
||||
>
|
||||
Clear
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<div class="card">
|
||||
<div class="card-header">One Click Utilities</div>
|
||||
<div class="card-body">
|
||||
<div class="card-text">
|
||||
<div class="table-responsive">
|
||||
<table class="table">
|
||||
<tbody>
|
||||
<tr>
|
||||
<th scope="row">Reboot</th>
|
||||
<td>
|
||||
<button
|
||||
type="submit"
|
||||
class="btn btn-danger"
|
||||
@click="showRebootModal()"
|
||||
:disabled="isLoading"
|
||||
>
|
||||
Reboot
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">Reset AT Commands Settings</th>
|
||||
<td>
|
||||
<button
|
||||
type="submit"
|
||||
class="btn btn-danger"
|
||||
@click="resetATCommands()"
|
||||
:disabled="isLoading"
|
||||
>
|
||||
Reset
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">ETH IP Passthrough</th>
|
||||
<td>
|
||||
<button
|
||||
type="submit"
|
||||
class="btn btn-primary"
|
||||
@click="ethPassthroughEnable()"
|
||||
x-show="ethPassStatus === false"
|
||||
:disabled="isLoading"
|
||||
>
|
||||
Enable
|
||||
</button>
|
||||
<button
|
||||
type="submit"
|
||||
class="btn btn-danger"
|
||||
@click="ethPassthroughDisable()"
|
||||
x-show="ethPassStatus === true"
|
||||
:disabled="isLoading"
|
||||
>
|
||||
Disable
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">Onboard DNS Proxy</th>
|
||||
<td>
|
||||
<button
|
||||
type="submit"
|
||||
class="btn btn-primary"
|
||||
@click="onBoardDNSProxyEnable()"
|
||||
x-show="DNSProxyStatus === false"
|
||||
:disabled="isLoading"
|
||||
>
|
||||
Enable
|
||||
</button>
|
||||
<button
|
||||
type="submit"
|
||||
class="btn btn-danger"
|
||||
@click="onBoardDNSProxyDisable()"
|
||||
x-show="DNSProxyStatus === true"
|
||||
:disabled="isLoading"
|
||||
>
|
||||
Disable
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">USB Mode</th>
|
||||
<td>
|
||||
<button
|
||||
type="submit"
|
||||
class="btn btn-primary"
|
||||
@click="usbModeEnable()"
|
||||
x-show="USBModeStatus === true"
|
||||
:disabled="isLoading"
|
||||
>
|
||||
Enable
|
||||
</button>
|
||||
<button
|
||||
type="submit"
|
||||
class="btn btn-danger"
|
||||
@click="usbModeDisable()"
|
||||
x-show="USBModeStatus === false"
|
||||
:disabled="isLoading"
|
||||
>
|
||||
Disable
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">Scan Neighbour LTE</th>
|
||||
<td>
|
||||
<button
|
||||
type="submit"
|
||||
class="btn btn-primary"
|
||||
@click="scanLTE()"
|
||||
:disabled="isLoading"
|
||||
>
|
||||
Scan LTE
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">Scan Neighbour NSA</th>
|
||||
<td>
|
||||
<button
|
||||
type="submit"
|
||||
class="btn btn-primary"
|
||||
@click="scanNSA()"
|
||||
:disabled="isLoading"
|
||||
>
|
||||
Scan NSA
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col">
|
||||
<div class="card mb-3">
|
||||
<div class="card-header">TTL and Network Scan Settings</div>
|
||||
<div class="card-body">
|
||||
<label for="TTLState" class="form-label"
|
||||
>TTL State and Value</label
|
||||
>
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<div
|
||||
class="p-3 text-primary-emphasis bg-primary-subtle border border-primary-subtle rounded-3"
|
||||
x-show="ttlStatus === true"
|
||||
>
|
||||
TTL is Active
|
||||
</div>
|
||||
|
||||
<div
|
||||
class="p-3 text-danger-emphasis bg-danger-subtle border border-danger-subtle rounded-3"
|
||||
x-show="ttlStatus === false"
|
||||
>
|
||||
TTL is Inactive
|
||||
</div>
|
||||
</div>
|
||||
<div class="col">
|
||||
<div
|
||||
class="p-3 text-info-emphasis bg-info-subtle border border-info-subtle rounded-3 mb-4"
|
||||
x-text="ttlvalue"
|
||||
></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-text mb-3">
|
||||
<div class="mb-4">
|
||||
<input
|
||||
type="text"
|
||||
class="form-control"
|
||||
id="ttlInput"
|
||||
placeholder="TTL Value"
|
||||
x-model="newTTL"
|
||||
/>
|
||||
<div id="ttlValueHelper" class="form-text">
|
||||
Set TTL Value to 0 to disable.
|
||||
</div>
|
||||
</div>
|
||||
<div class="d-grid gap-2">
|
||||
<button
|
||||
class="btn btn-primary"
|
||||
type="button"
|
||||
@click="setTTL()"
|
||||
>
|
||||
Update
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-text">
|
||||
<!-- Select Input Scan Here -->
|
||||
<div class="mb-3">
|
||||
<label for="networkScan" class="form-label"
|
||||
>Network Scan</label
|
||||
>
|
||||
<select
|
||||
class="form-select"
|
||||
id="networkScan"
|
||||
x-model="fullScanModeType"
|
||||
>
|
||||
<option selected>Choose Scan Mode</option>
|
||||
<option value="LTE">LTE</option>
|
||||
<option value="NR5G">NR5G</option>
|
||||
<option value="ALL">ALL</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="d-grid gap-2">
|
||||
<button
|
||||
class="btn btn-primary"
|
||||
type="button"
|
||||
@click="fullScanMode()"
|
||||
:disabled="isLoading"
|
||||
x-text="scanStart ? 'Scanning... Please wait.' : 'Start Scan'"
|
||||
></button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Loading Modal for Reboot -->
|
||||
<div class="modal-overlay" x-show="showModal">
|
||||
<div class="loading-modal">
|
||||
<div
|
||||
class="loading-text"
|
||||
style="display: flex; flex-direction: column"
|
||||
>
|
||||
<h3>This will reboot the modem.</h3>
|
||||
<p style="margin-top: 0.5rem">Continue?</p>
|
||||
</div>
|
||||
<div class="d-grid gap-2 d-md-block">
|
||||
<button
|
||||
class="btn btn-primary"
|
||||
type="button"
|
||||
@click="rebootDevice()"
|
||||
>
|
||||
Reboot
|
||||
</button>
|
||||
<button
|
||||
class="btn btn-danger"
|
||||
type="button"
|
||||
@click="closeModal()"
|
||||
>
|
||||
Cancel
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Reboot Modal Countdown -->
|
||||
<div class="modal-overlay" x-show="isRebooting">
|
||||
<div class="loading-modal">
|
||||
<div class="loader"></div>
|
||||
<div
|
||||
class="loading-text"
|
||||
style="display: flex; flex-direction: column"
|
||||
>
|
||||
<h3>Rebooting...</h3>
|
||||
<p style="margin-top: 0.5rem">
|
||||
Please wait for
|
||||
<span x-text="countdown" style="font-weight: 500"></span>
|
||||
seconds.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
<script src="/js/dark-mode.js"></script>
|
||||
<script>
|
||||
function simpleSettings() {
|
||||
return {
|
||||
isLoading: false,
|
||||
showSuccess: false,
|
||||
showError: false,
|
||||
isClean: true,
|
||||
showModal: false,
|
||||
isRebooting: false,
|
||||
atcmd: "",
|
||||
fetchATCommand: "",
|
||||
countdown: 0,
|
||||
atCommandResponse: "",
|
||||
currentSettingsResponse: "",
|
||||
ttldata: null,
|
||||
ttlvalue: 0,
|
||||
ttlStatus: false,
|
||||
newTTL: null,
|
||||
ethPassStatus: false,
|
||||
DNSProxyStatus: true,
|
||||
USBModeStatus: true,
|
||||
fullScanModeType: "",
|
||||
scanStart: false,
|
||||
|
||||
closeModal() {
|
||||
this.confirmModal = false;
|
||||
this.showModal = false;
|
||||
},
|
||||
|
||||
showRebootModal() {
|
||||
this.showModal = true;
|
||||
},
|
||||
|
||||
sendATCommand() {
|
||||
if (!this.atcmd) {
|
||||
// Use ATI as default command
|
||||
this.atcmd = "ATI";
|
||||
console.log(
|
||||
"AT Command is empty, using ATI as default command: ",
|
||||
this.atcmd
|
||||
);
|
||||
}
|
||||
|
||||
this.isLoading = true;
|
||||
fetch(
|
||||
"/cgi-bin/get_atcommand?" +
|
||||
new URLSearchParams({
|
||||
atcmd: this.atcmd,
|
||||
})
|
||||
)
|
||||
.then((res) => {
|
||||
return res.text();
|
||||
})
|
||||
.then((data) => {
|
||||
this.atCommandResponse = data;
|
||||
this.isLoading = false;
|
||||
this.isClean = false;
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error("Error: ", error);
|
||||
this.showError = true;
|
||||
});
|
||||
},
|
||||
|
||||
clearResponses() {
|
||||
this.atCommandResponse = "";
|
||||
this.isClean = true;
|
||||
},
|
||||
|
||||
rebootDevice() {
|
||||
this.atcmd = "AT+CFUN=1,1";
|
||||
this.sendATCommand();
|
||||
|
||||
this.atCommandResponse = "";
|
||||
this.showModal = false;
|
||||
this.isRebooting = true;
|
||||
this.countdown = 40;
|
||||
|
||||
// Do the countdown
|
||||
const interval = setInterval(() => {
|
||||
this.countdown--;
|
||||
if (this.countdown === 0) {
|
||||
clearInterval(interval);
|
||||
this.isRebooting = false;
|
||||
this.init();
|
||||
}
|
||||
}, 1000);
|
||||
},
|
||||
|
||||
resetATCommands() {
|
||||
this.atcmd = "AT&F";
|
||||
this.sendATCommand();
|
||||
console.log("Resetting AT Commands");
|
||||
this.atcmd = "";
|
||||
this.atCommandResponse = "";
|
||||
this.showRebootModal();
|
||||
},
|
||||
|
||||
ethPassthroughEnable() {
|
||||
this.atcmd = 'AT+QMAP="MPDN_RULE",0,1,0,1,1,"FF:FF:FF:FF:FF:FF"';
|
||||
this.sendATCommand();
|
||||
this.fetchCurrentSettings();
|
||||
},
|
||||
|
||||
ethPassthroughDisable() {
|
||||
this.atcmd = 'AT+QMAP="MPDN_RULE",0';
|
||||
this.sendATCommand();
|
||||
this.fetchCurrentSettings();
|
||||
},
|
||||
|
||||
onBoardDNSProxyEnable() {
|
||||
this.atcmd = 'AT+QMAP="DHCPV4DNS","enable"';
|
||||
this.sendATCommand();
|
||||
this.fetchCurrentSettings();
|
||||
},
|
||||
|
||||
onBoardDNSProxyDisable() {
|
||||
this.atcmd = 'AT+QMAP="DHCPV4DNS","disable"';
|
||||
this.sendATCommand();
|
||||
this.fetchCurrentSettings();
|
||||
},
|
||||
|
||||
usbModeEnable() {
|
||||
this.atcmd = "AT+QMAPWAC=1";
|
||||
this.sendATCommand();
|
||||
this.fetchCurrentSettings();
|
||||
},
|
||||
|
||||
usbModeDisable() {
|
||||
this.atcmd = "AT+QMAPWAC=0";
|
||||
this.sendATCommand();
|
||||
this.fetchCurrentSettings();
|
||||
},
|
||||
|
||||
scanLTE() {
|
||||
this.atcmd = 'AT+QENG="neighbourcell"';
|
||||
this.sendATCommand();
|
||||
},
|
||||
|
||||
scanNSA() {
|
||||
this.atcmd =
|
||||
'AT+QNWCFG="nr5g_meas_info",1;+QNWCFG="nr5g_meas_info"';
|
||||
this.sendATCommand();
|
||||
},
|
||||
|
||||
fullScanMode() {
|
||||
switch (this.fullScanModeType) {
|
||||
case "LTE":
|
||||
this.atcmd = "AT+QSCAN=1,1";
|
||||
this.scanStart = true;
|
||||
this.atCommandResponse = "Scanning all available LTE networks... This might take a while."
|
||||
this.sendATCommand();
|
||||
this.scanStart = false;
|
||||
break;
|
||||
case "NR5G":
|
||||
this.atcmd = "AT+QSCAN=2,1";
|
||||
this.scanStart = true;
|
||||
this.atCommandResponse = "Scanning all available NR5G-SA networks... This might take a while."
|
||||
this.sendATCommand();
|
||||
this.scanStart = false;
|
||||
break;
|
||||
case "ALL":
|
||||
this.atcmd = "AT+QSCAN=3,1";
|
||||
this.scanStart = true;
|
||||
this.atCommandResponse = "Scanning all available networks... This might take a while."
|
||||
this.sendATCommand();
|
||||
this.scanStart = false;
|
||||
break;
|
||||
default:
|
||||
alert("Select a Scan Mode First");
|
||||
}
|
||||
},
|
||||
|
||||
fetchCurrentSettings() {
|
||||
this.fetchATCommand =
|
||||
'AT+QMAP="MPDN_RULE";+QMAP="DHCPV4DNS";+QMAPWAC?';
|
||||
fetch(
|
||||
"/cgi-bin/get_atcommand?" +
|
||||
new URLSearchParams({
|
||||
atcmd: this.fetchATCommand,
|
||||
})
|
||||
)
|
||||
.then((res) => {
|
||||
return res.text();
|
||||
})
|
||||
.then((data) => {
|
||||
// Set the value of currentSettingsResponse
|
||||
this.currentSettingsResponse = data;
|
||||
const currentData = data.split("\n");
|
||||
|
||||
const testEthpass = currentData[1].match(
|
||||
/\+QMAP: "MPDN_rule",0,0,0,0,0/
|
||||
);
|
||||
|
||||
if (testEthpass) {
|
||||
this.ethPassStatus = false;
|
||||
} else {
|
||||
this.ethPassStatus = true;
|
||||
}
|
||||
|
||||
const testDNSProxy = currentData[6].match(
|
||||
/\+QMAP: "DHCPV4DNS","enable"/
|
||||
);
|
||||
|
||||
if (testDNSProxy) {
|
||||
this.DNSProxyStatus = true;
|
||||
} else {
|
||||
this.DNSProxyStatus = false;
|
||||
}
|
||||
|
||||
const testUSBMode = currentData[8].match(/\+QMAPWAC: 1/);
|
||||
|
||||
if (testUSBMode) {
|
||||
this.USBModeStatus = true;
|
||||
} else {
|
||||
this.USBModeStatus = false;
|
||||
}
|
||||
|
||||
// clear atcmd
|
||||
this.atcmd = "";
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error("Error: ", error);
|
||||
this.showError = true;
|
||||
});
|
||||
},
|
||||
|
||||
fetchTTL() {
|
||||
fetch("/cgi-bin/get_ttl_status")
|
||||
.then((res) => res.json())
|
||||
.then((data) => {
|
||||
this.ttldata = data;
|
||||
this.ttlStatus = this.ttldata.isEnabled;
|
||||
this.ttlvalue = this.ttldata.ttl;
|
||||
});
|
||||
},
|
||||
|
||||
setTTL() {
|
||||
this.isLoading = true; // Set loading state while updating TTL
|
||||
|
||||
fetch(
|
||||
"/cgi-bin/set_ttl?" +
|
||||
new URLSearchParams({
|
||||
ttlvalue: this.newTTL,
|
||||
})
|
||||
)
|
||||
.then((res) => res.json())
|
||||
.then((data) => {
|
||||
// Once TTL is updated, fetch the updated TTL data
|
||||
this.fetchTTL();
|
||||
this.isLoading = false; // Set loading state back to false
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error("Error updating TTL: ", error);
|
||||
this.isLoading = false; // Ensure loading state is properly handled in case of error
|
||||
});
|
||||
},
|
||||
|
||||
init() {
|
||||
this.fetchTTL();
|
||||
this.fetchCurrentSettings();
|
||||
},
|
||||
};
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,158 +1,294 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<html lang="en" data-bs-theme="light">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<!-- change to a much simpler tab title -->
|
||||
<title>Simple Admin</title>
|
||||
<!-- <link
|
||||
href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css"
|
||||
rel="stylesheet"
|
||||
integrity="sha384-QWTKZyjpPEjISv5WaRU9OFeRpok6YctnYmDr5pNlyT2bRjXh0JMhjY6hW+ALEwIH"
|
||||
crossorigin="anonymous"
|
||||
/> -->
|
||||
<!-- Import all the bootstrap css files from css folder -->
|
||||
<link rel="stylesheet" href="/css/styles.css" />
|
||||
<link rel="stylesheet" href="/css/bootstrap.min.css" />
|
||||
|
||||
<!-- Import BootStrap Javascript -->
|
||||
<script src="/js/bootstrap.bundle.min.js"></script>
|
||||
<script src="/js/alpinejs.min.js" defer></script>
|
||||
<link rel="stylesheet" href="/css/bulma.css" />
|
||||
<link rel="stylesheet" type="text/css" href="/css/admin.css" />
|
||||
<script src="/js/auth.js"></script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<!-- START NAV -->
|
||||
<nav class="navbar is-black" x-data="{ isOpen: false }">
|
||||
<div class="container">
|
||||
<div class="navbar-brand">
|
||||
<a class="navbar-item brand-text" href="/"> Simple Admin </a>
|
||||
<a
|
||||
role="button"
|
||||
class="navbar-burger burger"
|
||||
@click="isOpen = !isOpen"
|
||||
>
|
||||
<span aria-hidden="true"></span>
|
||||
<span aria-hidden="true"></span>
|
||||
<span aria-hidden="true"></span>
|
||||
</a>
|
||||
</div>
|
||||
<div
|
||||
id="navMenu"
|
||||
class="navbar-menu"
|
||||
:class="isOpen ? 'is-active' : ''"
|
||||
>
|
||||
<div class="navbar-start">
|
||||
<a class="navbar-item" href="/"> Connection Info </a>
|
||||
<a class="navbar-item" href="/atcommander.html"> AT Commands </a>
|
||||
<a class="navbar-item" href="/sms.html"> SMS </a>
|
||||
<a class="navbar-item" href="/ttl.html"> TTL Changer </a>
|
||||
<body onload="isAuthenticated()">
|
||||
<main>
|
||||
<div class="container my-4" x-data="fetchSMS()">
|
||||
<nav class="navbar navbar-expand-lg mt-2">
|
||||
<div class="container-fluid">
|
||||
<a class="navbar-brand" href="/"
|
||||
><span class="mb-0 h4">Simple Admin</span></a
|
||||
>
|
||||
<button
|
||||
class="navbar-toggler"
|
||||
type="button"
|
||||
data-bs-toggle="collapse"
|
||||
data-bs-target="#navbarText"
|
||||
aria-controls="navbarText"
|
||||
aria-expanded="false"
|
||||
aria-label="Toggle navigation"
|
||||
>
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
<div class="collapse navbar-collapse" id="navbarText">
|
||||
<ul class="navbar-nav me-auto mb-2 ml-4 mb-lg-0">
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="/">Home</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="/network.html">Simple Network</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="/settings.html">Simple Settings</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link active" href="/sms.html" aria-current="page">SMS</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="/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>
|
||||
<span class="navbar-text">
|
||||
<button class="btn btn-link" href="logout.html">Log Out</button>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
<!-- END NAV -->
|
||||
<div class="container" x-data="atCommands()">
|
||||
<div class="columns">
|
||||
<div class="column is-12">
|
||||
<div class="columns">
|
||||
<div class="column is-8">
|
||||
<div class="card">
|
||||
<header class="card-header">
|
||||
<p class="card-header-title">SMS Viewer</p>
|
||||
<div class="field">
|
||||
<p class="control">
|
||||
</nav>
|
||||
|
||||
<div class="row mt-5 mb-4">
|
||||
<div class="col">
|
||||
<div class="card">
|
||||
<div class="card-header">SMS Manager</div>
|
||||
<div class="card-body">
|
||||
<div class="card-text">
|
||||
<div class="col">
|
||||
<div
|
||||
style="
|
||||
max-height: 400px;
|
||||
overflow-y: scroll;
|
||||
overflow-x: hidden;
|
||||
"
|
||||
>
|
||||
<table class="table table-hover border-success">
|
||||
<tbody>
|
||||
<div class="card-subtitle" x-show="isLoading">
|
||||
<h4>Fetching SMS...</h4>
|
||||
</div>
|
||||
<!-- Only show template if isLoading is False -->
|
||||
<template x-if="messages.length === 0 && isLoading === false" >
|
||||
<div>
|
||||
<p>Message Empty</p>
|
||||
</div>
|
||||
</template>
|
||||
<template
|
||||
x-for="(message, index) in messages"
|
||||
:key="index"
|
||||
>
|
||||
<tr class="">
|
||||
<td>
|
||||
<div class="row column-gap-1 mb-2">
|
||||
<div class="col-md-3">
|
||||
<p x-text="'Sender: ' + senders[index]"></p>
|
||||
</div>
|
||||
<div class="col">
|
||||
<p
|
||||
x-text="'Date and Time: ' + dates[index]"
|
||||
></p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-9">
|
||||
<p x-text="message"></p>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</template>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<form>
|
||||
<div class="col-md-4 my-4">
|
||||
<label for="PhoneNumber" class="form-label"
|
||||
>Send SMS</label
|
||||
>
|
||||
<input
|
||||
type="text"
|
||||
class="form-control"
|
||||
placeholder="Phone Number"
|
||||
aria-label="Phone Number"
|
||||
x-model="phoneNumber"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="col-md-8 mb-3">
|
||||
<!-- Text Area Here for SMS Input -->
|
||||
<textarea
|
||||
class="form-control"
|
||||
id="smsInputBox"
|
||||
rows="5"
|
||||
placeholder="Enter SMS here (!!!CURRENTLY UNDER DEVELOPMENT!!!)"
|
||||
x-model="messageToSend"
|
||||
></textarea>
|
||||
</div>
|
||||
<div
|
||||
class="d-grid gap-2 d-md-flex justify-content-md-start"
|
||||
>
|
||||
<button class="btn btn-primary me-md-2" type="button" @click="sendSMS()" :disabled="true" >
|
||||
Send SMS
|
||||
</button>
|
||||
<button
|
||||
class="button is-success"
|
||||
@click="sendAtCommand()"
|
||||
:disabled="isLoading"
|
||||
class="btn btn-success"
|
||||
type="button"
|
||||
@click="init()"
|
||||
>
|
||||
Refresh
|
||||
</button>
|
||||
</p>
|
||||
</div>
|
||||
<div class="field">
|
||||
<p class="control">
|
||||
<button
|
||||
class="button is-danger"
|
||||
@click="sendAtCommand()"
|
||||
:disabled="isLoading"
|
||||
class="btn btn-danger"
|
||||
type="button"
|
||||
@click="deleteAllSMS()"
|
||||
>
|
||||
Delete
|
||||
Delete All SMS
|
||||
</button>
|
||||
</p>
|
||||
</div>
|
||||
</header>
|
||||
<div class="card-content">
|
||||
<div class="content">
|
||||
<textarea
|
||||
class="textarea"
|
||||
placeholder="SMS Viewer (Make sure to run: AT+CMGF=1 first)"
|
||||
readonly
|
||||
rows="10"
|
||||
cols="50"
|
||||
x-model="atCommandResponse"
|
||||
:disabled="isLoading"
|
||||
></textarea>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</main>
|
||||
<script src="/js/dark-mode.js"></script>
|
||||
<script>
|
||||
function atCommands() {
|
||||
function fetchSMS() {
|
||||
return {
|
||||
isLoading: false,
|
||||
atcmd: 'AT+CMGL="ALL"',
|
||||
atCommandResponse: null,
|
||||
sendAtCommand() {
|
||||
this.isLoading = true; // Set loading state to true before fetching data
|
||||
atCommandResponse: "",
|
||||
messageToSend: "",
|
||||
phoneNumber: "",
|
||||
messages: [],
|
||||
senders: [],
|
||||
dates: [],
|
||||
requestSMS() {
|
||||
this.isLoading = true;
|
||||
this.atCommandResponse = "Loading...";
|
||||
// Expect a text response from the server
|
||||
fetch("/cgi-bin/get_sms")
|
||||
.then((response) => response.text())
|
||||
.then((data) => {
|
||||
this.isLoading = false;
|
||||
this.atCommandResponse = data;
|
||||
})
|
||||
.finally(() => {
|
||||
this.parseSMSData(this.atCommandResponse);
|
||||
});
|
||||
},
|
||||
|
||||
parseSMSData(data) {
|
||||
const cmglRegex =
|
||||
/^\s*\+CMGL:\s*(\d+),"[^"]*","([^"]*)"[^"]*,"([^"]*)"/gm;
|
||||
|
||||
let match;
|
||||
while ((match = cmglRegex.exec(data)) !== null) {
|
||||
const index = parseInt(match[1]);
|
||||
const sender = match[2];
|
||||
let date = match[3];
|
||||
|
||||
// remove +32 from the date
|
||||
date = date.replace("+32", "");
|
||||
|
||||
// Find the start and end positions of the message
|
||||
const startIndex = cmglRegex.lastIndex;
|
||||
let endIndex = data.indexOf("+CMGL:", startIndex + 1);
|
||||
if (endIndex === -1) {
|
||||
// If no more +CMGL lines, set end index to end of string
|
||||
endIndex = data.length;
|
||||
}
|
||||
|
||||
// Extract the message from start to end index
|
||||
const message = data.substring(startIndex, endIndex).trim();
|
||||
|
||||
this.messages.push(message);
|
||||
this.senders.push(sender);
|
||||
this.dates.push(date);
|
||||
}
|
||||
},
|
||||
|
||||
deleteAllSMS() {
|
||||
const atcmd = "AT+CMGD=,4";
|
||||
fetch(
|
||||
"/cgi-bin/get_atcommand?" +
|
||||
new URLSearchParams({
|
||||
atcmd: this.atcmd,
|
||||
atcmd: atcmd,
|
||||
})
|
||||
)
|
||||
.then((res) => {
|
||||
return res.text();
|
||||
})
|
||||
.then((response) => response.text())
|
||||
.then((data) => {
|
||||
this.atCommandResponse = data;
|
||||
// Split the response into individual messages
|
||||
const messages = data.trim().split("\n\n");
|
||||
|
||||
// Parse each message and construct an array of objects
|
||||
const parsedMessages = messages.map((message) => {
|
||||
const lines = message.split("\n");
|
||||
const sender = decodeHexString(
|
||||
lines[1].split(",")[2].slice(1, -1)
|
||||
);
|
||||
const time = lines[2].split(',"')[1];
|
||||
const messageText = decodeHexString(lines[3]);
|
||||
return {
|
||||
"Người gửi": sender,
|
||||
"Thời gian": time,
|
||||
"Tin nhắn": messageText,
|
||||
};
|
||||
});
|
||||
|
||||
// Log the parsed messages array as JSON to the console
|
||||
console.log(JSON.stringify(parsedMessages, null, 2));
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error("Không thể tìm thấy dữ liệu:", error);
|
||||
console.log(data);
|
||||
})
|
||||
.finally(() => {
|
||||
this.isLoading = false; // Set loading state to false after fetching data
|
||||
this.requestSMS();
|
||||
});
|
||||
},
|
||||
|
||||
sendSMS() {
|
||||
this.isLoading = true;
|
||||
fetch(
|
||||
"/cgi-bin/send_sms?" +
|
||||
new URLSearchParams({
|
||||
phone_number: this.phoneNumber,
|
||||
message: this.messageToSend,
|
||||
})
|
||||
)
|
||||
.then((response) => response.text())
|
||||
.then((data) => {
|
||||
console.log(data);
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error("Error:", error);
|
||||
})
|
||||
.finally(() => {
|
||||
this.isLoading = false;
|
||||
this.requestSMS();
|
||||
});
|
||||
},
|
||||
|
||||
init() {
|
||||
// Send AT+CMGF=1 once to set the modem to text mode
|
||||
const atcmd = "AT+CMGF=1";
|
||||
fetch(
|
||||
"/cgi-bin/get_atcommand?" +
|
||||
new URLSearchParams({
|
||||
atcmd: atcmd,
|
||||
})
|
||||
)
|
||||
.then((response) => response.text())
|
||||
.then((data) => {
|
||||
console.log(data);
|
||||
})
|
||||
.finally(() => {
|
||||
this.requestSMS();
|
||||
});
|
||||
},
|
||||
};
|
||||
}
|
||||
// Hàm giải mã chuỗi hex sang văn bản
|
||||
function decodeHexString(hexString) {
|
||||
let decodedString = "";
|
||||
for (let i = 0; i < hexString.length; i += 4) {
|
||||
let hex = hexString.substr(i, 4);
|
||||
let intValue = parseInt(hex, 16);
|
||||
decodedString += String.fromCharCode(intValue);
|
||||
}
|
||||
return decodedString;
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -1,128 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>RM5xxx TTL Changer</title>
|
||||
|
||||
<script src="/js/alpinejs.min.js" defer></script>
|
||||
<link rel="stylesheet" href="/css/bulma.css">
|
||||
<link rel="stylesheet" type="text/css" href="/css/admin.css">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<!-- START NAV -->
|
||||
<nav class="navbar is-black" x-data="{ isOpen: false }">
|
||||
<div class="container">
|
||||
<div class="navbar-brand">
|
||||
<a class="navbar-item brand-text" href="/">
|
||||
Simple Admin
|
||||
</a>
|
||||
<a role="button" class="navbar-burger burger" @click="isOpen = !isOpen">
|
||||
<span aria-hidden="true"></span>
|
||||
<span aria-hidden="true"></span>
|
||||
<span aria-hidden="true"></span>
|
||||
</a>
|
||||
</div>
|
||||
<div id="navMenu" class="navbar-menu" :class="isOpen ? 'is-active' : ''">
|
||||
<div class="navbar-start">
|
||||
<a class="navbar-item" href="/"> Connection Info </a>
|
||||
<a class="navbar-item" href="/atcommander.html"> AT Commands </a>
|
||||
<a class="navbar-item" href="/sms.html"> SMS </a>
|
||||
<a class="navbar-item" href="/ttl.html"> TTL Changer </a>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
<!-- END NAV -->
|
||||
<div class="container" x-data="ttlCommands()" x-init="init">
|
||||
<div class="columns">
|
||||
<div class="column is-12">
|
||||
<div class="columns">
|
||||
<div class="column is-8">
|
||||
<div class="card">
|
||||
<header class="card-header">
|
||||
<p class="card-header-title">
|
||||
TTL Enabler
|
||||
</p>
|
||||
</header>
|
||||
<div class="card-content">
|
||||
<div class="content">
|
||||
<p>
|
||||
<h2>TTL Status</h2> <br>
|
||||
TTL is <span class="tag is-large" :class="ttldata.isEnabled ? 'is-success' : 'is-danger'" x-text="ttldata.isEnabled == true ? 'ON' : 'OFF'"></span>
|
||||
<br />
|
||||
TTL Set to <span x-text="ttldata.ttl"></span>
|
||||
</p>
|
||||
<div class="field">
|
||||
<label class="label">Set TTL</label>
|
||||
<div class="control">
|
||||
<input class="input" type="number" placeholder="64"
|
||||
x-model="newTTL">
|
||||
</div>
|
||||
</div>
|
||||
<div class="field">
|
||||
<div class="control">
|
||||
<button class="button is-link" @click="setTTL()">Set TTL</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="column is-4">
|
||||
<div class="card">
|
||||
<header class="card-header">
|
||||
<p class="card-header-title">
|
||||
Common TTL For Providers
|
||||
</p>
|
||||
</header>
|
||||
<div class="card-content">
|
||||
<div class="content">
|
||||
<ul>
|
||||
<li>Magenta: 65</li>
|
||||
<li>Red: 88</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<script>
|
||||
|
||||
function ttlCommands() {
|
||||
return {
|
||||
isLoading: false,
|
||||
ttldata: null,
|
||||
newTTL: 0,
|
||||
init() {
|
||||
fetch('/cgi-bin/get_ttl_status')
|
||||
.then((res) => res.json())
|
||||
.then((data) => {
|
||||
this.ttldata = data
|
||||
});
|
||||
},
|
||||
setTTL() {
|
||||
fetch('/cgi-bin/set_ttl?' + new URLSearchParams({
|
||||
ttlvalue: this.newTTL,
|
||||
}))
|
||||
.then((res) => res.json())
|
||||
.then((data) => {
|
||||
this.ttldata = data
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
1
simplefirewall/.rev
Normal file
1
simplefirewall/.rev
Normal file
@@ -0,0 +1 @@
|
||||
2
|
||||
@@ -1,7 +1,7 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Define the ports you want to block
|
||||
PORTS=("80" "8080" "8088" "443") # Default ports, will be modified by the install script
|
||||
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
|
||||
|
||||
1
simpleupdates/.rev
Normal file
1
simpleupdates/.rev
Normal file
@@ -0,0 +1 @@
|
||||
2
|
||||
202
simpleupdates/scripts/update_simpleadmin.sh
Normal file
202
simpleupdates/scripts/update_simpleadmin.sh
Normal file
@@ -0,0 +1,202 @@
|
||||
#!/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"
|
||||
|
||||
# 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 /
|
||||
}
|
||||
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_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 /
|
||||
}
|
||||
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 -rf /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 -O "$SIMPLE_ADMIN_DIR/lighttpd.conf" https://raw.githubusercontent.com/$GITUSER/quectel-rgmii-toolkit/$GITTREE/simpleadmin/lighttpd.conf
|
||||
wget -O "/lib/systemd/system/lighttpd.service" https://raw.githubusercontent.com/$GITUSER/quectel-rgmii-toolkit/$GITTREE/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/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 https://raw.githubusercontent.com/$GITUSER/quectel-rgmii-toolkit/$GITTREE/simpleadmin/systemd/lighttpd.service
|
||||
sleep 1
|
||||
cd $SIMPLE_ADMIN_DIR/www
|
||||
wget https://raw.githubusercontent.com/$GITUSER/quectel-rgmii-toolkit/$GITTREE/simpleadmin/www/deviceinfo.html
|
||||
wget https://raw.githubusercontent.com/$GITUSER/quectel-rgmii-toolkit/$GITTREE/simpleadmin/www/index.html
|
||||
wget https://raw.githubusercontent.com/$GITUSER/quectel-rgmii-toolkit/$GITTREE/simpleadmin/www/network.html
|
||||
wget https://raw.githubusercontent.com/$GITUSER/quectel-rgmii-toolkit/$GITTREE/simpleadmin/www/settings.html
|
||||
wget https://raw.githubusercontent.com/$GITUSER/quectel-rgmii-toolkit/$GITTREE/simpleadmin/www/sms.html
|
||||
wget https://raw.githubusercontent.com/$GITUSER/quectel-rgmii-toolkit/$GITTREE/simpleadmin/www/logout.html
|
||||
sleep 1
|
||||
cd $SIMPLE_ADMIN_DIR/www/js
|
||||
wget https://raw.githubusercontent.com/$GITUSER/quectel-rgmii-toolkit/$GITTREE/simpleadmin/www/js/alpinejs.min.js
|
||||
wget https://raw.githubusercontent.com/$GITUSER/quectel-rgmii-toolkit/$GITTREE/simpleadmin/www/js/bootstrap.bundle.min.js
|
||||
wget https://raw.githubusercontent.com/$GITUSER/quectel-rgmii-toolkit/$GITTREE/simpleadmin/www/js/dark-mode.js
|
||||
wget https://raw.githubusercontent.com/$GITUSER/quectel-rgmii-toolkit/$GITTREE/simpleadmin/www/js/generate-freq-box.js
|
||||
wget https://raw.githubusercontent.com/$GITUSER/quectel-rgmii-toolkit/$GITTREE/simpleadmin/www/js/parse-settings.js
|
||||
wget https://raw.githubusercontent.com/$GITUSER/quectel-rgmii-toolkit/$GITTREE/simpleadmin/www/js/populate-checkbox.js
|
||||
sleep 1
|
||||
cd $SIMPLE_ADMIN_DIR/www/css
|
||||
wget https://raw.githubusercontent.com/$GITUSER/quectel-rgmii-toolkit/$GITTREE/simpleadmin/www/css/bootstrap.min.css
|
||||
wget https://raw.githubusercontent.com/$GITUSER/quectel-rgmii-toolkit/$GITTREE/simpleadmin/www/css/styles.css
|
||||
sleep 1
|
||||
cd $SIMPLE_ADMIN_DIR/www/cgi-bin
|
||||
wget https://raw.githubusercontent.com/$GITUSER/quectel-rgmii-toolkit/$GITTREE/simpleadmin/www/cgi-bin/get_atcommand
|
||||
wget https://raw.githubusercontent.com/$GITUSER/quectel-rgmii-toolkit/$GITTREE/simpleadmin/www/cgi-bin/get_ping
|
||||
wget https://raw.githubusercontent.com/$GITUSER/quectel-rgmii-toolkit/$GITTREE/simpleadmin/www/cgi-bin/get_sms
|
||||
wget https://raw.githubusercontent.com/$GITUSER/quectel-rgmii-toolkit/$GITTREE/simpleadmin/www/cgi-bin/get_ttl_status
|
||||
wget https://raw.githubusercontent.com/$GITUSER/quectel-rgmii-toolkit/$GITTREE/simpleadmin/www/cgi-bin/set_ttl
|
||||
wget https://raw.githubusercontent.com/$GITUSER/quectel-rgmii-toolkit/$GITTREE/simpleadmin/www/cgi-bin/send_sms
|
||||
sleep 1
|
||||
cd /
|
||||
chmod +x $SIMPLE_ADMIN_DIR/www/cgi-bin/*
|
||||
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
|
||||
wget -O ttyd https://github.com/tsl0922/ttyd/releases/download/1.7.7/ttyd.armhf && chmod +x ttyd
|
||||
wget -O $SIMPLE_ADMIN_DIR/console/ttyd.bash "https://raw.githubusercontent.com/$GITUSER/quectel-rgmii-toolkit/$GITTREE/simpleadmin/console/ttyd.bash" && chmod +x console/ttyd.bash
|
||||
wget -O $SIMPLE_ADMIN_DIR/systemd/ttyd.service "https://raw.githubusercontent.com/$GITUSER/quectel-rgmii-toolkit/$GITTREE/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
|
||||
106
simpleupdates/scripts/update_simplefirewall.sh
Normal file
106
simpleupdates/scripts/update_simplefirewall.sh
Normal file
@@ -0,0 +1,106 @@
|
||||
#!/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 -O "$SIMPLE_FIREWALL_DIR/simplefirewall.sh" https://raw.githubusercontent.com/$GITUSER/quectel-rgmii-toolkit/$GITTREE/simplefirewall/simplefirewall.sh
|
||||
wget -O "$SIMPLE_FIREWALL_DIR/ttl-override" https://raw.githubusercontent.com/$GITUSER/quectel-rgmii-toolkit/$GITTREE/simplefirewall/ttl-override
|
||||
wget -O "$SIMPLE_FIREWALL_DIR/ttlvalue" https://raw.githubusercontent.com/$GITUSER/quectel-rgmii-toolkit/$GITTREE/simplefirewall/ttlvalue
|
||||
chmod 666 $SIMPLE_FIREWALL_DIR/ttlvalue
|
||||
chmod +x "$SIMPLE_FIREWALL_DIR/simplefirewall.sh"
|
||||
chmod +x "$SIMPLE_FIREWALL_DIR/ttl-override"
|
||||
wget -O "$SIMPLE_FIREWALL_SYSTEMD_DIR/simplefirewall.service" https://raw.githubusercontent.com/$GITUSER/quectel-rgmii-toolkit/$GITTREE/simplefirewall/systemd/simplefirewall.service
|
||||
wget -O "$SIMPLE_FIREWALL_SYSTEMD_DIR/ttl-override.service" https://raw.githubusercontent.com/$GITUSER/quectel-rgmii-toolkit/$GITTREE/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
|
||||
46
simpleupdates/scripts/update_simpleupdates.sh
Normal file
46
simpleupdates/scripts/update_simpleupdates.sh
Normal file
@@ -0,0 +1,46 @@
|
||||
#!/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
|
||||
147
simpleupdates/scripts/update_socat-at-bridge.sh
Normal file
147
simpleupdates/scripts/update_socat-at-bridge.sh
Normal file
@@ -0,0 +1,147 @@
|
||||
#!/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 https://raw.githubusercontent.com/$GITUSER/quectel-rgmii-toolkit/$GITTREE/socat-at-bridge/socat-armel-static
|
||||
wget https://raw.githubusercontent.com/$GITUSER/quectel-rgmii-toolkit/$GITTREE/socat-at-bridge/killsmd7bridge
|
||||
wget https://raw.githubusercontent.com/$GITUSER/quectel-rgmii-toolkit/$GITTREE/socat-at-bridge/atcmd
|
||||
cd $SOCAT_AT_SYSD_DIR
|
||||
wget https://raw.githubusercontent.com/$GITUSER/quectel-rgmii-toolkit/$GITTREE/socat-at-bridge/systemd_units/socat-smd11.service
|
||||
wget https://raw.githubusercontent.com/$GITUSER/quectel-rgmii-toolkit/$GITTREE/socat-at-bridge/systemd_units/socat-smd11-from-ttyIN.service
|
||||
wget https://raw.githubusercontent.com/$GITUSER/quectel-rgmii-toolkit/$GITTREE/socat-at-bridge/systemd_units/socat-smd11-to-ttyIN.service
|
||||
wget https://raw.githubusercontent.com/$GITUSER/quectel-rgmii-toolkit/$GITTREE/socat-at-bridge/systemd_units/socat-killsmd7bridge.service
|
||||
wget https://raw.githubusercontent.com/$GITUSER/quectel-rgmii-toolkit/$GITTREE/socat-at-bridge/systemd_units/socat-smd7-from-ttyIN2.service
|
||||
wget https://raw.githubusercontent.com/$GITUSER/quectel-rgmii-toolkit/$GITTREE/socat-at-bridge/systemd_units/socat-smd7-to-ttyIN2.service
|
||||
wget https://raw.githubusercontent.com/$GITUSER/quectel-rgmii-toolkit/$GITTREE/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
|
||||
|
||||
# Link new command for AT Commands from the shell
|
||||
ln -sf $SOCAT_AT_DIR/atcmd /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
|
||||
73
simpleupdates/scripts/update_sshd.sh
Normal file
73
simpleupdates/scripts/update_sshd.sh
Normal file
@@ -0,0 +1,73 @@
|
||||
#!/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 -O /lib/systemd/system/sshd.service "https://raw.githubusercontent.com/$GITUSER/quectel-rgmii-toolkit/$GITTREE/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
|
||||
87
simpleupdates/scripts/update_tailscale.sh
Normal file
87
simpleupdates/scripts/update_tailscale.sh
Normal file
@@ -0,0 +1,87 @@
|
||||
#!/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"
|
||||
|
||||
# Tmp Script dependent constants
|
||||
TAILSCALE_DIR="/usrdata/tailscale/"
|
||||
TAILSCALE_SYSD_DIR="/usrdata/tailscale/systemd"
|
||||
|
||||
# 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"
|
||||
TAILSCALE_DIR="/usrdata/tailscale/"
|
||||
TAILSCALE_SYSD_DIR="/usrdata/tailscale/systemd"
|
||||
|
||||
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
|
||||
wget https://pkgs.tailscale.com/stable/tailscale_1.64.0_arm.tgz
|
||||
tar -xzf tailscale_1.64.0_arm.tgz
|
||||
cd tailscale_1.64.0_arm
|
||||
mv tailscale tailscaled "$TAILSCALE_DIR/"
|
||||
rm -rf /usrdata/tailscale_1.64.0_arm
|
||||
echo "Downloading systemd files..."
|
||||
cd "$TAILSCALE_SYSD_DIR"
|
||||
wget https://raw.githubusercontent.com/$GITUSER/quectel-rgmii-toolkit/main/tailscale/systemd/tailscaled.service
|
||||
wget https://raw.githubusercontent.com/$GITUSER/quectel-rgmii-toolkit/main/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
|
||||
12
simpleupdates/simpleadmin.conf
Normal file
12
simpleupdates/simpleadmin.conf
Normal file
@@ -0,0 +1,12 @@
|
||||
# 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=
|
||||
255
simpleupdates/simpleupdate
Normal file
255
simpleupdates/simpleupdate
Normal file
@@ -0,0 +1,255 @@
|
||||
#!/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
|
||||
10
simpleupdates/systemd/simpleupdated.service
Normal file
10
simpleupdates/systemd/simpleupdated.service
Normal file
@@ -0,0 +1,10 @@
|
||||
[Unit]
|
||||
Description=Simple Update Daemon
|
||||
After=network.target
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
ExecStart=/usrdata/simpleupdates/simpleupdate d
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
1
socat-at-bridge/.rev
Normal file
1
socat-at-bridge/.rev
Normal file
@@ -0,0 +1 @@
|
||||
2
|
||||
@@ -10,24 +10,15 @@ setup_device() {
|
||||
-echoctl -echoke noflsh -ixon -crtscts
|
||||
}
|
||||
|
||||
# Prepare the device for communication
|
||||
setup_device
|
||||
|
||||
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
|
||||
|
||||
# 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
|
||||
echo -e "$user_input\r" > $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)
|
||||
@@ -52,4 +43,27 @@ while true; do
|
||||
|
||||
# Clean up
|
||||
rm "$tmpfile"
|
||||
done
|
||||
}
|
||||
|
||||
# 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
|
||||
|
||||
@@ -3,7 +3,7 @@ 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 pty,link=/dev/ttyOUT,raw,echo=1
|
||||
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
|
||||
|
||||
@@ -3,7 +3,7 @@ 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 pty,link=/dev/ttyOUT2,raw,echo=1
|
||||
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
|
||||
|
||||
17
sshd/sshd.service
Normal file
17
sshd/sshd.service
Normal file
@@ -0,0 +1,17 @@
|
||||
[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
tailscale/.rev
Normal file
1
tailscale/.rev
Normal file
@@ -0,0 +1 @@
|
||||
2
|
||||
Binary file not shown.
Binary file not shown.
@@ -1,101 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
# Configuration
|
||||
DEVICE_FILE="/dev/smd7"
|
||||
ICCID_FILE="/path/to/iccid_master_file" # Path to the ICCID-APN-IPType master file
|
||||
TMP_DIR="/tmp"
|
||||
TIMEOUT=4
|
||||
|
||||
# Start listening to device file
|
||||
start_listening() {
|
||||
cat "$DEVICE_FILE" > "$TMP_DIR/device_readout" &
|
||||
CAT_PID=$!
|
||||
}
|
||||
|
||||
# Send AT command
|
||||
send_at_command() {
|
||||
local command=$1
|
||||
echo -e "${command}\r" > "$DEVICE_FILE"
|
||||
}
|
||||
|
||||
# Wait for and process response
|
||||
wait_for_response() {
|
||||
local start_time=$(date +%s)
|
||||
local current_time
|
||||
local elapsed_time
|
||||
|
||||
while true; do
|
||||
if grep -q "OK" "$TMP_DIR/device_readout" || grep -q "ERROR" "$TMP_DIR/device_readout"; then
|
||||
RESPONSE=$(cat "$TMP_DIR/device_readout")
|
||||
echo "Response received: $RESPONSE"
|
||||
return 0
|
||||
fi
|
||||
current_time=$(date +%s)
|
||||
elapsed_time=$((current_time - start_time))
|
||||
if [ "$elapsed_time" -ge "$TIMEOUT" ]; then
|
||||
echo "Error: Response timed out."
|
||||
return 1
|
||||
fi
|
||||
sleep 1
|
||||
done
|
||||
}
|
||||
|
||||
# Cleanup function
|
||||
cleanup() {
|
||||
kill "$CAT_PID"
|
||||
wait "$CAT_PID" 2>/dev/null
|
||||
rm -f "$TMP_DIR/device_readout"
|
||||
}
|
||||
|
||||
# Function to send AT command and wait for response
|
||||
send_and_wait() {
|
||||
send_at_command "$1"
|
||||
wait_for_response
|
||||
}
|
||||
|
||||
# Function to update the APN
|
||||
update_apn() {
|
||||
local slot=$1
|
||||
local apn=$2
|
||||
local iptype=$3
|
||||
send_and_wait "AT+CGDCONT=$slot,\"$iptype\",\"$apn\""
|
||||
if [ $? -eq 0 ]; then
|
||||
echo "APN updated successfully."
|
||||
else
|
||||
echo "Failed to update APN."
|
||||
fi
|
||||
}
|
||||
|
||||
# Main Execution
|
||||
if [ -c "$DEVICE_FILE" ]; then
|
||||
start_listening
|
||||
|
||||
# Get ICCID
|
||||
send_and_wait "AT+CCID"
|
||||
ICCID=$(echo "$RESPONSE" | grep "+CCID" | cut -d ':' -f2 | tr -d '[:space:]')
|
||||
echo "ICCID: $ICCID"
|
||||
|
||||
# Check ICCID in master file
|
||||
if grep -q "$ICCID" "$ICCID_FILE"; then
|
||||
APN=$(grep "$ICCID" "$ICCID_FILE" | cut -d ',' -f2)
|
||||
IP_TYPE=$(grep "$ICCID" "$ICCID_FILE" | cut -d ',' -f3)
|
||||
IP_TYPE=${IP_TYPE:-"IPV4V6"} # Default to IPV4V6 if not specified
|
||||
|
||||
# Get current APN settings
|
||||
send_and_wait "AT+CGDCONT?"
|
||||
CURRENT_APN=$(echo "$RESPONSE" | grep "+CGDCONT: 1" | cut -d ',' -f3 | tr -d '"')
|
||||
|
||||
# Compare and update APN if necessary
|
||||
if [ "$APN" != "$CURRENT_APN" ]; then
|
||||
update_apn 1 "$APN" "$IP_TYPE"
|
||||
else
|
||||
echo "No APN update needed."
|
||||
fi
|
||||
else
|
||||
echo "ICCID not found in the master file."
|
||||
fi
|
||||
|
||||
cleanup
|
||||
else
|
||||
echo "Error: Device $DEVICE_FILE does not exist or is not a character special file."
|
||||
fi
|
||||
@@ -1,21 +0,0 @@
|
||||
edit_iccid_file() {
|
||||
local iccid_file="/path/to/iccid_master_file" # Path to the ICCID-APN-IPType master file
|
||||
|
||||
echo "Enter ICCID to add or edit:"
|
||||
read iccid
|
||||
echo "Enter APN for $iccid:"
|
||||
read apn
|
||||
echo "Enter IP Type (IPV4, IPV6, IPV4V6) for $iccid [Default: IPV4V6]:"
|
||||
read iptype
|
||||
iptype=${iptype:-"IPV4V6"} # Default to IPV4V6 if not specified
|
||||
|
||||
# Check if ICCID already exists
|
||||
if grep -q "$iccid" "$iccid_file"; then
|
||||
# Update existing ICCID's APN and IP Type
|
||||
sed -i "/$iccid/c\\$iccid,$apn,$iptype" "$iccid_file"
|
||||
else
|
||||
# Add new ICCID, APN, and IP Type
|
||||
echo "$iccid,$apn,$iptype" >> "$iccid_file"
|
||||
fi
|
||||
echo "ICCID file updated."
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
[Unit]
|
||||
Description=TTYD Service
|
||||
After=network.target
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
ExecStartPre=/bin/sleep 5
|
||||
ExecStart=/usrdata/ttyd/ttyd -p 443 -t 'theme={"foreground":"white","background":"black"}' -t fontSize=25 --writable /usrdata/ttyd/scripts/ttyd.bash
|
||||
Restart=on-failure
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
Reference in New Issue
Block a user