ready for PR

This commit is contained in:
Russel Yasol
2024-10-02 19:22:00 +08:00
parent 39907e983a
commit b70ada6b9c
227 changed files with 102724 additions and 11540 deletions

229
README.md
View File

@@ -1,40 +1,46 @@
# RGMII Toolkit # RC PCIe Toolkit
Software deployment Toolkit for Quectel RM5xxx series 5G modems utilizing an m.2 to RJ45 adapter (RGMII) Software deployment Toolkit for Quectel RM5xxx series 5G modems utilizing an m.2 to RJ45 adapter (RC PCIe)
Current Branch: **Development** Example: https://rework.network/collections/lte-home-gateway/products/5g2phy
Please PR to this branch instead of main :) Current Branch: **SDXPINN**
Fork development, and PR development to development :) This is a work in progress branch for early development for the RM551E-GL modem (Will probably work on the 550 as well)
# The below commands will download the beta/work in progress toolkit only for RM55x modems/SDXPINN platform
#### [JUMP TO HOW TO USE](#how-to-use) # Current state:
**Currently:** This will allow you to install or if already installed, update, remove, or modify: The toolkit will do the following:
- Simple Admin: A simple web interface for managing your Quectel m.2 modem through it's gateway address 1. AT Commands
- It will install socat-at-bridge: sets up ttyOUT and ttyOUT2 for AT commands. You'll be able to use the `atcmd` command as well for an interactive at command session from adb, ssh, or ttyd - Currently Not working. Just needs coded in.
- It will install simplefirewall: A simple firewall that blocks definable incoming ports and a TTL mangle option/modifier. As of now only the TTL is controllable through Simple Admin. You can edit port block options and TTL from the 3rd option in the toolkit
- Tailscale: A magic VPN for accessing Simple Admin, SSH, and ttyd on the go. The Toolkit installs the Tailscale client directly to the modem and allows you to login and configure other settings. Head over to tailscale.com to sign up for a free account and learn more. 2. First time setup/run me after a flash!
- Schedule a Daily Reboot at a specified time - You must reboot twise anytime after for this to be fully installed
- A fix for certain modems that don't start in CFUN=1 mode - Can only be ran after a flash at this time
- Entware/OPKG: A package installer/manager/repo - The biggest thing this option does is completely redoes the overlay system. By default the mounts are screwy. Installs mount-fix that does it at boot
- Run `opkg help` to see how to use it - Installs init-watchdog to keep the real root filesystem's init.d in sync with the overlay filesystem in realtime
- These packages are installable: https://bin.entware.net/armv7sf-k3.2/Packages.html - Enables luci and installs the luci AT commands app
- TTYd: A shell session right from your browser - Installs ttyd and shadow-login
- Currently this uses port 443 but SSL/TLS is not in use (http only for now) - Installs other packages
- Entware/OPKG is required so it will install it if it isn't installed - Enables dropbear ssh server
- This will replace the stock Quectel login and passwd binaries with ones from entware
3. TTL Setup
- Will allow you to set a TTL value
4. Set root password
- Runs the passwd utility so you can set your password for root
5. Tailscale Management
- Will let you install tailscale
- First installs from opkg
- Then updates the tailscale and tailscaled to the latest from the static builds
- Will let you configure tailscale
- No web server yet
**My goal** is for this to also include any new useful scripts or software for this modem and others that support RGMII mode. 6. Install Speedtest.net CLI app (speedtest command)
## Screenshots - Will install the speedtest command (speedtest.net test)
- After install type speedtest to use it
![Home Page](https://github.com/iamromulan/quectel-rgmii-configuration-notes/blob/main/images/iamromulansimpleindex.png?raw=true)
![AT Commands](https://github.com/iamromulan/quectel-rgmii-configuration-notes/blob/main/images/iamromulanatcommands.png?raw=true)
![TTL](https://github.com/iamromulan/quectel-rgmii-configuration-notes/blob/main/images/iamromulansimpleTTL.png?raw=true)
![Toolkit](https://github.com/iamromulan/quectel-rgmii-configuration-notes/blob/main/images/iamromulantoolkit.png?raw=true)
# Devleopment Branch: the below commands will download the beta/work in progress toolkit
## How to Use ## How to Use
**To run the Toolkit:** **To run the Toolkit:**
@@ -44,95 +50,116 @@ Fork development, and PR development to development :)
- Run `adb shell ping 8.8.8.8` to make sure the shell can access the internet. If you get an error, make sure the modem is connected to a cellular network and make sure `AT+QMAPWAC=1` as covered in the troubleshooting section: [I Can't get internet access from the Ethernet port (Common)](https://github.com/iamromulan/quectel-rgmii-configuration-notes/tree/main?tab=readme-ov-file#i-cant-get-internet-access-from-the-ethernet-port-common) - Run `adb shell ping 8.8.8.8` to make sure the shell can access the internet. If you get an error, make sure the modem is connected to a cellular network and make sure `AT+QMAPWAC=1` as covered in the troubleshooting section: [I Can't get internet access from the Ethernet port (Common)](https://github.com/iamromulan/quectel-rgmii-configuration-notes/tree/main?tab=readme-ov-file#i-cant-get-internet-access-from-the-ethernet-port-common)
- If you don't get an error you should be getting replies back endlessly, press `CTRL-C` to stop it. - If you don't get an error you should be getting replies back endlessly, press `CTRL-C` to stop it.
- Simply Copy/Paste this into your Command Prompt/Shell - Simply Copy/Paste this into your Command Prompt/Shell
```bash
adb shell "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 /
```
**Or, if you want to stay in the modems shell when you are done**
``` ```
adb root
adb shell adb shell
``` ```
Then run Then run
``` ```
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 / cd /tmp && wget -O rcPCIe_SDXPINN_toolkit.sh https://raw.githubusercontent.com/iamromulan/quectel-rgmii-toolkit/SDXPINN/rcPCIe_SDXPINN_toolkit.sh && chmod +x rcPCIe_SDXPINN_toolkit.sh && ./rcPCIe_SDXPINN_toolkit.sh && cd /
``` ```
**You should see:**
![Toolkit](https://github.com/iamromulan/quectel-rgmii-configuration-notes/blob/main/images/iamromulantoolkit.png?raw=true)
## Tailscale Installation and Config
> :warning: Your modem must already be connected to the internet for this to install
### Installation:
Open up the toolkit main menu and **press 4** to enter the Tailscale menu
![Toolkit](https://github.com/iamromulan/quectel-rgmii-configuration-notes/blob/main/images/tailscalemenu.png?raw=true)
**Press 1, wait for it to install. This is a very large file for the system so give it some time.**
**Once done and it says Tailscale installed successfully press 2/enter to configure it.**
![Toolkit](https://github.com/iamromulan/quectel-rgmii-configuration-notes/blob/main/images/tailscaleconfig.png?raw=true)
If you want to, enable the Tailscale Web UI on port 8088 for configuration from the browser later by **pressing 1/enter**.
To do it in the toolkit:
First time connecting you'll be given a link to login with
- Press 3 to just connect only.
- Press 4 to connect and enable SSH access (remote command line) over tailscale.
- Press 5 to reconnect with SSH off while connected with SSH on
- Press 6 to disconnect
- Press 7 to Logout
That's it! From another device running tailscale you should be able to access your modem through the IP assigned to it by your tailnet. To access SSH from another device on the tailnet, open a terminal/command prompt and type
tailscale ssh root@(IP or Hostname)
IP or Hostname being the IP or hostname assigned to it in your tailnet
- Note that your SSH client must be able to give you a link to sign in with upon connecting. That's how the session is authorized. Works fine in Windows CMD or on Android use JuiceSSH.
## Advanced/Beta
### Entware/OPKG installation
It isn't perfect yet so it goes here under Advanced/Beta for now. # Useful AT Commands
Here's what you gotta know about going into it:
- After installing, the `opkg` command will work You can send more than one command at once by sperating them with ``;`` and not including the AT part. ``AT+QENG="servingcell";+QCAINFO`` for example to see the info from both ``AT+QENG="servingcell"`` and ``AT+QCAINFO``
- You can run `opkg list` to see a list of installable packages, or head over to https://bin.entware.net/armv7sf-k3.2/Packages.html
- Everything opkg does is installed to /opt
- `/opt` is actually located at `/usrdata/opt` to save space but is
mounted at `/opt`
- Anything `opkg` installs will not be available in the system path by
default but you can get around this either:
#### Temporarily:
Run this at the start of each adb shell or SSH shell session
export PATH=/opt/bin:/opt/sbin:$PATH ## PCIe RC Ethernet mode setup
#### Permanently: For use with a board like the [Rework.Network PoE 2.5gig RJ45 sled](https://rework.network/collections/lte-home-gateway/products/5g2phy)
Symbolic linking each binary installed by the package to `/bin` and `/sbin` from `/opt/bin` and `/opt/sbin`
For example, if you were to install zerotier:
opkg install zerotier ### For x70 modems (RM550/551)
ln -sf /opt/bin/zerotier-one /bin
ln -sf /opt/bin/zerotier-cli /bin
ln -sf /opt/bin/zerotier-idtool /bin
Now you can run those 3 binaries from the shell anytime since they are linked in a place already part of the system path. For BETA versions of firmware: the adb value 2 trick still works so one and done:
``AT+QCFG="pcie/mode",1;+QCFG="usbnet",1;+QCFG="usbcfg",0x2C7C,0x0122,1,1,1,1,1,2,0;+CFUN=1,1``
OR if you are running the latest non-beta firmware
``AT+QCFG="pcie/mode",1;+QCFG="usbnet",1``
Then unlock ADB:
Ask the modem for its adb code by sending: ``AT+QADBKEY?``
It'll respond with something like ``+QADBKEY: 29229988``
Take that number and paste it in this generator: https://onecompiler.com/python/3znepjcsq (hint: where it says STDIN)
You should get something like
``AT+QADBKEY="mrX4zOPwdSIEjfM"``
Send that command to the modem and adb will be able to be turned on with the next command
Now you can turn it on with the usbcfg command ``AT+QCFG="usbcfg"``
***Be super careful, this controls what ports are on/off over USB.***
Run it and you will get the current settings. Something like this:
``+QCFG: "usbcfg",0x2C7C,0x0122,1,1,1,1,1,0,0``
Send ``AT+QCFG="usbcfg",0x2C7C,0x0122,1,1,1,1,1,1,0`` to enable adb
Now you can reboot: ``AT+CFUN=1,1``
This will do the following:
- Enable PCIe RC mode (Driver selection is automatic now)
- Set to ECM mode via USB and AP mode connection behavior
- Force Enables ADB Access
- Reboots after all the above
Tip: APN automatic selection will somtimes choose the wrong APN. You may need to set your APN after powering up with the SIM inserted.
## The List
- ``AT+CFUN=1,1`` (reboot)
- ``AT+CFUN=0;CFUN=1`` (Disconnect then reconnect)(tip: run this after chnaging APN and you don't have to reboot)
- ``AT+QMAPWAC? ``(get current status of auto connect, 0=disabled 1=enabled)
- ``AT+QMAPWAC=1`` (enable auto connect internet for ethernet)
- ``AT+QMAPWAC=0`` (disable auto connect for ethernet; use when you want internet over USB to work; IPPT must be disabled)
- ``AT+QUIMSLOT?`` (get active sim slot; 1=Slot 1; 2=Slot 2)
- ``AT+QUIMSLOT=1`` (switch to sim slot 1)
- ``AT+QUIMSLOT=2`` (switch to sim slot 2)
- ``AT+CGDCONT?`` (Get active APN profle st 1 through 8)
- ``AT+QMBNCFG="AutoSel",0;+QMBNCFG="Deactivate"`` (Disable Automatic APN selection)(You will need to set your APN when you switch SIMs or Slots)(Can also set APN after you switch the run ``AT+CFUN=0;CFUN=1``
- ``AT+CGDCONT=1,"IPV4V6","APNHERE"`` (Sets APN profile 1 to APNHERE using both IPV4 and IPV6)
- ``AT+GSN`` (Show current IMEI)
- ``AT+EGMR=0,7`` (Show current IMEI)
- ``AT+EGMR=1,7,"IMEIGOESHERE"`` (sets/repairs IMEI)
- ``AT+QCFG="usbcfg",0x2C7C,0x0801,1,1,1,1,1,2,0`` (enables adb bypasses adb key)
- ``AT+QENG="servingcell"`` (shows anchor band and network connection status)
- ``AT+QCAINFO`` (Show all connected bands/CA info)
- ``AT+QNWPREFCFG="mode_pref"`` (Check what the current network search mode is set to)
- ``AT+QNWPREFCFG="mode_pref",AUTO`` (Set network search mode to automatic)
- ``AT+QNWPREFCFG="mode_pref",NR5G:LTE`` (Set network search mode to 5GNR and 4GLTE only)
- ``AT+QNWPREFCFG="mode_pref",NR5G`` (Set network search mode to 5GNR only)
- ``AT+QNWPREFCFG="mode_pref",LTE`` (Set network search mode to 4GLTE only)
- ``AT+QNWPREFCFG="nr5g_disable_mode"`` (Check to see if SA or NSA NR5G is disabled)
- ``AT+QNWPREFCFG="nr5g_disable_mode",0`` (Enable Both SA and NSA 5GNR)
- ``AT+QNWPREFCFG="nr5g_disable_mode",1`` (Disable SA 5GNR only)
- ``AT+QNWPREFCFG="nr5g_disable_mode",2`` (Disable NSA 5GNR only)
- ``AT+QNWPREFCFG="nr5g_band"`` (Get current SA 5GNR bandlock settings)
- ``AT+QNWPREFCFG="nsa_nr5g_band"`` (Get current NSA 5GNR bandlock settings)
- ``AT+QNWPREFCFG="nr5g_band",1:2:3:4:5:6`` (Example: Lock to SA 5G/NR bands n1,n2,n3,n4,n5, and n6)
- ``AT+QNWPREFCFG="nsa_nr5g_band",1:2:3:4:5:6`` (Example: Lock to SA 5G/NR bands n1,n2,n3,n4,n5, and n6)
- ``AT+QNWPREFCFG="lte_band"`` (Get current 4GLTE bandlock settings)
- ``AT+QNWPREFCFG="lte_band",1:2:3:4:5:6`` (Example: Lock to 4G/LTE bands 1,2,3,4,5, and 6)
- ``AT+QMAP="WWAN"`` (Show currently assigned IPv4 and IPv6 from the provider)
- ``AT+QMAP="LANIP"`` (Show current DHCP range and Gateway address for VLAN0)
- ``AT+QMAP="LANIP",IP_start_range,IP_end_range,Gateway_IP `` (Set IPv4 Start/End range and Gateway IP of DHCP for VLAN0)
- ``AT+QMAP="DHCPV4DNS","disable"`` (disable the onboard DNS proxy; recommended for IPPT)
- ``AT+QMAP="MPDN_rule",0,1,0,1,1,"FF:FF:FF:FF:FF:FF"``
(:warning: On the RM551E-GL you must specify the ethernet devices MAC address instead of FF:FF:FF...)
- ``AT+QMAP="MPDN_rule",0`` (turn off IPPT/clear MPDN rule 0; Remember to run AT+QMAPWAC=1 and reboot after)
I plan to create a watchdog service for /opt/bin and /opt/sbin that will automaticly link new packages to /bin or /sbin later on in order to combat this.
### TTYd installation
It isn't perfect yet so it goes here under Advanced/Beta for now.
Here's what you gotta know about going into it:
- This listens on port 443 for http requests (no SSL/TLS yet)
- This will automaticly install entware and patch the login and passwd binaries with ones from entware
- It will ask you to set a password for the `root` user account
- TTYd doesn't seem to be too mobile friendly for now but I optimized it the best i could for now so it is at least usable through a smartphone browser. Hopefully the startup script can be improved even more later.
## Acknowledgements ## Acknowledgements
### GitHub Users/Individuals: ### GitHub Users/Individuals:

View File

@@ -1,938 +0,0 @@
#!/bin/sh
# Define toolkit paths
GITUSER="iamromulan"
GITTREE="development"
GITMAINTREE="main"
GITDEVTREE="development"
TMP_DIR="/tmp"
USRDATA_DIR="/usrdata"
SOCAT_AT_DIR="/usrdata/socat-at-bridge"
SOCAT_AT_SYSD_DIR="/usrdata/socat-at-bridge/systemd_units"
SIMPLE_ADMIN_DIR="/usrdata/simpleadmin"
SIMPLE_FIREWALL_DIR="/usrdata/simplefirewall"
SIMPLE_FIREWALL_SCRIPT="$SIMPLE_FIREWALL_DIR/simplefirewall.sh"
SIMPLE_FIREWALL_SYSTEMD_DIR="$SIMPLE_FIREWALL_DIR/systemd"
TAILSCALE_DIR="/usrdata/tailscale"
TAILSCALE_SYSD_DIR="/usrdata/tailscale/systemd"
# AT Command Script Variables and Functions
DEVICE_FILE="/dev/smd7"
TIMEOUT=4 # Set a timeout for the response
# Function to remount file system as read-write
remount_rw() {
mount -o remount,rw /
}
# Function to remount file system as read-only
remount_ro() {
mount -o remount,ro /
}
# Basic AT commands without socat bridge for fast responce commands only
start_listening() {
cat "$DEVICE_FILE" > /tmp/device_readout &
CAT_PID=$!
}
send_at_command() {
echo -e "\e[1;31mThis only works for basic quick responding commands!\e[0m" # Red
echo -e "\e[1;36mType 'install' to simply type atcmd in shell from now on\e[0m"
echo -e "\e[1;36mThe installed version is much better than this portable version\e[0m"
echo -e "\e[1;32mEnter AT command (or type 'exit' to quit): \e[0m"
read at_command
if [ "$at_command" = "exit" ]; then
return 1
fi
if [ "$at_command" = "install" ]; then
install_update_at_socat
echo -e "\e[1;32mInstalled. Type atcmd from adb shell or ssh to start an AT Command session\e[0m"
return 1
fi
echo -e "${at_command}\r" > "$DEVICE_FILE"
}
wait_for_response() {
local start_time=$(date +%s)
local current_time
local elapsed_time
echo -e "\e[1;32mCommand sent, waiting for response...\e[0m"
while true; do
if grep -qe "OK" -e "ERROR" /tmp/device_readout; then
echo -e "\e[1;32mResponse received:\e[0m"
cat /tmp/device_readout
return 0
fi
current_time=$(date +%s)
elapsed_time=$((current_time - start_time))
if [ "$elapsed_time" -ge "$TIMEOUT" ]; then
echo -e "\e[1;31mError: Response timed out.\e[0m" # Red
echo -e "\e[1;32mIf the responce takes longer than a second or 2 to respond this will not work\e[0m" # Green
echo -e "\e[1;36mType install to install the better version of this that will work.\e[0m" # Cyan
return 1
fi
sleep 1
done
}
cleanup() {
kill "$CAT_PID"
wait "$CAT_PID" 2>/dev/null
rm -f /tmp/device_readout
}
send_at_commands() {
if [ -c "$DEVICE_FILE" ]; then
while true; do
start_listening
send_at_command
if [ $? -eq 1 ]; then
cleanup
break
fi
wait_for_response
cleanup
done
else
echo -e "\e[1;31mError: Device $DEVICE_FILE does not exist!\e[0m"
fi
}
# Check for existing Entware/opkg installation, install if not installed
ensure_entware_installed() {
remount_rw
if [ ! -f "/opt/bin/opkg" ]; then
echo -e "\e[1;32mInstalling Entware/OPKG\e[0m"
cd /tmp && wget -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
}
#Uninstall Entware if the Users chooses
uninstall_entware() {
echo -e '\033[31mInfo: Starting Entware/OPKG uninstallation...\033[0m'
# Stop services
systemctl stop rc.unslung.service
/opt/etc/init.d/rc.unslung stop
rm /lib/systemd/system/multi-user.target.wants/rc.unslung.service
rm /lib/systemd/system/rc.unslung.service
systemctl stop opt.mount
rm /lib/systemd/system/multi-user.target.wants/start-opt-mount.service
rm /lib/systemd/system/opt.mount
rm /lib/systemd/system/start-opt-mount.service
# Unmount /opt if mounted
mountpoint -q /opt && umount /opt
# Remove Entware installation directory
rm -rf /usrdata/opt
rm -rf /opt
# Reload systemctl daemon
systemctl daemon-reload
# Optionally, clean up any modifications to /etc/profile or other system files
# Restore original link to login binary compiled by Quectel
rm /bin/login
ln /bin/login.shadow /bin/login
echo -e '\033[32mInfo: Entware/OPKG has been uninstalled successfully.\033[0m'
}
# function to configure the fetures of simplefirewall
configure_simple_firewall() {
if [ ! -f "$SIMPLE_FIREWALL_SCRIPT" ]; then
echo -e "\033[0;31mSimplefirewall is not installed, would you like to install it?\033[0m"
echo -e "\033[0;32m1) Yes\033[0m"
echo -e "\033[0;31m2) No\033[0m"
read -p "Enter your choice (1-2): " install_choice
case $install_choice in
1)
install_simple_firewall
;;
2)
return
;;
*)
echo -e "\033[0;31mInvalid choice. Please select either 1 or 2.\033[0m"
;;
esac
fi
echo -e "\e[1;32mConfigure Simple Firewall:\e[0m"
echo -e "\e[38;5;208m1) Configure incoming port block\e[0m"
echo -e "\e[38;5;27m2) Configure TTL\e[0m"
read -p "Enter your choice (1-2): " menu_choice
case $menu_choice in
1)
# Original ports configuration code with exit option
current_ports_line=$(grep '^PORTS=' "$SIMPLE_FIREWALL_SCRIPT")
ports=$(echo "$current_ports_line" | cut -d'=' -f2 | tr -d '()' | tr ' ' '\n' | grep -o '[0-9]\+')
echo -e "\e[1;32mCurrent configured ports:\e[0m"
echo "$ports" | awk '{print NR") "$0}'
while true; do
echo -e "\e[1;32mEnter a port number to add/remove, or type 'done' or 'exit' to finish:\e[0m"
read port
if [ "$port" = "done" ] || [ "$port" = "exit" ]; then
if [ "$port" = "exit" ]; then
echo -e "\e[1;31mExiting without making changes...\e[0m"
return
fi
break
elif ! echo "$port" | grep -qE '^[0-9]+$'; then
echo -e "\e[1;31mInvalid input: Please enter a numeric value.\e[0m"
elif echo "$ports" | grep -q "^$port\$"; then
ports=$(echo "$ports" | grep -v "^$port\$")
echo -e "\e[1;32mPort $port removed.\e[0m"
else
ports=$(echo "$ports"; echo "$port" | grep -o '[0-9]\+')
echo -e "\e[1;32mPort $port added.\e[0m"
fi
done
if [ "$port" != "exit" ]; then
new_ports_line="PORTS=($(echo "$ports" | tr '\n' ' '))"
sed -i "s/$current_ports_line/$new_ports_line/" "$SIMPLE_FIREWALL_SCRIPT"
fi
;;
2)
# TTL configuration code
ttl_value=$(cat /usrdata/simplefirewall/ttlvalue)
if [ "$ttl_value" -eq 0 ]; then
echo -e "\e[1;31mTTL is not set.\e[0m"
else
echo -e "\e[1;32mTTL value is set to $ttl_value.\e[0m"
fi
echo -e "\e[1;31mType 'exit' to cancel.\e[0m"
read -p "What do you want the TTL value to be: " new_ttl_value
if [ "$new_ttl_value" = "exit" ]; then
echo -e "\e[1;31mExiting TTL configuration...\e[0m"
return
elif ! echo "$new_ttl_value" | grep -qE '^[0-9]+$'; then
echo -e "\e[1;31mInvalid input: Please enter a numeric value.\e[0m"
return
else
/usrdata/simplefirewall/ttl-override stop
echo "$new_ttl_value" > /usrdata/simplefirewall/ttlvalue
/usrdata/simplefirewall/ttl-override start
echo -e "\033[0;32mTTL value updated to $new_ttl_value.\033[0m"
fi
;;
*)
echo -e "\e[1;31mInvalid choice. Please select either 1 or 2.\e[0m"
;;
esac
systemctl restart simplefirewall
echo -e "\e[1;32mFirewall configuration updated.\e[0m"
}
set_simpleadmin_passwd(){
ensure_entware_installed
opkg update
opkg install libaprutil
wget -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 80/443 on test build\e[0m"
echo -e "\e[1;32m1) Stable current version, (Main Branch)\e[0m"
echo -e "\e[1;31m2) Install Test Build (Development Branch)\e[0m"
echo -e "\e[0;33m3) Return to Main Menu\e[0m"
echo -e "\e[1;32mSelect your choice: \e[0m"
read choice
case $choice in
1)
echo -e "\e[1;32mYou are using the development toolkit; Use the one from main if you want the stable version right now\e[0m"
break
;;
2)
ensure_entware_installed
echo -e "\e[1;31m2) Installing simpleadmin from the development test branch\e[0m"
mkdir /usrdata/simpleupdates > /dev/null 2>&1
mkdir /usrdata/simpleupdates/scripts > /dev/null 2>&1
wget -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
;;
*)
echo "Invalid choice. Please try again."
;;
esac
done
}
# Function to Uninstall Simpleadmin and dependencies
uninstall_simpleadmin_components() {
echo -e "\e[1;32mStarting the uninstallation process for Simpleadmin components.\e[0m"
echo -e "\e[1;32mNote: Uninstalling certain components may affect the functionality of others.\e[0m"
remount_rw
# Uninstall Simple Firewall
echo -e "\e[1;32mDo you want to uninstall Simplefirewall?\e[0m"
echo -e "\e[1;31mIf you do, the TTL part of simpleadmin will no longer work.\e[0m"
echo -e "\e[1;32m1) Yes\e[0m"
echo -e "\e[1;31m2) No\e[0m"
read -p "Enter your choice (1 or 2): " choice_simplefirewall
if [ "$choice_simplefirewall" -eq 1 ]; then
echo "Uninstalling Simplefirewall..."
systemctl stop simplefirewall
systemctl stop ttl-override
rm -f /lib/systemd/system/simplefirewall.service
rm -f /lib/systemd/system/ttl-override.service
systemctl daemon-reload
rm -rf "$SIMPLE_FIREWALL_DIR"
echo "Simplefirewall uninstalled."
fi
# Uninstall socat-at-bridge
echo -e "\e[1;32mDo you want to uninstall socat-at-bridge?\e[0m"
echo -e "\e[1;31mIf you do, AT commands and the stat page will no longer work. atcmd won't either.\e[0m"
echo -e "\e[1;32m1) Yes\e[0m"
echo -e "\e[1;31m2) No\e[0m"
read -p "Enter your choice (1 or 2): " choice_socat_at_bridge
if [ "$choice_socat_at_bridge" -eq 1 ]; then
echo -e "\033[0;32mRemoving installed AT Socat Bridge services...\033[0m"
systemctl stop at-telnet-daemon > /dev/null 2>&1
systemctl disable at-telnet-daemon > /dev/null 2>&1
systemctl stop socat-smd11 > /dev/null 2>&1
systemctl stop socat-smd11-to-ttyIN > /dev/null 2>&1
systemctl stop socat-smd11-from-ttyIN > /dev/null 2>&1
systemctl stop socat-smd7 > /dev/null 2>&1
systemctl stop socat-smd7-to-ttyIN2 > /dev/null 2>&1
systemctl stop socat-smd7-to-ttyIN > /dev/null 2>&1
systemctl stop socat-smd7-from-ttyIN2 > /dev/null 2>&1
systemctl stop socat-smd7-from-ttyIN > /dev/null 2>&1
rm /lib/systemd/system/at-telnet-daemon.service > /dev/null 2>&1
rm /lib/systemd/system/socat-smd11.service > /dev/null 2>&1
rm /lib/systemd/system/socat-smd11-to-ttyIN.service > /dev/null 2>&1
rm /lib/systemd/system/socat-smd11-from-ttyIN.service > /dev/null 2>&1
rm /lib/systemd/system/socat-smd7.service > /dev/null 2>&1
rm /lib/systemd/system/socat-smd7-to-ttyIN2.service > /dev/null 2>&1
rm /lib/systemd/system/socat-smd7-to-ttyIN.service > /dev/null 2>&1
rm /lib/systemd/system/socat-smd7-from-ttyIN.service > /dev/null 2>&1
rm /lib/systemd/system/socat-smd7-from-ttyIN2.service > /dev/null 2>&1
systemctl daemon-reload > /dev/null 2>&1
rm -rf "$SOCAT_AT_DIR" > /dev/null 2>&1
rm -rf "$SOCAT_AT_DIR" > /dev/null 2>&1
rm -rf "/usrdata/micropython" > /dev/null 2>&1
rm -rf "/usrdata/at-telnet" > /dev/null 2>&1
echo -e "\033[0;32mAT Socat Bridge services removed!...\033[0m"
fi
# Uninstall ttyd
echo -e "\e[1;32mDo you want to uninstall ttyd (simpleadmin console)?\e[0m"
echo -e "\e[1;31mWarning: Do not uninstall if you are currently using ttyd to do this!!!\e[0m"
echo -e "\e[1;32m1) Yes\e[0m"
echo -e "\e[1;31m2) No\e[0m"
read -p "Enter your choice (1 or 2): " choice_simpleadmin
if [ "$choice_simpleadmin" -eq 1 ]; then
echo -e "\e[1;34mUninstalling ttyd...\e[0m"
systemctl stop ttyd
rm -rf /usrdata/ttyd
rm /lib/systemd/system/ttyd.service
rm /lib/systemd/system/multi-user.target.wants/ttyd.service
rm /bin/ttyd
echo -e "\e[1;32mttyd has been uninstalled.\e[0m"
fi
echo "Uninstalling the rest of Simpleadmin..."
# Check if Lighttpd service is installed and remove it if present
if [ -f "/lib/systemd/system/lighttpd.service" ]; then
echo "Lighttpd detected, uninstalling Lighttpd and its modules..."
systemctl stop lighttpd
opkg --force-remove --force-removal-of-dependent-packages remove lighttpd-mod-authn_file lighttpd-mod-auth lighttpd-mod-cgi lighttpd-mod-openssl lighttpd-mod-proxy lighttpd
rm -rf $LIGHTTPD_DIR
fi
systemctl stop simpleadmin_generate_status
systemctl stop simpleadmin_httpd
rm -f /lib/systemd/system/simpleadmin_httpd.service
rm -f /lib/systemd/system/simpleadmin_generate_status.service
systemctl daemon-reload
rm -rf "$SIMPLE_ADMIN_DIR"
echo "The rest of Simpleadmin and Lighttpd (if present) uninstalled."
remount_ro
echo "Uninstallation process completed."
}
# Function for Tailscale Submenu
tailscale_menu() {
while true; do
echo -e "\e[1;32mTailscale Menu\e[0m"
echo -e "\e[1;32m1) Install/Update Tailscale\e[0m"
echo -e "\e[1;36m2) Configure Tailscale\e[0m"
echo -e "\e[1;31m3) Return to Main Menu\e[0m"
read -p "Enter your choice: " tailscale_choice
case $tailscale_choice in
1) install_update_tailscale;;
2) configure_tailscale;;
3) break;;
*) echo "Invalid option";;
esac
done
}
# Function to install, update, or remove Tailscale
install_update_tailscale() {
echo -e "\e[1;31m2) Installing tailscale from the $GITTREE branch\e[0m"
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
configure_tailscale() {
while true; do
echo "Configure Tailscale"
echo -e "\e[38;5;40m1) Enable Tailscale Web UI at http://192.168.225.1:8088 (Gateway on port 8088)\e[0m" # Green
echo -e "\e[38;5;196m2) Disable Tailscale Web UI\e[0m" # Red
echo -e "\e[38;5;27m3) Connect to Tailnet\e[0m" # Brown
echo -e "\e[38;5;87m4) Connect to Tailnet with SSH ON\e[0m" # Light cyan
echo -e "\e[38;5;105m5) Reconnect to Tailnet with SSH OFF\e[0m" # Light magenta
echo -e "\e[38;5;172m6) Disconnect from Tailnet (reconnects at reboot)\e[0m" # Light yellow
echo -e "\e[1;31m7) Logout from tailscale account\e[0m"
echo -e "\e[38;5;27m8) Return to Tailscale Menu\e[0m"
read -p "Enter your choice: " config_choice
case $config_choice in
1)
remount_rw
cd /lib/systemd/system/
wget -O tailscale-webui.service https://raw.githubusercontent.com/$GITUSER/quectel-rgmii-toolkit/main/tailscale/systemd/tailscale-webui.service
wget -O tailscale-webui-trigger.service https://raw.githubusercontent.com/$GITUSER/quectel-rgmii-toolkit/main/tailscale/systemd/tailscale-webui-trigger.service
ln -sf /lib/systemd/system/tailscale-webui-trigger.service /lib/systemd/system/multi-user.target.wants/
systemctl daemon-reload
echo "Tailscale Web UI Enabled"
echo "Starting Web UI..."
systemctl start tailscale-webui
echo "Web UI started!"
remount_ro
;;
2)
remount_rw
systemctl stop tailscale-webui
systemctl disable tailscale-webui-trigger
rm /lib/systemd/system/multi-user.target.wants/tailscale-webui.service
rm /lib/systemd/system/multi-user.target.wants/tailscale-webui-trigger.service
rm /lib/systemd/system/tailscale-webui.service
rm /lib/systemd/system/tailscale-webui-trigger.service
systemctl daemon-reload
echo "Tailscale Web UI Stopped and Disabled"
remount_ro
;;
3) $TAILSCALE_DIR/tailscale up --accept-dns=false --reset;;
4) $TAILSCALE_DIR/tailscale up --ssh --accept-dns=false --reset;;
5) $TAILSCALE_DIR/tailscale up --accept-dns=false --reset;;
6) $TAILSCALE_DIR/tailscale down;;
7) $TAILSCALE_DIR/tailscale logout;;
8) break;;
*) echo "Invalid option";;
esac
done
}
# Function to manage Daily Reboot Timer
manage_reboot_timer() {
# Remount root filesystem as read-write
mount -o remount,rw /
# Check if the rebootmodem service, timer, or trigger already exists
if [ -f /lib/systemd/system/rebootmodem.service ] || [ -f /lib/systemd/system/rebootmodem.timer ] || [ -f /lib/systemd/system/rebootmodem-trigger.service ]; then
echo -e "\e[1;32mThe rebootmodem service/timer/trigger is already installed.\e[0m"
echo -e "\e[1;32m1) Change\e[0m" # Green
echo -e "\e[1;31m2) Remove\e[0m" # Red
read -p "Enter your choice (1 for Change, 2 for Remove): " reboot_choice
case $reboot_choice in
2)
# Stop and disable timer and trigger service by removing symlinks
systemctl stop rebootmodem.timer
systemctl stop rebootmodem-trigger.service
# Remove symbolic links and files
rm -f /lib/systemd/system/multi-user.target.wants/rebootmodem-trigger.service
rm -f /lib/systemd/system/rebootmodem.service
rm -f /lib/systemd/system/rebootmodem.timer
rm -f /lib/systemd/system/rebootmodem-trigger.service
rm -f "$USRDATA_DIR/reboot_modem.sh"
# Reload systemd to apply changes
systemctl daemon-reload
echo -e "\e[1;32mRebootmodem service, timer, trigger, and script removed successfully.\e[0m"
;;
1)
printf "Enter the new time for daily reboot (24-hour format in Coordinated Universal Time, HH:MM): "
read new_time
# Validate the new time format using grep
if ! echo "$new_time" | grep -qE '^([01]?[0-9]|2[0-3]):[0-5][0-9]$'; then
echo "Invalid time format. Exiting."
exit 1
else
# Remove old symlinks and script
rm -f /lib/systemd/system/multi-user.target.wants/rebootmodem-trigger.service
rm -f "$USRDATA_DIR/reboot_modem.sh"
# Set the user time to the new time and recreate the service, timer, trigger, and script
user_time=$new_time
create_service_and_timer
fi
;;
*)
echo -e "\e[1;31mInvalid choice. Exiting.\e[0m"
exit 1
;;
esac
else
printf "Enter the time for daily reboot (24-hour format in UTC, HH:MM): "
read user_time
# Validate the time format using grep
if ! echo "$user_time" | grep -qE '^([01]?[0-9]|2[0-3]):[0-5][0-9]$'; then
echo "Invalid time format. Exiting."
exit 1
else
create_service_and_timer
fi
fi
# Remount root filesystem as read-only
mount -o remount,ro /
}
# Function to create systemd service and timer files with the user-specified time for the reboot timer
create_service_and_timer() {
remount_rw
# Define the path for the modem reboot script
MODEM_REBOOT_SCRIPT="$USRDATA_DIR/reboot_modem.sh"
# Create the modem reboot script
echo "#!/bin/sh
/bin/echo -e 'AT+CFUN=1,1 \r' > /dev/smd7" > "$MODEM_REBOOT_SCRIPT"
# Make the script executable
chmod +x "$MODEM_REBOOT_SCRIPT"
# Create the systemd service file for reboot
echo "[Unit]
Description=Reboot Modem Daily
[Service]
Type=oneshot
ExecStart=/bin/sh /usrdata/reboot_modem.sh
Restart=no
RemainAfterExit=no" > /lib/systemd/system/rebootmodem.service
# Create the systemd timer file with the user-specified time
echo "[Unit]
Description=Starts rebootmodem.service daily at the specified time
[Timer]
OnCalendar=*-*-* $user_time:00
Persistent=false" > /lib/systemd/system/rebootmodem.timer
# Create a trigger service that starts the timer at boot
echo "[Unit]
Description=Trigger the rebootmodem timer at boot
[Service]
Type=oneshot
ExecStart=/bin/systemctl start rebootmodem.timer
RemainAfterExit=yes" > /lib/systemd/system/rebootmodem-trigger.service
# Create symbolic links for the trigger service in the wanted directory
ln -sf /lib/systemd/system/rebootmodem-trigger.service /lib/systemd/system/multi-user.target.wants/
# Reload systemd to recognize the new timer and trigger service
systemctl daemon-reload
sleep 2s
# Start the trigger service, which will start the timer
systemctl start rebootmodem-trigger.service
remount_ro
# Confirmation
echo -e "\e[1;32mRebootmodem-trigger service created and started successfully.\e[0m"
echo -e "\e[1;32mReboot schedule set successfully. The modem will reboot daily at $user_time UTC.\e[0m"
}
manage_cfun_fix() {
cfun_service_path="/lib/systemd/system/cfunfix.service"
cfun_fix_script="/usrdata/cfun_fix.sh"
mount -o remount,rw /
if [ -f "$cfun_service_path" ]; then
echo -e "\e[1;32mThe CFUN fix is already installed. Do you want to remove it?\e[0m" # Green
echo -e "\e[1;32m1) Yes\e[0m" # Green
echo -e "\e[1;31m2) No\e[0m" # Red
read -p "Enter your choice: " choice
if [ "$choice" = "1" ]; then
echo "Removing CFUN fix..."
systemctl stop cfunfix.service
rm -f /lib/systemd/system/multi-user.target.wants/cfunfix.service
rm -f "$cfun_service_path"
rm -f "$cfun_fix_script"
systemctl daemon-reload
echo "CFUN fix has been removed."
else
echo "Returning to main menu..."
fi
else
echo -e "\e[1;32mInstalling CFUN fix...\e[0m"
# Create the CFUN fix script
echo "#!/bin/sh
/bin/echo -e 'AT+CFUN=1 \r' > /dev/smd7" > "$cfun_fix_script"
chmod +x "$cfun_fix_script"
# Create the systemd service file to execute the CFUN fix script at boot
echo "[Unit]
Description=CFUN Fix Service
After=network.target
[Service]
Type=oneshot
ExecStart=$cfun_fix_script
RemainAfterExit=yes
[Install]
WantedBy=multi-user.target" > "$cfun_service_path"
ln -sf "$cfun_service_path" "/lib/systemd/system/multi-user.target.wants/"
systemctl daemon-reload
mount -o remount,ro /
echo -e "\e[1;32mCFUN fix has been installed and will execute at every boot.\e[0m"
fi
}
install_sshd() {
if [ -d "/usrdata/sshd" ]; then
echo -e "\e[1;31mSSHD is currently installed.\e[0m"
echo -e "Do you want to update or uninstall?"
echo -e "1.) Update"
echo -e "2.) Uninstall"
read -p "Select an option (1 or 2): " sshd_choice
case $sshd_choice in
1)
echo -e "\e[1;31m2) Installing sshd from the $GITTREE branch\e[0m"
;;
2)
echo -e "\e[1;31mUninstalling SSHD...\e[0m"
systemctl stop sshd
rm /lib/systemd/system/sshd.service
opkg remove openssh-server-pam
echo -e "\e[1;32mSSHD has been uninstalled successfully.\e[0m"
return 0
;;
*)
echo -e "\e[1;31mInvalid option. Please select 1 or 2.\e[0m"
return 1
;;
esac
fi
# Proceed with installation or updating if not uninstalling
ensure_entware_installed
mkdir /usrdata/simpleupdates > /dev/null 2>&1
mkdir /usrdata/simpleupdates/scripts > /dev/null 2>&1
wget -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"
}
# Main menu
while true; do
echo " .%+: "
echo " .*@@@-. "
echo " :@@@@- "
echo " @@@@#. "
echo " -@@@@#. "
echo " :. %@@@@: -# "
echo " .+- #@@@@%.+@- "
echo " .#- . +@@@@# #@- "
echo " -@*@*@% @@@@@::@@= "
echo ".+%@@@@@@@@@%=. =@@@@# #@@- .. "
echo " .@@@@@: :@@@@@ =@@@..%= "
echo " -::@-.+. @@@@@.=@@@- =@- "
echo " .@- .@@@@@:.@@@* @@. "
echo " .%- -@@@@@:=@@@@ @@# "
echo " .#- .%@@@@@@#. +@@@@@.#@@@@ @@@."
echo " .*- .@@@@@@@@@@=. @@@@@@ @@@@@ @@@:"
echo " :. .%@@@@@@@@@@@%. .@@@@@+:@@@@@ @@@-"
echo " -@@@@@@@@@@@@@@@..@@@@@@.-@@@@@ .@@@-"
echo " -@@@@@@@@@@%. .@@@@@@. @@@@@+ =@@@="
echo " =@@@@@@@@* .@@@@@@. @@@@@@..@@@@-"
echo " #@@@@@@@@-*@@@@@%..@@@@@@+ #@@@@-"
echo " @@@@@@:.-@@@@@@. @@@@@@= %@@@@@."
echo " .@@@@. *@@@@@@- .+@@@@@@-.@@@@@@+ "
echo " %@@. =@@@@@*. +@@@@@@%.-@@@@@@% "
echo " .@@ .@@@@@= :@@@@@@@@..@@@@@@@= "
echo " =@.+@@@@@. -@@@@@@@*.:@@@@@@@*. "
echo " %.*@@@@= .@@@@@@@-.:@@@@@@@+. "
echo " ..@@@@= .@@@@@@: #@@@@@@@: "
echo " .@@@@ +@@@@..%@@@@@+. "
echo " .@@@. @@@@.:@@@@+. "
echo " @@@. @@@. @@@* .@. "
echo " :@@@ %@@..@@#. *@ "
echo " -*: .@@* :@@. @@. -..@@ "
echo " =@@@@@@.*@- :@% @* =@:=@# "
echo " .@@@-+@@@@:%@..%- ...@%:@@: "
echo " .@@. @@-%@: .%@@*@@%. "
echo " :@@ :+ *@ *@@#*@@@. "
echo " =@@@.@@@@ "
echo " .*@@@:=@@@@: "
echo " .@@@@:.@@@@@: "
echo " .@@@@#.-@@@@@. "
echo " #@@@@: =@@@@@- "
echo " .@@@@@..@@@@@@* "
echo " -@@@@@. @@@@@@#. "
echo " -@@@@@ @@@@@@% "
echo " @@@@@. #@@@@@@. "
echo " :@@@@# =@@@@@@% "
echo " @@@@@: @@@@@@@: "
echo " *@@@@ @@@@@@@. "
echo " .@@@@ @@@@@@@ "
echo " #@@@. @@@@@@* "
echo " @@@# @@@@@@@ "
echo " .@@+=@@@@@@. "
echo " *@@@@@@ "
echo " :@@@@@= "
echo " .@@@@@@. "
echo " :@@@@@*. "
echo " .=@@@@@- "
echo " :+##+. "
echo -e "\e[92m"
echo "Welcome to iamromulan's RGMII Toolkit script for Quectel RMxxx Series modems!"
echo "Visit https://github.com/iamromulan for more!"
echo -e "\e[0m"
echo "Select an option:"
echo -e "\e[0m"
echo -e "\e[96m1) Send AT Commands\e[0m" # Cyan
echo -e "\e[93m2) Install Simple Admin\e[0m" # Yellow
echo -e "\e[95m3) Set Simpleadmin (admin) password\e[0m" # Light Purple
echo -e "\e[94m4) Set Console/ttyd (root) password\e[0m" # Light Blue
echo -e "\e[91m5) Uninstall Simple Admin\e[0m" # Light Red
echo -e "\e[95m6) Simple Firewall Management\e[0m" # Light Purple
echo -e "\e[94m7) Tailscale Management\e[0m" # Light Blue
echo -e "\e[92m8) Install/Change or remove Daily Reboot Timer\e[0m" # Light Green
echo -e "\e[96m9) Install/Uninstall CFUN 0 Fix\e[0m" # Cyan (repeated color for additional options)
echo -e "\e[91m10) Uninstall Entware/OPKG\e[0m" # Light Red
echo -e "\e[92m11) Install Speedtest.net CLI app (speedtest command)\e[0m" # Light Green
echo -e "\e[92m12) Install Fast.com CLI app (fast command)(tops out at 40Mbps)\e[0m" # Light Green
echo -e "\e[92m13) Install OpenSSH Server\e[0m" # Light Green
echo -e "\e[93m14) Exit\e[0m" # Yellow (repeated color for exit option)
read -p "Enter your choice: " choice
case $choice in
1)
send_at_commands
;;
2)
install_simple_admin
;;
3) set_simpleadmin_passwd
;;
4)
set_root_passwd
;;
5)
uninstall_simpleadmin_components
;;
6)
configure_simple_firewall
;;
7)
tailscale_menu
;;
8)
manage_reboot_timer
;;
9)
manage_cfun_fix
;;
10)
echo -e "\033[31mAre you sure you want to uninstall entware?\033[0m"
echo -e "\033[31m1) Yes\033[0m"
echo -e "\033[31m2) No\033[0m"
read -p "Select an option (1 or 2): " user_choice
case $user_choice in
1)
# If yes, uninstall existing entware
echo -e "\033[31mUninstalling existing entware...\033[0m"
uninstall_entware # Assuming uninstall_entware is a defined function or command
echo -e "\033[31mEntware has been uninstalled.\033[0m"
;;
2)
# If no, exit the script
echo -e "\033[31mUninstallation cancelled.\033[0m"
exit # Use 'exit' to terminate the script outside a loop
;;
*)
# Handle invalid input
echo -e "\033[31mInvalid option. Please select 1 or 2.\033[0m"
;;
esac
;;
11)
ensure_entware_installed
echo -e "\e[1;32mInstalling Speedtest.net CLI (speedtest command)\e[0m"
remount_rw
mkdir /usrdata/root
mkdir /usrdata/root/bin
cd /usrdata/root/bin
wget https://install.speedtest.net/app/cli/ookla-speedtest-1.2.0-linux-armhf.tgz
tar -xzf ookla-speedtest-1.2.0-linux-armhf.tgz
rm ookla-speedtest-1.2.0-linux-armhf.tgz
rm speedtest.md
cd /
ln -sf /usrdata/root/bin/speedtest /bin
remount_ro
echo -e "\e[1;32mSpeedtest CLI (speedtest command) installed!!\e[0m"
echo -e "\e[1;32mTry running the command 'speedtest'\e[0m"
echo -e "\e[1;32mNote that it will not work unless you login to the root account first\e[0m"
echo -e "\e[1;32mNormaly only an issue in adb, ttyd and ssh you are forced to login\e[0m"
echo -e "\e[1;32mIf in adb just type login and then try to run the speedtest command\e[0m"
;;
12)
echo -e "\e[1;32mInstalling fast.com CLI (fast command)\e[0m"
remount_rw
mkdir /usrdata/root
mkdir /usrdata/root/bin
cd /usrdata/root/bin
wget -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"
;;
esac
done

View File

@@ -0,0 +1,24 @@
Reboot;AT+CFUN=1,1
Disconnect;AT+CFUN=0
Connect;AT+CFUN=1
Signal Info;AT+QENG="servingcell"
CA Info;AT+QCAINFO
Get current SIM Slot;AT+QUIMSLOT?
Switch to SIM Slot 1;AT+QUIMSLOT=1
Switch to SIM Slot 2;AT+QUIMSLOT=2
Get current APN List;AT+CGDCONT?
Set APN to NRBROADBAND;AT+CGDCONT=1,"IPV4V6","NRBROADBAND"
Show Current IMEI;AT+EGMR=0,7
Show Current Network Mode;AT+QNWPREFCFG="mode_pref"
Set Network Mode to AUTO;AT+QNWPREFCFG="mode_pref",AUTO
Set Network Mode to 5G NR/4G LTE Only;AT+QNWPREFCFG="mode_pref",NR5G:LTE
Set Network Mode to 5G NR Only;AT+QNWPREFCFG="mode_pref",NR5G
Set Network Mode to 4G LTE Only;AT+QNWPREFCFG="mode_pref",LTE
Check to see if SA or NSA is disabled;AT+QNWPREFCFG="nr5g_disable_mode"
Enable Both SA and NSA;AT+QNWPREFCFG="nr5g_disable_mode",0
Disable SA Only;AT+QNWPREFCFG="nr5g_disable_mode",1
Disable NSA Only;AT+QNWPREFCFG="nr5g_disable_mode",2
Get Currently Enabled 5G/NR SA Bands;AT+QNWPREFCFG="nr5g_band"
Get Currently Enabled 5G/NR NSA Bands;AT+QNWPREFCFG="nsa_nr5g_band"
Get Currently Enabled 4G/LTE Bands;AT+QNWPREFCFG="lte_band"
View assigned IPv4/IPv6 addresses from the provider;AT+QMAP="WWAN"

4
etc/config/atinout Normal file
View File

@@ -0,0 +1,4 @@
config atinout 'general'
option atcport '/dev/smd11'

6
etc/config/ttyd Normal file
View File

@@ -0,0 +1,6 @@
config ttyd
option interface '@lan'
option debug '7'
option command '/usr/bin/login'

View File

@@ -0,0 +1,20 @@
#!/bin/ash /etc/rc.common
START=04
USE_PROCD=1
start_service() {
procd_open_instance
procd_set_param command /usr/sbin/init-overlay-watchdog.sh
procd_set_param respawn 3600 5 5
procd_set_param stdout 1
procd_set_param stderr 1
procd_set_param pidfile /var/run/init-overlay-watchdog.pid
procd_set_param tracking
procd_close_instance
}
stop_service() {
echo "Stopping init-overlay-watchdog service"
# `procd` will handle stopping the service and its processes
}

133
etc/init.d/mount-fix Normal file
View File

@@ -0,0 +1,133 @@
#!/bin/sh /etc/rc.common
START=03
start() {
# Log to tmp
rm /tmp/mount-fix.log
/bin/touch /tmp/mount-fix.log
/bin/echo "Begin mount fix process to make a usable userspace" >> /tmp/mount-fix.log
# Forcefully unmount /etc
/bin/echo "Unmounting the tiny overlay at /etc" >> /tmp/mount-fix.log
/bin/umount -lf /etc >> /tmp/mount-fix.log
# Remount root filesystem as read-write
/bin/echo "Remounting / as read-write" >> /tmp/mount-fix.log
/bin/mount -o remount,rw / >> /tmp/mount-fix.log
# Check if /overlay/etc-upper/merged.done exists
/bin/echo "First time this is ran the stuff you have been putting in the old overlay needs merged." >> /tmp/mount-fix.log
/bin/echo "Looking for evidence that this has already happened..." >> /tmp/mount-fix.log
if [ ! -f /overlay/etc-upper/merged.done ]; then
/bin/echo "/overlay/etc-upper/merged.done not found, merging /overlay/etc-upper/* to /etc/" >> /tmp/mount-fix.log
cp -rf /overlay/etc-upper/* /etc/ >> /tmp/mount-fix.log
/bin/touch /overlay/etc-upper/merged.done >> /tmp/mount-fix.log
else
/bin/echo "/overlay/etc-upper/merged.done found, skipping merge" >> /tmp/mount-fix.log
fi
# Unmount /overlay
/bin/echo "Unmounting the no longer needed /overlay" >> /tmp/mount-fix.log
/bin/umount /overlay >> /tmp/mount-fix.log
# Check if /etc/opkg.conf has a line containing "option overlay_root /overlay" and remove it if it exists
/bin/echo "Lets be sure your opkg config isn't using the old overlay" >> /tmp/mount-fix.log
if grep -q "option overlay_root /overlay" /etc/opkg.conf; then
/bin/echo "Removing 'option overlay_root /overlay' from /etc/opkg.conf" >> /tmp/mount-fix.log
sed -i '/option overlay_root \/overlay/d' /etc/opkg.conf >> /tmp/mount-fix.log
else
/bin/echo "'option overlay_root /overlay' not found in /etc/opkg.conf, no changes made" >> /tmp/mount-fix.log
fi
# Ensure necessary directories exist for overlay and pivot_root
/bin/echo "Creating new overlay system" >> /tmp/mount-fix.log
if [ ! -d /data/rootfs ]; then
mkdir -p /data/rootfs
fi
if [ ! -d /data/rootfs-workdir ]; then
mkdir -p /data/rootfs-workdir
fi
if [ ! -d /rootfs ]; then
mkdir -p /rootfs
fi
# Mount the new overlay filesystem
/bin/mount -t overlay overlay -o lowerdir=/,upperdir=/data/rootfs,workdir=/data/rootfs-workdir /rootfs >> /tmp/mount-fix.log
# Create the real_rootfs directory in the new root
if [ ! -d /rootfs/real_rootfs ]; then
mkdir -p /rootfs/real_rootfs
fi
# Pivot root to the new root
/bin/echo "Pivoting Root / to /rootfs; Be back soon!!" >> /tmp/mount-fix.log
/sbin/pivot_root /rootfs /rootfs/real_rootfs >> /tmp/mount-fix.log
# Move the mounted filesystems to the new locations
/bin/mount --move /real_rootfs/sys /sys >> /tmp/mount-fix.log
/bin/mount --move /real_rootfs/proc /proc >> /tmp/mount-fix.log
/bin/mount --move /real_rootfs/tmp /tmp >> /tmp/mount-fix.log
/bin/mount --move /real_rootfs/dev /dev >> /tmp/mount-fix.log
/bin/mount --move /real_rootfs/firmware /firmware >> /tmp/mount-fix.log
/bin/mount --move /real_rootfs/persist /persist >> /tmp/mount-fix.log
/bin/mount --move /real_rootfs/cache /cache >> /tmp/mount-fix.log
/bin/mount --move /real_rootfs/data /data >> /tmp/mount-fix.log
# Synchronize /etc/rc.d/ and /real_rootfs/etc/rc.d/
/bin/echo "Synchronizing /etc/rc.d/ and /real_rootfs/etc/rc.d/" >> /tmp/mount-fix.log
for link in /etc/rc.d/*; do
if [ -L "$link" ]; then
link_name=$(basename "$link")
if [ ! -e "/real_rootfs/etc/rc.d/$link_name" ]; then
/bin/echo "Copying $link_name to /real_rootfs/etc/rc.d/" >> /tmp/mount-fix.log
cp -a "$link" "/real_rootfs/etc/rc.d/$link_name" >> /tmp/mount-fix.log
fi
fi
done
for link in /real_rootfs/etc/rc.d/*; do
if [ -L "$link" ]; then
link_name=$(basename "$link")
if [ ! -e "/etc/rc.d/$link_name" ]; then
/bin/echo "Removing $link_name from /real_rootfs/etc/rc.d/" >> /tmp/mount-fix.log
rm "/real_rootfs/etc/rc.d/$link_name" >> /tmp/mount-fix.log
fi
fi
done
# Final logs and remount the original root as read-only
/bin/echo "...and we're back! The original root now lives at /real_rootfs" >> /tmp/mount-fix.log
/bin/echo "Lets mount it as read-only for now, If you need it just remount it as read-write" >> /tmp/mount-fix.log
/bin/mount -o remount,ro /real_rootfs >> /tmp/mount-fix.log
/bin/echo "Overlay and pivot_root setup completed" >> /tmp/mount-fix.log
}
stop() {
/bin/echo "Stopping and reverting overlay and pivot_root" >> /tmp/mount-fix.log
# Remount the original root filesystem as read-write
/bin/mount -o remount,rw /real_rootfs >> /tmp/mount-fix.log
# Move the mounted filesystems back to the original locations
/bin/mount --move /sys /real_rootfs/sys >> /tmp/mount-fix.log
/bin/mount --move /proc /real_rootfs/proc >> /tmp/mount-fix.log
/bin/mount --move /tmp /real_rootfs/tmp >> /tmp/mount-fix.log
/bin/mount --move /dev /real_rootfs/dev >> /tmp/mount-fix.log
/bin/mount --move /firmware /real_rootfs/firmware >> /tmp/mount-fix.log
/bin/mount --move /persist /real_rootfs/persist >> /tmp/mount-fix.log
/bin/mount --move /cache /real_rootfs/cache >> /tmp/mount-fix.log
/bin/mount --move /data /real_rootfs/data >> /tmp/mount-fix.log
# Pivot root back to the original root
/sbin/pivot_root /real_rootfs /real_rootfs/rootfs >> /tmp/mount-fix.log
/bin/echo "Reverted pivot_root" >> /tmp/mount-fix.log
/bin/echo "Previous root overlay available at /rootfs" >> /tmp/mount-fix.log
}
restart() {
/bin/echo "This script should only be executed once at boot"
/bin/echo "Use Stop to undo the pivot"
/bin/echo "Use Start to put it back"
}

View File

@@ -0,0 +1,51 @@
#!/bin/sh /etc/rc.common
START=99
STOP=10
USE_PROCD=1
PROG_PATH="/usr/bin"
start_service() {
# Start socat services
procd_open_instance socat_smd11
procd_set_param command $PROG_PATH/socat -d -d pty,link=/dev/ttyIN,raw,echo=0,group=20,perm=660 pty,link=/dev/ttyOUT,raw,echo=1,group=20,perm=660
procd_set_param respawn
procd_close_instance
sleep 1
procd_open_instance socat_smd7
procd_set_param command $PROG_PATH/socat -d -d pty,link=/dev/ttyIN2,raw,echo=0,group=20,perm=660 pty,link=/dev/ttyOUT2,raw,echo=1,group=20,perm=660
procd_set_param respawn
procd_close_instance
sleep 1
# Start forwarding services
procd_open_instance socat_smd11_from_ttyIN
procd_set_param command /bin/ash -c "/bin/cat /dev/ttyIN > /dev/smd11"
procd_set_param respawn
procd_close_instance
procd_open_instance socat_smd11_to_ttyIN
procd_set_param command /bin/ash -c "/bin/cat /dev/smd11 > /dev/ttyIN"
procd_set_param respawn
procd_close_instance
procd_open_instance socat_smd7_from_ttyIN2
procd_set_param command /bin/ash -c "/bin/cat /dev/ttyIN2 > /dev/smd7"
procd_set_param respawn
procd_close_instance
procd_open_instance socat_smd7_to_ttyIN2
procd_set_param command /bin/ash -c "/bin/cat /dev/smd7 > /dev/ttyIN2"
procd_set_param respawn
procd_close_instance
}
stop_service() {
killall socat
}

44
etc/opkg/distfeeds.conf Normal file
View File

@@ -0,0 +1,44 @@
# src/gz openwrt_core https://downloads.openwrt.org/releases/22.03.5/targets/sdx75/generic/packages
src/gz openwrt_base https://downloads.openwrt.org/releases/22.03.5/packages/aarch64_cortex-a53/base
src/gz openwrt_luci https://downloads.openwrt.org/releases/22.03.5/packages/aarch64_cortex-a53/luci
src/gz openwrt_packages https://downloads.openwrt.org/releases/22.03.5/packages/aarch64_cortex-a53/packages
# src/gz openwrt_qtiagm https://downloads.openwrt.org/releases/22.03.5/packages/aarch64_cortex-a53/qtiagm
# src/gz openwrt_qtiargs https://downloads.openwrt.org/releases/22.03.5/packages/aarch64_cortex-a53/qtiargs
# src/gz openwrt_qtiaudio https://downloads.openwrt.org/releases/22.03.5/packages/aarch64_cortex-a53/qtiaudio
# src/gz openwrt_qtiaudioprop https://downloads.openwrt.org/releases/22.03.5/packages/aarch64_cortex-a53/qtiaudioprop
# src/gz openwrt_qtibsp https://downloads.openwrt.org/releases/22.03.5/packages/aarch64_cortex-a53/qtibsp
# src/gz openwrt_qtibspprop https://downloads.openwrt.org/releases/22.03.5/packages/aarch64_cortex-a53/qtibspprop
# src/gz openwrt_qtibt https://downloads.openwrt.org/releases/22.03.5/packages/aarch64_cortex-a53/qtibt
# src/gz openwrt_qtibtprop https://downloads.openwrt.org/releases/22.03.5/packages/aarch64_cortex-a53/qtibtprop
# src/gz openwrt_qticore https://downloads.openwrt.org/releases/22.03.5/packages/aarch64_cortex-a53/qticore
# src/gz openwrt_qticoreinternal https://downloads.openwrt.org/releases/22.03.5/packages/aarch64_cortex-a53/qticoreinternal
# src/gz openwrt_qticoreprop https://downloads.openwrt.org/releases/22.03.5/packages/aarch64_cortex-a53/qticoreprop
# src/gz openwrt_qtictainternal https://downloads.openwrt.org/releases/22.03.5/packages/aarch64_cortex-a53/qtictainternal
# src/gz openwrt_qtidata https://downloads.openwrt.org/releases/22.03.5/packages/aarch64_cortex-a53/qtidata
# src/gz openwrt_qtidatainternal https://downloads.openwrt.org/releases/22.03.5/packages/aarch64_cortex-a53/qtidatainternal
# src/gz openwrt_qtidataprop https://downloads.openwrt.org/releases/22.03.5/packages/aarch64_cortex-a53/qtidataprop
# src/gz openwrt_qtiipq https://downloads.openwrt.org/releases/22.03.5/packages/aarch64_cortex-a53/qtiipq
# src/gz openwrt_qtiipqezmesh https://downloads.openwrt.org/releases/22.03.5/packages/aarch64_cortex-a53/qtiipqezmesh
# src/gz openwrt_qtiipqprop https://downloads.openwrt.org/releases/22.03.5/packages/aarch64_cortex-a53/qtiipqprop
# src/gz openwrt_qtilocation https://downloads.openwrt.org/releases/22.03.5/packages/aarch64_cortex-a53/qtilocation
# src/gz openwrt_qtilocationinternal https://downloads.openwrt.org/releases/22.03.5/packages/aarch64_cortex-a53/qtilocationinternal
# src/gz openwrt_qtilocationprop https://downloads.openwrt.org/releases/22.03.5/packages/aarch64_cortex-a53/qtilocationprop
# src/gz openwrt_qtimsdcprop https://downloads.openwrt.org/releases/22.03.5/packages/aarch64_cortex-a53/qtimsdcprop
# src/gz openwrt_qtinternal https://downloads.openwrt.org/releases/22.03.5/packages/aarch64_cortex-a53/qtinternal
# src/gz openwrt_qtipal https://downloads.openwrt.org/releases/22.03.5/packages/aarch64_cortex-a53/qtipal
# src/gz openwrt_qtiperfprop https://downloads.openwrt.org/releases/22.03.5/packages/aarch64_cortex-a53/qtiperfprop
# src/gz openwrt_qtippatprop https://downloads.openwrt.org/releases/22.03.5/packages/aarch64_cortex-a53/qtippatprop
# src/gz openwrt_qtiquectel https://downloads.openwrt.org/releases/22.03.5/packages/aarch64_cortex-a53/qtiquectel
# src/gz openwrt_qtiquectelprop https://downloads.openwrt.org/releases/22.03.5/packages/aarch64_cortex-a53/qtiquectelprop
# src/gz openwrt_qtirilprop https://downloads.openwrt.org/releases/22.03.5/packages/aarch64_cortex-a53/qtirilprop
# src/gz openwrt_qtisecurity https://downloads.openwrt.org/releases/22.03.5/packages/aarch64_cortex-a53/qtisecurity
# src/gz openwrt_qtisecurityinternal https://downloads.openwrt.org/releases/22.03.5/packages/aarch64_cortex-a53/qtisecurityinternal
# src/gz openwrt_qtisecurityprop https://downloads.openwrt.org/releases/22.03.5/packages/aarch64_cortex-a53/qtisecurityprop
# src/gz openwrt_qtisensorsinternal https://downloads.openwrt.org/releases/22.03.5/packages/aarch64_cortex-a53/qtisensorsinternal
# src/gz openwrt_qtisensorsprop https://downloads.openwrt.org/releases/22.03.5/packages/aarch64_cortex-a53/qtisensorsprop
# src/gz openwrt_qtissdk https://downloads.openwrt.org/releases/22.03.5/packages/aarch64_cortex-a53/qtissdk
# src/gz openwrt_qtissmgr https://downloads.openwrt.org/releases/22.03.5/packages/aarch64_cortex-a53/qtissmgr
# src/gz openwrt_qtissmgrprop https://downloads.openwrt.org/releases/22.03.5/packages/aarch64_cortex-a53/qtissmgrprop
# src/gz openwrt_qtiwlan https://downloads.openwrt.org/releases/22.03.5/packages/aarch64_cortex-a53/qtiwlan
# src/gz openwrt_qtiwlanprop https://downloads.openwrt.org/releases/22.03.5/packages/aarch64_cortex-a53/qtiwlanprop
src/gz openwrt_routing https://downloads.openwrt.org/releases/22.03.5/packages/aarch64_cortex-a53/routing

View File

@@ -1,167 +0,0 @@
#!/bin/sh
# Modified by iamromulan to set up a proper entware environment for Quectel RM5xx series m.2 modems
TYPE='generic'
#|---------|-----------------|
#| TARGET | Quectel Modem |
#| ARCH | armv7sf-k3.2 |
#| LOADER | ld-linux.so.3 |
#| GLIBC | 2.27 |
#|---------|-----------------|
unset LD_LIBRARY_PATH
unset LD_PRELOAD
ARCH=armv7sf-k3.2
LOADER=ld-linux.so.3
GLIBC=2.27
PRE_OPKG_PATH=$(which opkg)
# Remount filesystem as read-write
mount -o remount,rw /
create_opt_mount() {
# Bind /usrdata/opt to /opt
echo -e '\033[32mInfo: Setting up /opt mount to /usrdata/opt...\033[0m'
cat <<EOF > /lib/systemd/system/opt.mount
[Unit]
Description=Bind /usrdata/opt to /opt
[Mount]
What=/usrdata/opt
Where=/opt
Type=none
Options=bind
[Install]
WantedBy=multi-user.target
EOF
systemctl daemon-reload
systemctl start opt.mount
# Additional systemd service to ensure opt.mount starts at boot
echo -e '\033[32mInfo: Creating service to start opt.mount at boot...\033[0m'
cat <<EOF > /lib/systemd/system/start-opt-mount.service
[Unit]
Description=Ensure opt.mount is started at boot
After=network.target
[Service]
Type=oneshot
ExecStart=/bin/systemctl start opt.mount
[Install]
WantedBy=multi-user.target
EOF
systemctl daemon-reload
ln -s /lib/systemd/system/start-opt-mount.service /lib/systemd/system/multi-user.target.wants/start-opt-mount.service
}
if [ -n "$PRE_OPKG_PATH" ]; then
# Automatically rename the existing opkg binary
mv "$PRE_OPKG_PATH" "${PRE_OPKG_PATH}_old"
echo -e "\033[32mFactory/Already existing opkg has been renamed to opkg_old.\033[0m"
else
echo "Info: no existing opkg binary detected, proceeding with installation"
fi
echo -e '\033[32mInfo: Creating /opt mount pointed to /usrdata/opt ...\033[0m'
create_opt_mount
echo -e '\033[32mInfo: Proceeding with main installation ...\033[0m'
# no need to create many folders. entware-opt package creates most
for folder in bin etc lib/opkg tmp var/lock
do
if [ -d "/opt/$folder" ]; then
echo -e '\033[31mWarning: Folder /opt/$folder exists!\033[0m'
echo -e '\033[31mWarning: If something goes wrong please clean /opt folder and try again.\033[0m'
else
mkdir -p /opt/$folder
fi
done
echo -e '\033[32mInfo: Opkg package manager deployment...\033[0m'
URL=http://bin.entware.net/${ARCH}/installer
wget $URL/opkg -O /opt/bin/opkg
chmod 755 /opt/bin/opkg
wget $URL/opkg.conf -O /opt/etc/opkg.conf
echo -e '\033[32mInfo: Basic packages installation...\033[0m'
/opt/bin/opkg update
/opt/bin/opkg install entware-opt
# Fix for multiuser environment
chmod 777 /opt/tmp
for file in passwd group shells shadow gshadow; do
if [ $TYPE = 'generic' ]; then
if [ -f /etc/$file ]; then
ln -sf /etc/$file /opt/etc/$file
else
[ -f /opt/etc/$file.1 ] && cp /opt/etc/$file.1 /opt/etc/$file
fi
else
if [ -f /opt/etc/$file.1 ]; then
cp /opt/etc/$file.1 /opt/etc/$file
fi
fi
done
[ -f /etc/localtime ] && ln -sf /etc/localtime /opt/etc/localtime
# Create and enable rc.unslung service
echo -e '\033[32mInfo: Creating rc.unslung (Entware init.d service)...\033[0m'
cat <<EOF > /lib/systemd/system/rc.unslung.service
[Unit]
Description=Start Entware services
[Service]
Type=oneshot
# Add a delay to give /opt time to mount
ExecStartPre=/bin/sleep 5
ExecStart=/opt/etc/init.d/rc.unslung start
RemainAfterExit=yes
[Install]
WantedBy=multi-user.target
EOF
systemctl daemon-reload
ln -s /lib/systemd/system/rc.unslung.service /lib/systemd/system/multi-user.target.wants/rc.unslung.service
systemctl start rc.unslung.service
echo -e '\033[32mInfo: Congratulations!\033[0m'
echo -e '\033[32mInfo: If there are no errors above then Entware was successfully initialized.\033[0m'
echo -e '\033[32mInfo: Add /opt/bin & /opt/sbin to $PATH variable\033[0m'
ln -sf /opt/bin/opkg /bin
echo -e '\033[32mInfo: Patching Quectel Login Binary\033[0m'
opkg update && opkg install shadow-login shadow-passwd shadow-useradd
if [ "$?" -ne 0 ]; then
echo -e "\e[1;31mPackage installation failed. Please check your internet connection and try again.\e[0m"
exit 1
fi
# Replace the login and passwd binaries and set home for root to a writable directory
rm /opt/etc/shadow
rm /opt/etc/passwd
cp /etc/shadow /opt/etc/
cp /etc/passwd /opt/etc
mkdir /usrdata/root
mkdir /usrdata/root/bin
touch /usrdata/root/.profile
echo "# Set PATH for all shells" > /usrdata/root/.profile
echo "export PATH=/bin:/usr/sbin:/usr/bin:/sbin:/opt/sbin:/opt/bin:/usrdata/root/bin" >> /usrdata/root/.profile
chmod +x /usrdata/root/.profile
sed -i '1s|/home/root:/bin/sh|/usrdata/root:/bin/bash|' /opt/etc/passwd
rm /bin/login /usr/bin/passwd
ln -sf /opt/bin/login /bin
ln -sf /opt/bin/passwd /usr/bin/
ln -sf /opt/bin/useradd /usr/bin/
echo -e "\e[1;31mPlease set the root password.\e[0m"
/usr/bin/passwd
# Install basic and useful utilites
opkg install mc htop dfc lsof
ln -sf /opt/bin/mc /bin
ln -sf /opt/bin/htop /bin
ln -sf /opt/bin/dfc /bin
ln -sf /opt/bin/lsof /bin
# Remount filesystem as read-only
mount -o remount,ro /

35
opkg-feed/Packages Normal file
View File

@@ -0,0 +1,35 @@
Lost field SourceName, atinout
Lost field LicenseFiles, LICENSE
Lost field SourceDateEpoch, 1691250335
Lost field Installed-Size, 3571
Lost field SourceName, luci-app-atinout-mod
Lost field SourceDateEpoch, 1636930326
Lost field Installed-Size, 3790
Package: atinout
Version: 0.9.1
Depends: libc
Section: net
Architecture: aarch64_cortex-a53
Maintainer: Adrian Guenter <a@gntr.me>
MD5Sum: 6c8d3c910477e31940ee7740111a7fdf
Size: 4226
Filename: atinout_0.9.1_aarch64_cortex-a53.ipk
Source: feeds/kiddin9/atinout
Description: Atinout is a program that will execute AT commands in sequence and
License: GPLv2
Package: luci-app-atinout-mod
Version: 1.3.2-20220315
Depends: libc, atinout, luci-compat
Section: luci
Architecture: all
Maintainer: OpenWrt LuCI community
MD5Sum: 92a24b32ebcbd41501895fc0748a22d1
Size: 4617
Filename: luci-app-atinout-mod_1.3.2-20220315_all.ipk
Source: package/luci-app-atinout-mod
Description: Web UI for atinout
License: GPLv3

BIN
opkg-feed/Packages.gz Normal file

Binary file not shown.

2
opkg-feed/Packages.sig Normal file
View File

@@ -0,0 +1,2 @@
untrusted comment: signed by key 2585d2dfe7e59028
RWQlhdLf5+WQKHWdQyQdLxIrKqkDw8qMwdMnUvku9kAeFA4ibt9OtqMfObgPHGgzc5ai7Bao7ngdDe6+6yAfx8MYBwtdYP36Zgc=

Binary file not shown.

View File

@@ -0,0 +1,2 @@
untrusted comment: public key 2585d2dfe7e59028
RWQlhdLf5+WQKAVdfAaG8TkXZi5WfCnsxMiupWrh0Lt2yEubx05UYYfx

Binary file not shown.

View File

@@ -0,0 +1,6 @@
Package: SDXPINN-mount-fix
Version: 1.0
Architecture: arm64
Maintainer: Cameron Thompson iamromulan@github.com
Description: Creates a usable mount space and overlay for SDXPINN modems
Depends: libc

View File

@@ -0,0 +1,15 @@
#!/bin/ash
# Make the init script executable
chmod +x /etc/init.d/mount-fix
chmod +x /etc/init.d/init-overlay-watchdog
chmod +x /usr/sbin/init-overlay-watchdog.sh
# Enable and start the service
service mount-fix enable
service init-overlay-watchdog enable
service mount-fix start
opkg update
opkg install inotifywait inotifywatch
service init-overlay-watchdog start
exit 0

View File

@@ -0,0 +1,15 @@
#!/bin/ash
# Check if /etc is mounted
if grep -qs '/etc ' /proc/mounts; then
echo "Unmounting /etc..."
umount -lf /etc
fi
# Check if root filesystem is mounted as read-only
if grep -qs " / " /proc/mounts | grep "(ro,"; then
echo "Remounting root filesystem as read-write..."
mount -o remount,rw /
fi
exit 0

View File

@@ -0,0 +1,8 @@
#!/bin/ash
service stop mount-fix
service stop init-overlay-watchdog
service disable mount-fix
service disable init-overlay-watchdog
exit 0

View File

@@ -0,0 +1,20 @@
#!/bin/ash /etc/rc.common
START=04
USE_PROCD=1
start_service() {
procd_open_instance
procd_set_param command /usr/sbin/init-overlay-watchdog.sh
procd_set_param respawn 3600 5 5
procd_set_param stdout 1
procd_set_param stderr 1
procd_set_param pidfile /var/run/init-overlay-watchdog.pid
procd_set_param tracking
procd_close_instance
}
stop_service() {
echo "Stopping init-overlay-watchdog service"
# `procd` will handle stopping the service and its processes
}

View File

@@ -0,0 +1,133 @@
#!/bin/sh /etc/rc.common
START=03
start() {
# Log to tmp
rm /tmp/mount-fix.log
/bin/touch /tmp/mount-fix.log
/bin/echo "Begin mount fix process to make a usable userspace" >> /tmp/mount-fix.log
# Forcefully unmount /etc
/bin/echo "Unmounting the tiny overlay at /etc" >> /tmp/mount-fix.log
/bin/umount -lf /etc >> /tmp/mount-fix.log
# Remount root filesystem as read-write
/bin/echo "Remounting / as read-write" >> /tmp/mount-fix.log
/bin/mount -o remount,rw / >> /tmp/mount-fix.log
# Check if /overlay/etc-upper/merged.done exists
/bin/echo "First time this is ran the stuff you have been putting in the old overlay needs merged." >> /tmp/mount-fix.log
/bin/echo "Looking for evidence that this has already happened..." >> /tmp/mount-fix.log
if [ ! -f /overlay/etc-upper/merged.done ]; then
/bin/echo "/overlay/etc-upper/merged.done not found, merging /overlay/etc-upper/* to /etc/" >> /tmp/mount-fix.log
cp -rf /overlay/etc-upper/* /etc/ >> /tmp/mount-fix.log
/bin/touch /overlay/etc-upper/merged.done >> /tmp/mount-fix.log
else
/bin/echo "/overlay/etc-upper/merged.done found, skipping merge" >> /tmp/mount-fix.log
fi
# Unmount /overlay
/bin/echo "Unmounting the no longer needed /overlay" >> /tmp/mount-fix.log
/bin/umount /overlay >> /tmp/mount-fix.log
# Check if /etc/opkg.conf has a line containing "option overlay_root /overlay" and remove it if it exists
/bin/echo "Lets be sure your opkg config isn't using the old overlay" >> /tmp/mount-fix.log
if grep -q "option overlay_root /overlay" /etc/opkg.conf; then
/bin/echo "Removing 'option overlay_root /overlay' from /etc/opkg.conf" >> /tmp/mount-fix.log
sed -i '/option overlay_root \/overlay/d' /etc/opkg.conf >> /tmp/mount-fix.log
else
/bin/echo "'option overlay_root /overlay' not found in /etc/opkg.conf, no changes made" >> /tmp/mount-fix.log
fi
# Ensure necessary directories exist for overlay and pivot_root
/bin/echo "Creating new overlay system" >> /tmp/mount-fix.log
if [ ! -d /data/rootfs ]; then
mkdir -p /data/rootfs
fi
if [ ! -d /data/rootfs-workdir ]; then
mkdir -p /data/rootfs-workdir
fi
if [ ! -d /rootfs ]; then
mkdir -p /rootfs
fi
# Mount the new overlay filesystem
/bin/mount -t overlay overlay -o lowerdir=/,upperdir=/data/rootfs,workdir=/data/rootfs-workdir /rootfs >> /tmp/mount-fix.log
# Create the real_rootfs directory in the new root
if [ ! -d /rootfs/real_rootfs ]; then
mkdir -p /rootfs/real_rootfs
fi
# Pivot root to the new root
/bin/echo "Pivoting Root / to /rootfs; Be back soon!!" >> /tmp/mount-fix.log
/sbin/pivot_root /rootfs /rootfs/real_rootfs >> /tmp/mount-fix.log
# Move the mounted filesystems to the new locations
/bin/mount --move /real_rootfs/sys /sys >> /tmp/mount-fix.log
/bin/mount --move /real_rootfs/proc /proc >> /tmp/mount-fix.log
/bin/mount --move /real_rootfs/tmp /tmp >> /tmp/mount-fix.log
/bin/mount --move /real_rootfs/dev /dev >> /tmp/mount-fix.log
/bin/mount --move /real_rootfs/firmware /firmware >> /tmp/mount-fix.log
/bin/mount --move /real_rootfs/persist /persist >> /tmp/mount-fix.log
/bin/mount --move /real_rootfs/cache /cache >> /tmp/mount-fix.log
/bin/mount --move /real_rootfs/data /data >> /tmp/mount-fix.log
# Synchronize /etc/rc.d/ and /real_rootfs/etc/rc.d/
/bin/echo "Synchronizing /etc/rc.d/ and /real_rootfs/etc/rc.d/" >> /tmp/mount-fix.log
for link in /etc/rc.d/*; do
if [ -L "$link" ]; then
link_name=$(basename "$link")
if [ ! -e "/real_rootfs/etc/rc.d/$link_name" ]; then
/bin/echo "Copying $link_name to /real_rootfs/etc/rc.d/" >> /tmp/mount-fix.log
cp -a "$link" "/real_rootfs/etc/rc.d/$link_name" >> /tmp/mount-fix.log
fi
fi
done
for link in /real_rootfs/etc/rc.d/*; do
if [ -L "$link" ]; then
link_name=$(basename "$link")
if [ ! -e "/etc/rc.d/$link_name" ]; then
/bin/echo "Removing $link_name from /real_rootfs/etc/rc.d/" >> /tmp/mount-fix.log
rm "/real_rootfs/etc/rc.d/$link_name" >> /tmp/mount-fix.log
fi
fi
done
# Final logs and remount the original root as read-only
/bin/echo "...and we're back! The original root now lives at /real_rootfs" >> /tmp/mount-fix.log
/bin/echo "Lets mount it as read-only for now, If you need it just remount it as read-write" >> /tmp/mount-fix.log
/bin/mount -o remount,ro /real_rootfs >> /tmp/mount-fix.log
/bin/echo "Overlay and pivot_root setup completed" >> /tmp/mount-fix.log
}
stop() {
/bin/echo "Stopping and reverting overlay and pivot_root" >> /tmp/mount-fix.log
# Remount the original root filesystem as read-write
/bin/mount -o remount,rw /real_rootfs >> /tmp/mount-fix.log
# Move the mounted filesystems back to the original locations
/bin/mount --move /sys /real_rootfs/sys >> /tmp/mount-fix.log
/bin/mount --move /proc /real_rootfs/proc >> /tmp/mount-fix.log
/bin/mount --move /tmp /real_rootfs/tmp >> /tmp/mount-fix.log
/bin/mount --move /dev /real_rootfs/dev >> /tmp/mount-fix.log
/bin/mount --move /firmware /real_rootfs/firmware >> /tmp/mount-fix.log
/bin/mount --move /persist /real_rootfs/persist >> /tmp/mount-fix.log
/bin/mount --move /cache /real_rootfs/cache >> /tmp/mount-fix.log
/bin/mount --move /data /real_rootfs/data >> /tmp/mount-fix.log
# Pivot root back to the original root
/sbin/pivot_root /real_rootfs /real_rootfs/rootfs >> /tmp/mount-fix.log
/bin/echo "Reverted pivot_root" >> /tmp/mount-fix.log
/bin/echo "Previous root overlay available at /rootfs" >> /tmp/mount-fix.log
}
restart() {
/bin/echo "This script should only be executed once at boot"
/bin/echo "Use Stop to undo the pivot"
/bin/echo "Use Start to put it back"
}

View File

@@ -0,0 +1,44 @@
# src/gz openwrt_core https://downloads.openwrt.org/releases/22.03.5/targets/sdx75/generic/packages
src/gz openwrt_base https://downloads.openwrt.org/releases/22.03.5/packages/aarch64_cortex-a53/base
src/gz openwrt_luci https://downloads.openwrt.org/releases/22.03.5/packages/aarch64_cortex-a53/luci
src/gz openwrt_packages https://downloads.openwrt.org/releases/22.03.5/packages/aarch64_cortex-a53/packages
# src/gz openwrt_qtiagm https://downloads.openwrt.org/releases/22.03.5/packages/aarch64_cortex-a53/qtiagm
# src/gz openwrt_qtiargs https://downloads.openwrt.org/releases/22.03.5/packages/aarch64_cortex-a53/qtiargs
# src/gz openwrt_qtiaudio https://downloads.openwrt.org/releases/22.03.5/packages/aarch64_cortex-a53/qtiaudio
# src/gz openwrt_qtiaudioprop https://downloads.openwrt.org/releases/22.03.5/packages/aarch64_cortex-a53/qtiaudioprop
# src/gz openwrt_qtibsp https://downloads.openwrt.org/releases/22.03.5/packages/aarch64_cortex-a53/qtibsp
# src/gz openwrt_qtibspprop https://downloads.openwrt.org/releases/22.03.5/packages/aarch64_cortex-a53/qtibspprop
# src/gz openwrt_qtibt https://downloads.openwrt.org/releases/22.03.5/packages/aarch64_cortex-a53/qtibt
# src/gz openwrt_qtibtprop https://downloads.openwrt.org/releases/22.03.5/packages/aarch64_cortex-a53/qtibtprop
# src/gz openwrt_qticore https://downloads.openwrt.org/releases/22.03.5/packages/aarch64_cortex-a53/qticore
# src/gz openwrt_qticoreinternal https://downloads.openwrt.org/releases/22.03.5/packages/aarch64_cortex-a53/qticoreinternal
# src/gz openwrt_qticoreprop https://downloads.openwrt.org/releases/22.03.5/packages/aarch64_cortex-a53/qticoreprop
# src/gz openwrt_qtictainternal https://downloads.openwrt.org/releases/22.03.5/packages/aarch64_cortex-a53/qtictainternal
# src/gz openwrt_qtidata https://downloads.openwrt.org/releases/22.03.5/packages/aarch64_cortex-a53/qtidata
# src/gz openwrt_qtidatainternal https://downloads.openwrt.org/releases/22.03.5/packages/aarch64_cortex-a53/qtidatainternal
# src/gz openwrt_qtidataprop https://downloads.openwrt.org/releases/22.03.5/packages/aarch64_cortex-a53/qtidataprop
# src/gz openwrt_qtiipq https://downloads.openwrt.org/releases/22.03.5/packages/aarch64_cortex-a53/qtiipq
# src/gz openwrt_qtiipqezmesh https://downloads.openwrt.org/releases/22.03.5/packages/aarch64_cortex-a53/qtiipqezmesh
# src/gz openwrt_qtiipqprop https://downloads.openwrt.org/releases/22.03.5/packages/aarch64_cortex-a53/qtiipqprop
# src/gz openwrt_qtilocation https://downloads.openwrt.org/releases/22.03.5/packages/aarch64_cortex-a53/qtilocation
# src/gz openwrt_qtilocationinternal https://downloads.openwrt.org/releases/22.03.5/packages/aarch64_cortex-a53/qtilocationinternal
# src/gz openwrt_qtilocationprop https://downloads.openwrt.org/releases/22.03.5/packages/aarch64_cortex-a53/qtilocationprop
# src/gz openwrt_qtimsdcprop https://downloads.openwrt.org/releases/22.03.5/packages/aarch64_cortex-a53/qtimsdcprop
# src/gz openwrt_qtinternal https://downloads.openwrt.org/releases/22.03.5/packages/aarch64_cortex-a53/qtinternal
# src/gz openwrt_qtipal https://downloads.openwrt.org/releases/22.03.5/packages/aarch64_cortex-a53/qtipal
# src/gz openwrt_qtiperfprop https://downloads.openwrt.org/releases/22.03.5/packages/aarch64_cortex-a53/qtiperfprop
# src/gz openwrt_qtippatprop https://downloads.openwrt.org/releases/22.03.5/packages/aarch64_cortex-a53/qtippatprop
# src/gz openwrt_qtiquectel https://downloads.openwrt.org/releases/22.03.5/packages/aarch64_cortex-a53/qtiquectel
# src/gz openwrt_qtiquectelprop https://downloads.openwrt.org/releases/22.03.5/packages/aarch64_cortex-a53/qtiquectelprop
# src/gz openwrt_qtirilprop https://downloads.openwrt.org/releases/22.03.5/packages/aarch64_cortex-a53/qtirilprop
# src/gz openwrt_qtisecurity https://downloads.openwrt.org/releases/22.03.5/packages/aarch64_cortex-a53/qtisecurity
# src/gz openwrt_qtisecurityinternal https://downloads.openwrt.org/releases/22.03.5/packages/aarch64_cortex-a53/qtisecurityinternal
# src/gz openwrt_qtisecurityprop https://downloads.openwrt.org/releases/22.03.5/packages/aarch64_cortex-a53/qtisecurityprop
# src/gz openwrt_qtisensorsinternal https://downloads.openwrt.org/releases/22.03.5/packages/aarch64_cortex-a53/qtisensorsinternal
# src/gz openwrt_qtisensorsprop https://downloads.openwrt.org/releases/22.03.5/packages/aarch64_cortex-a53/qtisensorsprop
# src/gz openwrt_qtissdk https://downloads.openwrt.org/releases/22.03.5/packages/aarch64_cortex-a53/qtissdk
# src/gz openwrt_qtissmgr https://downloads.openwrt.org/releases/22.03.5/packages/aarch64_cortex-a53/qtissmgr
# src/gz openwrt_qtissmgrprop https://downloads.openwrt.org/releases/22.03.5/packages/aarch64_cortex-a53/qtissmgrprop
# src/gz openwrt_qtiwlan https://downloads.openwrt.org/releases/22.03.5/packages/aarch64_cortex-a53/qtiwlan
# src/gz openwrt_qtiwlanprop https://downloads.openwrt.org/releases/22.03.5/packages/aarch64_cortex-a53/qtiwlanprop
src/gz openwrt_routing https://downloads.openwrt.org/releases/22.03.5/packages/aarch64_cortex-a53/routing

View File

@@ -0,0 +1,39 @@
#!/bin/ash
# Paths to monitor and synchronize
WATCH_DIR="/etc/rc.d"
TARGET_DIR="/real_rootfs/etc/rc.d"
# Function to synchronize init scripts
synchronize_init_scripts() {
mount -o remount,rw /real_rootfs
# Copy new or updated symlinks from WATCH_DIR to TARGET_DIR
for link in "$WATCH_DIR"/*; do
if [ -L "$link" ]; then
link_name=$(basename "$link")
if [ ! -e "$TARGET_DIR/$link_name" ] || [ "$link" -nt "$TARGET_DIR/$link_name" ]; then
cp -af "$link" "$TARGET_DIR/$link_name"
fi
fi
done
# Remove symlinks in TARGET_DIR that no longer exist in WATCH_DIR
for link in "$TARGET_DIR"/*; do
if [ -L "$link" ]; then
link_name=$(basename "$link")
if [ ! -e "$WATCH_DIR/$link_name" ]; then
rm -f "$TARGET_DIR/$link_name"
fi
fi
done
mount -o remount,ro /real_rootfs
}
# Initial synchronization
synchronize_init_scripts
# Monitor WATCH_DIR for changes using inotifywait
while true; do
inotifywait -e create,delete,modify,move "$WATCH_DIR"
synchronize_init_scripts
done

424
rcPCIe_SDXPINN_toolkit.sh Normal file
View File

@@ -0,0 +1,424 @@
#!/bin/ash
#WORK IN PROGRESS
# Define toolkit paths
GITUSER="iamromulan"
GITREPO="quectel-rgmii-toolkit"
GITTREE="development-SDXPINN"
GITMAINTREE="SDXPINN"
GITDEVTREE="development-SDXPINN"
TMP_DIR="/tmp"
USRDATA_DIR="/data"
SIMPLE_FIREWALL_DIR="/data/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 /
}
send_at_commands_using_atcmd() {
while true; do
echo -e "\e[1;32mEnter AT command (or type 'exit' to return to the main menu): \e[0m"
read at_command
if [ "$at_command" = "exit" ]; then
echo -e "\e[1;32mReturning to the main menu.\e[0m"
break
fi
echo -e "\e[1;32mSending AT command: $at_command\e[0m"
echo -e "\e[1;32mResponse:\e[0m"
# Use atcmd to send the command and display the output
atcmd_output=$(atcmd "$at_command")
echo "$atcmd_output"
echo -e "\e[1;32m----------------------------------------\e[0m"
done
}
overlay_check() {
if ! grep -qs '/real_rootfs ' /proc/mounts; then
echo -e "\e[31mYou have not ran Option 2 yet!!! Please run option 2!!\e[0m"
return 1
fi
}
basic_55x_setup() {
# Check if neither /etc nor /real_rootfs is mounted
if ! grep -qs '/etc ' /proc/mounts && ! grep -qs '/real_rootfs ' /proc/mounts; then
# Echo message in red
echo -e "\033[31mSomething is wrong or this is not an SDXPINN modem.\033[0m"
echo -e "\033[31mI was expecting either /etc or /real_rootfs to be a mount point.\033[0m"
exit 1
fi
# Check if /etc is mounted
if grep -qs '/etc ' /proc/mounts; then
echo "Unmounting /etc..."
umount -lf /etc
fi
# Check if /real_rootfs is mounted
if grep -qs '/real_rootfs ' /proc/mounts; then
# Echo message in red
echo -e "\033[31mThe environment has already been setup. If you want to undo the changes temporarily run service mount-fix stop.\033[0m"
exit 1
fi
cd /etc/init.d/
wget https://raw.githubusercontent.com/$GITUSER/$GITREPO/$GITTREE/etc/init.d/mount-fix
wget https://raw.githubusercontent.com/$GITUSER/$GITREPO/$GITTREE/etc/init.d/init-overlay-watchdog
# Set executable permissions
chmod +x mount-fix
chmod +x init-overlay-watchdog
cd /usr/sbin
wget https://raw.githubusercontent.com/$GITUSER/$GITREPO/$GITTREE/usr/sbin/init-overlay-watchdog.sh
cd /
service mount-fix enable
service init-overlay-watchdog enable
service mount-fix start
echo "src/gz iamromulan-SDXPINN-repo https://raw.githubusercontent.com/iamromulan/quectel-rgmii-toolkit/SDXPINN/opkg-feed" >> /etc/opkg/customfeeds.conf
rm /etc/opkg/distfeeds.conf
cd /etc/opkg/
wget https://raw.githubusercontent.com/$GITUSER/$GITREPO/$GITTREE/etc/opkg/distfeeds.conf
cd /
wget https://raw.githubusercontent.com/$GITUSER/$GITREPO/$GITTREE/opkg-feed/iamromulan-SDXPINN-repo.key -O /tmp/iamromulan-SDXPINN-repo.key
opkg-key add /tmp/iamromulan-SDXPINN-repo.key
opkg update
opkg install inotifywait inotifywatch
service init-overlay-watchdog start
echo -e "\e[92m"
echo "Mount fix completed!"
echo "Visit https://github.com/iamromulan for more!"
echo "Proceeding with basic packages installation...."
echo -e "\e[0m"
opkg install atinout luci-app-atinout-mod
opkg install shadow-login
opkg install luci-app-ttyd
opkg install mc-skins
rm /etc/config/atcommands.user
rm /etc/config/atinout
rm /etc/config/ttyd
cd /etc/config/
wget https://raw.githubusercontent.com/$GITUSER/$GITREPO/$GITTREE/etc/config/atcommands.user
wget https://raw.githubusercontent.com/$GITUSER/$GITREPO/$GITTREE/etc/config/ttyd
wget https://raw.githubusercontent.com/$GITUSER/$GITREPO/$GITTREE/etc/config/atinout
cd /
service uhttpd enable
service dropbear enable
service uhttpd start
service dropbear start
echo -e "\e[92m"
echo "Set your root password:"
echo -e "\e[0m"
set_root_passwd
echo -e "\e[92m"
echo "Basic packages installed!"
echo "Visit https://github.com/iamromulan for more!"
echo -e "\e[0m"
}
ttl_setup() {
local ttl_file="/etc/firewall.user.ttl"
local lan_utils_script="/etc/data/lanUtils.sh"
local combine_function="util_combine_iptable_rules"
local temp_file="/tmp/temp_firewall_user_ttl"
overlay_check || return
while true; do
if [ ! -f "$ttl_file" ]; then
echo "Creating $ttl_file..."
touch "$ttl_file"
echo "Modifying $combine_function in $lan_utils_script..."
# Backup the original script
cp "$lan_utils_script" "${lan_utils_script}.bak"
# Add the local ttl_firewall_file line if it's not already present
if ! grep -q "local ttl_firewall_file" "$lan_utils_script"; then
sed -i '/local tcpmss_firewall_filev6/a \ local ttl_firewall_file=/etc/firewall.user.ttl' "$lan_utils_script"
fi
# Add the condition to include the ttl_firewall_file if it's not already present
if (! grep -q "if \[ -f \"\$ttl_firewall_file\" \]; then" "$lan_utils_script"); then
sed -i '/if \[ -f "\$tcpmss_firewall_filev6" \]; then/i \ if [ -f "\$ttl_firewall_file" ]; then\n cat \$ttl_firewall_file >> \$firewall_file\n fi' "$lan_utils_script"
fi
fi
if [ ! -s "$ttl_file" ]; then
echo -e "\e[31mTTL is not enabled\e[0m"
else
ipv4_ttl=$(grep 'iptables -t mangle -A POSTROUTING' "$ttl_file" | awk '{for(i=1;i<=NF;i++){if($i=="--ttl-set"){print $(i+1)}}}')
ipv6_ttl=$(grep 'ip6tables -t mangle -A POSTROUTING' "$ttl_file" | awk '{for(i=1;i<=NF;i++){if($i=="--hl-set"){print $(i+1)}}}')
echo -e "\e[32mCurrent IPv4 TTL: $ipv4_ttl\e[0m"
echo -e "\e[32mCurrent IPv6 TTL: $ipv6_ttl\e[0m"
fi
echo -e "\e[32mWould you like to edit the TTL settings?\e[0m"
echo -e "\e[32mTTL Value will be set without needing a reboot \e[0m"
echo -e "\e[33mType yes or exit:\e[0m" && read -r response
if [ "$response" = "exit" ]; then
echo "Exiting..."
break
elif [ "$response" = "yes" ]; then
echo -e "\e[32mType 0 to disable TTL\e[0m"
echo -e "\e[33mEnter the TTL value (number only):\e[0m" && read -r ttl_value
if ! [[ "$ttl_value" =~ ^[0-9]+$ ]]; then
echo "Invalid input, please enter a number."
else
# Clear existing TTL rules
echo "Clearing existing TTL rules..."
iptables -t mangle -D POSTROUTING -o rmnet+ -j TTL --ttl-set "$ipv4_ttl"
ip6tables -t mangle -D POSTROUTING -o rmnet+ -j HL --hl-set "$ipv6_ttl"
if [ "$ttl_value" -eq 0 ]; then
echo "Disabling TTL..."
> "$ttl_file"
else
echo "Setting TTL to $ttl_value..."
echo "iptables -t mangle -A POSTROUTING -o rmnet+ -j TTL --ttl-set $ttl_value" > "$ttl_file"
echo "ip6tables -t mangle -A POSTROUTING -o rmnet+ -j HL --hl-set $ttl_value" >> "$ttl_file"
iptables -t mangle -A POSTROUTING -o rmnet+ -j TTL --ttl-set $ttl_value
ip6tables -t mangle -A POSTROUTING -o rmnet+ -j HL --hl-set $ttl_value
fi
fi
fi
done
}
set_root_passwd() {
passwd
}
# Function for Tailscale Submenu
tailscale_menu() {
while true; do
echo -e "\e[1;32mTailscale Menu\e[0m"
echo -e "\e[1;32m1) Install/Update Tailscale\e[0m"
echo -e "\e[1;36m2) Configure Tailscale\e[0m"
echo -e "\e[1;31m3) Return to Main Menu\e[0m"
read -p "Enter your choice: " tailscale_choice
case $tailscale_choice in
1) install_update_tailscale ;;
2) configure_tailscale ;;
3) break ;;
*) echo "Invalid option" ;;
esac
done
}
# Function to install, update, or remove Tailscale
install_update_tailscale() {
echo -e "\e[1;31mInstalling Tailscale from opkg...\e[0m"
opkg install tailscale
if [ $? -ne 0 ]; then
echo -e "\e[1;31mFailed to install Tailscale via opkg.\e[0m"
return 1
fi
echo -e "\e[1;32mTailscale has been installed via opkg.\e[0m"
echo -e "\e[1;32mUpdating to the latest Tailscale version...\e[0m"
# Stop Running Service
service tailscale stop
# Define variables for the download
TAILSCALE_URL="https://pkgs.tailscale.com/stable/tailscale_1.74.1_arm64.tgz"
TAILSCALE_TGZ="/tmp/tailscale_1.74.1_arm64.tgz"
TAILSCALE_TMP_DIR="/tmp/tailscale_update"
# Download the latest Tailscale package
echo -e "\e[1;32mDownloading latest Tailscale package...\e[0m"
curl "$TAILSCALE_URL" -o "$TAILSCALE_TGZ"
if [ $? -ne 0 ]; then
echo -e "\e[1;31mFailed to download Tailscale package. Please check your internet connection.\e[0m"
rm -f "$TAILSCALE_TGZ"
return 1
fi
# Extract the package
echo -e "\e[1;32mExtracting Tailscale package...\e[0m"
mkdir -p "$TAILSCALE_TMP_DIR"
tar -xzf "$TAILSCALE_TGZ" -C "$TAILSCALE_TMP_DIR"
if [ $? -ne 0 ]; then
echo -e "\e[1;31mFailed to extract Tailscale package.\e[0m"
rm -f "$TAILSCALE_TGZ"
rm -rf "$TAILSCALE_TMP_DIR"
return 1
fi
# Replace the binaries with force option
echo -e "\e[1;32mUpdating Tailscale binaries...\e[0m"
cp -f "$TAILSCALE_TMP_DIR/tailscale_1.74.1_arm64/tailscale" /usr/sbin/
cp -f "$TAILSCALE_TMP_DIR/tailscale_1.74.1_arm64/tailscaled" /usr/sbin/
if [ $? -ne 0 ]; then
echo -e "\e[1;31mFailed to copy new Tailscale binaries.\e[0m"
rm -f "$TAILSCALE_TGZ"
rm -rf "$TAILSCALE_TMP_DIR"
return 1
fi
# Set the correct permissions
chmod +x /usr/sbin/tailscale /usr/sbin/tailscaled
# Clean up temporary files
rm -f "$TAILSCALE_TGZ"
rm -rf "$TAILSCALE_TMP_DIR"
# Start Tailscale service if available
service tailscale start
echo -e "\e[1;32mTailscale version 1.74.1 installed\e[0m"
}
# Function to Configure Tailscale
configure_tailscale() {
while true; do
echo "Configure Tailscale"
echo -e "\e[38;5;40m1) Enable Tailscale Web UI at http://192.168.225.1:8088 (Gateway on port 8088)\e[0m" # Green
echo -e "\e[38;5;196m2) Disable Tailscale Web UI\e[0m" # Red
echo -e "\e[38;5;27m3) Connect to Tailnet\e[0m" # Brown
echo -e "\e[38;5;87m4) Connect to Tailnet with SSH ON\e[0m" # Light cyan
echo -e "\e[38;5;105m5) Reconnect to Tailnet with SSH OFF\e[0m" # Light magenta
echo -e "\e[38;5;172m6) Disconnect from Tailnet (reconnects at reboot)\e[0m" # Light yellow
echo -e "\e[1;31m7) Logout from tailscale account\e[0m"
echo -e "\e[38;5;27m8) Return to Tailscale Menu\e[0m"
read -p "Enter your choice: " config_choice
case $config_choice in
1) echo -e "\e[38;5;196mNot for the 551 yet\e[0m" ;; # Red
2) echo -e "\e[38;5;196mNot for the 551 yet\e[0m" ;; # Red
3) tailscale up --accept-dns=false --reset ;;
4) tailscale up --ssh --accept-dns=false --reset ;;
5) tailscale up --accept-dns=false --reset ;;
6) tailscale down ;;
7) tailscale logout ;;
8) break ;;
*) echo "Invalid option" ;;
esac
done
}
# Main menu
while true; do
echo " .%+: "
echo " .*@@@-. "
echo " :@@@@- "
echo " @@@@#. "
echo " -@@@@#. "
echo " :. %@@@@: -# "
echo " .+- #@@@@%.+@- "
echo " .#- . +@@@@# #@- "
echo " -@*@*@% @@@@@::@@= "
echo ".+%@@@@@@@@@%=. =@@@@# #@@- .. "
echo " .@@@@@: :@@@@@ =@@@..%= "
echo " -::@-.+. @@@@@.=@@@- =@- "
echo " .@- .@@@@@:.@@@* @@. "
echo " .%- -@@@@@:=@@@@ @@# "
echo " .#- .%@@@@@@#. +@@@@@.#@@@@ @@@."
echo " .*- .@@@@@@@@@@=. @@@@@@ @@@@@ @@@:"
echo " :. .%@@@@@@@@@@@%. .@@@@@+:@@@@@ @@@-"
echo " -@@@@@@@@@@@@@@@..@@@@@@.-@@@@@ .@@@-"
echo " -@@@@@@@@@@%. .@@@@@@. @@@@@+ =@@@="
echo " =@@@@@@@@* .@@@@@@. @@@@@@..@@@@-"
echo " #@@@@@@@@-*@@@@@%..@@@@@@+ #@@@@-"
echo " @@@@@@:.-@@@@@@. @@@@@@= %@@@@@."
echo " .@@@@. *@@@@@@- .+@@@@@@-.@@@@@@+ "
echo " %@@. =@@@@@*. +@@@@@@%.-@@@@@@% "
echo " .@@ .@@@@@= :@@@@@@@@..@@@@@@@= "
echo " =@.+@@@@@. -@@@@@@@*.:@@@@@@@*. "
echo " %.*@@@@= .@@@@@@@-.:@@@@@@@+. "
echo " ..@@@@= .@@@@@@: #@@@@@@@: "
echo " .@@@@ +@@@@..%@@@@@+. "
echo " .@@@. @@@@.:@@@@+. "
echo " @@@. @@@. @@@* .@. "
echo " :@@@ %@@..@@#. *@ "
echo " -*: .@@* :@@. @@. -..@@ "
echo " =@@@@@@.*@- :@% @* =@:=@# "
echo " .@@@-+@@@@:%@..%- ...@%:@@: "
echo " .@@. @@-%@: .%@@*@@%. "
echo " :@@ :+ *@ *@@#*@@@. "
echo " =@@@.@@@@ "
echo " .*@@@:=@@@@: "
echo " .@@@@:.@@@@@: "
echo " .@@@@#.-@@@@@. "
echo " #@@@@: =@@@@@- "
echo " .@@@@@..@@@@@@* "
echo " -@@@@@. @@@@@@#. "
echo " -@@@@@ @@@@@@% "
echo " @@@@@. #@@@@@@. "
echo " :@@@@# =@@@@@@% "
echo " @@@@@: @@@@@@@: "
echo " *@@@@ @@@@@@@. "
echo " .@@@@ @@@@@@@ "
echo " #@@@. @@@@@@* "
echo " @@@# @@@@@@@ "
echo " .@@+=@@@@@@. "
echo " *@@@@@@ "
echo " :@@@@@= "
echo " .@@@@@@. "
echo " :@@@@@*. "
echo " .=@@@@@- "
echo " :+##+. "
echo -e "\e[92m"
echo "Welcome to iamromulan's rcPCIe Toolkit script for Quectel RM55x Series modems!"
echo "Visit https://github.com/iamromulan for more!"
echo -e "\e[0m"
echo -e "\e[91mThis is a test version of the toolkit for the new RM550/551 modems\e[0m" # Light Red
echo "Select an option:"
echo -e "\e[0m"
echo -e "\e[96m1) Send AT Commands\e[0m" # Cyan
echo -e "\e[92m2) First time setup/run me after a flash!\e[0m" # Green
echo -e "\e[94m3) TTL Setup\e[0m" # Light Blue
echo -e "\e[94m4) Set root password\e[0m" # Light Blue
echo -e "\e[94m5) Tailscale Management\e[0m" # Light Blue
echo -e "\e[92m6) Install Speedtest.net CLI app (speedtest command)\e[0m" # Light Green
echo -e "\e[93m7) Exit\e[0m" # Yellow (repeated color for exit option)
read -p "Enter your choice: " choice
case $choice in
1) send_at_commands_using_atcmd ;;
2) remount_rw; basic_55x_setup ;;
3)
overlay_check
if [ $? -eq 1 ]; then continue; fi
ttl_setup
;;
4)
overlay_check
if [ $? -eq 1 ]; then continue; fi
set_root_passwd
;;
5) tailscale_menu ;;
6)
overlay_check
if [ $? -eq 1 ]; then continue; fi
echo -e "\e[1;32mInstalling Speedtest.net CLI (speedtest command)\e[0m"
cd /usr/bin
curl -O https://install.speedtest.net/app/cli/ookla-speedtest-1.2.0-linux-aarch64.tgz
tar -xzf ookla-speedtest-1.2.0-linux-aarch64.tgz
rm ookla-speedtest-1.2.0-linux-aarch64.tgz
rm speedtest.7
rm speedtest.md
cd /
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;32mNormally 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"
;;
7) echo -e "\e[1;32mGoodbye!\e[0m"; break ;;
*) echo -e "\e[1;31mInvalid option\e[0m" ;;
esac
done

View File

@@ -1 +0,0 @@
2

View File

@@ -1,7 +0,0 @@
#!/bin/bash
#Path
export PATH=/bin:/sbin:/usr/bin:/usr/sbin:/opt/bin:/opt/sbin:/usrdata/root/bin
#Post-login execution
/usrdata/simpleadmin/console/menu/start_menu.sh

View File

@@ -1,150 +0,0 @@
#!/bin/bash
CONFIG_FILE="/etc/data/mobileap_cfg.xml"
# Display Messages in Colors
display_random_color() {
local msg="$1"
local colors=(33 34 35 36 37) # ANSI color codes for yellow, blue, magenta, cyan, white
local num_colors=${#colors[@]}
local random_color_index=$(($RANDOM % num_colors)) # Pick a random index from the colors array
echo -e "\033[${colors[$random_color_index]}m$msg\033[0m"
}
display_green() {
echo -e "\033[0;32m$1\033[0m"
}
display_red() {
echo -e "\033[0;31m$1\033[0m"
}
# Check and Install xml binary if not present
check_and_install_xml() {
if [ ! -f "/opt/bin/xml" ]; then
echo "xml binary not found. Attempting to install xmlstarlet..."
opkg update
opkg install xmlstarlet
# Verify installation
if [ ! -f "/opt/bin/xml" ]; then
echo "Failed to install xmlstarlet. Exiting..."
exit 1
fi
fi
echo "xml binary is available."
}
# Edit XML Value
edit_xml_value() {
local node="$1"
local new_value="$2"
/opt/bin/xml ed -L -u "$node" -v "$new_value" "$CONFIG_FILE"
}
# Get Current XML Value
get_current_value() {
/opt/bin/xml sel -t -v "$1" "$CONFIG_FILE"
}
# Enable/Disable Menu
enable_disable_menu() {
local node="$1"
local current_value=$(get_current_value "$node")
echo "Current status: $([ "$current_value" == "1" ] && echo "Enabled" || echo "Disabled")"
echo "1. Enable"
echo "2. Disable"
read -p "Choose an option to toggle (1-2): " choice
local new_value="$([ "$choice" == "1" ] && echo "1" || echo "0")"
edit_xml_value "$node" "$new_value"
display_green "After making changes, please reboot to have them take effect."
}
# Edit Simple Value
edit_simple_value() {
local node="$1"
local description="$2"
local current=$(get_current_value "$node")
echo "Current $description: $current"
read -p "Enter new $description: " new_value
edit_xml_value "$node" "$new_value"
display_green "After making changes, please reboot to have them take effect."
}
# Edit DHCP IP Range
edit_dhcp_range() {
local start_ip=$(get_current_value "//MobileAPLanCfg/DHCPCfg/StartIP")
local end_ip=$(get_current_value "//MobileAPLanCfg/DHCPCfg/EndIP")
echo "Current Start IP: $start_ip"
echo "Current End IP: $end_ip"
read -p "Enter new Start IP: " new_start_ip
read -p "Enter new End IP: " new_end_ip
edit_xml_value "//MobileAPLanCfg/DHCPCfg/StartIP" "$new_start_ip"
edit_xml_value "//MobileAPLanCfg/DHCPCfg/EndIP" "$new_end_ip"
display_green "After making changes, please reboot to have them take effect."
}
# Reboot the system
reboot_system() {
echo "Rebooting system..."
atcmd 'AT+CFUN=1,1' # Ensure this command is correct for your system
echo "System reboot initiated. Good luck."
}
# Main Menu
main_menu() {
while true; do
clear
display_red "Warning, these changes can break access over the network. Know what you are doing, and be prepared to use ADB to fix this just in case."
echo "Configuration Menu"
echo "------------------"
display_green "1. Edit Gateway IPV4 Address"
display_green "2. Edit Gateway URL"
display_green "3. Edit LAN DHCP Start/End Range"
display_green "4. Edit LAN Subnet Mask"
display_green "5. Edit DHCPv6 Base address"
display_green "6. Toggle IPv4 NAT"
display_green "7. Toggle IPv6 NAT"
display_green "8. Toggle DHCP Server"
display_green "9. Toggle DHCPv4"
display_green "10. Toggle DHCPv6"
display_green "11. Toggle WAN Autoconnect"
display_green "12. Toggle WAN AutoReconnect"
display_green "13. Toggle Roaming"
display_green "14. Toggle WAN DNSv4 Passthrough"
display_green "15. Toggle WAN DNSv6 Passthrough"
display_green "16. Toggle IPPT NAT/Ability to access gateway while in IPPT mode"
display_green "17. Toggle UPnP"
display_green "18. Reboot System"
display_green "19. Exit"
echo
read -p "Select an option (1-19): " option
case "$option" in
1) edit_simple_value "//MobileAPLanCfg/APIPAddr" "Gateway IPV4 Address";;
2) edit_simple_value "//MobileAPLanCfg/GatewayURL" "Gateway URL";;
3) edit_dhcp_range;;
4) edit_simple_value "//MobileAPLanCfg/SubNetMask" "LAN Subnet Mask";;
5) edit_simple_value "//MobileAPLanCfg/ULAIPv6BaseAddr" "DHCPv6 Base Address";;
6) enable_disable_menu "//MobileAPNatCfg/IPv4NATDisable";;
7) enable_disable_menu "//MobileAPNatv6Cfg/EnableIPv6NAT";;
8) enable_disable_menu "//MobileAPLanCfg/EnableDHCPServer";;
9) enable_disable_menu "//MobileAPLanCfg/EnableIPV4";;
10) enable_disable_menu "//MobileAPLanCfg/EnableIPV6";;
11) enable_disable_menu "//MobileAPWanCfg/AutoConnect";;
12) enable_disable_menu "//MobileAPWanCfg/ReConnect";;
13) enable_disable_menu "//MobileAPWanCfg/Roaming";;
14) enable_disable_menu "//Dhcpv4Cfg/EnableDhcpv4Dns";;
15) enable_disable_menu "//Dhcpv6Cfg/EnableDhcpv6Dns";;
16) enable_disable_menu "//IPPassthroughFeatureWithNAT";;
17) enable_disable_menu "//MobileAPSrvcCfg/UPnP";;
18) reboot_system;;
19) break;;
*) echo "Invalid option. Please try again.";;
esac
done
}
# Start by checking and installing xml if necessary, then mount filesystem as rw and run the menu
mount -o remount,rw /
check_and_install_xml
main_menu

View File

@@ -1,125 +0,0 @@
#!/bin/bash
SIMPLE_FIREWALL_DIR="/usrdata/simplefirewall"
SIMPLE_FIREWALL_SCRIPT="$SIMPLE_FIREWALL_DIR/simplefirewall.sh"
SIMPLE_FIREWALL_SYSTEMD_DIR="$SIMPLE_FIREWALL_DIR/systemd"
# Display Messages in Colors
display_random_color() {
local msg="$1"
local colors=(33 34 35 36 37) # ANSI color codes for yellow, blue, magenta, cyan, white
local num_colors=${#colors[@]}
local random_color_index=$(($RANDOM % num_colors)) # Pick a random index from the colors array
echo -e "\033[${colors[$random_color_index]}m$msg\033[0m"
}
display_green() {
echo -e "\033[0;32m$1\033[0m"
}
display_red() {
echo -e "\033[0;31m$1\033[0m"
}
set_portblocks() {
current_ports_line=$(grep '^PORTS=' "$SIMPLE_FIREWALL_SCRIPT")
ports=$(echo "$current_ports_line" | cut -d'=' -f2 | tr -d '()' | tr ' ' '\n' | grep -o '[0-9]\+')
echo -e "\e[1;32mCurrent configured ports:\e[0m"
echo "$ports" | awk '{print NR") "$0}'
while true; do
echo -e "\e[1;32mEnter a port number to add/remove, or type 'done' or 'exit' to finish:\e[0m"
read port
if [ "$port" = "done" ] || [ "$port" = "exit" ]; then
if [ "$port" = "exit" ]; then
echo -e "\e[1;31mExiting without making changes...\e[0m"
return
fi
break
elif ! echo "$port" | grep -qE '^[0-9]+$'; then
echo -e "\e[1;31mInvalid input: Please enter a numeric value.\e[0m"
elif echo "$ports" | grep -q "^$port\$"; then
ports=$(echo "$ports" | grep -v "^$port\$")
echo -e "\e[1;32mPort $port removed.\e[0m"
else
ports=$(echo "$ports"; echo "$port" | grep -o '[0-9]\+')
echo -e "\e[1;32mPort $port added.\e[0m"
fi
done
if [ "$port" != "exit" ]; then
new_ports_line="PORTS=($(echo "$ports" | tr '\n' ' '))"
sed -i "s/$current_ports_line/$new_ports_line/" "$SIMPLE_FIREWALL_SCRIPT"
fi
}
set_ttl(){
# TTL configuration code
ttl_value=$(cat /usrdata/simplefirewall/ttlvalue)
if [ "$ttl_value" -eq 0 ]; then
echo -e "\e[1;31mTTL is not set.\e[0m"
else
echo -e "\e[1;32mTTL value is set to $ttl_value.\e[0m"
fi
echo -e "\e[1;31mType 'exit' to cancel.\e[0m"
read -p "What do you want the TTL value to be: " new_ttl_value
if [ "$new_ttl_value" = "exit" ]; then
echo -e "\e[1;31mExiting TTL configuration...\e[0m"
return
elif ! echo "$new_ttl_value" | grep -qE '^[0-9]+$'; then
echo -e "\e[1;31mInvalid input: Please enter a numeric value.\e[0m"
return
else
/usrdata/simplefirewall/ttl-override stop
echo "$new_ttl_value" > /usrdata/simplefirewall/ttlvalue
/usrdata/simplefirewall/ttl-override start
echo -e "\033[0;32mTTL value updated to $new_ttl_value.\033[0m"
fi
}
# function to configure the fetures of simplefirewall
simple_firewall_menu() {
if [ ! -f "$SIMPLE_FIREWALL_SCRIPT" ]; then
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

View File

@@ -1,116 +0,0 @@
#!/bin/bash
# Define executable files path
MENU_SH=/usrdata/simpleadmin/console/menu
# Display Messages in Colors
display_random_color() {
local msg="$1"
local colors=(33 34 35 36 37) # ANSI color codes for yellow, blue, magenta, cyan, white
local num_colors=${#colors[@]}
local random_color_index=$(($RANDOM % num_colors)) # Pick a random index from the colors array
echo -e "\033[${colors[$random_color_index]}m$msg\033[0m"
}
display_green() {
echo -e "\033[0;32m$1\033[0m"
}
display_red() {
echo -e "\033[0;31m$1\033[0m"
}
# Menus
toolkit_menu() {
while true; do
display_green "Run a Toolkit version"
display_green "Select an option:"
echo "------------------"
display_green "1. Get and run the Toolkit"
display_red "2. Get and run the Development/unstable Toolkit"
display_red "3. Exit (Enter Root Shell)"
echo
read -p "Select an option (1-11): " option
case "$option" in
1) 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 / ;;
2) 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 / ;;
3) break ;;
*) echo "Invalid option. Please try again." ;;
esac
done
}
apps_menu() {
while true; do
display_green "Run a modem App"
display_green "Select an option:"
echo "------------------"
display_random_color "1. Open File Browser/Editor (mc)"
display_random_color "2. View Used/Available space"
display_random_color "3. Open Task Manager/View CPU Load"
display_random_color "4. Run speedtest.net test"
display_random_color "5. Run fast.com test (30Mbps max)"
display_red "6. Go Back"
echo
read -p "Select an option (1-11): " option
case "$option" in
4) mc ;;
5) dfc ;;
6) htop ;;
7) speedtest ;;
8) fast ;;
11) break ;;
*) echo "Invalid option. Please try again." ;;
esac
done
}
settings_menu() {
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_menu ;;
2) settings_menu ;;
3) toolkit_menu ;;
4) break ;;
*) echo "Invalid option. Please try again." ;;
esac
done
}
main_menu

View File

@@ -1,27 +0,0 @@
#!/bin/bash
# Define the command to execute when the ethernet port breaks
command_to_execute="/usrdata/socat-at-bridge/atcmd 'AT+CFUN=1,1'"
# Define the monitoring function
watch() {
while true; do
# Extract the last 60 lines of dmesg and count the specific pattern occurrences
count=$(dmesg | tail -60 | grep -e "eth0: cmd = 0xff, should be 0x47" -e "eth0: pci link is down" | grep -c "eth0")
# Check if the count of patterns is 4 or more
if [ "$count" -ge 4 ]; then
echo "Condition met, executing command..."
eval "$command_to_execute"
# Optionally, add a break here if you want the script to stop after executing the command
# break
fi
# Sleep for 3 seconds before checking again
sleep 3
done
}
# Initial delay before starting monitoring
sleep 30
watch

View File

@@ -1,28 +0,0 @@
#!/bin/bash
# Define the hostname or IP address to ping
HOSTNAME="google.com"
# Number of pings to attempt
PING_COUNT=6
# Initialize a counter for successful pings
success_count=0
# Attempt to ping the specified number of times
for i in $(seq 1 $PING_COUNT); do
# Ping the hostname with a timeout of 1 second per ping
if ping -c 1 -W 1 $HOSTNAME &> /dev/null; then
((success_count++))
else
echo "Ping attempt $i failed."
fi
done
# Check if all pings failed
if [ $success_count -eq 0 ]; then
echo "All $PING_COUNT ping attempts failed, executing AT command."
/bin/atcmd 'AT+CFUN=1,1'
else
echo "$success_count out of $PING_COUNT ping attempts were successful."
fi

View File

@@ -1,14 +0,0 @@
[Unit]
Description=Ping Watchdog Service
Wants=network.target
After=network.target
[Service]
Type=simple
ExecStartPre=/bin/sleep 60 # Sleep for 60 seconds to ensure the network is ready
ExecStart=/usrdata/simpleadmin/console/services/ping_watchdog.sh
Restart=on-failure
RestartSec=30s
[Install]
WantedBy=multi-user.target

View File

@@ -1,99 +0,0 @@
#!/bin/bash
# Check if /usrdata/socat-at-bridge/atcmd exists
if [ -f "/usrdata/socat-at-bridge/atcmd" ]; then
# Read the serial number
serial_number=$(/usrdata/socat-at-bridge/atcmd 'AT+EGMR=0,5' | grep '+EGMR:' | cut -d '"' -f2)
# Read the firmware revision
firmware_revision=$(/usrdata/socat-at-bridge/atcmd 'AT+CGMR' | grep -o 'RM[0-9A-Z]*' | head -1)
else
serial_number="UNKNOWN"
firmware_revision="UNKNOWN"
fi
echo "=============================================================="
echo "=============================================================="
echo "=============================================================="
echo "=============================================================="
echo "=============================================================="
echo "=============================================================="
echo "=============================================================="
echo "=============================================================="
echo "=============================================================="
echo "=============================================================="
echo "=============================================================="
echo "=============================================================="
echo "=============================================================="
echo "=============================================================="
echo "=============================================================="
echo "=============================================================="
echo "=============================================================="
# Start your Actual echo output here, 17 lines omitted for mobile compatibility. ttyd font needs to be size 25.
# Echo "Logo"
echo " .%+: "
echo " .*@@@-. "
echo " :@@@@- "
echo " @@@@#. "
echo " -@@@@#. "
echo " :. %@@@@: -# "
echo " .+- #@@@@%.+@- "
echo " .#- . +@@@@# #@- "
echo " -@*@*@% @@@@@::@@= "
echo ".+%@@@@@@@@@%=. =@@@@# #@@- .. "
echo " .@@@@@: :@@@@@ =@@@..%= "
echo " -::@-.+. @@@@@.=@@@- =@- "
echo " .@- .@@@@@:.@@@* @@. "
echo " .%- -@@@@@:=@@@@ @@# "
echo " .#- .%@@@@@@#. +@@@@@.#@@@@ @@@."
echo " .*- .@@@@@@@@@@=. @@@@@@ @@@@@ @@@:"
echo " :. .%@@@@@@@@@@@%. .@@@@@+:@@@@@ @@@-"
echo " -@@@@@@@@@@@@@@@..@@@@@@.-@@@@@ .@@@-"
echo " -@@@@@@@@@@%. .@@@@@@. @@@@@+ =@@@="
echo " =@@@@@@@@* .@@@@@@. @@@@@@..@@@@-"
echo " #@@@@@@@@-*@@@@@%..@@@@@@+ #@@@@-"
echo " @@@@@@:.-@@@@@@. @@@@@@= %@@@@@."
echo " .@@@@. *@@@@@@- .+@@@@@@-.@@@@@@+ "
echo " %@@. =@@@@@*. +@@@@@@%.-@@@@@@% "
echo " .@@ .@@@@@= :@@@@@@@@..@@@@@@@= "
echo " =@.+@@@@@. -@@@@@@@*.:@@@@@@@*. "
echo " %.*@@@@= .@@@@@@@-.:@@@@@@@+. "
echo " ..@@@@= .@@@@@@: #@@@@@@@: "
echo " .@@@@ +@@@@..%@@@@@+. "
echo " .@@@. @@@@.:@@@@+. "
echo " @@@. @@@. @@@* .@. "
echo " :@@@ %@@..@@#. *@ "
echo " -*: .@@* :@@. @@. -..@@ "
echo " =@@@@@@.*@- :@% @* =@:=@# "
echo " .@@@-+@@@@:%@..%- ...@%:@@: "
echo " .@@. @@-%@: .%@@*@@%. "
echo " :@@ :+ *@ *@@#*@@@. "
echo " =@@@.@@@@ "
echo " .*@@@:=@@@@: "
echo " .@@@@:.@@@@@: "
echo " .@@@@#.-@@@@@. "
echo " #@@@@: =@@@@@- "
echo " .@@@@@..@@@@@@* "
echo " -@@@@@. @@@@@@#. "
echo " -@@@@@ @@@@@@% "
echo " @@@@@. #@@@@@@. "
echo " :@@@@# =@@@@@@% "
echo " @@@@@: @@@@@@@: "
echo " *@@@@ @@@@@@@. "
echo " .@@@@ @@@@@@@ "
echo " #@@@. @@@@@@* "
echo " @@@# @@@@@@@ "
echo " .@@+=@@@@@@. "
echo " *@@@@@@ "
echo " :@@@@@= "
echo " .@@@@@@. "
echo " :@@@@@*. "
echo " .=@@@@@- "
echo " :+##+. "
echo "=============================================================="
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

Binary file not shown.

View File

@@ -1,47 +0,0 @@
server.modules = (
"mod_redirect",
"mod_cgi",
"mod_proxy",
"mod_openssl",
"mod_authn_file",
)
server.username = "www-data"
server.groupname = "dialout"
server.port = 80
server.document-root = "/usrdata/simpleadmin/www"
index-file.names = ( "index.html" )
auth.backend = "htpasswd"
auth.backend.htpasswd.userfile = "/opt/etc/.htpasswd"
$SERVER["socket"] == "0.0.0.0:443" {
ssl.engine = "enable"
ssl.privkey= "/usrdata/simpleadmin/server.key"
ssl.pemfile= "/usrdata/simpleadmin/server.crt"
ssl.acme-tls-1 = "/etc/simpleadmin/dehydrated/tls-alpn-01"
ssl.openssl.ssl-conf-cmd = ("MinProtocol" => "TLSv1.2") # (lighttpd 1.4.56 default; recommended to accept only TLSv1.2 and TLSv1.3)
auth.require = ( "/" => (
"method" => "basic",
"realm" => "Authorized users only",
"require" => "valid-user"
)
)
}
# Redirect everything to https
$HTTP["scheme"] == "http" {
url.redirect = ("" => "https://${url.authority}${url.path}${qsa}")
}
# Anything in /cgi-bin will be run as a script
$HTTP["url"] =~ "/cgi-bin/" {
cgi.assign = ( "" => "" )
}
# Handle proxy to ttyd if it's running
$HTTP["url"] =~ "(^/console)" {
proxy.header = ("map-urlpath" => ( "/console" => "/" ), "upgrade" => "enable" )
proxy.server = ( "" => ("" => ( "host" => "127.0.0.1", "port" => 8080 )))
}

View File

@@ -1,60 +0,0 @@
#!/bin/sh
# Function to create and run the Watchcat script
create_and_run_watchcat_script() {
local ip=$1
local timeout=$2
local failure_count=$3
local script_path="/usrdata/simpleadmin/script/watchcat.sh"
# Create the script with the watchcat logic
sudo cat << EOF > $script_path
#!/bin/sh
failures=0
while :; do
if ping -c 1 $ip > /dev/null 2>&1; then
failures=0
else
failures=\$((failures + 1))
if [ "\$failures" -ge "$failure_count" ]; then
echo "Rebooting system due to \$failures consecutive ping failures."
/sbin/reboot
exit 0
fi
fi
sleep $timeout
done
EOF
# Make the watchcat script executable
chmod +x $script_path
# Create a JSON to be fetched later
echo "{\"enabled\": true, \"track_ip\": \"$ip\", \"ping_timeout\": $timeout, \"ping_failure_count\": $failure_count}" > /usrdata/simpleadmin/script/watchcat.json
# Check if the script was created successfully
if [ -f "$script_path" ]; then
# Make the script executable
chmod +x "$script_path"
# Run the script in the background
# nohup /bin/sh "$script_path" &
/bin/sh "$script_path" &
echo "Watchcat script created and running."
else
echo "Failed to create the Watchcat script."
echo "Please check the script path: $script_path"
fi
}
# Check if the script is called with the required parameters
if [ "$#" -ne 3 ]; then
echo "Usage: $0 <IP> <timeout> <failure_count>"
exit 1
fi
# Call the function with the provided arguments
create_and_run_watchcat_script "$1" "$2" "$3"

View File

@@ -1,32 +0,0 @@
#!/bin/sh
# Function to remove the Watchcat script and JSON file
remove_watchcat_script() {
local script_path="/usrdata/simpleadmin/script/watchcat.sh"
local json_path="/usrdata/simpleadmin/script/watchcat.json"
# Mount as read-write
mount -o remount,rw /
# Remove the watchcat script if it exists
if [ -f "$script_path" ]; then
rm "$script_path"
echo "Removed $script_path"
else
echo "$script_path does not exist"
fi
# Remove the JSON file if it exists
if [ -f "$json_path" ]; then
rm "$json_path"
echo "Removed $json_path"
else
echo "$json_path does not exist"
fi
# Mount as read-only
mount -o remount,ro /
}
# Call the function to remove the scripts
remove_watchcat_script

View File

@@ -1,43 +0,0 @@
#!/bin/sh
# Check if the required parameters are provided
if [ "$#" -ne 2 ]; then
echo "Usage: $0 <enable|disable> <ttl_value>"
exit 1
fi
# Assign the provided parameters to variables
mode="$1"
ttl_value="$2"
# Check if iptables is still set
ttlcheck=$(/opt/bin/sudo /usr/sbin/iptables -w 5 -t mangle -vnL | grep TTL | awk '{print $13}')
# If TTL is still set, manually remove values
if [ ! -z "${ttlcheck}" ]; then
/opt/bin/sudo /usr/sbin/iptables -w 5 -t mangle -D POSTROUTING -o rmnet+ -j TTL --ttl-set "${ttlcheck}" &>/dev/null || true
/opt/bin/sudo /usr/sbin/ip6tables -w 5 -t mangle -D POSTROUTING -o rmnet+ -j HL --hl-set "${ttlcheck}" &>/dev/null || true
fi
# Handle the enable/disable mode
case "${mode}" in
enable)
# Echo TTL to file
echo "${ttl_value}" > /usrdata/simplefirewall/ttlvalue
# Set Start Service
/opt/bin/sudo /usrdata/simplefirewall/ttl-override start
;;
disable)
# Remove TTL value file
rm -f /usrdata/simplefirewall/ttlvalue
# Stop the service
/opt/bin/sudo /usrdata/simplefirewall/ttl-override stop
;;
*)
echo "Invalid mode: ${mode}"
echo "Usage: $0 <enable|disable> <ttl_value>"
exit 1
;;
esac

View File

@@ -1,5 +0,0 @@
#/bin/bash
echo -e "\e[1;31mPlease set your simpleadmin (User: admin) web login password.\e[0m"
/usrdata/root/bin/htpasswd -c /opt/etc/.htpasswd admin
echo -e "\e[1;32mPassword set.\e[0m"

View File

@@ -1,14 +0,0 @@
[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

View File

@@ -1,12 +0,0 @@
[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

View File

@@ -1,26 +0,0 @@
#!/bin/bash
QUERY_STRING=$(echo "${QUERY_STRING}" | sed 's/;//g')
function urldecode() { : "${*//+/ }"; echo -e "${_//%/\\x}"; }
if [ "${QUERY_STRING}" ]; then
export IFS="&"
for cmd in ${QUERY_STRING}; do
if [ "$(echo $cmd | grep '=')" ]; then
key=$(echo $cmd | awk -F '=' '{print $1}')
value=$(echo $cmd | awk -F '=' '{print $2}')
eval $key=$value
fi
done
fi
x=$(urldecode "$atcmd")
MYATCMD=$(printf '%b\n' "${atcmd//%/\\x}")
if [ -n "${MYATCMD}" ]; then
# Capture the response and remove ANSI color codes using awk
runcmd=$(atcmd11 "$x" | awk '{ gsub(/\x1B\[[0-9;]*[mG]/, "") }1')
fi
echo "Content-type: text/plain"
echo $x
echo ""
echo "$runcmd"

View File

@@ -1,19 +0,0 @@
#!/bin/bash
# This script will ping 8.8.8.8 and return the result
# If the ping is successful, it will return "OK"
# If the ping fails, it will return "ERROR"
# Send the ping command and store the output
ping_output=$(ping -c 1 8.8.8.8)
# Check if the output contains "0% packet loss"
if echo "$ping_output" | grep -q "0% packet loss"; then
echo "Content-type: text/plain"
echo ""
echo "OK"
else
echo "Content-type: text/plain"
echo ""
echo "ERROR"
fi

View File

@@ -1,20 +0,0 @@
#!/bin/bash
# Check iptables for ttlvalue
ttlvalue=$(/opt/bin/sudo /usr/sbin/iptables -w 5 -t mangle -vnL | grep TTL | awk '{print $13}' | head -n1)
ttlenabled=true;
# Set Variables
if [ -z "${ttlvalue}" ]; then
ttlvalue=0
ttlenabled=false
fi
echo "Content-type: text/json"
echo ""
cat <<EOT
{
"isEnabled": $ttlenabled,
"ttl": $ttlvalue
}
EOT

View File

@@ -1,11 +0,0 @@
#!/bin/bash
# Execute the uptime command and store the result
uptime_output=$(uptime)
# Set header for plain text content
echo "Content-Type: text/plain"
echo ""
# Output the uptime result
echo "$uptime_output"

View File

@@ -1,17 +0,0 @@
#!/bin/bash
# Content type header
echo "Content-type: application/json"
echo ""
# This script fetches the watchCat parameters from the /tmp/watchcat.json and returns it as JSON
# Example content of /tmp/watchcat:
# {"watchcat": {"enabled": true, "track_ip": "1.1.1.1", "ping_timeout": 30, "ping_failure_count": 10}}
# Check if the file exists
if [ -f /tmp/watchcat.json ]; then
cat /tmp/watchcat.json
else
# return an empty JSON object
echo "{}"
fi

View File

@@ -1,31 +0,0 @@
#!/bin/bash
QUERY_STRING=$(echo "${QUERY_STRING}" | sed 's/;//g')
urldecode() {
local data
data="${*//+/ }"
echo -e "${data//%/\\x}"
}
if [ "${QUERY_STRING}" ]; then
export IFS="&"
for cmd in ${QUERY_STRING}; do
if [[ "$cmd" == *=* ]]; then
key=$(echo "$cmd" | awk -F '=' '{print $1}')
value=$(echo "$cmd" | awk -F '=' '{print $2}')
eval "$key"="$(urldecode "$value")"
fi
done
fi
phone_number="$number"
message_encoded="$msg"
send_at_command() {
local cmd=$1
echo -en "$cmd\r" | microcom -t 100 /dev/ttyOUT2
}
send_at_command "AT+CMGS=\"$phone_number\","$Command""
runcmd=$((echo -en "$message_encoded"; echo -en "\x1A") | microcom -t 500 /dev/ttyOUT2)
echo "$runcmd"

View File

@@ -1,64 +0,0 @@
#!/bin/bash
# Debug log function
log_debug() {
local message="$1"
debug_logs+=("$message")
}
# Initialize debug logs array
declare -a debug_logs=()
# Get query
QUERY_STRING=$(echo "${QUERY_STRING}" | sed 's/;//g')
if [ "${QUERY_STRING}" ]; then
export IFS="&"
for cmd in ${QUERY_STRING}; do
if [ "$(echo $cmd | grep '=')" ]; then
key=$(echo $cmd | awk -F '=' '{print $1}')
value=$(echo $cmd | awk -F '=' '{print $2}')
eval $key=$value
log_debug "Received parameter: $key=$value"
fi
done
fi
setTTL=$(printf '%b\n' "${ttlvalue//%/\\x}")
if [ -n "${setTTL}" ]; then
log_debug "Stopping service to remove rules"
/usrdata/simplefirewall/ttl-override stop
# Convert ttlvalue to integer
if [ "${ttlvalue}" ]; then
ttlvalue_int=$(echo "${ttlvalue}" | sed 's/[^0-9]//g')
log_debug "Converted ttlvalue to integer: $ttlvalue_int"
fi
# Call the sh script with the appropriate parameters
if [ "${ttlvalue_int}" != 0 ]; then
log_debug "Enabling TTL with value: ${setTTL}"
/usrdata/simpleadmin/script/ttl_script.sh enable "${setTTL}"
commandRan="/usrdata/simpleadmin/script/ttl_script.sh enable ${setTTL}"
ttlenabled=true
ttlvalue=$ttlvalue_int
elif [ "${ttlvalue_int}" = 0 ]; then
log_debug "Disabling TTL"
/usrdata/simpleadmin/script/ttl_script.sh disable 0
commandRan="/usrdata/simpleadmin/script/ttl_script.sh disable 0"
ttlenabled=false
ttlvalue=0
fi
log_debug "Starting service to apply rules"
/usrdata/simplefirewall/ttl-override start
fi
echo "Content-type: text/text"
echo ""
cat <<EOT
{
"debug_logs": [
$(printf '"%s",' "${debug_logs[@]}")
]
}
EOT

View File

@@ -1,125 +0,0 @@
#!/bin/bash
QUERY_STRING=$(echo "${QUERY_STRING}" | sed 's/;//g')
function urldecode() { : "${*//+/ }"; echo -e "${_//%/\\x}"; }
if [ "${QUERY_STRING}" ]; then
export IFS="&"
for cmd in ${QUERY_STRING}; do
if [[ "$cmd" == *"="* ]]; then
key=$(echo $cmd | awk -F '=' '{print $1}')
value=$(echo $cmd | awk -F '=' '{print $2}')
eval $key=$(urldecode $value)
fi
done
fi
if [ -z "$status" ] || [ -z "$IpDNS" ] || [ -z "$cooldown" ] || [ -z "$failures" ] || [ -z "$action" ]; then
response="Missing parameters. Please provide the following parameters: IpDNS, cooldown, failures, action."
echo "Content-type: text/plain"
echo ""
echo "$response"
exit 1
fi
if [ "$status" == "enabled" ]; then
watch_script="/usrdata/simpleadmin/script/watchat.sh"
mount -o remount,rw /
cat <<EOF > $watch_script
#!/bin/bash
ip_or_dns="$IpDNS"
cooldown=$cooldown
action="$action"
fail_count=0
max_failures=$failures
# Process the action variable.
# Create a JSON file containing the parameters of the script
echo -n '{"ip_or_dns":"$ip_or_dns","cooldown":$cooldown,"action":"$action","fail_count":$fail_count,"max_failures":$max_failures}' > /tmp/watchatParams.json
while true; do
if ping -c 1 -W 1 \$ip_or_dns > /dev/null; then
fail_count=0
echo "Success at \$(date)" >> /tmp/watchat.log
# Convert /tmp/watchat.log to json format
echo -n '{"log":[' > /tmp/watchat.json
cat /tmp/watchat.log | sed 's/$/,/' | tr -d '\n' | sed 's/,$//' >> /tmp/watchat.json
echo -n ']}' >> /tmp/watchat.json
else
((fail_count++))
if [ \$fail_count -ge \$max_failures ]; then
case "\$action" in
reboot)
echo "Rebooting system..."
/sbin/reboot
;;
switch_sim)
echo "Switching SIM..."
echo -ne "AT+CNMI=2,1\r" > /dev/ttyOUT2
sleep 1
echo "Switching SIM at \$(date)" >> /tmp/watchat.log
;;
none)
echo "No action taken."
echo "No action taken at \$(date)" >> /tmp/watchat.log
;;
*)
echo "Unknown action: \$action"
;;
esac
# Reset fail count
fail_count=0
fi
fi
echo "Fail count: \$fail_count at \$(date)" >> /tmp/watchat.log
# Convert /tmp/watchat.log to json format
echo -n '{"log":[' > /tmp/watchat.json
cat /tmp/watchat.log | sed 's/$/,/' | tr -d '\n' | sed 's/,$//' >> /tmp/watchat.json
echo -n ']}' >> /tmp/watchat.json
sleep \$cooldown
done
EOF
chmod +x $watch_script
cat <<EOF > /lib/systemd/system/watchcat.service
[Unit]
Description=Ping Watcher Service
[Service]
ExecStart=$watch_script
Restart=always
[Install]
WantedBy=multi-user.target
EOF
ln -s /lib/systemd/system/watchcat.service /etc/systemd/system/multi-user.target.wants/watchcat.service
systemctl daemon-reload
systemctl start watchcat.service
response="Script created at $watch_script and made executable. Service created and started."
elif [ "$status" == "disabled" ]; then
watch_script="/usrdata/simpleadmin/script/watchat.sh"
rm -f $watch_script
systemctl stop watchcat.service
rm -f /lib/systemd/system/watchcat.service
rm -f /etc/systemd/system/multi-user.target.wants/watchcat.service
systemctl daemon-reload
response="Script removed at $watch_script. Service stopped and removed."
else
response="Invalid status. Please provide either enabled or disabled."
fi
echo "Content-type: text/plain"
echo ""
echo "$response"

View File

@@ -1,26 +0,0 @@
#!/bin/bash
QUERY_STRING=$(echo "${QUERY_STRING}" | sed 's/;//g')
function urldecode() { : "${*//+/ }"; echo -e "${_//%/\\x}"; }
if [ "${QUERY_STRING}" ]; then
export IFS="&"
for cmd in ${QUERY_STRING}; do
if [ "$(echo $cmd | grep '=')" ]; then
key=$(echo $cmd | awk -F '=' '{print $1}')
value=$(echo $cmd | awk -F '=' '{print $2}')
eval $key=$value
fi
done
fi
x=$(urldecode "$atcmd")
MYATCMD=$(printf '%b\n' "${atcmd//%/\\x}")
if [ -n "${MYATCMD}" ]; then
# Capture the response and remove ANSI color codes using awk
runcmd=$(atcmd "$x" | awk '{ gsub(/\x1B\[[0-9;]*[mG]/, "") }1')
fi
echo "Content-type: text/plain"
echo $x
echo ""
echo "$runcmd"

View File

@@ -1,72 +0,0 @@
#!/bin/bash
# Decode URL-encoded strings
function urldecode() {
local data=${1//+/ }
printf '%b' "${data//%/\\x}"
}
# Parse QUERY_STRING
QUERY_STRING=$(echo "${QUERY_STRING}" | sed 's/;//g')
if [ "${QUERY_STRING}" ]; then
export IFS="&"
for cmd in ${QUERY_STRING}; do
if [[ "$cmd" == *"="* ]]; then
key=$(echo $cmd | awk -F '=' '{print $1}')
value=$(echo $cmd | awk -F '=' '{print $2}')
eval $key=$(urldecode $value)
fi
done
fi
# Set default values
WATCHCAT_ENABLED=${WATCHCAT_ENABLED:-"disable"}
TRACK_IP=${TRACK_IP:-"1.1.1.1"}
PING_TIMEOUT=${PING_TIMEOUT:-30}
PING_FAILURE_COUNT=${PING_FAILURE_COUNT:-3}
# Validate input
if ! [[ "$WATCHCAT_ENABLED" =~ ^(enable|disable)$ ]]; then
echo "Content-type: text/plain"
echo ""
echo "Invalid value for WATCHCAT_ENABLED. Use 'enable' or 'disable'."
exit 1
fi
if ! [[ "$TRACK_IP" =~ ^([0-9]{1,3}\.){3}[0-9]{1,3}$ ]]; then
echo "Content-type: text/plain"
echo ""
echo "Invalid IP address format for TRACK_IP."
exit 1
fi
if ! [[ "$PING_TIMEOUT" =~ ^[0-9]+$ ]] || [ "$PING_TIMEOUT" -le 0 ]; then
echo "Content-type: text/plain"
echo ""
echo "PING_TIMEOUT must be a positive integer."
exit 1
fi
if ! [[ "$PING_FAILURE_COUNT" =~ ^[0-9]+$ ]] || [ "$PING_FAILURE_COUNT" -le 0 ]; then
echo "Content-type: text/plain"
echo ""
echo "PING_FAILURE_COUNT must be a positive integer."
exit 1
fi
# Implement the Watchcat logic
if [ "$WATCHCAT_ENABLED" == "enable" ]; then
echo "Content-type: text/plain"
echo ""
echo "Watchcat is enabled. Tracking IP: $TRACK_IP, Ping timeout: $PING_TIMEOUT seconds, Ping failure count: $PING_FAILURE_COUNT"
# Call the create script here and use the needed parameters
sudo /usrdata/simpleadmin/script/create_watchcat.sh "$TRACK_IP" "$PING_TIMEOUT" "$PING_FAILURE_COUNT"
else
echo "Content-type: text/plain"
echo ""
echo "Watchcat is disabled."
# Call the remove script here
sudo /usrdata/simpleadmin/script/remove_watchcat.sh
fi
exit 0

File diff suppressed because one or more lines are too long

View File

@@ -1,95 +0,0 @@
/* import poppins */
@import url("https://fonts.googleapis.com/css2?family=Poppins:wght@300;400;500;600;700&display=swap");
/* import fontawesome icons */
@import url("https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.3/css/all.min.css");
* {
font-family: "Poppins", sans-serif;
}
.custom-checkbox .form-check-input {
margin-right: 1px;
}
.modal-overlay {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.5);
z-index: 1000;
display: flex;
justify-content: center;
align-items: center;
}
.loading-modal {
background-color: #fff;
padding: 3rem;
border-radius: 10px;
text-align: center;
}
.loading-text {
font-size: 18px;
color: #333;
}
.loader {
width: 64px;
height: 64px;
border: 3px dotted #000;
border-style: solid solid dotted dotted;
border-radius: 50%;
display: inline-block;
position: relative;
box-sizing: border-box;
animation: rotation 2s linear infinite;
margin-bottom: 2rem;
}
.loader::after {
content: "";
box-sizing: border-box;
position: absolute;
left: 0;
right: 0;
top: 0;
bottom: 0;
margin: auto;
border: 3px dotted #0b5ed7;
border-style: solid solid dotted;
width: 24px;
height: 24px;
border-radius: 50%;
animation: rotationBack 1s linear infinite;
transform-origin: center center;
}
@keyframes rotation {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
@keyframes rotationBack {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(-360deg);
}
}
.is-warning {
background-color: #ffb70f !important;
color: #000 !important;
}
.is-medium {
font-weight: 600;
}

View File

@@ -1,522 +0,0 @@
<!DOCTYPE html>
<html lang="en" data-bs-theme="light">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Simple Admin</title>
<!-- <link
href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css"
rel="stylesheet"
integrity="sha384-QWTKZyjpPEjISv5WaRU9OFeRpok6YctnYmDr5pNlyT2bRjXh0JMhjY6hW+ALEwIH"
crossorigin="anonymous"
/> -->
<!-- Import all the bootstrap css files from css folder -->
<link rel="stylesheet" href="css/styles.css" />
<link rel="stylesheet" href="css/bootstrap.min.css" />
<!-- Import BootStrap Javascript -->
<script src="js/bootstrap.bundle.min.js"></script>
<script src="js/alpinejs.min.js" defer></script>
</head>
<body>
<main>
<div class="container my-4" x-data="fetchDeviceInfo()">
<nav class="navbar navbar-expand-lg mt-2">
<div class="container-fluid">
<a class="navbar-brand" href="/"
><span class="mb-0 h4">Simple Admin</span></a
>
<button
class="navbar-toggler"
type="button"
data-bs-toggle="collapse"
data-bs-target="#navbarText"
aria-controls="navbarText"
aria-expanded="false"
aria-label="Toggle navigation"
>
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarText">
<ul class="navbar-nav me-auto mb-2 mb-lg-0">
<li class="nav-item">
<a class="nav-link" href="/">Home</a>
</li>
<li class="nav-item">
<a class="nav-link" href="/network.html">Simple Network</a>
</li>
<li class="nav-item">
<a class="nav-link" href="/scanner.html">Simple Scan</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>
</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">Phone Number</th>
<td class="col-md-2" x-text="phoneNumber"></td>
</tr>
<tr>
<th scope="row">IMSI</th>
<td class="col-md-2" x-text="imsi"></td>
</tr>
<tr>
<th scope="row">ICCID</th>
<td class="col-md-2" x-text="iccid"></td>
</tr>
<tr>
<th scope="row">IMEI</th>
<td class="col-md-2">
<input
class="form-control"
type="text"
x-model="newImei"
x-bind:placeholder="imei === '-' ? '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.9</td>
</tr>
<tr>
<th>Project Contributors</th>
<td>
<!-- Button trigger modal -->
<p
type="button"
class="link-info link-opacity-50-hover link-offset-2"
data-bs-toggle="modal"
data-bs-target="#staticBackdrop"
>
Show Contributors
</p>
<!-- Modal -->
<div
class="modal fade"
id="staticBackdrop"
data-bs-backdrop="static"
data-bs-keyboard="false"
tabindex="-1"
aria-labelledby="staticBackdropLabel"
aria-hidden="true"
>
<div class="modal-dialog modal-dialog-centered">
<div class="modal-content">
<div class="modal-header">
<h1
class="modal-title fs-5"
id="staticBackdropLabel"
>
Contributors
</h1>
<button
type="button"
class="btn-close"
data-bs-dismiss="modal"
aria-label="Close"
></button>
</div>
<div class="modal-body">
<table>
<tbody>
<tr>
<th>
RGMII Toolkit and Documentation
</th>
<td class="col-md-2">
<a
href="https://github.com/iamromulan"
target="_blank"
>iamromulan</a
>
</td>
</tr>
<tr>
<th>Simple Admin 2.0</th>
<td class="col-md-2">
<a
href="https://github.com/dr-dolomite"
target="_blank"
>dr-dolomite</a
>
</td>
</tr>
<tr>
<th>SMS Feature</th>
<td class="col-md-2">
<a
href="https://github.com/snjzb"
target="_blank"
>snjzb</a
>
</td>
</tr>
<tr>
<th>Original Simple Admin</th>
<td class="col-md-2">
<a
href="https://github.com/aesthernr"
target="_blank"
>aesthernr</a
>
</td>
</tr>
<tr>
<th>Original Socat Bridge</th>
<td class="col-md-2">
<a
href="https://github.com/natecarlson"
target="_blank"
>natecarlson</a
>
</td>
</tr>
<tr>
<th>Original Simple Admin Fixes</th>
<td class="col-md-2">
<a
href="https://github.com/rbflurry/"
target="_blank"
>rbflurry</a
>
</td>
</tr>
<tr>
<th>SA Parsing Patch</th>
<td class="col-md-2">
<a
href="https://github.com/tarunVreddy"
target="_blank"
>tarunVreddy</a
>
</td>
</tr>
</tbody>
</table>
</div>
<div class="modal-footer">
<button
type="button"
class="btn btn-secondary"
data-bs-dismiss="modal"
>
Close
</button>
</div>
</div>
</div>
</div>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
<div class="card-footer">
Visit our
<a
href="https://github.com/iamromulan/quectel-rgmii-toolkit/tree/development"
target="_blank"
class="text-reset"
>repository</a
>
or
<a
href="https://github.com/iamromulan/quectel-rgmii-configuration-notes.git"
target="_blank"
class="text-reset"
>documentation</a
>
for more information. All rights reserved. 2024
</div>
</div>
</div>
</div>
<!-- Loading Modal for Reboot -->
<div class="modal-overlay" x-show="showModal">
<div class="loading-modal">
<div
class="loading-text"
style="display: flex; flex-direction: column"
>
<h3>This will reboot the modem.</h3>
<p style="margin-top: 0.5rem">Continue?</p>
</div>
<div class="d-grid gap-2 d-md-block">
<button
class="btn btn-primary"
type="button"
@click="updateIMEI()"
>
Reboot
</button>
<button
class="btn btn-danger"
type="button"
@click="closeModal()"
>
Cancel
</button>
</div>
</div>
</div>
<!-- Reboot Modal Countdown -->
<div class="modal-overlay" x-show="isRebooting">
<div class="loading-modal">
<div class="loader"></div>
<div
class="loading-text"
style="display: flex; flex-direction: column"
>
<h3>Rebooting...</h3>
<p style="margin-top: 0.5rem">
Please wait for
<span x-text="countdown" style="font-weight: 500"></span>
seconds.
</p>
</div>
</div>
</div>
</div>
</main>
<script src="js/dark-mode.js"></script>
<script>
function fetchDeviceInfo() {
return {
manufacturer: "-",
modelName: "-",
firmwareVersion: "-",
imsi: "-",
iccid: "-",
imei: "-",
newImei: null,
lanIp: "-",
wwanIpv4: "-",
wwanIpv6: "-",
phoneNumber: "Unknown",
simpleAdminVersion: "-",
atcmd: null,
atCommandResponse: "",
showModal: false,
isLoading: false,
isRebooting: false,
countdown: 3,
sendATCommand() {
if (!this.atcmd) {
// Use ATI as default command
console.log(
"AT Command is empty, using ATI as default command: "
);
}
this.isLoading = true;
fetch(
"/cgi-bin/get_atcommand?" +
new URLSearchParams({
atcmd: this.atcmd,
})
)
.then((res) => {
return res.text();
})
.then((data) => {
this.atCommandResponse = data;
})
.catch((error) => {
console.error("Error: ", error);
this.showError = true;
});
},
fetchATCommand() {
this.atcmd =
'AT+CGMI;+CGMM;+QGMR;+CIMI;+ICCID;+CGSN;+QMAP="LANIP";+QMAP="WWAN";+CNUM';
this.isLoading = true;
fetch(
"/cgi-bin/get_atcommand?" +
new URLSearchParams({
atcmd: this.atcmd,
})
)
.then((res) => {
return res.text();
})
.then((data) => {
this.atCommandResponse = data;
this.parseFetchedData();
})
.catch((error) => {
console.error("Error: ", error);
this.showError = true;
});
},
parseFetchedData() {
const lines = this.atCommandResponse.split("\n");
console.log("AT Command Response: ", lines);
this.manufacturer = lines[1].trim();
this.modelName = lines[3].trim();
this.firmwareVersion = lines[5].trim();
this.imei = lines[11].trim();
this.lanIp = lines[13].trim().split(",")[3];
this.wwanIpv4 = lines[15].trim().split(",")[4].replace(/"/g, "");
this.wwanIpv6 = lines[16].trim().split(",")[4].replace(/"/g, "");
try {
this.imsi = lines[7].trim();
this.iccid = lines[9].trim().replace("+ICCID: ", "");
this.phoneNumber = lines[18]
.trim()
.split(",")[1]
.replace(/"/g, "");
if (this.phoneNumber === "") {
this.phoneNumber = "Unknown";
}
} catch (error) {
this.phoneNumber = "No SIM Card Inserted or Detected";
this.imsi = " ";
this.iccid = " ";
}
this.simpleAdminVersion = "SimpleAdminRev-Beta-1.0";
this.isLoading = false;
},
updateIMEI() {
this.atcmd = `AT+EGMR=1,7,"${this.newImei}"`;
this.sendATCommand();
this.rebootDevice();
},
rebootDevice() {
this.atcmd = "AT+CFUN=1,1";
this.sendATCommand();
this.isLoading = true;
this.showModal = false;
this.isRebooting = true;
this.countdown = 40;
const interval = setInterval(() => {
this.countdown--;
if (this.countdown === 0) {
clearInterval(interval);
this.isLoading = false;
this.showModal = false;
this.isRebooting = false;
this.init();
}
}, 1000);
},
openModal() {
if (!this.newImei) {
alert("No new IMEI provided.");
return;
}
if (this.newImei.length !== 15) {
alert("IMEI is invalid");
return;
}
if (this.newImei === this.imei) {
alert("IMEI is the same as the current IMEI");
return;
}
this.showModal = true;
},
closeModal() {
this.showModal = false;
},
init() {
this.fetchATCommand();
},
};
}
</script>
</body>
</html>

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -1,37 +0,0 @@
// Function to toggle dark mode
const toggleDarkMode = () => {
const html = document.querySelector('html');
const currentTheme = html.getAttribute('data-bs-theme');
if (currentTheme === 'dark') {
html.removeAttribute('data-bs-theme');
darkModeToggle.textContent = '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');
const html = document.querySelector('html');
if (storedTheme) {
html.setAttribute('data-bs-theme', storedTheme);
if (storedTheme === 'dark') {
darkModeToggle.textContent = 'Light Mode';
} else {
darkModeToggle.textContent = 'Dark Mode';
}
} else {
// If no preference is stored, default to dark mode
html.setAttribute('data-bs-theme', 'dark');
darkModeToggle.textContent = 'Light Mode';
localStorage.setItem('theme', 'dark');
}
darkModeToggle.addEventListener('click', toggleDarkMode);

View File

@@ -1,37 +0,0 @@
const freqNumbersContainer = document.getElementById(
"freqNumbersContainer"
);
function generateFreqNumberInputs(num) {
let html = "";
const maxFields = Math.min(num, 10); // Limit to a maximum of 10 fields
for (let i = 1; i <= maxFields; i++) {
html += `
<div class="input-group mb-3" x-show="cellNum >= ${i} && networkModeCell == 'LTE'">
<input
type="text"
aria-label="EARFCN"
placeholder="EARFCN"
class="form-control"
x-model="earfcn${i}"
/>
<input
type="text"
aria-label="PCI"
placeholder="PCI"
class="form-control"
x-model="pci${i}"
/>
</div>
`;
}
return html;
}
document.addEventListener("DOMContentLoaded", function () {
const cellNumInput = document.querySelector("[aria-label='NumCells']");
cellNumInput.addEventListener("input", function () {
const cellNum = parseInt(this.value);
freqNumbersContainer.innerHTML = generateFreqNumberInputs(cellNum);
});
});

View File

@@ -1,99 +0,0 @@
function parseCurrentSettings(rawdata) {
const data = rawdata;
const lines = data.split("\n");
console.log(lines);
// Remove QUIMSLOT and only take 1 or 2
this.sim = lines
.find(
(line) => line.includes("QUIMSLOT: 1") || line.includes("QUIMSLOT: 2")
)
.split(":")[1]
// remove spaces
.replace(/\s/g, "");
// .replace(/\"/g, "");
try {
this.apn = lines
.find((line) => line.includes("+CGCONTRDP: 1"))
.split(",")[2]
.replace(/\"/g, "");
} catch (error) {
this.apn = "Failed fetching APN";
}
this.cellLock4GStatus = lines
.find((line) => line.includes('+QNWLOCK: "common/4g"'))
.split(",")[1]
.replace(/\"/g, "");
this.cellLock5GStatus = lines
.find((line) => line.includes('+QNWLOCK: "common/5g"'))
.split(",")[1]
.replace(/\"/g, "");
this.prefNetwork = lines
.find((line) => line.includes('+QNWPREFCFG: "mode_pref"'))
.split(",")[1]
.replace(/\"/g, "");
this.nrModeControlStatus = lines
.find((line) => line.includes('+QNWPREFCFG: "nr5g_disable_mode"'))
.split(",")[1]
.replace(/\"/g, "");
this.apnIP = lines
.find((line) => line.includes("+CGDCONT: 1"))
.split(",")[1]
.replace(/\"/g, "");
try {
const PCCbands = lines
.find((line) => line.includes('+QCAINFO: "PCC"'))
.split(",")[3]
.replace(/\"/g, "");
// Loop over all QCAINFO: "SCC" lines and get the bands
try {
const SCCbands = lines
.filter((line) => line.includes('+QCAINFO: "SCC"'))
.map((line) => line.split(",")[3].replace(/\"/g, ""))
.join(", ");
this.bands = `${PCCbands}, ${SCCbands}`;
} catch (error) {
this.bands = PCCbands;
}
} catch (error) {
this.bands = "Failed fetching bands";
}
if (this.cellLock4GStatus == 1 && this.cellLock5GStatus == 1) {
this.cellLockStatus = "Locked to 4G and 5G";
} else if (this.cellLock4GStatus == 1) {
this.cellLockStatus = "Locked to 4G";
} else if (this.cellLock5GStatus == 1) {
this.cellLockStatus = "Locked to 5G";
} else {
this.cellLockStatus = "Not Locked";
}
if (this.nrModeControlStatus == 0) {
this.nrModeControlStatus = "Not Disabled";
} else if (this.nrModeControlStatus == 1) {
this.nrModeControlStatus = "SA Disabled";
} else {
this.nrModeControlStatus = "NSA Disabled";
}
return {
sim: sim,
apn: apn,
apnIP: apnIP,
cellLockStatus: cellLockStatus,
prefNetwork: prefNetwork,
nrModeControl: nrModeControlStatus,
bands: bands,
};
}

View File

@@ -1,81 +0,0 @@
function populateCheckboxes(lte_band, nsa_nr5g_band, nr5g_band, locked_lte_bands, locked_nsa_bands, locked_sa_bands, cellLock) {
var checkboxesForm = document.getElementById("checkboxForm");
var selectedMode = document.getElementById("networkModeBand").value;
var bands;
var prefix;
// Determine bands and prefix based on selected network mode
if (selectedMode === "LTE") {
bands = lte_band;
prefix = "B";
} else if (selectedMode === "NSA") {
bands = nsa_nr5g_band;
prefix = "N";
} else if (selectedMode === "SA") {
bands = nr5g_band;
prefix = "N";
}
checkboxesForm.innerHTML = ""; // Clear existing checkboxes
// Store the locked bands in arrays
var locked_lte_bands_array = locked_lte_bands.split(":");
var locked_nsa_bands_array = locked_nsa_bands.split(":");
var locked_sa_bands_array = locked_sa_bands.split(":");
var isBandLocked = function(band) {
if (selectedMode === "LTE" && locked_lte_bands_array.includes(band)) {
return true;
}
if (selectedMode === "NSA" && locked_nsa_bands_array.includes(band)) {
return true;
}
if (selectedMode === "SA" && locked_sa_bands_array.includes(band)) {
return true;
}
return false;
};
var fragment = document.createDocumentFragment();
if (bands !== null && bands !== "0") {
var bandsArray = bands.split(":");
var currentRow;
bandsArray.forEach(function(band, index) {
if (index % 5 === 0) {
currentRow = document.createElement("div");
currentRow.className = "row mb-2 mx-auto"; // Add margin bottom for spacing
fragment.appendChild(currentRow);
}
var checkboxDiv = document.createElement("div");
checkboxDiv.className = "form-check form-check-reverse col-2"; // Each checkbox takes a column
var checkboxInput = document.createElement("input");
checkboxInput.className = "form-check-input";
checkboxInput.type = "checkbox";
checkboxInput.id = "inlineCheckbox" + band;
checkboxInput.value = band;
checkboxInput.autocomplete = "off";
checkboxInput.checked = isBandLocked(band);
var checkboxLabel = document.createElement("label");
checkboxLabel.className = "form-check-label";
checkboxLabel.htmlFor = "inlineCheckbox" + band;
checkboxLabel.innerText = prefix + band;
checkboxDiv.appendChild(checkboxInput);
checkboxDiv.appendChild(checkboxLabel);
currentRow.appendChild(checkboxDiv);
});
} else {
// Create a text saying that no bands are available
var noBandsText = document.createElement("p");
noBandsText.className = "text-center";
noBandsText.innerText = "No supported bands available";
fragment.appendChild(noBandsText);
}
checkboxesForm.appendChild(fragment);
addCheckboxListeners(cellLock);
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,667 +0,0 @@
<!DOCTYPE html>
<html lang="en" data-bs-theme="light">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Simple Admin</title>
<link rel="stylesheet" href="css/styles.css" />
<link rel="stylesheet" href="css/bootstrap.min.css" />
<!-- Logo -->
<link rel="simpleadmin-logo" href="favicon.ico" />
<!-- Import BootStrap Javascript -->
<script src="js/bootstrap.bundle.min.js"></script>
<script src="js/alpinejs.min.js" defer></script>
</head>
<body>
<main>
<div class="container my-4" x-data="simpleSettings()">
<nav class="navbar navbar-expand-lg mt-2">
<div class="container-fluid">
<a class="navbar-brand" href="/"
><span class="mb-0 h4">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="/scanner.html">Simple Scan</a>
</li>
<li class="nav-item">
<a
class="nav-link active"
href="/settings.html"
aria-current="page"
>Simple Settings</a
>
</li>
<li class="nav-item">
<a class="nav-link" href="/sms.html">SMS</a>
</li>
<li class="nav-item">
<a class="nav-link" href="/console">Console</a>
</li>
<li class="nav-item">
<a class="nav-link" href="/deviceinfo.html"
>Device Information</a
>
</li>
</ul>
<span class="navbar-text">
<button class="btn btn-link text-reset" id="darkModeToggle">
Dark Mode
</button>
</span>
</div>
</div>
</nav>
<div class="row mt-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: 210px"
x-text="atCommandResponse"
readonly
>
<label for="floatingTextarea">ATI</label>
</textarea>
</div>
<div>
<div class="col-md-4 mb-3">
<label for="exampleInputEmail1" class="form-label"
>AT Command</label
>
<input
type="text"
class="form-control"
id="atCommandInput"
placeholder="ATI"
aria-describedby="atCommandInput"
x-model="atcmd"
@keydown.enter="sendUserATCommand()"
/>
<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="sendUserATCommand()"
: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">IP Passthrough</th>
<td>
<select
class="form-select"
id="ipPassModeSelect"
x-model="ipPassMode"
>
<option selected>Passthrough Mode</option>
<option value="ETH">ETH</option>
<option value="USB">USB (ECM/RNDIS)</option>
</select>
</td>
<td>
<button
type="submit"
class="btn btn-primary"
@click="ipPassThroughEnable()"
x-show="ipPassStatus === false"
:disabled="isLoading"
>
Enable
</button>
<button
type="submit"
class="btn btn-danger"
@click="ipPassThroughDisable()"
x-show="ipPassStatus === true"
:disabled="isLoading"
>
Disable
</button>
</td>
</tr>
<tr>
<th scope="row">USB Modem Protocol</th>
<td>
<select
class="form-select"
id="usbNetModeSelect"
x-model="usbNetMode"
>
<option
selected
x-text="currentUsbNetMode"
></option>
<option value="RMNET">RMNET</option>
<option value="ECM">ECM (Recommended)</option>
<option value="MBIM">MBIM</option>
<option value="RNDIS">RNDIS</option>
</select>
</td>
<td>
<button
type="submit"
class="btn btn-primary"
@click="usbNetModeChanger()"
:disabled="isLoading"
>
Change
</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>
</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-1">
<button
class="btn btn-primary"
type="button"
@click="setTTL()"
>
Update
</button>
</div>
</div>
<!-- <div class="card-text">
<div class="d-flex flex-row gap-4 w-full">
<p><a class="link-info link-opacity-50-hover link-offset-2" href="/scanner.html">Go to Cell Scanner</a></p>
<p><a class="link-info link-opacity-50-hover link-offset-2" href="/watchcat.html">Go to WatchCat</a></p>
</div>
</div> -->
</div>
</div>
</div>
</div>
<!-- Loading Modal for Reboot -->
<div class="modal-overlay" x-show="showModal">
<div class="loading-modal">
<div
class="loading-text"
style="display: flex; flex-direction: column"
>
<h3>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,
ipPassMode: "Unspecified",
ipPassStatus: false,
usbNetMode: "Unspecified",
currentUsbNetMode: "Unknown",
DNSProxyStatus: true,
closeModal() {
this.confirmModal = false;
this.showModal = false;
},
showRebootModal() {
this.showModal = true;
},
sendATCommand() {
if (!this.atcmd) {
// Use ATI as default command
this.atcmd = "ATI";
console.log(
"AT Command is empty, using ATI as default command: ",
this.atcmd
);
}
this.isLoading = true;
const encodedATCmd = encodeURIComponent(this.atcmd);
const url = `/cgi-bin/get_atcommand?atcmd=${encodedATCmd}`;
fetch(url)
.then((res) => {
if (!res.ok) {
throw new Error(`HTTP error! status: ${res.status}`);
}
return res.text();
})
.then((data) => {
this.atCommandResponse = data;
this.isLoading = false;
this.isClean = false;
this.fetchCurrentSettings();
})
.catch((error) => {
console.error("Error: ", error);
this.showError = true;
this.isLoading = false;
});
},
sendUserATCommand() {
this.isLoading = true;
const encodedATCmd = encodeURIComponent(this.atcmd);
const url = `/cgi-bin/user_atcommand?atcmd=${encodedATCmd}`;
fetch(url)
.then((res) => {
if (!res.ok) {
throw new Error(`HTTP error! status: ${res.status}`);
}
return res.text();
})
.then((data) => {
this.atCommandResponse = data;
this.isLoading = false;
this.isClean = false;
})
.catch((error) => {
console.error("Error: ", error);
this.showError = true;
this.isLoading = false;
});
},
clearResponses() {
this.atCommandResponse = "";
this.isClean = true;
},
rebootDevice() {
this.atcmd = "AT+CFUN=1,1";
this.sendATCommand();
this.atCommandResponse = "";
this.showModal = false;
this.isRebooting = true;
this.countdown = 40;
// Do the countdown
const interval = setInterval(() => {
this.countdown--;
if (this.countdown === 0) {
clearInterval(interval);
this.isRebooting = false;
this.init();
}
}, 1000);
},
resetATCommands() {
this.atcmd = "AT&F";
this.sendATCommand();
console.log("Resetting AT Commands");
this.atcmd = "";
this.atCommandResponse = "";
this.showRebootModal();
},
ipPassThroughEnable() {
if (this.ipPassMode != "Unspecified") {
if (this.ipPassMode == "ETH") {
this.atcmd =
// at+qmap="mpdn_rule",0,1,1,1,1,"FF:FF:FF:FF:FF:FF"
'AT+QMAP="MPDN_RULE",0,1,0,1,1,"FF:FF:FF:FF:FF:FF"';
this.sendATCommand();
} else if (this.ipPassMode == "USB") {
this.atcmd =
'AT+QMAP="MPDN_RULE",0,1,0,3,1,"FF:FF:FF:FF:FF:FF"';
this.sendATCommand();
} else {
console.error("Invalid IP Passthrough Mode");
}
} else {
console.error("IP Passthrough Mode not specified");
}
},
ipPassThroughDisable() {
this.atcmd = 'AT+QMAP="MPDN_RULE",0;+QMAPWAC=1';
this.sendATCommand();
},
onBoardDNSProxyEnable() {
this.atcmd = 'AT+QMAP="DHCPV4DNS","enable"';
this.sendATCommand().then(() => {
this.fetchCurrentSettings();
});
},
onBoardDNSProxyDisable() {
this.atcmd = 'AT+QMAP="DHCPV4DNS","disable"';
this.sendATCommand().then(() => {
this.fetchCurrentSettings();
});
},
usbNetModeChanger() {
if (this.usbNetMode != "Unspecified") {
if (this.usbNetMode == "RMNET") {
this.atcmd = 'AT+QCFG="usbnet",0;';
this.sendATCommand();
} else if (this.usbNetMode == "ECM") {
this.atcmd = 'AT+QCFG="usbnet",1;';
this.sendATCommand();
} else if (this.usbNetMode == "MBIM") {
this.atcmd = 'AT+QCFG="usbnet",2;';
this.sendATCommand();
} else if (this.usbNetMode == "RNDIS") {
this.atcmd = 'AT+QCFG="usbnet",3;';
this.sendATCommand();
} else {
console.log("USB Net Mode Invalid");
}
} else {
console.error("USB Net Mode not specified");
}
this.rebootDevice();
},
fetchCurrentSettings() {
this.fetchATCommand =
'AT+QMAP="MPDN_RULE";+QMAP="DHCPV4DNS";+QCFG="usbnet"';
fetch(
"/cgi-bin/get_atcommand?" +
new URLSearchParams({
atcmd: this.fetchATCommand,
})
)
.then((res) => {
return res.text();
})
.then((data) => {
// Set the value of currentSettingsResponse
this.currentSettingsResponse = data;
const currentData = data.split("\n");
console.log("Lines: ", currentData);
const testEthpass = currentData[1].match(
/\+QMAP: "MPDN_rule",0,0,0,0,0/
);
if (testEthpass) {
this.ipPassStatus = false;
} else {
this.ipPassStatus = true;
}
const testDNSProxy = currentData[6].match(
/\+QMAP: "DHCPV4DNS","enable"/
);
if (testDNSProxy) {
this.DNSProxyStatus = true;
} else {
this.DNSProxyStatus = false;
}
const testUSBNet = currentData[8].match(
/\+QCFG: "usbnet",(\d)/
);
if (testUSBNet[1] == "0") {
this.currentUsbNetMode = "RMNET";
} else if (testUSBNet[1] == "1") {
this.currentUsbNetMode = "ECM";
} else if (testUSBNet[1] == "2") {
this.currentUsbNetMode = "MBIM";
} else if (testUSBNet[1] == "3") {
this.currentUsbNetMode = "RNDIS";
} else {
this.currentUsbNetMode = "Unknown";
}
// clear atcmd
this.atcmd = "";
})
.catch((error) => {
console.error("Error: ", error);
this.showError = true;
});
},
fetchTTL() {
fetch("/cgi-bin/get_ttl_status")
.then((res) => res.json())
.then((data) => {
this.ttldata = data;
this.ttlStatus = this.ttldata.isEnabled;
this.ttlvalue = this.ttldata.ttl;
});
},
setTTL() {
this.isLoading = true; // Set loading state while updating TTL
const ttlval = this.newTTL;
fetch(
"/cgi-bin/set_ttl?" + new URLSearchParams({ ttlvalue: ttlval })
)
.then((res) => res.text()) // Use res.text() instead of res.json()
.then((data) => {
// Manually handle the response data
console.log("Response from server:", data);
// You can try to parse the JSON manually or handle the response as needed
// Once TTL is updated, fetch the updated TTL data
this.fetchTTL();
this.isLoading = false; // Set loading state back to false
})
.catch((error) => {
console.error("Error updating TTL: ", error);
this.isLoading = false; // Ensure loading state is properly handled in case of error
});
},
init() {
this.fetchCurrentSettings();
this.fetchTTL();
},
};
}
</script>
</body>
</html>

View File

@@ -1,418 +0,0 @@
<!DOCTYPE html>
<html lang="en" data-bs-theme="dark">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Simple Admin</title>
<!-- 导入自定义和Bootstrap样式 -->
<link rel="stylesheet" href="css/styles.css" />
<link rel="stylesheet" href="css/bootstrap.min.css" />
<!-- 网站图标 -->
<link rel="icon" href="favicon.ico" />
<!-- 导入Bootstrap和Alpine.js脚本 -->
<script src="js/bootstrap.bundle.min.js"></script>
<script src="js/alpinejs.min.js" defer></script>
<!-- Contributed By: snjzb -->
</head>
<body>
<main>
<div class="container my-4" x-data="fetchSMS()">
<nav class="navbar navbar-expand-lg mt-2">
<div class="container-fluid">
<a class="navbar-brand" href="/"><span class="mb-0 h4">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="切换导航">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarText">
<ul class="navbar-nav me-auto mb-2 ml-4 mb-lg-0">
<li class="nav-item">
<a class="nav-link" href="/">Home</a>
</li>
<li class="nav-item">
<a class="nav-link" href="/network.html">Simple Network</a>
</li>
<li class="nav-item">
<a class="nav-link" href="/scanner.html">Simple Scan</a>
</li>
<li class="nav-item">
<a class="nav-link" href="/settings.html">Simple Settings</a>
</li>
<li class="nav-item">
<a class="nav-link active" aria-current="page" href="/sms.html">SMS</a>
</li>
<li class="nav-item">
<a class="nav-link" href="/console">Console</a>
</li>
<li class="nav-item">
<a class="nav-link" href="/deviceinfo.html">Device Information</a>
</li>
</ul>
<span class="navbar-text">
<button class="btn btn-link text-reset" id="darkModeToggle">
Dark Mode
</button>
</span>
</div>
</div>
</nav>
<div class="row mt-5 mb-4">
<div class="col">
<div class="card">
<div class="card-header">SMS Inbox</div>
<div class="card-body">
<div class="card-text">
<div class="col">
<div style="
max-height: 400px;
overflow-y: scroll;
overflow-x: hidden;
">
<div x-show="isLoading">
<h4>Fetching SMS...</h4>
</div>
<table class="table table-hover border-success" x-show="!isLoading">
<tbody>
<!-- 没有消息时显示 -->
<!-- Display when there are no messages -->
<template x-if="messages.length === 0 && !isLoading">
<div>
<p>Inbox is Empty</p>
</div>
</template>
<!-- 循环显示短信消息 -->
<!-- "Loop display SMS messages" -->
<template x-for="(message, index) in messages" :key="index">
<tr>
<td>
<div class="form-check">
<input class="form-check-input" type="checkbox" :value="index"
x-model="selectedMessages" />
<div class="row column-gap-1 mb-2">
<div class="col-md-3">
<p x-text="'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.text"></p>
</div>
</div>
</td>
</tr>
</template>
</tbody>
</table>
</div>
</div>
</div>
</div>
<!-- 添加判断只有当messages数组有内容时才显示全选复选框及其区域 -->
<!-- Add a judgment, only when the messages array has content will the select all checkbox and its area be displayed" -->
<div class="card-body border-top" x-show="messages.length > 0">
<div class="form-check">
<input id="selectAllCheckbox" class="form-check-input" type="checkbox" @change="toggleAll($event)" />
<label class="form-check-label">Select All</label>
</div>
</div>
<div class="card-footer">
<div class="d-grid gap-2 d-md-flex justify-content-md-start">
<!-- 刷新按钮 -->
<!-- Refresh button -->
<button class="btn btn-success" type="button" @click="init()">
Refresh
</button>
<!-- 删除选中短信按钮 -->
<!-- Delete selected SMS button -->
<button class="btn btn-danger" type="button" @click="deleteSelectedSMS()">
Delete Selected SMS
</button>
</div>
</div>
</div>
</div>
</div>
<div class="row mt-5 mb-4">
<div class="col">
<div class="card">
<div class="card-header">Send Message</div>
<div class="card-body">
<div class="mb-3">
<label for="phoneNumber" class="form-label">Recipient's Number</label>
<input type="text" class="form-control" id="phoneNumber" x-model="phoneNumber"
placeholder="Enter the recipient's number." />
</div>
<div class="mb-3">
<label for="messageToSend" class="form-label">SMS Content</label>
<textarea class="form-control" id="messageToSend" rows="3" x-model="messageToSend"
placeholder="Enter SMS content."></textarea>
</div>
<div id="notification" class="alert" style="display: none;"></div>
<button class="btn btn-primary" @click="sendSMS()">
Send SMS
</button>
</div>
</div>
</div>
</div>
</div>
</main>
<script src="js/dark-mode.js"></script>
<script>
function fetchSMS() {
return {
isLoading: false,
atCommandResponse: "",
messages: [],
senders: [],
dates: [],
selectedMessages: [],
phoneNumber: '',
messageToSend: '',
messageIndices: [], // 确保初始化messageIndices数组
// 清除现有数据
clearData() {
this.messages = [];
this.senders = [];
this.dates = [];
this.selectedMessages = [];
this.messageIndices = [];
const selectAllCheckbox = document.getElementById('selectAllCheckbox');
if (selectAllCheckbox) {
selectAllCheckbox.checked = false;
}
},
// 请求获取短信
requestSMS() {
this.isLoading = true;
fetch(`/cgi-bin/get_atcommand?${new URLSearchParams({ atcmd: "AT+CSMS=1;+CSDH=0;+CNMI=2,1,0,0,0;+CMGF=1;+CSCA?;+CSMP=17,167,0,8;+CPMS=\"ME\",\"ME\",\"ME\";+CSCS=\"UCS2\";+CMGL=\"ALL\"" })}`)
.then(response => response.text())
.then(data => {
this.atCommandResponse = data.split('\n')
.filter(line => line.trim() !== "OK" && line.trim() !== "")
.join('\n');
})
.finally(() => {
this.isLoading = false;
this.clearData();
this.parseSMSData(this.atCommandResponse);
});
},
// 解析短信数据的方法
parseSMSData(data) {
const cmglRegex = /^\s*\+CMGL:\s*(\d+),"[^"]*","([^"]*)"[^"]*,"([^"]*)"/gm;
const cscaRegex = /^\s*\+CSCA:\s*"([^"]*)"/gm;
this.messageIndices = [];
this.serviceCenters = [];
this.dates = [];
this.senders = [];
this.messages = [];
let match;
let lastIndex = null;
while ((match = cmglRegex.exec(data)) !== null) {
const index = parseInt(match[1]);
const senderHex = match[2];
const sender = senderHex.startsWith("003") ? this.convertHexToText(senderHex) : senderHex;
const dateStr = match[3].replace(/\+\d{2}$/, "");
const date = this.parseCustomDate(dateStr);
if (isNaN(date)) {
console.error(`Invalid Date: ${dateStr}`);
continue;
}
const startIndex = cmglRegex.lastIndex;
const endIndex = data.indexOf("+CMGL:", startIndex) !== -1 ? data.indexOf("+CMGL:", startIndex) : data.length;
const messageHex = data.substring(startIndex, endIndex).trim();
const message = /^[0-9a-fA-F]+$/.test(messageHex) ? this.convertHexToText(messageHex) : messageHex;
if (lastIndex !== null && this.messages[lastIndex].sender === sender && (date - this.messages[lastIndex].date) / 1000 <= 1) {
this.messages[lastIndex].text += " " + message;
this.messages[lastIndex].indices.push(index);
this.dates[lastIndex] = this.formatDate(date);
} else {
this.messageIndices.push([index]);
this.senders.push(sender);
this.dates.push(this.formatDate(date));
this.messages.push({ text: message, sender: sender, date: date, indices: [index] });
lastIndex = this.messages.length - 1;
}
}
while ((match = cscaRegex.exec(data)) !== null) {
const serviceCenterHex = match[1];
const serviceCenter = this.convertHexToText(serviceCenterHex);
this.serviceCenters.push(serviceCenter);
}
},
// 将十六进制转换为文本(假设使用 UTF-16BE 编码)
convertHexToText(hex) {
const bytes = new Uint8Array(hex.match(/.{1,2}/g).map(byte => parseInt(byte, 16)));
return new TextDecoder('utf-16be').decode(bytes);
},
// 自定义解析日期函数
parseCustomDate(dateStr) {
const [datePart, timePart] = dateStr.split(',');
const [day, month, year] = datePart.split('/').map(part => parseInt(part, 10));
const [hour, minute, second] = timePart.split(':').map(part => parseInt(part, 10));
// 将日期转换为标准格式的日期对象
return new Date(Date.UTC(2000 + year, month - 1, day, hour, minute, second));
},
// 自定义格式化日期函数
formatDate(date) {
const year = date.getUTCFullYear() - 2000;
const month = (date.getUTCMonth() + 1).toString().padStart(2, '0');
const day = date.getUTCDate().toString().padStart(2, '0');
const hour = date.getUTCHours().toString().padStart(2, '0');
const minute = date.getUTCMinutes().toString().padStart(2, '0');
const second = date.getUTCSeconds().toString().padStart(2, '0');
return `${day}/${month}/${year},${hour}:${minute}:${second}`;
},
// 删除选中的短信
deleteSelectedSMS() {
if (this.selectedMessages.length === 0) {
console.warn("没有选中的短信");
return;
}
if (!this.messageIndices || this.messageIndices.length === 0) {
console.error("短信索引未正确初始化或为空");
return;
}
// 检查是否全选
const isAllSelected = this.selectedMessages.length === this.messages.length;
if (isAllSelected) {
// 如果全选,则调用删除所有短信的方法
this.deleteAllSMS();
} else {
// 否则,删除选中的短信
const indicesToDelete = [];
this.selectedMessages.forEach(index => {
indicesToDelete.push(...this.messages[index].indices);
});
if (indicesToDelete.length === 0) {
console.warn("没有有效的短信索引");
return;
}
// 拼接 AT 命令
const atCommands = indicesToDelete.map((index, i) => i === 0 ? `AT+CMGD=${index}` : `+CMGD=${index}`).join(';');
fetch(`/cgi-bin/get_atcommand?${new URLSearchParams({ atcmd: atCommands })}`)
.finally(() => {
this.selectedMessages = [];
this.requestSMS();
});
}
},
// 删除所有短信
deleteAllSMS() {
fetch(`/cgi-bin/get_atcommand?${new URLSearchParams({ atcmd: "AT+CMGD=,4" })}`)
.finally(() => {
this.init();
});
},
// 发送短信
encodeUCS2(input) {
let output = '';
for (let i = 0; i < input.length; i++) {
const hex = input.charCodeAt(i).toString(16).toUpperCase().padStart(4, '0');
output += hex;
}
return output;
},
async sendSMS() {
let phoneNumberWithCountryCode;
if (this.phoneNumber.length < 11) {
phoneNumberWithCountryCode = this.phoneNumber;
} else {
const serviceCenterPrefix = this.serviceCenters[0].substring(0, 3);
phoneNumberWithCountryCode = `${serviceCenterPrefix}${this.phoneNumber}`;
}
const encodedPhoneNumber = this.encodeUCS2(phoneNumberWithCountryCode);
const messageSegments = this.splitMessage(this.messageToSend, 70); // 将消息分段
const uid = Math.floor(Math.random() * 256); // 生成随机的UID
const totalSegments = messageSegments.length;
let allSegmentsSent = true;
let errorCode = null;
for (let i = 0; i < totalSegments; i++) {
const segment = messageSegments[i];
const encodedMessage = this.encodeUCS2(segment);
const currentSegment = i + 1;
const Command = `${uid},${currentSegment},${totalSegments}`;
const params = new URLSearchParams({
number: encodedPhoneNumber,
msg: encodedMessage,
Command: Command
});
try {
const response = await fetch(`/cgi-bin/send_sms?${params.toString()}`);
const data = await response.text();
console.log("Response from server:", data);
// 检查返回的数据中是否包含 '+CMS ERROR'
if (data.includes('+CMS ERROR')) {
errorCode = data.match(/\+CMS ERROR: (\d+)/)?.[1];
console.error("SMS send error:", data);
allSegmentsSent = false;
break; // 停止发送剩余的段
}
} catch (error) {
console.error("Fetch error:", error);
allSegmentsSent = false;
break; // 停止发送剩余的段
}
}
if (allSegmentsSent) {
this.showNotification("SMS sent successfully!");
} else {
this.showNotification(`SMS sending failed!: ${errorCode}`);
}
},
splitMessage(message, length) {
const segments = [];
for (let i = 0; i < message.length; i += length) {
segments.push(message.substring(i, i + length));
}
return segments;
},
showNotification(message, type) {
const notification = document.getElementById('notification');
notification.innerText = message;
notification.className = `alert alert-${type}`;
notification.style.display = 'block';
setTimeout(() => {
notification.style.display = 'none';
}, 3000); // 3秒后自动关闭
},
// 初始化
// Initialize
init() {
this.clearData();
this.requestSMS();
},
// 全选/取消全选
// Select all/deselect all
toggleAll(event) {
this.selectedMessages = event.target.checked ? this.messages.map((_, index) => index) : [];
}
};
}
</script>
</body>
</html>

View File

@@ -1,275 +0,0 @@
<!DOCTYPE html>
<html lang="en" data-bs-theme="light">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Simple Admin</title>
<!-- Import all the bootstrap css files from css folder -->
<link rel="stylesheet" href="css/styles.css" />
<link rel="stylesheet" href="css/bootstrap.min.css" />
<!-- Logo -->
<link rel="simpleadmin-logo" href="favicon.ico" />
<!-- Import BootStrap Javascript -->
<script src="js/bootstrap.bundle.min.js"></script>
<script src="js/alpinejs.min.js" defer></script>
<style>
.form-switch .form-check-input {
width: 2.4em;
height: 1.2em;
}
</style>
</head>
<body>
<main>
<div class="container my-4" x-data="simpleWatchCat()">
<nav class="navbar navbar-expand-lg mt-2">
<div class="container-fluid">
<a class="navbar-brand" href="/"
><span class="mb-0 h4">Simple Admin</span></a
>
<button
class="navbar-toggler"
type="button"
data-bs-toggle="collapse"
data-bs-target="#navbarText"
aria-controls="navbarText"
aria-expanded="false"
aria-label="Toggle navigation"
>
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarText">
<ul class="navbar-nav me-auto mb-2 ml-4 mb-lg-0">
<li class="nav-item">
<a class="nav-link" href="/">Home</a>
</li>
<li class="nav-item">
<a class="nav-link" href="/network.html">Simple Network</a>
</li>
<li class="nav-item">
<a class="nav-link" href="/scanner.html">Simple Scan</a>
</li>
<li class="nav-item">
<a
class="nav-link active"
href="/settings.html"
aria-current="page"
>Simple Settings</a
>
</li>
<li class="nav-item">
<a class="nav-link" href="/sms.html">SMS</a>
</li>
<li class="nav-item">
<a class="nav-link" href="/console">Console</a>
</li>
<li class="nav-item">
<a class="nav-link" href="/deviceinfo.html"
>Device Information</a
>
</li>
</ul>
<span class="navbar-text">
<button class="btn btn-link text-reset" id="darkModeToggle">
Dark Mode
</button>
</span>
</div>
</div>
</nav>
<div class="row mt-3 mb-4">
<div class="col">
<div class="card">
<div class="card-header">Simple Watchcat</div>
<div class="card-body">
<div class="card-text">
<div class="row mt-3 mb-5 align-content-center mx-4">
<div class="col">
<div class="mt-3">
<label> Enable Watchcat </label>
</div>
</div>
<div class="col-5">
<div class="mt-2">
<div class="form-check form-switch form-switch-lg">
<input
class="form-check-input"
type="checkbox"
role="switch"
id="watchCatSwitch"
x-model="watchCatStatus"
:disabled="!isFormComplete"
x-on:change="setWatchCatSettings"
/>
</div>
</div>
</div>
</div>
<div class="row mt-3 mb-3 align-items-center mx-4">
<div class="col">
<div class="mt-3 mb-4">
<label> Track IP </label>
</div>
<div class="mt-3 mb-4">
<label> Ping Request Timeout </label>
</div>
<div class="mt-3 mb-4">
<label> Ping Failure Amount </label>
</div>
</div>
<div class="col-5">
<div class="mt-3 mb-4">
<select
class="form-select"
aria-label="Select Site to Ping"
x-model="trackIP"
>
<option selected>Select IP</option>
<option value="1.1.1.1">1.1.1.1</option>
<option value="8.8.8.8">8.8.8.8</option>
<option value="9.9.9.9">9.9.9.9</option>
</select>
</div>
<div class="mt-3 mb-4">
<input
type="number"
class="form-control"
aria-label="Ping Timeout"
aria-describedby="inputGroup-sizing-default"
placeholder="Enter Ping Timeout in Seconds."
x-model="pingTimeout"
/>
</div>
<div class="mt-3 mb-4">
<input
type="number"
class="form-control"
aria-label="Sizing example input"
aria-describedby="inputGroup-sizing-default"
placeholder="Enter Ping Failure Amount."
x-model="pingFailureCount"
/>
</div>
</div>
</div>
</div>
</div>
<div class="card-footer">
Still under development. Coming soon...
</div>
</div>
</div>
</div>
<div class="row mt-3 mb-3">
<div class="col">
<div class="card">
<div class="card-header">Simple Watchcat Logs</div>
<div class="card-body">
<div class="card-text">
<div class="form-floating">
<textarea
class="form-control"
placeholder="Leave a comment here"
id="floatingTextarea2"
style="height: 100px"
x-text="response"
readonly
></textarea>
<label for="floatingTextarea2">Logs</label>
</div>
</div>
</div>
<div class="card-footer">
No log is provided when successfully enabling the watchcat.
</div>
</div>
</div>
</div>
</div>
</main>
<script src="js/dark-mode.js"></script>
<script>
function simpleWatchCat() {
return {
watchCatStatus: false, // Initialize as false (not enabled)
trackIP: "",
pingTimeout: "",
pingFailureCount: "",
response: "",
setWatchCatSettings() {
fetch(
"/cgi-bin/watchcat_maker?" +
new URLSearchParams({
WATCHCAT_ENABLED: this.watchCatStatus ? "enable" : "disable",
TRACK_IP: this.trackIP,
PING_TIMEOUT: this.pingTimeout,
PING_FAILURE_COUNT: this.pingFailureCount,
})
)
.then((response) => response.text()) // Convert response to text
.then((data) => {
this.response = data; // Store the response data
console.log(data); // Log the response for debugging
})
.then(() => {
this.fetchWatchCatSettings();
})
.catch((error) => {
console.error("Error:", error); // Handle any errors
this.response = "An error occurred.";
});
},
// Computed property to check if the form is complete
get isFormComplete() {
return (
this.trackIP !== "" &&
this.pingTimeout !== "" &&
this.pingFailureCount !== ""
);
},
// Fetch the current watchcat settings
fetchWatchCatSettings() {
fetch("/cgi-bin/get_watchcat_status")
.then((response) => {
if (!response.ok) {
throw new Error("Network response was not ok");
}
return response.json(); // Parse response as JSON
})
.then((data) => {
console.log(data); // Log the parsed data for debugging
// Check if the JSON is not empty
if (data) {
this.watchCatStatus = data.enabled === true;
this.trackIP = data.track_ip;
this.pingTimeout = data.ping_timeout;
this.pingFailureCount = data.ping_failure_count;
}
})
.catch((error) => {
console.error("Error:", error); // Handle any errors
this.response = "An error occurred.";
});
},
init() {
this.fetchWatchCatSettings();
},
};
}
</script>
</body>
</html>

View File

@@ -1,351 +0,0 @@
<!DOCTYPE html>
<html lang="en" data-bs-theme="light">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Simple Admin</title>
<!-- <link
href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css"
rel="stylesheet"
integrity="sha384-QWTKZyjpPEjISv5WaRU9OFeRpok6YctnYmDr5pNlyT2bRjXh0JMhjY6hW+ALEwIH"
crossorigin="anonymous"
/> -->
<!-- Import all the bootstrap css files from css folder -->
<link rel="stylesheet" href="css/styles.css" />
<link rel="stylesheet" href="css/bootstrap.min.css" />
<!-- Logo -->
<link rel="simpleadmin-logo" href="favicon.ico" />
<!-- Import BootStrap Javascript -->
<script src="js/bootstrap.bundle.min.js"></script>
<script src="js/alpinejs.min.js" defer></script>
<style>
.form-switch .form-check-input {
width: 2.4em;
height: 1.2em;
}
</style>
</head>
<body>
<main>
<div class="container my-4" x-data="simpleWatchCat()">
<nav class="navbar navbar-expand-lg mt-2">
<div class="container-fluid">
<a class="navbar-brand" href="/"
><span class="mb-0 h4">Simple Admin</span></a
>
<button
class="navbar-toggler"
type="button"
data-bs-toggle="collapse"
data-bs-target="#navbarText"
aria-controls="navbarText"
aria-expanded="false"
aria-label="Toggle navigation"
>
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarText">
<ul class="navbar-nav me-auto mb-2 ml-4 mb-lg-0">
<li class="nav-item">
<a class="nav-link" href="/">Home</a>
</li>
<li class="nav-item">
<a class="nav-link" href="/network.html">Simple Network</a>
</li>
<li class="nav-item">
<a
class="nav-link active"
href="/settings.html"
aria-current="page"
>Simple Settings</a
>
</li>
<li class="nav-item">
<a class="nav-link" href="/sms.html">SMS</a>
</li>
<li class="nav-item">
<a class="nav-link" href="/console">Console</a>
</li>
<li class="nav-item">
<a class="nav-link" href="/deviceinfo.html"
>Device Information</a
>
</li>
</ul>
<span class="navbar-text">
<button class="btn btn-link text-reset" id="darkModeToggle">
Dark Mode
</button>
</span>
</div>
</div>
</nav>
<div class="row mt-3 mb-4">
<div class="col">
<div class="card">
<div class="card-header">Simple Watchcat</div>
<div class="card-body">
<div class="card-text">
<div class="row mt-3 mb-5 align-content-center mx-4">
<div class="col">
<div class="mt-3">
<label> Enable Watchcat </label>
</div>
</div>
<div class="col-5">
<div class="mt-2">
<div class="form-check form-switch form-switch-lg">
<input
class="form-check-input"
type="checkbox"
role="switch"
id="watchCatSwitch"
x-model="watchCatStatus"
:disabled="!isFormComplete"
x:onchange="setWatchCatSettings"
/>
</div>
</div>
</div>
</div>
<div class="row mt-3 mb-3 align-items-center mx-4">
<div class="col">
<div class="mt-3 mb-4">
<label> Track IP </label>
</div>
<div class="mt-3 mb-4">
<label> Ping Request Timeout </label>
</div>
<div class="mt-3 mb-4">
<label> Ping Failure Amount </label>
</div>
</div>
<div class="col-5">
<div class="mt-3 mb-4">
<select
class="form-select"
aria-label="Select Site to Ping"
x-model="trackIP"
>
<option selected>Select IP</option>
<option value="1.1.1.1">1.1.1.1</option>
<option value="8.8.8.8">8.8.8.8</option>
<option value="9.9.9.9">9.9.9.9</option>
</select>
</div>
<div class="mt-3 mb-4">
<input
type="number"
class="form-control"
aria-label="Ping Timeout"
aria-describedby="inputGroup-sizing-default"
placeholder="Enter Ping Timeout in Seconds."
x-model="pingTimeout"
/>
</div>
<div class="mt-3 mb-4">
<input
type="number"
class="form-control"
aria-label="Sizing example input"
aria-describedby="inputGroup-sizing-default"
placeholder="Enter Ping Failure Amount."
x-model="pingFailureCount"
/>
</div>
</div>
</div>
<!-- <div class="row mt-3 mb-5 align-content-center mx-4">
<div class="col">
<div class="mt-3">
<label>Sim Auto Switch</label>
</div>
</div>
<div class="col-5">
<div class="mt-2">
<div class="form-check form-switch form-switch-lg">
<input
class="form-check-input"
type="checkbox"
role="switch"
id="simAutoSwitch"
x-model="simAutoSwitchStatus"
disabled
/>
</div>
</div>
</div>
</div> -->
<!-- <div class="row mt-3 mb-3 align-items-center mx-4">
<div class="col">
<div class="mt-3 mb-4">
<label> Select Preferred SIM </label>
</div>
<div class="mt-3 mb-4">
<label> SIM 1 APN </label>
</div>
<div class="mt-3 mb-4">
<label> SIM 2 APN </label>
</div>
<div class="mt-3 mb-4">
<label> Failover Interval </label>
</div>
<div class="mt-3 mb-4">
<label> Scheduled SIM Hot Swap</label>
</div>
</div>
<div class="col-5">
<div class="mt-3 mb-3">
<select
class="form-select"
aria-label="Select Sim"
x-model="preferredSim"
>
<option selected>Select SIM</option>
<option value="1">SIM 1</option>
<option value="2">SIM 2</option>
</select>
</div>
<div class="mt-3 mb-3">
<input
type="number"
class="form-control"
aria-label="SIM 1 APN"
aria-describedby="inputGroup-sizing-default"
placeholder="Input APN for SIM 1. (Optional)"
x-model="sim1APN"
/>
</div>
<div class="mt-3 mb-3">
<input
type="number"
class="form-control"
aria-label="SIM 2 APN"
aria-describedby="inputGroup-sizing-default"
placeholder="Input APN for SIM 2. (Optional)"
x-model="sim2APN"
/>
</div>
<div class="mt-3 mb-3 d-flex align-items-center">
<select
class="form-select"
aria-label="Failover Interval"
>
<option selected>Failover Interval</option>
<option value="5">5</option>
<option value="10">10</option>
<option value="15">15</option>
<option value="20">20</option>
</select>
<label class="mx-3">Minutes</label>
</div>
<div class="mt-3 mb-3">
<input
type="time"
class="form-control"
aria-label="Scheduled SIM Hot Swap"
aria-describedby="inputGroup-sizing-default"
x-model="scheduledSIMHotSwap"
/>
</div>
</div>
</div> -->
</div>
</div>
<div class="card-footer">
<!-- Setting a low ping timeout and ping failure count may cause
intermittent disconnections due to high sensitivity. <br />
Select appropriate values for both based on your needs.<br /> -->
Still under development. Coming soon...
</div>
</div>
</div>
</div>
<div class="row mt-3 mb-3">
<div class="col">
<div class="card">
<div class="card-header">Simple Watchcat Logs</div>
<div class="card-body">
<div class="card-text">
<div class="form-floating">
<textarea
class="form-control"
placeholder="Leave a comment here"
id="floatingTextarea2"
style="height: 100px"
x-text="response"
readonly
></textarea>
<label for="floatingTextarea2">Logs Here</label>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</main>
<script src="js/dark-mode.js"></script>
<script>
function simpleWatchCat() {
return {
watchCatStatus: false,
trackIP: "",
pingTimeout: "",
pingFailureCount: "",
response: "",
setWatchCatSettings() {
fetch(
"/cgi-bin/watchcat_maker?" +
new URLSearchParams({
WATCHCAT_ENABLED: this.watchCatStatus,
TRACK_IP: this.trackIP,
PING_TIMEOUT: this.pingTimeout,
PING_FAILURE_COUNT: this.pingFailureCount,
})
)
.then((response) => response.text()) // Convert response to text
.then((data) => {
this.response = data; // Store the response data
console.log(data); // Log the response for debugging
})
.catch((error) => {
console.error("Error:", error); // Handle any errors
this.response = "An error occurred.";
});
},
// Computed property to check if the form is complete
get isFormComplete() {
return (
this.trackIP !== "" &&
this.pingTimeout !== "" &&
this.pingFailureCount !== ""
);
},
};
}
</script>
</body>
</html>

View File

@@ -1 +0,0 @@
2

View File

@@ -1,16 +0,0 @@
#!/bin/bash
# Define the ports you want to block
PORTS=("80" "443") # Default ports, will be modified by the install script
# First, allow specified ports on bridge0, eth0, and tailscale0
for port in "${PORTS[@]}"; do
iptables -A INPUT -i bridge0 -p tcp --dport $port -j ACCEPT
iptables -A INPUT -i eth0 -p tcp --dport $port -j ACCEPT
iptables -A INPUT -i tailscale0 -p tcp --dport $port -j ACCEPT
done
# Then, block specified ports on all other interfaces
for port in "${PORTS[@]}"; do
iptables -A INPUT -p tcp --dport $port -j DROP
done

View File

@@ -1,11 +0,0 @@
[Unit]
Description=Simple Firewall Setup
After=network.target
[Service]
Type=oneshot
ExecStart=/bin/bash /usrdata/simplefirewall/simplefirewall.sh
RemainAfterExit=yes
[Install]
WantedBy=multi-user.target

View File

@@ -1,12 +0,0 @@
[Unit]
Description=TTL Override
After=ql-netd.service
DefaultDependencies=no
[Service]
Type=oneshot
ExecStart=/usrdata/simplefirewall/ttl-override start
User=root
[Install]
WantedBy=multi-user.target

View File

@@ -1,53 +0,0 @@
#! /bin/bash
# Adapted from https://github.com/natecarlson/quectel-rgmii-configuration-notes/blob/main/files/ttl-override
# Uses ttlvalue file to read what ttl should be set to
if [ -f /usrdata/simplefirewall/ttlvalue ];
then
ttlfile=$(</usrdata/simplefirewall/ttlvalue)
TTLVALUE=$(echo $ttlfile | grep -o "[0-9]\{1,3\}")
if [ -z "${TTLVALUE}" ]; then
echo "Couldnt get proper ttl value from file" >&2
exit 1
fi
else
# Couldnt find ttlvalue file, lets generate one with 0 ttlvalue (0 = disabled)
touch /usrdata/simplefirewall/ttlvalue && echo '0' > /usrdata/simplefirewall/ttlvalue
exit 1
fi
case "$1" in
start)
if (( $TTLVALUE > 0 )); then
echo "Adding TTL override rules: "
iptables -t mangle -I POSTROUTING -o rmnet+ -j TTL --ttl-set ${TTLVALUE}
ip6tables -t mangle -I POSTROUTING -o rmnet+ -j HL --hl-set ${TTLVALUE}
else
echo "TTLVALUE set to 0, nothing to do..."
fi
echo "done"
;;
stop)
if (( $TTLVALUE > 0 )); then
echo "Removing TTL override rules: "
iptables -t mangle -D POSTROUTING -o rmnet+ -j TTL --ttl-set ${TTLVALUE} &>/dev/null || true
ip6tables -t mangle -D POSTROUTING -o rmnet+ -j HL --hl-set ${TTLVALUE} &>/dev/null || true
else
echo "TTLVALUE set to 0, nothing to do..."
fi
echo "done"
;;
restart)
$0 stop
$0 start
;;
*)
echo "Usage ttl-override { start | stop | restart }" >&2
exit 1
;;
esac
exit 0

View File

@@ -1 +0,0 @@
0

View File

@@ -1 +0,0 @@
2

View File

@@ -1,221 +0,0 @@
#!/bin/bash
# Define constants
GITUSER="iamromulan"
GITTREE="development"
DIR_NAME="simpleadmin"
SERVICE_FILE="/lib/systemd/system/install_simpleadmin.service"
SERVICE_NAME="install_simpleadmin"
TMP_SCRIPT="/tmp/install_simpleadmin.sh"
LOG_FILE="/tmp/install_simpleadmin.log"
# Tmp Script dependent constants
SIMPLE_ADMIN_DIR="/usrdata/simpleadmin"
# Function to remount file system as read-write
remount_rw() {
mount -o remount,rw /
}
# Function to remount file system as read-only
remount_ro() {
mount -o remount,ro /
}
# Installation Prep
remount_rw
systemctl daemon-reload
rm $SERVICE_FILE > /dev/null 2>&1
rm $SERVICE_NAME > /dev/null 2>&1
# Create the systemd service file
cat <<EOF > "$SERVICE_FILE"
[Unit]
Description=Update $DIR_NAME temporary service
[Service]
Type=oneshot
ExecStart=/bin/bash $TMP_SCRIPT > $LOG_FILE 2>&1
[Install]
WantedBy=multi-user.target
EOF
# Create and populate the temporary shell script for installation
cat <<EOF > "$TMP_SCRIPT"
#!/bin/bash
GITUSER="iamromulan"
GITTREE="development"
SIMPLE_ADMIN_DIR="/usrdata/simpleadmin"
# Function to remount file system as read-write
remount_rw() {
mount -o remount,rw /
}
# Function to remount file system as read-only
remount_ro() {
mount -o remount,ro /
}
remount_rw
uninstall_simpleadmin() {
echo "Uninstalling Simpleadmin..."
# Check if Lighttpd service is installed and remove it if present
if [ -f "/lib/systemd/system/lighttpd.service" ]; then
echo "Lighttpd detected, uninstalling Lighttpd webserver and its modules..."
systemctl stop lighttpd
rm -f /lib/systemd/system/lighttpd.service
opkg --force-remove --force-removal-of-dependent-packages remove lighttpd-mod-authn_file lighttpd-mod-auth lighttpd-mod-cgi lighttpd-mod-openssl lighttpd-mod-proxy lighttpd
fi
echo -e "\e[1;34mUninstalling simpleadmin content...\e[0m"
systemctl stop simpleadmin_generate_status
systemctl stop simpleadmin_httpd
rm -f /lib/systemd/system/simpleadmin_httpd.service
rm -f /lib/systemd/system/simpleadmin_generate_status.service
systemctl daemon-reload
echo -e "\e[1;34mUninstalling ttyd...\e[0m"
systemctl stop ttyd
rm -rf /usrdata/ttyd
rm -rf "$SIMPLE_ADMIN_DIR"
rm -f /lib/systemd/system/ttyd.service
rm -f /lib/systemd/system/multi-user.target.wants/ttyd.service
rm -f /bin/ttyd
echo -e "\e[1;32mttyd has been uninstalled.\e[0m"
echo "Uninstallation process completed."
}
install_lighttpd() {
# Check for simpleadmin_httpd service and remove if exists
if [ -f "/lib/systemd/system/simpleadmin_httpd.service" ]; then
systemctl stop simpleadmin_httpd
rm /lib/systemd/system/simpleadmin_httpd.service
rm /lib/systemd/system/multi-user.target.wants/simpleadmin_httpd.service
fi
/opt/bin/opkg install sudo lighttpd lighttpd-mod-auth lighttpd-mod-authn_file lighttpd-mod-cgi lighttpd-mod-openssl lighttpd-mod-proxy
# Ensure rc.unslung doesn't try to start it
# Dynamically find and remove any Lighttpd-related init script
for script in /opt/etc/init.d/*lighttpd*; do
if [ -f "$script" ]; then
echo "Removing existing Lighttpd init script: $script"
rm "$script" # Remove the script if it contains 'lighttpd' in its name
fi
done
systemctl stop lighttpd
echo -e "\033[0;32mInstalling/Updating Lighttpd...\033[0m"
mkdir -p "$SIMPLE_ADMIN_DIR"
wget -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/script
mkdir $SIMPLE_ADMIN_DIR/console
mkdir $SIMPLE_ADMIN_DIR/console/menu
mkdir $SIMPLE_ADMIN_DIR/console/services
mkdir $SIMPLE_ADMIN_DIR/console/services/systemd
mkdir $SIMPLE_ADMIN_DIR/www
mkdir $SIMPLE_ADMIN_DIR/www/cgi-bin
mkdir $SIMPLE_ADMIN_DIR/www/css
mkdir $SIMPLE_ADMIN_DIR/www/js
cd $SIMPLE_ADMIN_DIR/systemd
wget https://raw.githubusercontent.com/$GITUSER/quectel-rgmii-toolkit/$GITTREE/simpleadmin/systemd/lighttpd.service
sleep 1
cd $SIMPLE_ADMIN_DIR/script
wget https://raw.githubusercontent.com/$GITUSER/quectel-rgmii-toolkit/$GITTREE/simpleadmin/script/ttl_script.sh
wget https://raw.githubusercontent.com/$GITUSER/quectel-rgmii-toolkit/$GITTREE/simpleadmin/script/remove_watchcat.sh
wget https://raw.githubusercontent.com/$GITUSER/quectel-rgmii-toolkit/$GITTREE/simpleadmin/script/create_watchcat.sh
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/favicon.ico
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/scanner.html
wget https://raw.githubusercontent.com/$GITUSER/quectel-rgmii-toolkit/$GITTREE/simpleadmin/www/watchcat.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
wget https://raw.githubusercontent.com/$GITUSER/quectel-rgmii-toolkit/$GITTREE/simpleadmin/www/cgi-bin/get_uptime
wget https://raw.githubusercontent.com/$GITUSER/quectel-rgmii-toolkit/$GITTREE/simpleadmin/www/cgi-bin/get_watchcat_status
wget https://raw.githubusercontent.com/$GITUSER/quectel-rgmii-toolkit/$GITTREE/simpleadmin/www/cgi-bin/set_watchcat
wget https://raw.githubusercontent.com/$GITUSER/quectel-rgmii-toolkit/$GITTREE/simpleadmin/www/cgi-bin/watchcat_maker
sleep 1
cd /
chmod +x $SIMPLE_ADMIN_DIR/www/cgi-bin/*
chmod +x $SIMPLE_ADMIN_DIR/script/*
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

View File

@@ -1,106 +0,0 @@
#!/bin/bash
# Define constants
GITUSER="iamromulan"
GITTREE="development"
DIR_NAME="simplefirewall"
SERVICE_FILE="/lib/systemd/system/install_simplefirewall.service"
SERVICE_NAME="install_simplefirewall"
TMP_SCRIPT="/tmp/install_simple_firewall.sh"
LOG_FILE="/tmp/install_simplefirewall.log"
# Tmp Script dependent constants
SIMPLE_FIREWALL_DIR="/usrdata/simplefirewall"
SIMPLE_FIREWALL_SCRIPT="$SIMPLE_FIREWALL_DIR/simplefirewall.sh"
SIMPLE_FIREWALL_SYSTEMD_DIR="$SIMPLE_FIREWALL_DIR/systemd"
# Function to remount file system as read-write
remount_rw() {
mount -o remount,rw /
}
# Function to remount file system as read-only
remount_ro() {
mount -o remount,ro /
}
remount_rw
# Create the systemd service file
cat <<EOF > "$SERVICE_FILE"
[Unit]
Description=Update $DIR_NAME temporary service
[Service]
Type=oneshot
ExecStart=/bin/bash $TMP_SCRIPT > $LOG_FILE 2>&1
[Install]
WantedBy=multi-user.target
EOF
# Create and populate the temporary shell script for installation
cat <<EOF > "$TMP_SCRIPT"
#!/bin/bash
GITUSER="iamromulan"
GITTREE="development"
SIMPLE_FIREWALL_DIR="/usrdata/simplefirewall"
SIMPLE_FIREWALL_SCRIPT="$SIMPLE_FIREWALL_DIR/simplefirewall.sh"
SIMPLE_FIREWALL_SYSTEMD_DIR="$SIMPLE_FIREWALL_DIR/systemd"
# Function to remount file system as read-write
remount_rw() {
mount -o remount,rw /
}
# Function to remount file system as read-only
remount_ro() {
mount -o remount,ro /
}
remount_rw
# Function to remove Simple Firewall
uninstall_simple_firewall() {
echo "Uninstalling Simplefirewall..."
systemctl stop simplefirewall
systemctl stop ttl-override
rm -f /lib/systemd/system/simplefirewall.service
rm -f /lib/systemd/system/ttl-override.service
systemctl daemon-reload
rm -rf "$SIMPLE_FIREWALL_DIR"
echo "Simplefirewall uninstalled."
}
# Function to install Simple Firewall
install_simple_firewall() {
systemctl stop simplefirewall
systemctl stop ttl-override
echo -e "\033[0;32mInstalling/Updating Simple Firewall...\033[0m"
mount -o remount,rw /
mkdir -p "$SIMPLE_FIREWALL_DIR"
mkdir -p "$SIMPLE_FIREWALL_SYSTEMD_DIR"
wget -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

View File

@@ -1,46 +0,0 @@
#!/bin/bash
# WORK IN PROGRESS
# Define constants
GITUSER="iamromulan"
GITTREE="development"
DIR_NAME="simpleupdates"
SERVICE_FILE="/lib/systemd/system/install_simpleupdates.service"
SERVICE_NAME="install_simpleupdates"
TMP_SCRIPT="/tmp/install_simpleupdates.sh"
LOG_FILE="/tmp/install_simpleupdates.log"
# Tmp Script dependent constants
# Create the systemd service file
cat <<EOF > "$SERVICE_FILE"
[Unit]
Description=Update $DIR_NAME temporary service
[Service]
Type=oneshot
ExecStart=/bin/bash $TMP_SCRIPT > $LOG_FILE 2>&1
[Install]
WantedBy=multi-user.target
EOF
# Create and populate the temporary shell script for installation
cat <<EOF > "$TMP_SCRIPT"
#!/bin/bash
install_simpleupdates() {
# CONTENT
}
install_simpleupdates
exit 0
EOF
# Make the temporary script executable
chmod +x "$TMP_SCRIPT"
# Reload systemd to recognize the new service and start the update
systemctl daemon-reload
systemctl start $SERVICE_NAME

View File

@@ -1,147 +0,0 @@
#!/bin/bash
# Define constants
GITUSER="iamromulan"
GITTREE="development"
DIR_NAME="socat-at-bridge"
SERVICE_FILE="/lib/systemd/system/install_socat-at-bridge.service"
SERVICE_NAME="install_socat-at-bridge"
TMP_SCRIPT="/tmp/install_socat-at-bridge.sh"
LOG_FILE="/tmp/install_socat-at-bridge.log"
# Tmp Script dependent constants
SOCAT_AT_DIR="/usrdata/socat-at-bridge"
SOCAT_AT_SYSD_DIR="/usrdata/socat-at-bridge/systemd_units"
# Function to remount file system as read-write
remount_rw() {
mount -o remount,rw /
}
# Function to remount file system as read-only
remount_ro() {
mount -o remount,ro /
}
remount_rw
# Create the systemd service file
cat <<EOF > "$SERVICE_FILE"
[Unit]
Description=Update $DIR_NAME temporary service
[Service]
Type=oneshot
ExecStart=/bin/bash $TMP_SCRIPT > $LOG_FILE 2>&1
[Install]
WantedBy=multi-user.target
EOF
# Create and populate the temporary shell script for installation
cat <<EOF > "$TMP_SCRIPT"
#!/bin/bash
GITUSER="iamromulan"
GITTREE="development"
SOCAT_AT_DIR="/usrdata/socat-at-bridge"
SOCAT_AT_SYSD_DIR="/usrdata/socat-at-bridge/systemd_units"
# Function to remount file system as read-write
remount_rw() {
mount -o remount,rw /
}
# Function to remount file system as read-only
remount_ro() {
mount -o remount,ro /
}
remount_rw
uninstall_at_socat() {
echo -e "\033[0;32mRemoving installed AT Socat Bridge services...\033[0m"
systemctl stop at-telnet-daemon > /dev/null 2>&1
systemctl disable at-telnet-daemon > /dev/null 2>&1
systemctl stop socat-smd11 > /dev/null 2>&1
systemctl stop socat-smd11-to-ttyIN > /dev/null 2>&1
systemctl stop socat-smd11-from-ttyIN > /dev/null 2>&1
systemctl stop socat-smd7 > /dev/null 2>&1
systemctl stop socat-smd7-to-ttyIN2 > /dev/null 2>&1
systemctl stop socat-smd7-to-ttyIN > /dev/null 2>&1
systemctl stop socat-smd7-from-ttyIN2 > /dev/null 2>&1
systemctl stop socat-smd7-from-ttyIN > /dev/null 2>&1
rm /lib/systemd/system/at-telnet-daemon.service > /dev/null 2>&1
rm /lib/systemd/system/socat-smd11.service > /dev/null 2>&1
rm /lib/systemd/system/socat-smd11-to-ttyIN.service > /dev/null 2>&1
rm /lib/systemd/system/socat-smd11-from-ttyIN.service > /dev/null 2>&1
rm /lib/systemd/system/socat-smd7.service > /dev/null 2>&1
rm /lib/systemd/system/socat-smd7-to-ttyIN2.service > /dev/null 2>&1
rm /lib/systemd/system/socat-smd7-to-ttyIN.service > /dev/null 2>&1
rm /lib/systemd/system/socat-smd7-from-ttyIN.service > /dev/null 2>&1
rm /lib/systemd/system/socat-smd7-from-ttyIN2.service > /dev/null 2>&1
systemctl daemon-reload > /dev/null 2>&1
rm -rf "$SOCAT_AT_DIR" > /dev/null 2>&1
}
install_at_socat() {
# Install service units
echo -e "\033[0;32mInstalling AT Socat Bridge services...\033[0m"
mkdir $SOCAT_AT_DIR
cd $SOCAT_AT_DIR
mkdir $SOCAT_AT_SYSD_DIR
wget 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

View File

@@ -1,73 +0,0 @@
#!/bin/bash
# Define constants
GITUSER="iamromulan"
GITTREE="development"
DIR_NAME="simpleupdates"
SERVICE_FILE="/lib/systemd/system/install_sshd.service"
SERVICE_NAME="install_sshd"
TMP_SCRIPT="/tmp/install_sshd.sh"
LOG_FILE="/tmp/install_sshd.log"
# Tmp Script dependent constants
# Create the systemd service file
cat <<EOF > "$SERVICE_FILE"
[Unit]
Description=Update $DIR_NAME temporary service
[Service]
Type=oneshot
ExecStart=/bin/bash $TMP_SCRIPT > $LOG_FILE 2>&1
[Install]
WantedBy=multi-user.target
EOF
# Create and populate the temporary shell script for installation
cat <<EOF > "$TMP_SCRIPT"
#!/bin/bash
GITUSER="iamromulan"
GITTREE="development"
install_sshd() {
echo -e "\e[1;32mOpenSSH Server\e[0m"
remount_rw
mkdir /usrdata/sshd
wget -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

View File

@@ -1,113 +0,0 @@
#!/bin/bash
# Define constants
GITUSER="iamromulan"
GITTREE="development"
DIR_NAME="tailscale"
SERVICE_FILE="/lib/systemd/system/install_tailscale.service"
SERVICE_NAME="install_tailscale"
TMP_SCRIPT="/tmp/install_tailscale.sh"
LOG_FILE="/tmp/install_sshd.log"
# Tmp Script dependent constants
TAILSCALE_DIR="/usrdata/tailscale/"
TAILSCALE_SYSD_DIR="/usrdata/tailscale/systemd"
# Function to remount file system as read-write
remount_rw() {
mount -o remount,rw /
}
# Function to remount file system as read-only
remount_ro() {
mount -o remount,ro /
}
# Installation Prep
remount_rw
systemctl daemon-reload
rm $SERVICE_FILE > /dev/null 2>&1
rm $SERVICE_NAME > /dev/null 2>&1
# Create the systemd service file
cat <<EOF > "$SERVICE_FILE"
[Unit]
Description=Update $DIR_NAME temporary service
[Service]
Type=oneshot
ExecStart=/bin/bash $TMP_SCRIPT > $LOG_FILE 2>&1
[Install]
WantedBy=multi-user.target
EOF
# Create and populate the temporary shell script for installation
cat <<EOF > "$TMP_SCRIPT"
#!/bin/bash
export HOME=/usrdata/root
GITUSER="iamromulan"
GITTREE="development"
TAILSCALE_DIR="/usrdata/tailscale/"
TAILSCALE_SYSD_DIR="/usrdata/tailscale/systemd"
# Function to remount file system as read-write
remount_rw() {
mount -o remount,rw /
}
# Function to remount file system as read-only
remount_ro() {
mount -o remount,ro /
}
install_update_tailscale() {
echo "Checking if Tailscale is already installed..."
if [ -f "$TAILSCALE_DIR/tailscale" ]; then
echo "Tailscale binary found. Updating Tailscale..."
ln -sf "$TAILSCALE_DIR/tailscale" "/usrdata/root/bin/tailscale"
echo y | $TAILSCALE_DIR/tailscale update
echo -e "\e[32mTailscale updated!\e[0m"
remount_ro
exit 0
else
echo "Installing Tailscale..."
mkdir -p "$TAILSCALE_DIR" "$TAILSCALE_SYSD_DIR"
echo "Downloading binary files..."
cd /usrdata
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

View File

@@ -1,12 +0,0 @@
# Enable or disable update checks
CONF_ENABLED=no
# Check for updates at boot
CHECK_AT_BOOT=no
# Update frequency: daily, weekly, monthly, or none
UPDATE_FREQUENCY=none
# Scheduled time for updates (24-hour UTC format)
SCHEDULED_TIME=00:00
# Day for weekly updates (e.g., Mon, Tues, Wed, Thurs, Fri)
WEEKLY_DAY=
# Date for monthly updates (e.g., 15 for the 15th of the month)
MONTHLY_DATE=

View File

@@ -1,255 +0,0 @@
#!/bin/bash
# Configuration and directories
CONFIG_FILE="/usrdata/simpleupdates/simpleupdate.conf"
GITUSER="iamromulan"
GITTREE="main"
DIRECTORIES=("simpleadmin" "socat-at-bridge" "simplefirewall" "tailscale" "ttyd")
BASE_URL="https://raw.githubusercontent.com/$GITUSER/quectel-rgmii-toolkit/$GITTREE"
LOG_FILE="/tmp/simpleupdate.log"
# Load configuration
load_config() {
if [[ -f "$CONFIG_FILE" ]]; then
source "$CONFIG_FILE"
else
echo "Configuration file ($CONFIG_FILE) not found."
exit 1
fi
}
# Function to trim the log file to the last 100 lines
trim_log_file() {
tail -n 100 "$LOG_FILE" > "$LOG_FILE.tmp" && mv "$LOG_FILE.tmp" "$LOG_FILE"
}
# Function to check for updates
check_for_updates() {
echo "$(date): Checking for updates..."
for dir in "${DIRECTORIES[@]}"; do
local remote_rev=$(wget -qO- "$BASE_URL/$dir/.rev")
local local_rev_file="/usrdata/$dir/.rev"
if [[ ! -f "$local_rev_file" ]]; then
echo "No local revision file found for $dir, skipping."
continue
fi
local local_rev=$(cat "$local_rev_file")
if [[ "$remote_rev" -gt "$local_rev" ]]; then
echo "Update available for $dir, updating..."
wget -qO "/tmp/update_${dir}.sh" "$BASE_URL/simpleupdates/scripts/update_${dir}.sh"
chmod +x "/tmp/update_${dir}.sh"
"/tmp/update_${dir}.sh"
else
echo "$dir is up to date."
fi
done
trim_log_file
wait_to_update
}
# Function to wait and trigger updates based on scheduling
wait_to_update() {
echo "Waiting for the next update check according to schedule..."
while true; do
local current_time=$(date "+%H:%M")
local current_day=$(date "+%a")
local current_date=$(date "+%d")
case $UPDATE_FREQUENCY in
daily)
if [[ "$current_time" == "$SCHEDULED_TIME" ]]; then
check_for_updates
fi
;;
weekly)
if [[ "$current_day" == "$WEEKLY_DAY" && "$current_time" == "$SCHEDULED_TIME" ]]; then
check_for_updates
fi
;;
monthly)
if [[ "$current_date" == "$MONTHLY_DATE" && "$current_time" == "$SCHEDULED_TIME" ]]; then
check_for_updates
fi
;;
none)
echo "Update checking is disabled by frequency setting."
exit 0
;;
esac
sleep 30 # Sleep for 30 seconds for more granular checks
trim_log_file
done
}
# Daemon mode to wait and trigger updates based on scheduling
daemon_mode() {
load_config
exec > >(tee -a "$LOG_FILE") 2>&1
echo "Daemon mode started."
# Validate only one update frequency is defined
frequency_count=0
[[ "$UPDATE_FREQUENCY" == "daily" ]] && ((frequency_count++))
[[ "$UPDATE_FREQUENCY" == "weekly" ]] && ((frequency_count++))
[[ "$UPDATE_FREQUENCY" == "monthly" ]] && ((frequency_count++))
if [[ $frequency_count -gt 1 ]]; then
echo "Error: More than one update frequency is defined. Exiting."
exit 1
elif [[ $frequency_count -eq 0 && "$UPDATE_FREQUENCY" != "none" ]]; then
echo "Error: No valid update frequency defined. Exiting."
exit 1
fi
if [[ "$CONF_ENABLED" == "no" ]]; then
echo "Updates are disabled in the configuration."
exit 0
fi
if [[ "$CHECK_AT_BOOT" == "yes" ]]; then
check_for_updates
else
wait_to_update
fi
}
# Function to check for updates
force_check_for_updates() {
echo "$(date): Checking for updates..."
for dir in "${DIRECTORIES[@]}"; do
local remote_rev=$(wget -qO- "$BASE_URL/$dir/.rev")
local local_rev_file="/usrdata/$dir/.rev"
if [[ ! -f "$local_rev_file" ]]; then
echo "No local revision file found for $dir, skipping."
continue
fi
local local_rev=$(cat "$local_rev_file")
if [[ "$remote_rev" -gt "$local_rev" ]]; then
echo "Update available for $dir, updating..."
wget -qO "/tmp/update_${dir}.sh" "$BASE_URL/simpleupdates/scripts/update_${dir}.sh"
chmod +x "/tmp/update_${dir}.sh"
"/tmp/update_${dir}.sh"
else
echo "$dir is up to date."
fi
done
exit 0
}
# Helper function to load and update the configuration
update_config() {
local key="$1"
local value="$2"
if grep -q "^$key=" "$CONFIG_FILE"; then
sed -i "s|^$key=.*|$key=$value|" "$CONFIG_FILE"
else
echo "$key=$value" >> "$CONFIG_FILE"
fi
}
# Display the current configuration status
status() {
echo "Current Configuration Status:"
if [[ -f "$CONFIG_FILE" ]]; then
while IFS= read -r line; do
echo "$line"
done < "$CONFIG_FILE"
else
echo "Configuration file not found."
fi
}
# Enable automatic updates
enable_updates() {
update_config "CONF_ENABLED" "yes"
echo "Automatic updates have been enabled."
}
# Disable automatic updates
disable_updates() {
update_config "CONF_ENABLED" "no"
echo "Automatic updates have been disabled."
}
# Interactive setup for the update configuration
setup() {
read -p "Enable automatic updates? [yes/no]: " enable_updates
if [[ "$enable_updates" == "yes" ]]; then
enable_updates
else
disable_updates
fi
read -p "Check for updates at boot? [yes/no]: " check_boot
update_config "CHECK_AT_BOOT" "$check_boot"
read -p "Update frequency (none, daily, weekly, monthly): " frequency
update_config "UPDATE_FREQUENCY" "$frequency"
case $frequency in
daily)
read -p "Scheduled time (HH:MM in 24-hour format): " time
update_config "SCHEDULED_TIME" "$time"
;;
weekly)
echo "Please enter the day of the week."
read -p "Day (full name or abbreviation, e.g., Monday or Mon): " day_input
# Normalize input to abbreviated form
day_abbr=$(date -d "$day_input" +%a 2>/dev/null)
if [[ $? -ne 0 ]]; then
echo "Invalid day of the week. Please try again."
return 1
fi
update_config "WEEKLY_DAY" "$day_abbr"
read -p "Scheduled time (HH:MM in 24-hour format): " time
update_config "SCHEDULED_TIME" "$time"
;;
monthly)
read -p "Date of the month (1-31): " date
update_config "MONTHLY_DATE" "$date"
read -p "Scheduled time (HH:MM in 24-hour format): " time
update_config "SCHEDULED_TIME" "$time"
;;
*)
echo "No scheduling will be set."
;;
esac
echo "Update configuration has been set."
}
# Command operations: status, enable, disable, update, setup
case "$1" in
d)
daemon_mode
;;
update)
load_config
force_check_for_updates
;;
status)
status
;;
enable)
enable_updates
;;
disable)
disable_updates
;;
setup)
setup
;;
*)
echo "Usage:"
echo "d: Run as a background check daemon"
echo "update: Force check for and install updates"
echo "status: Display current set update schedule"
echo "enable: Enable automatic updates"
echo "disable: Disable automatic updates"
echo "setup: Set up an automatic update schedule"
;;
esac

View File

@@ -1,10 +0,0 @@
[Unit]
Description=Simple Update Daemon
After=network.target
[Service]
Type=simple
ExecStart=/usrdata/simpleupdates/simpleupdate d
[Install]
WantedBy=multi-user.target

View File

@@ -1 +0,0 @@
2

View File

@@ -1,69 +0,0 @@
#!/bin/bash
DEVICE=/dev/ttyOUT2
BAUD=115200
# Function to setup device communication parameters
setup_device() {
stty -F $DEVICE cs8 $BAUD ignbrk -brkint -icrnl -imaxbel \
-opost -onlcr -isig -icanon -iexten -echo -echoe -echok \
-echoctl -echoke noflsh -ixon -crtscts
}
# Function to send AT command and capture the output
send_at_command() {
local command="$1"
# Clear the device buffer before sending a new command
echo -n > $DEVICE
# Send the AT command, preserving the integrity of the input
echo -e "$command\r" > $DEVICE
# Use a temporary file to capture the command output
tmpfile=$(mktemp)
# Start reading the device output to the temporary file
cat $DEVICE > "$tmpfile" &
CAT_PID=$!
# Monitor the output file for "OK" or "ERROR"
while ! grep -qe "OK" -e "ERROR" "$tmpfile"; do
sleep 1
done
# Kill the `cat` process after capturing the response
kill $CAT_PID
wait $CAT_PID 2>/dev/null
# Display the response
cat "$tmpfile" | while IFS= read -r line; do
echo -e "\033[0;32m$line\033[0m"
done
# Clean up
rm "$tmpfile"
}
# Prepare the device for communication
setup_device
# Check if an AT command is provided as an argument
if [ $# -gt 0 ]; then
# Concatenate all arguments to handle commands with spaces and/or quotes correctly
FULL_CMD="$*"
send_at_command "$FULL_CMD"
else
echo -e "\033[0;36mType 'exit' to end the session.\033[0m"
while true; do
echo -en "\033[0;36mEnter AT Command: \033[0m"
read user_input
if [[ "$user_input" == "exit" ]]; then
echo -e "\033[0;32mExiting...\033[0m"
break
fi
send_at_command "$user_input"
done
fi

View File

@@ -1,4 +0,0 @@
#!/bin/bash
# Look for the process by its command and kill it so socat can have smd7 instead
pkill -f "/usr/bin/port_bridge smd7 at_usb2 1"

Binary file not shown.

View File

@@ -1,9 +0,0 @@
[Unit]
Description=Kill port_bridge process on boot
[Service]
Type=oneshot
ExecStart=/usrdata/socat-at-bridge/killsmd7bridge
[Install]
WantedBy=multi-user.target

View File

@@ -1,14 +0,0 @@
[Unit]
Description=Read from /dev/ttyIN and write to smd11
BindsTo=socat-smd11.service
After=socat-smd11.service
[Service]
ExecStart=/bin/bash -c "/bin/cat /dev/ttyIN > /dev/smd11"
ExecStartPost=/bin/sleep 2s
StandardInput=tty-force
Restart=always
RestartSec=1s
[Install]
WantedBy=multi-user.target

View File

@@ -1,14 +0,0 @@
[Unit]
Description=Read from /dev/smd11 and write to ttyIN
BindsTo=socat-smd11.service
After=socat-smd11.service
[Service]
ExecStart=/bin/bash -c "/bin/cat /dev/smd11 > /dev/ttyIN"
ExecStartPost=/bin/sleep 2s
StandardInput=tty-force
Restart=always
RestartSec=1s
[Install]
WantedBy=multi-user.target

View File

@@ -1,13 +0,0 @@
[Unit]
Description=Socat Serial Emulation for smd11
After=ql-netd.service
[Service]
ExecStart=/usrdata/socat-at-bridge/socat-armel-static -d -d pty,link=/dev/ttyIN,raw,echo=0,group=20,perm=660 pty,link=/dev/ttyOUT,raw,echo=1,group=20,perm=660
# Add a delay to prevent the clients from starting too early
ExecStartPost=/bin/sleep 2s
Restart=always
RestartSec=1s
[Install]
WantedBy=multi-user.target

View File

@@ -1,14 +0,0 @@
[Unit]
Description=Read from /dev/ttyIN2 and write to smd7
BindsTo=socat-smd7.service
After=socat-smd7.service
[Service]
ExecStart=/bin/bash -c "/bin/cat /dev/ttyIN2 > /dev/smd7"
ExecStartPost=/bin/sleep 2s
StandardInput=tty-force
Restart=always
RestartSec=1s
[Install]
WantedBy=multi-user.target

View File

@@ -1,14 +0,0 @@
[Unit]
Description=Read from /dev/smd7 and write to ttyIN2
BindsTo=socat-smd7.service
After=socat-smd7.service
[Service]
ExecStart=/bin/bash -c "/bin/cat /dev/smd7 > /dev/ttyIN2"
ExecStartPost=/bin/sleep 2s
StandardInput=tty-force
Restart=always
RestartSec=1s
[Install]
WantedBy=multi-user.target

View File

@@ -1,13 +0,0 @@
[Unit]
Description=Socat Serial Emulation for smd7
After=ql-netd.service
[Service]
ExecStart=/usrdata/socat-at-bridge/socat-armel-static -d -d pty,link=/dev/ttyIN2,raw,echo=0,group=20,perm=660 pty,link=/dev/ttyOUT2,raw,echo=1,group=20,perm=660
# Add a delay to prevent the clients from starting too early
ExecStartPost=/bin/sleep 2s
Restart=always
RestartSec=1s
[Install]
WantedBy=multi-user.target

View File

@@ -1 +0,0 @@
2

View File

@@ -1,17 +0,0 @@
[Unit]
Description=OpenBSD Secure Shell server
Documentation=man:sshd(8) man:sshd_config(5)
After=network.target
[Service]
Type=simple
PIDFile=/opt/var/run/sshd.pid
ExecStartPre=/opt/sbin/sshd -t
ExecStart=/opt/sbin/sshd -D
ExecReload=/bin/kill -HUP $MAINPID
KillMode=process
Restart=on-failure
[Install]
WantedBy=multi-user.target
Alias=sshd.service

View File

@@ -1 +0,0 @@
2

View File

@@ -1,8 +0,0 @@
[Unit]
Description=Trigger the Tailscale Web UI
After=tailscaled.service
[Service]
Type=oneshot
ExecStart=/bin/systemctl start tailscale-webui
RemainAfterExit=yes

View File

@@ -1,12 +0,0 @@
Description=Tailscale Web Interface
After=tailscaled.service
Requires=tailscaled.service
[Service]
Type=simple
ExecStartPre=/bin/sleep 5
ExecStart=/usrdata/tailscale/tailscale web --listen 0.0.0.0:8088
RemainAfterExit=yes
[Install]
WantedBy=multi-user.target

Some files were not shown because too many files have changed in this diff Show More