Compare commits
30 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0d962f3130 | ||
|
|
6bf2d640c3 | ||
|
|
1d91aebcc8 | ||
|
|
0b1f3b22d8 | ||
|
|
7ed145d7bc | ||
|
|
74d7d3f3ef | ||
|
|
3962c5cf5a | ||
|
|
67a9ddfff8 | ||
|
|
84439e332e | ||
|
|
4446e6287e | ||
|
|
0f7f5a258c | ||
|
|
766e6c5457 | ||
|
|
5546c9e3ac | ||
|
|
2fa9596106 | ||
|
|
cadd1fbb8b | ||
|
|
d18e3be937 | ||
|
|
47dded4538 | ||
|
|
9ac6bdf597 | ||
|
|
16bb998c72 | ||
|
|
20e2aca705 | ||
|
|
de74eecd77 | ||
|
|
c01c9e88e0 | ||
|
|
36e3ff1da3 | ||
|
|
dea33f9ad9 | ||
|
|
f44eba7d4d | ||
|
|
0669bfc693 | ||
|
|
898482b80f | ||
|
|
3ee103c3dd | ||
|
|
0231ac55b2 | ||
|
|
977cd261bc |
193
README.md
193
README.md
@@ -1,162 +1,61 @@
|
||||
# RGMII Toolkit
|
||||
Software deployment Toolkit for Quectel RM5xxx series 5G modems utilizing an m.2 to RJ45 adapter (RGMII)
|
||||
# Quectel Application Processor Repository (repo to be renamed soon)
|
||||
Current Branch: **Main**
|
||||
|
||||
Current Branch: **SDXLEMUR**
|
||||
# About
|
||||
- Software deployment Toolkits and opkg repositories intended to deploy directly to the Application Processor (AP) (Linux OS running the modem) of a Quectel Cellular Modem.
|
||||
- Basic goal for each branch/platform: A deployment script that sets up a usable mount space and deploys an opkg setup + an opkg feed for said platform.
|
||||
- Target use scenario: RC PCIe Mode where the modem utilizes an ethernet chipset EP directly. (Example hardware: [Rework.Network PHY Adapter](https://www.rework.network/collections/lte-home-gateway/products/5g2phy))
|
||||
- Should be possible to benefit from this repo as well if you use the modem in other scenarios as well. Through tailscale you can acess the AP's LAN and other services installable from this repo.
|
||||
|
||||
Please PR to [development-SDXLEMUR](https://github.com/iamromulan/quectel-rgmii-toolkit/tree/development-SDXLEMUR) instead of the main one :)
|
||||
# Branches
|
||||
|
||||
Fork development, and PR development to development :)
|
||||
## Main/Stable:
|
||||
|
||||
- [SDXLEMUR and SDXPRAIRIE platforms (QTI Linux system armv7 32-bit)](https://github.com/iamromulan/quectel-rgmii-toolkit/tree/SDXLEMUR)
|
||||
- Confirmed working / For use with the following modems:
|
||||
|
||||
- RM500Q-GL (No page yet, i don't own one)
|
||||
|
||||
- [RM502Q-AE](https://github.com/iamromulan/cellular-modem-wiki/blob/main/quectel/sdxprairie/RM502Q-AE.md)
|
||||
|
||||
- [RM520N-GL](https://github.com/iamromulan/cellular-modem-wiki/blob/main/quectel/sdxlemur/RM520N-GL.md)
|
||||
|
||||
- [RM521F-GL](https://github.com/iamromulan/cellular-modem-wiki/blob/main/quectel/sdxlemur/RM521F-GL.md)
|
||||
|
||||
- Will probably work fine on:
|
||||
|
||||
- RM530N-GL
|
||||
|
||||
- Other Quectel SDXLEMUR/SDXPRAIRIE modems with a QTI Linux system and armv7 32-bit processor
|
||||
|
||||
- [SDXPINN platform OpenWRT system armv8-A 64-bit](https://github.com/iamromulan/quectel-rgmii-toolkit/tree/SDXPINN)
|
||||
- Confirmed working / For use with the following modems:
|
||||
|
||||
- [RM550V-GL](https://github.com/iamromulan/cellular-modem-wiki/blob/main/quectel/sdxpinn/RM550V-GL.md) :warning: You need iamromulan's RM550V-GL firmware for PCIe RC mode to work :warning:
|
||||
|
||||
- [RM551E-GL](https://github.com/iamromulan/cellular-modem-wiki/blob/main/quectel/sdxpinn/RM551E-GL.md)
|
||||
|
||||
- Will probably work fine on:
|
||||
|
||||
- Other Quectel SDXPINN modems with a OpenWRT system and armv8-A 64-bit processor
|
||||
|
||||
|
||||
#### [JUMP TO HOW TO USE](#how-to-use)
|
||||
**Currently:** This will allow you to install or if already installed, update, remove, or modify:
|
||||
- Simple Admin: A simple web interface for managing your Quectel m.2 modem through it's gateway address
|
||||
- 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
|
||||
- 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.
|
||||
- Schedule a Daily Reboot at a specified time
|
||||
- A fix for certain modems that don't start in CFUN=1 mode
|
||||
- Entware/OPKG: A package installer/manager/repo
|
||||
- Run `opkg help` to see how to use it
|
||||
- These packages are installable: https://bin.entware.net/armv7sf-k3.2/Packages.html
|
||||
- TTYd: A shell session right from your browser
|
||||
- Currently this uses port 443 but SSL/TLS is not in use (http only for now)
|
||||
- Entware/OPKG is required so it will install it if it isn't installed
|
||||
- This will replace the stock Quectel login and passwd binaries with ones from entware
|
||||
## Development/Testing/Unstable
|
||||
|
||||
|
||||
> :bulb: Open pull requests pointed to these branches.
|
||||
|
||||
**My goal** is for this to also include any new useful scripts or software for this modem and others that support RGMII mode.
|
||||
## Screenshots
|
||||
These branches are meant for testing new changes and edits. Do not deploy or install packages from these branches unless you are ready to handle any issues that occur. In general these branches are for testing recent PRs and commits.
|
||||
|
||||

|
||||

|
||||

|
||||

|
||||

|
||||

|
||||

|
||||

|
||||
- [SDXLEMUR and SDXPRAIRIE platforms (QTI Linux system armv7 32-bit)](https://github.com/iamromulan/quectel-rgmii-toolkit/tree/development-SDXLEMUR)
|
||||
|
||||
# Devleopment Branch: the below commands will download the beta/work in progress toolkit
|
||||
- [SDXPINN platform OpenWRT system armv8-A 64-bit](https://github.com/iamromulan/quectel-rgmii-toolkit/tree/development-SDXPINN)
|
||||
|
||||
## How to Use
|
||||
**To run the Toolkit:**
|
||||
- Open ADB & Fastboot++ covered in [Using ADB](https://github.com/iamromulan/quectel-rgmii-configuration-notes?tab=readme-ov-file#unlocking-and-using-adb) or just use adb
|
||||
- Make sure your modem is connected by USB to your computer
|
||||
- Run `adb devices` to make sure your modem is detected by adb
|
||||
- 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.
|
||||
- Simply Copy/Paste this into your Command Prompt/Shell
|
||||
```bash
|
||||
adb shell "cd /tmp && wget -O RMxxx_rgmii_toolkit.sh http://git.ievo.top/tyk/quectel-rgmii-toolkit/raw/branch/SDXLEMUR/RMxxx_rgmii_toolkit.sh && chmod +x RMxxx_rgmii_toolkit.sh && ./RMxxx_rgmii_toolkit.sh" && cd /
|
||||
```
|
||||
## Temporary/Experimental/Overhaul branches
|
||||
|
||||
**Or, if you want to stay in the modems shell when you are done**
|
||||
These branches are for large overhauls or experimentation that needs to happen on their own branch. These are usualy temporary branches and are deleted when no longer needed.
|
||||
|
||||
```
|
||||
adb shell
|
||||
```
|
||||
Then run
|
||||
```
|
||||
cd /tmp && wget -O RMxxx_rgmii_toolkit.sh http://git.ievo.top/tyk/quectel-rgmii-toolkit/raw/branch/SDXLEMUR/RMxxx_rgmii_toolkit.sh && chmod +x RMxxx_rgmii_toolkit.sh && ./RMxxx_rgmii_toolkit.sh && cd /
|
||||
```
|
||||
**You should see:**
|
||||

|
||||
- [OVERHAUL: SDXLEMUR and SDXPRAIRIE platforms (QTI Linux system armv7 32-bit)](https://github.com/iamromulan/quectel-rgmii-toolkit/tree/overhaul-SDXLEMUR)
|
||||
|
||||
## 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
|
||||
|
||||

|
||||
|
||||
**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.**
|
||||
|
||||

|
||||
|
||||
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
|
||||
- This branch is being used to create a similar model to how SDXPINN branches behave. A new mount-fix is needed along with a solid plan for how to approch the opkg rework. Indexing already installed "packages" is recomeneded in order to avoid duplicate installs/save space. The goal will be to package all applications as IPKs and hopefuly port QuecManager and Luci over to it.
|
||||
|
||||
|
||||
It isn't perfect yet so it goes here under Advanced/Beta for now.
|
||||
Here's what you gotta know about going into it:
|
||||
|
||||
- After installing, the `opkg` command will work
|
||||
- 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
|
||||
|
||||
#### Permanently:
|
||||
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
|
||||
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.
|
||||
|
||||
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
|
||||
### GitHub Users/Individuals:
|
||||
Thank You to:
|
||||
|
||||
[Nate Carlson](https://github.com/natecarlson) for the Original Telnet Deamon/socat bridge usage and the Original RGMII Notes
|
||||
|
||||
[aesthernr](https://github.com/aesthernr) for creating the Original Simple Admin
|
||||
|
||||
[rbflurry](https://github.com/rbflurry/) for inital Simple Admin fixes
|
||||
|
||||
[dr-dolomite](https://github.com/dr-dolomite) for some major stat page improvements and this repos first approved external PR!
|
||||
|
||||
[tarunVreddy](https://github.com/tarunVreddy) for helping with the SA band aggregation parse
|
||||
|
||||
### Existing projects:
|
||||
Simpleadmin heavily uses the AT Command Parsing Scripts (Basically a copy with new changes and tweaks) of Dairyman's Rooter Source https://github.com/ofmodemsandmen/ROOterSource2203
|
||||
|
||||
Tailscale was obtained through Tailscale's static build page. Since these modems have a 32-bit ARM processor on-board I used the arm package. https://pkgs.tailscale.com/stable/#static
|
||||
|
||||
Entware/opkg was obtained through [Entware's wiki](https://github.com/Entware/Entware/wiki/Alternative-install-vs-standard) and the installer heavily modified by [iamromulan](https://github.com/iamromulan) for use with Quectel modems
|
||||
|
||||
TTYd was obtained from the [TTYd Project](https://github.com/tsl0922/ttyd)
|
||||
|
||||
109
at-list.md
109
at-list.md
@@ -1,109 +0,0 @@
|
||||
# Useful AT Commands
|
||||
|
||||
You can send more than one command at once by sperating them with ``;`` and not including the AT part. ``AT+QENG="servingcell";+QCAINFO`` for example to see the info from both ``AT+QENG="servingcell"`` and ``AT+QCAINFO``
|
||||
|
||||
|
||||
## PCIe RC Ethernet mode setup
|
||||
|
||||
### For RM500-RM521 modems
|
||||
``AT+QETH="eth_driver","r8125",1;+QCFG="pcie/mode",1;+QCFG="usbnet",1;+QMAP="MPDN_rule",0,1,0,1,1,"FF:FF:FF:FF:FF:FF";+QMAP="DHCPV4DNS","disable";+QCFG="usbcfg",0x2C7C,0x0801,1,1,1,1,1,2,0;+CFUN=1,1``
|
||||
|
||||
This will do the following:
|
||||
|
||||
- Set the 2.5Gig Ethernet driver as active
|
||||
- Enable PCIe RC mode
|
||||
- Set to ECM mode via USB and AP mode connection behavior
|
||||
- Enable IPPT
|
||||
- Enable DNS IPPT (disables onboard proxy)
|
||||
- Force Enables ADB Access
|
||||
- Reboots after all the above
|
||||
|
||||
|
||||
|
||||
### For x70 modems (RM550/551)
|
||||
|
||||
For BETA versions of firmware: the adb value 2 trick still works so one and done:
|
||||
|
||||
``AT+QCFG="pcie/mode",1;+QCFG="usbnet",1;+QCFG="usbcfg",0x2C7C,0x0122,1,1,1,1,1,2,0;+CFUN=1,1``
|
||||
|
||||
OR if you are running the latest non-beta firmware
|
||||
|
||||
``AT+QCFG="pcie/mode",1;+QCFG="usbnet",1``
|
||||
|
||||
Then unlock ADB:
|
||||
|
||||
Ask the modem for its adb code by sending: ``AT+QADBKEY?``
|
||||
|
||||
It'll respond with something like ``+QADBKEY: 29229988``
|
||||
|
||||
Take that number and paste it in this generator: https://onecompiler.com/python/3znepjcsq (hint: where it says STDIN)
|
||||
|
||||
You should get something like
|
||||
|
||||
``AT+QADBKEY="mrX4zOPwdSIEjfM"``
|
||||
|
||||
Send that command to the modem and adb will be able to be turned on with the next command
|
||||
|
||||
Now you can turn it on with the usbcfg command ``AT+QCFG="usbcfg"``
|
||||
|
||||
***Be super careful, this controls what ports are on/off over USB.***
|
||||
|
||||
Run it and you will get the current settings. Something like this:
|
||||
|
||||
``+QCFG: "usbcfg",0x2C7C,0x0122,1,1,1,1,1,0,0``
|
||||
|
||||
Send ``AT+QCFG="usbcfg",0x2C7C,0x0122,1,1,1,1,1,1,0`` to enable adb
|
||||
|
||||
Now you can reboot: ``AT+CFUN=1,1``
|
||||
|
||||
|
||||
|
||||
This will do the following:
|
||||
|
||||
- Enable PCIe RC mode (Driver selection is automatic now)
|
||||
- Set to ECM mode via USB and AP mode connection behavior
|
||||
- Force Enables ADB Access
|
||||
- Reboots after all the above
|
||||
|
||||
Tip: APN automatic selection will somtimes choose the wrong APN. You may need to set your APN after powering up with the SIM inserted.
|
||||
|
||||
## The List
|
||||
- ``AT+CFUN=1,1`` (reboot)
|
||||
- ``AT+CFUN=0;CFUN=1`` (Disconnect then reconnect)(tip: run this after chnaging APN and you don't have to reboot)
|
||||
- ``AT+QMAPWAC? ``(get current status of auto connect, 0=disabled 1=enabled)
|
||||
- ``AT+QMAPWAC=1`` (enable auto connect internet for ethernet)
|
||||
- ``AT+QMAPWAC=0`` (disable auto connect for ethernet; use when you want internet over USB to work; IPPT must be disabled)
|
||||
- ``AT+QUIMSLOT?`` (get active sim slot; 1=Slot 1; 2=Slot 2)
|
||||
- ``AT+QUIMSLOT=1`` (switch to sim slot 1)
|
||||
- ``AT+QUIMSLOT=2`` (switch to sim slot 2)
|
||||
- ``AT+CGDCONT?`` (Get active APN profle st 1 through 8)
|
||||
- ``AT+QMBNCFG="AutoSel",0;+QMBNCFG="Deactivate"`` (Disable Automatic APN selection)(You will need to set your APN when you switch SIMs or Slots)(Can also set APN after you switch the run ``AT+CFUN=0;CFUN=1``
|
||||
- ``AT+CGDCONT=1,"IPV4V6","APNHERE"`` (Sets APN profile 1 to APNHERE using both IPV4 and IPV6)
|
||||
- ``AT+GSN`` (Show current IMEI)
|
||||
- ``AT+EGMR=0,7`` (Show current IMEI)
|
||||
- ``AT+EGMR=1,7,"IMEIGOESHERE"`` (sets/repairs IMEI)
|
||||
- ``AT+QCFG="usbcfg",0x2C7C,0x0801,1,1,1,1,1,2,0`` (enables adb bypasses adb key)
|
||||
- ``AT+QENG="servingcell"`` (shows anchor band and network connection status)
|
||||
- ``AT+QCAINFO`` (Show all connected bands/CA info)
|
||||
- ``AT+QNWPREFCFG="mode_pref"`` (Check what the current network search mode is set to)
|
||||
- ``AT+QNWPREFCFG="mode_pref",AUTO`` (Set network search mode to automatic)
|
||||
- ``AT+QNWPREFCFG="mode_pref",NR5G:LTE`` (Set network search mode to 5GNR and 4GLTE only)
|
||||
- ``AT+QNWPREFCFG="mode_pref",NR5G`` (Set network search mode to 5GNR only)
|
||||
- ``AT+QNWPREFCFG="mode_pref",LTE`` (Set network search mode to 4GLTE only)
|
||||
- ``AT+QNWPREFCFG="nr5g_disable_mode"`` (Check to see if SA or NSA NR5G is disabled)
|
||||
- ``AT+QNWPREFCFG="nr5g_disable_mode",0`` (Enable Both SA and NSA 5GNR)
|
||||
- ``AT+QNWPREFCFG="nr5g_disable_mode",1`` (Disable SA 5GNR only)
|
||||
- ``AT+QNWPREFCFG="nr5g_disable_mode",2`` (Disable NSA 5GNR only)
|
||||
- ``AT+QNWPREFCFG="nr5g_band"`` (Get current SA 5GNR bandlock settings)
|
||||
- ``AT+QNWPREFCFG="nsa_nr5g_band"`` (Get current NSA 5GNR bandlock settings)
|
||||
- ``AT+QNWPREFCFG="nr5g_band",1:2:3:4:5:6`` (Example: Lock to SA 5G/NR bands n1,n2,n3,n4,n5, and n6)
|
||||
- ``AT+QNWPREFCFG="nsa_nr5g_band",1:2:3:4:5:6`` (Example: Lock to SA 5G/NR bands n1,n2,n3,n4,n5, and n6)
|
||||
- ``AT+QNWPREFCFG="lte_band"`` (Get current 4GLTE bandlock settings)
|
||||
- ``AT+QNWPREFCFG="lte_band",1:2:3:4:5:6`` (Example: Lock to 4G/LTE bands 1,2,3,4,5, and 6)
|
||||
- ``AT+QMAP="WWAN"`` (Show currently assigned IPv4 and IPv6 from the provider)
|
||||
- ``AT+QMAP="LANIP"`` (Show current DHCP range and Gateway address for VLAN0)
|
||||
- ``AT+QMAP="LANIP",IP_start_range,IP_end_range,Gateway_IP `` (Set IPv4 Start/End range and Gateway IP of DHCP for VLAN0)
|
||||
- ``AT+QMAP="DHCPV4DNS","disable"`` (disable the onboard DNS proxy; recommended for IPPT)
|
||||
- ``AT+QMAP="MPDN_rule",0,1,0,1,1,"FF:FF:FF:FF:FF:FF"`` (Turn on IP Passthrough for Ethernet)
|
||||
(:warning: On the RM551E-GL you must specify the ethernet devices MAC address instead of FF:FF:FF...)
|
||||
- ``AT+QMAP="MPDN_rule",0`` (turn off IPPT/clear MPDN rule 0; Remember to run AT+QMAPWAC=1 and reboot after)
|
||||
114
download
114
download
@@ -1,114 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
# Determine the absolute path of the script
|
||||
SCRIPT_PATH=$(realpath "$0")
|
||||
|
||||
download() {
|
||||
if [ "$1" = "github" ]; then
|
||||
download_github_directory "$2" "$3"
|
||||
else
|
||||
download_file "$1" "$2"
|
||||
fi
|
||||
}
|
||||
|
||||
download_file() {
|
||||
url="$1"
|
||||
output="${2:-$(basename "$url")}"
|
||||
|
||||
echo "Attempting to download file from URL: $url"
|
||||
echo "Saving to output: $output"
|
||||
|
||||
# Ensure the output directory exists
|
||||
mkdir -p "$(dirname "$output")"
|
||||
|
||||
if command -v curl > /dev/null 2>&1; then
|
||||
curl -L -o "$output" "$url"
|
||||
elif command -v wget > /dev/null 2>&1; then
|
||||
wget -O "$output" "$url"
|
||||
else
|
||||
echo "Error: Neither curl nor wget is available."
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
download_github_directory() {
|
||||
github_url="$1"
|
||||
output_dir="${2:-.}" # Set output directory to the provided parameter or current directory
|
||||
|
||||
repo_info=$(echo "$github_url" | sed -n 's|https://github.com/\([^/]*\)/\([^/]*\)/tree/\([^/]*\)/\(.*\)|\1 \2 \3 \4|p')
|
||||
owner=$(echo "$repo_info" | cut -d' ' -f1)
|
||||
repo=$(echo "$repo_info" | cut -d' ' -f2)
|
||||
branch=$(echo "$repo_info" | cut -d' ' -f3)
|
||||
directory=$(echo "$repo_info" | cut -d' ' -f4)
|
||||
|
||||
echo "Owner: $owner, Repo: $repo, Branch: $branch, Directory: $directory"
|
||||
|
||||
if [ -z "$owner" ] || [ -z "$repo" ] || [ -z "$branch" ] || [ -z "$directory" ]; then
|
||||
echo "Error: Invalid GitHub URL."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Output directory set to: $output_dir"
|
||||
|
||||
api_url="https://api.github.com/repos/$owner/$repo/contents/$directory?ref=$branch"
|
||||
echo "Fetching directory contents from API URL: $api_url"
|
||||
|
||||
if command -v curl > /dev/null 2>&1; then
|
||||
contents=$(curl -s -H "Accept: application/vnd.github.v3+json" "$api_url")
|
||||
elif command -v wget > /dev/null 2>&1; then
|
||||
contents=$(wget -qO- --header="Accept: application/vnd.github.v3+json" "$api_url")
|
||||
else
|
||||
echo "Error: Neither curl nor wget is available."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "API Response Contents:"
|
||||
echo "$contents"
|
||||
|
||||
# Use awk to parse JSON content and prepare commands
|
||||
echo "$contents" | awk -v output_dir="$output_dir" -v owner="$owner" -v repo="$repo" -v branch="$branch" -v script_path="$SCRIPT_PATH" '
|
||||
BEGIN {
|
||||
RS="},"; FS=","; # Set Record Separator to "}," and Field Separator to ","
|
||||
}
|
||||
/"type": "file"/ {
|
||||
file_path = ""; download_url = "";
|
||||
for (i = 1; i <= NF; i++) {
|
||||
if ($i ~ /"path": "/) {
|
||||
gsub(/.*"path": "/, "", $i);
|
||||
gsub(/".*/, "", $i);
|
||||
file_path = $i;
|
||||
}
|
||||
if ($i ~ /"download_url": "/) {
|
||||
gsub(/.*"download_url": "/, "", $i);
|
||||
gsub(/".*/, "", $i);
|
||||
download_url = $i;
|
||||
}
|
||||
}
|
||||
if (file_path && download_url) {
|
||||
output_file_path = output_dir "/" file_path;
|
||||
print "Calling download_file for:", download_url, "to", output_file_path;
|
||||
system("'"$SCRIPT_PATH"'" " \"" download_url "\" \"" output_file_path "\"");
|
||||
}
|
||||
}
|
||||
/"type": "dir"/ {
|
||||
sub_dir = "";
|
||||
for (i = 1; i <= NF; i++) {
|
||||
if ($i ~ /"path": "/) {
|
||||
gsub(/.*"path": "/, "", $i);
|
||||
gsub(/".*/, "", $i);
|
||||
sub_dir = $i;
|
||||
}
|
||||
}
|
||||
if (sub_dir) {
|
||||
print "Calling download_github_directory for sub-directory:", sub_dir;
|
||||
system("'"$SCRIPT_PATH"'" " github \"https://github.com/" owner "/" repo "/tree/" branch "/" sub_dir "\" \"" output_dir "\"");
|
||||
}
|
||||
}'
|
||||
}
|
||||
|
||||
if [ "$#" -eq 0 ]; then
|
||||
echo "Usage: download <type> <url> [output_directory]"
|
||||
exit 1
|
||||
else
|
||||
download "$@"
|
||||
fi
|
||||
141
old/original_main_repo/README.md
Normal file
141
old/original_main_repo/README.md
Normal file
@@ -0,0 +1,141 @@
|
||||
# ORIGINAL PROJECT PRESERVED HERE
|
||||
|
||||
# RGMII Toolkit
|
||||
## Software deployment Toolkit for Quectel RM5xxx series 5G modems utilizing an m.2 to RJ45 adapter (RGMII)
|
||||
|
||||
Current Branch: **Main**
|
||||
|
||||
Please Fork and PR with/to [Development](https://github.com/iamromulan/quectel-rgmii-toolkit/tree/development) instead of main, it has the latest changes and is meant to be commits ahead of main for testing. :)
|
||||
|
||||
"Don't push to production 😂"
|
||||
|
||||
Fork development, and PR development to development :)
|
||||
|
||||
|
||||
|
||||
|
||||
#### [JUMP TO HOW TO USE](#how-to-use)
|
||||
**Currently:** This will allow you to install or if already installed, update, remove, or modify:
|
||||
- Simple Admin: A simple web interface for managing your Quectel m.2 modem through it's gateway address
|
||||
- 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
|
||||
- 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.
|
||||
- Schedule a Daily Reboot at a specified time
|
||||
- A fix for certain modems that don't start in CFUN=1 mode
|
||||
- Entware/OPKG: A package installer/manager/repo
|
||||
- Run `opkg help` to see how to use it
|
||||
- These packages are installable: https://bin.entware.net/armv7sf-k3.2/Packages.html
|
||||
- TTYd: A shell session right from your browser
|
||||
- Currently this uses port 443 but SSL/TLS is not in use (http only for now)
|
||||
- Entware/OPKG is required so it will install it if it isn't installed
|
||||
- This will replace the stock Quectel login and passwd binaries with ones from entware
|
||||
|
||||
|
||||
|
||||
**My goal** is for this to also include any new useful scripts or software for this modem and others that support RGMII mode.
|
||||
## Screenshots
|
||||
|
||||

|
||||

|
||||

|
||||
|
||||

|
||||

|
||||
|
||||

|
||||
|
||||
|
||||
|
||||
## How to Use
|
||||
**To run the Toolkit:**
|
||||
- Open ADB & Fastboot++ covered in [Using ADB](https://github.com/iamromulan/quectel-rgmii-configuration-notes?tab=readme-ov-file#unlocking-and-using-adb) or just use adb
|
||||
- Make sure your modem is connected by USB to your computer
|
||||
- Run `adb devices` to make sure your modem is detected by adb
|
||||
- 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.
|
||||
- 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/main/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 shell
|
||||
```
|
||||
Then run
|
||||
```
|
||||
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 /
|
||||
```
|
||||
**You should see:**
|
||||
|
||||
|
||||

|
||||
|
||||
## 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
|
||||
|
||||

|
||||
|
||||
**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.**
|
||||
|
||||

|
||||
|
||||
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.
|
||||
### Entware/OPKG installation
|
||||
|
||||
- After installing, the `opkg` command will work
|
||||
- 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`
|
||||
- To properly use entware/opkg run the `login` command first if using adb to use stufff installed by entware/opkg
|
||||
- Be aware of space and CPU limits, run `dfc` to see what the available space in `/opt` is. Run `htop` to see CPU usage and memory usage
|
||||
|
||||
### TTYd installation
|
||||
|
||||
- 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\so you can login
|
||||
- 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. Some people have a better experience depending on mobile browser
|
||||
|
||||
## Acknowledgements
|
||||
### GitHub Users/Individuals:
|
||||
Thank You to:
|
||||
|
||||
[Nate Carlson](https://github.com/natecarlson) for the Original Telnet Deamon/socat bridge usage and the Original RGMII Notes
|
||||
|
||||
[aesthernr](https://github.com/aesthernr) for creating the Original Simple Admin
|
||||
|
||||
[rbflurry](https://github.com/rbflurry/) for inital Simple Admin fixes
|
||||
|
||||
[dr-dolomite](https://github.com/dr-dolomite) for some major stat page improvements and this repos first approved external PR!
|
||||
|
||||
### Existing projects:
|
||||
Simpleadmin heavily uses the AT Command Parsing Scripts (Basically a copy with new changes and tweaks) of Dairyman's Rooter Source https://github.com/ofmodemsandmen/ROOterSource2203
|
||||
|
||||
Tailscale was obtained through Tailscale's static build page. Since these modems have a 32-bit ARM processor on-board I used the arm package. https://pkgs.tailscale.com/stable/#static
|
||||
|
||||
Entware/opkg was obtained through [Entware's wiki](https://github.com/Entware/Entware/wiki/Alternative-install-vs-standard) and the installer heavily modified by [iamromulan](https://github.com/iamromulan) for use with Quectel modems
|
||||
|
||||
TTYd was obtained from the [TTYd Project](https://github.com/tsl0922/ttyd)
|
||||
@@ -1,15 +1,8 @@
|
||||
#!/bin/sh
|
||||
|
||||
# Define toolkit paths
|
||||
export PATH=/bin:/sbin:/usr/bin:/usr/sbin:/opt/bin:/opt/sbin:/usrdata/root/bin
|
||||
GITUSER="tyk"
|
||||
REPONAME="quectel-rgmii-toolkit"
|
||||
GITTREE="SDXLEMUR"
|
||||
GITMAINTREE="SDXLEMUR"
|
||||
GITDEVTREE="development-SDXLEMUR"
|
||||
GITROOT="http://git.ievo.top/tyk/quectel-rgmii-toolkit/raw/branch/SDXLEMUR"
|
||||
GITROOTMAIN="http://git.ievo.top/$GITUSER/$REPONAME/$GITMAINTREE"
|
||||
GITROOTDEV="http://git.ievo.top/$GITUSER/$REPONAME/$GITDEVTREE"
|
||||
GITUSER="iamromulan"
|
||||
GITTREE="main"
|
||||
TMP_DIR="/tmp"
|
||||
USRDATA_DIR="/usrdata"
|
||||
SOCAT_AT_DIR="/usrdata/socat-at-bridge"
|
||||
@@ -18,7 +11,7 @@ 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_DIR="/usrdata/tailscale/"
|
||||
TAILSCALE_SYSD_DIR="/usrdata/tailscale/systemd"
|
||||
# AT Command Script Variables and Functions
|
||||
DEVICE_FILE="/dev/smd7"
|
||||
@@ -104,12 +97,11 @@ send_at_commands() {
|
||||
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 "$GITROOT/installentware.sh" && chmod +x installentware.sh && ./installentware.sh
|
||||
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
|
||||
@@ -140,7 +132,7 @@ ensure_entware_installed() {
|
||||
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
|
||||
/usr/bin/passwd
|
||||
|
||||
# Install basic and useful utilities
|
||||
opkg install mc htop dfc lsof
|
||||
@@ -166,53 +158,121 @@ ensure_entware_installed() {
|
||||
else
|
||||
echo "useradd already exists. Continuing..."
|
||||
fi
|
||||
|
||||
if [ ! -f "/usr/bin/curl" ] && [ ! -f "/opt/bin/curl" ]; then
|
||||
echo "curl does not exist. Installing curl..."
|
||||
opkg update && opkg install curl
|
||||
if [ "$?" -ne 0 ]; then
|
||||
echo -e "\e[1;31mFailed to install curl. Please check your internet connection and try again.\e[0m"
|
||||
exit 1
|
||||
fi
|
||||
else
|
||||
echo "curl already exists. Continuing..."
|
||||
fi
|
||||
|
||||
}
|
||||
|
||||
#Uninstall Entware if the Users chooses
|
||||
uninstall_entware() {
|
||||
echo -e '\033[31mInfo: Starting Entware/OPKG uninstallation...\033[0m'
|
||||
# Check if Simple Admin is installed
|
||||
is_simple_admin_installed() {
|
||||
[ -d "$SIMPLE_ADMIN_DIR" ] && return 0 || return 1
|
||||
}
|
||||
|
||||
# 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
|
||||
# Function to install/update AT Socat Bridge
|
||||
install_update_at_socat() {
|
||||
remount_rw
|
||||
|
||||
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
|
||||
# Stop and disable existing services/files before installing new ones
|
||||
echo -e "\033[0;32mRemoving installed AT Socat Bridge services...\033[0m"
|
||||
systemctl stop at-telnet-daemon > /dev/null 2>&1
|
||||
systemctl disable at-telnet-daemon > /dev/null 2>&1
|
||||
systemctl stop socat-smd11 > /dev/null 2>&1
|
||||
systemctl stop socat-smd11-to-ttyIN > /dev/null 2>&1
|
||||
systemctl stop socat-smd11-from-ttyIN > /dev/null 2>&1
|
||||
systemctl stop socat-smd7 > /dev/null 2>&1
|
||||
systemctl stop socat-smd7-to-ttyIN2 > /dev/null 2>&1
|
||||
systemctl stop socat-smd7-to-ttyIN > /dev/null 2>&1
|
||||
systemctl stop socat-smd7-from-ttyIN2 > /dev/null 2>&1
|
||||
systemctl stop socat-smd7-from-ttyIN > /dev/null 2>&1
|
||||
rm /lib/systemd/system/at-telnet-daemon.service > /dev/null 2>&1
|
||||
rm /lib/systemd/system/socat-smd11.service > /dev/null 2>&1
|
||||
rm /lib/systemd/system/socat-smd11-to-ttyIN.service > /dev/null 2>&1
|
||||
rm /lib/systemd/system/socat-smd11-from-ttyIN.service > /dev/null 2>&1
|
||||
rm /lib/systemd/system/socat-smd7.service > /dev/null 2>&1
|
||||
rm /lib/systemd/system/socat-smd7-to-ttyIN2.service > /dev/null 2>&1
|
||||
rm /lib/systemd/system/socat-smd7-to-ttyIN.service > /dev/null 2>&1
|
||||
rm /lib/systemd/system/socat-smd7-from-ttyIN.service > /dev/null 2>&1
|
||||
rm /lib/systemd/system/socat-smd7-from-ttyIN2.service > /dev/null 2>&1
|
||||
systemctl daemon-reload > /dev/null 2>&1
|
||||
rm -rf "$SOCAT_AT_DIR" > /dev/null 2>&1
|
||||
|
||||
# Install service units
|
||||
echo -e "\033[0;32mInstalling AT Socat Bridge services...\033[0m"
|
||||
mkdir $SOCAT_AT_DIR
|
||||
cd $SOCAT_AT_DIR
|
||||
mkdir $SOCAT_AT_SYSD_DIR
|
||||
wget https://raw.githubusercontent.com/$GITUSER/quectel-rgmii-toolkit/$GITTREE/socat-at-bridge/socat-armel-static
|
||||
wget https://raw.githubusercontent.com/$GITUSER/quectel-rgmii-toolkit/$GITTREE/socat-at-bridge/killsmd7bridge
|
||||
wget https://raw.githubusercontent.com/$GITUSER/quectel-rgmii-toolkit/$GITTREE/socat-at-bridge/atcmd
|
||||
cd $SOCAT_AT_SYSD_DIR
|
||||
wget https://raw.githubusercontent.com/$GITUSER/quectel-rgmii-toolkit/$GITTREE/socat-at-bridge/systemd_units/socat-smd11.service
|
||||
wget https://raw.githubusercontent.com/$GITUSER/quectel-rgmii-toolkit/$GITTREE/socat-at-bridge/systemd_units/socat-smd11-from-ttyIN.service
|
||||
wget https://raw.githubusercontent.com/$GITUSER/quectel-rgmii-toolkit/$GITTREE/socat-at-bridge/systemd_units/socat-smd11-to-ttyIN.service
|
||||
wget https://raw.githubusercontent.com/$GITUSER/quectel-rgmii-toolkit/$GITTREE/socat-at-bridge/systemd_units/socat-killsmd7bridge.service
|
||||
wget https://raw.githubusercontent.com/$GITUSER/quectel-rgmii-toolkit/$GITTREE/socat-at-bridge/systemd_units/socat-smd7-from-ttyIN2.service
|
||||
wget https://raw.githubusercontent.com/$GITUSER/quectel-rgmii-toolkit/$GITTREE/socat-at-bridge/systemd_units/socat-smd7-to-ttyIN2.service
|
||||
wget https://raw.githubusercontent.com/$GITUSER/quectel-rgmii-toolkit/$GITTREE/socat-at-bridge/systemd_units/socat-smd7.service
|
||||
|
||||
# Unmount /opt if mounted
|
||||
mountpoint -q /opt && umount /opt
|
||||
|
||||
# Remove Entware installation directory
|
||||
rm -rf /usrdata/opt
|
||||
rm -rf /opt
|
||||
|
||||
# Reload systemctl daemon
|
||||
# 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
|
||||
|
||||
# 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'
|
||||
systemctl start socat-smd11
|
||||
sleep 2s
|
||||
systemctl start socat-smd11-to-ttyIN
|
||||
systemctl start socat-smd11-from-ttyIN
|
||||
echo -e "\033[0;32mAT Socat Bridge service online: smd11 to ttyOUT\033[0m"
|
||||
systemctl start socat-killsmd7bridge
|
||||
sleep 1s
|
||||
systemctl start socat-smd7
|
||||
sleep 2s
|
||||
systemctl start socat-smd7-to-ttyIN2
|
||||
systemctl start socat-smd7-from-ttyIN2
|
||||
echo -e "\033[0;32mAT Socat Bridge service online: smd7 to ttyOUT2\033[0m"
|
||||
remount_ro
|
||||
cd /
|
||||
echo -e "\033[0;32mAT Socat Bridge services Installed!\033[0m"
|
||||
}
|
||||
|
||||
# Function to install Simple Firewall
|
||||
install_simple_firewall() {
|
||||
systemctl stop simplefirewall
|
||||
systemctl stop ttl-override
|
||||
echo -e "\033[0;32mInstalling/Updating Simple Firewall...\033[0m"
|
||||
mount -o remount,rw /
|
||||
mkdir -p "$SIMPLE_FIREWALL_DIR"
|
||||
mkdir -p "$SIMPLE_FIREWALL_SYSTEMD_DIR"
|
||||
wget -O "$SIMPLE_FIREWALL_DIR/simplefirewall.sh" https://raw.githubusercontent.com/$GITUSER/quectel-rgmii-toolkit/$GITTREE/simplefirewall/simplefirewall.sh
|
||||
wget -O "$SIMPLE_FIREWALL_DIR/ttl-override" https://raw.githubusercontent.com/$GITUSER/quectel-rgmii-toolkit/$GITTREE/simplefirewall/ttl-override
|
||||
wget -O "$SIMPLE_FIREWALL_DIR/ttlvalue" https://raw.githubusercontent.com/$GITUSER/quectel-rgmii-toolkit/$GITTREE/simplefirewall/ttlvalue
|
||||
chmod +x "$SIMPLE_FIREWALL_DIR/simplefirewall.sh"
|
||||
chmod +x "$SIMPLE_FIREWALL_DIR/ttl-override"
|
||||
wget -O "$SIMPLE_FIREWALL_SYSTEMD_DIR/simplefirewall.service" https://raw.githubusercontent.com/$GITUSER/quectel-rgmii-toolkit/$GITTREE/simplefirewall/systemd/simplefirewall.service
|
||||
wget -O "$SIMPLE_FIREWALL_SYSTEMD_DIR/ttl-override.service" https://raw.githubusercontent.com/$GITUSER/quectel-rgmii-toolkit/$GITTREE/simplefirewall/systemd/ttl-override.service
|
||||
cp -rf $SIMPLE_FIREWALL_SYSTEMD_DIR/* /lib/systemd/system
|
||||
ln -sf "/lib/systemd/system/simplefirewall.service" "/lib/systemd/system/multi-user.target.wants/"
|
||||
ln -sf "/lib/systemd/system/ttl-override.service" "/lib/systemd/system/multi-user.target.wants/"
|
||||
systemctl daemon-reload
|
||||
systemctl start simplefirewall
|
||||
systemctl start ttl-override
|
||||
remount_ro
|
||||
echo -e "\033[0;32mSimple Firewall installation/update complete.\033[0m"
|
||||
}
|
||||
|
||||
# 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"
|
||||
@@ -304,56 +364,96 @@ configure_simple_firewall() {
|
||||
echo -e "\e[1;32mFirewall configuration updated.\e[0m"
|
||||
}
|
||||
|
||||
set_simpleadmin_passwd(){
|
||||
ensure_entware_installed
|
||||
opkg update
|
||||
opkg install libaprutil
|
||||
wget -O /usrdata/root/bin/htpasswd $GITROOT/simpleadmin/htpasswd && chmod +x /usrdata/root/bin/htpasswd
|
||||
wget -O /usrdata/root/bin/simplepasswd $GITROOT/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() {
|
||||
echo -e "\e[1;32mInstalling Simpleadmin 2.0\e[0m"
|
||||
ensure_entware_installed
|
||||
echo -e "\e[1;31m2) Installing Simpleadmin 2.0\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 $GITROOT/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 $GITROOT/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 $GITROOT/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
|
||||
while true; do
|
||||
echo -e "\e[1;32mWhat version of Simple Admin do you want to install? This will start a webserver on port 8080\e[0m"
|
||||
echo -e "\e[1;32m1) 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;32mInstalling simpleadmin from the main stable branch\e[0m"
|
||||
install_update_at_socat
|
||||
sleep 1
|
||||
install_simple_firewall
|
||||
sleep 1
|
||||
remount_rw
|
||||
sleep 1
|
||||
mkdir $SIMPLE_ADMIN_DIR
|
||||
mkdir $SIMPLE_ADMIN_DIR/systemd
|
||||
mkdir $SIMPLE_ADMIN_DIR/scripts
|
||||
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/main/simpleadmin/systemd/simpleadmin_generate_status.service
|
||||
wget https://raw.githubusercontent.com/$GITUSER/quectel-rgmii-toolkit/main/simpleadmin/systemd/simpleadmin_httpd.service
|
||||
sleep 1
|
||||
cd $SIMPLE_ADMIN_DIR/scripts
|
||||
wget https://raw.githubusercontent.com/$GITUSER/quectel-rgmii-toolkit/main/simpleadmin/scripts/build_modem_status
|
||||
wget https://raw.githubusercontent.com/$GITUSER/quectel-rgmii-toolkit/main/simpleadmin/scripts/modemstatus_parse.sh
|
||||
wget https://raw.githubusercontent.com/$GITUSER/quectel-rgmii-toolkit/main/simpleadmin/scripts/tojson.sh
|
||||
sleep 1
|
||||
cd $SIMPLE_ADMIN_DIR/www
|
||||
wget https://raw.githubusercontent.com/$GITUSER/quectel-rgmii-toolkit/main/simpleadmin/www/atcommander.html
|
||||
wget https://raw.githubusercontent.com/$GITUSER/quectel-rgmii-toolkit/main/simpleadmin/www/index.html
|
||||
wget https://raw.githubusercontent.com/$GITUSER/quectel-rgmii-toolkit/main/simpleadmin/www/speedtest.html
|
||||
wget https://raw.githubusercontent.com/$GITUSER/quectel-rgmii-toolkit/main/simpleadmin/www/styles.css
|
||||
wget https://raw.githubusercontent.com/$GITUSER/quectel-rgmii-toolkit/main/simpleadmin/www/ttl.html
|
||||
wget https://raw.githubusercontent.com/$GITUSER/quectel-rgmii-toolkit/main/simpleadmin/www/bandlock.html
|
||||
sleep 1
|
||||
cd $SIMPLE_ADMIN_DIR/www/js
|
||||
wget https://raw.githubusercontent.com/$GITUSER/quectel-rgmii-toolkit/main/simpleadmin/www/js/alpinejs.min.js
|
||||
sleep 1
|
||||
cd $SIMPLE_ADMIN_DIR/www/css
|
||||
wget https://raw.githubusercontent.com/$GITUSER/quectel-rgmii-toolkit/main/simpleadmin/www/css/admin.css
|
||||
wget https://raw.githubusercontent.com/$GITUSER/quectel-rgmii-toolkit/main/simpleadmin/www/css/bulma.css
|
||||
sleep 1
|
||||
cd $SIMPLE_ADMIN_DIR/www/cgi-bin
|
||||
wget https://raw.githubusercontent.com/$GITUSER/quectel-rgmii-toolkit/main/simpleadmin/www/cgi-bin/get_atcommand
|
||||
wget https://raw.githubusercontent.com/$GITUSER/quectel-rgmii-toolkit/main/simpleadmin/www/cgi-bin/get_csq
|
||||
wget https://raw.githubusercontent.com/$GITUSER/quectel-rgmii-toolkit/main/simpleadmin/www/cgi-bin/get_ttl_status
|
||||
wget https://raw.githubusercontent.com/$GITUSER/quectel-rgmii-toolkit/main/simpleadmin/www/cgi-bin/set_ttl
|
||||
sleep 1
|
||||
cd /
|
||||
chmod +x $SIMPLE_ADMIN_DIR/scripts/*
|
||||
chmod +x $SIMPLE_ADMIN_DIR/www/cgi-bin/*
|
||||
cp -rf $SIMPLE_ADMIN_DIR/systemd/* /lib/systemd/system
|
||||
systemctl daemon-reload
|
||||
sleep 1
|
||||
ln -sf /lib/systemd/system/simpleadmin_httpd.service /lib/systemd/system/multi-user.target.wants/
|
||||
ln -sf /lib/systemd/system/simpleadmin_generate_status.service /lib/systemd/system/multi-user.target.wants/
|
||||
systemctl start simpleadmin_generate_status
|
||||
sleep 1
|
||||
systemctl start simpleadmin_httpd
|
||||
remount_ro
|
||||
echo -e "\e[1;32msimpleadmin has been installed and is now ready for use!\e[0m"
|
||||
break
|
||||
;;
|
||||
2)
|
||||
echo -e "\e[1;31m2) Development Branch is currently not ready. Major updates coming soon!!\e[0m"
|
||||
;;
|
||||
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"
|
||||
echo -e "\e[1;36mIf you are upgrading from an older version of the toolkit uninstall/say yes to all everything.\e[0m"
|
||||
remount_rw
|
||||
|
||||
# Uninstall Simple Firewall
|
||||
@@ -381,67 +481,49 @@ uninstall_simpleadmin_components() {
|
||||
read -p "Enter your choice (1 or 2): " choice_socat_at_bridge
|
||||
if [ "$choice_socat_at_bridge" -eq 1 ]; then
|
||||
echo -e "\033[0;32mRemoving installed AT Socat Bridge services...\033[0m"
|
||||
systemctl stop at-telnet-daemon > /dev/null 2>&1
|
||||
systemctl disable at-telnet-daemon > /dev/null 2>&1
|
||||
systemctl stop socat-smd11 > /dev/null 2>&1
|
||||
systemctl stop socat-smd11-to-ttyIN > /dev/null 2>&1
|
||||
systemctl stop socat-smd11-from-ttyIN > /dev/null 2>&1
|
||||
systemctl stop socat-smd7 > /dev/null 2>&1
|
||||
systemctl stop socat-smd7-to-ttyIN2 > /dev/null 2>&1
|
||||
systemctl stop socat-smd7-to-ttyIN > /dev/null 2>&1
|
||||
systemctl stop socat-smd7-from-ttyIN2 > /dev/null 2>&1
|
||||
systemctl stop socat-smd7-from-ttyIN > /dev/null 2>&1
|
||||
rm /lib/systemd/system/at-telnet-daemon.service > /dev/null 2>&1
|
||||
rm /lib/systemd/system/socat-smd11.service > /dev/null 2>&1
|
||||
rm /lib/systemd/system/socat-smd11-to-ttyIN.service > /dev/null 2>&1
|
||||
rm /lib/systemd/system/socat-smd11-from-ttyIN.service > /dev/null 2>&1
|
||||
rm /lib/systemd/system/socat-smd7.service > /dev/null 2>&1
|
||||
rm /lib/systemd/system/socat-smd7-to-ttyIN2.service > /dev/null 2>&1
|
||||
rm /lib/systemd/system/socat-smd7-to-ttyIN.service > /dev/null 2>&1
|
||||
rm /lib/systemd/system/socat-smd7-from-ttyIN.service > /dev/null 2>&1
|
||||
rm /lib/systemd/system/socat-smd7-from-ttyIN2.service > /dev/null 2>&1
|
||||
systemctl daemon-reload > /dev/null 2>&1
|
||||
rm -rf "$SOCAT_AT_DIR" > /dev/null 2>&1
|
||||
rm -rf "$SOCAT_AT_DIR" > /dev/null 2>&1
|
||||
rm -rf "/usrdata/micropython" > /dev/null 2>&1
|
||||
rm -rf "/usrdata/at-telnet" > /dev/null 2>&1
|
||||
echo -e "\033[0;32mAT Socat Bridge services removed!...\033[0m"
|
||||
systemctl stop at-telnet-daemon > /dev/null 2>&1
|
||||
systemctl disable at-telnet-daemon > /dev/null 2>&1
|
||||
systemctl stop socat-smd11 > /dev/null 2>&1
|
||||
systemctl stop socat-smd11-to-ttyIN > /dev/null 2>&1
|
||||
systemctl stop socat-smd11-from-ttyIN > /dev/null 2>&1
|
||||
systemctl stop socat-smd7 > /dev/null 2>&1
|
||||
systemctl stop socat-smd7-to-ttyIN2 > /dev/null 2>&1
|
||||
systemctl stop socat-smd7-to-ttyIN > /dev/null 2>&1
|
||||
systemctl stop socat-smd7-from-ttyIN2 > /dev/null 2>&1
|
||||
systemctl stop socat-smd7-from-ttyIN > /dev/null 2>&1
|
||||
rm /lib/systemd/system/at-telnet-daemon.service > /dev/null 2>&1
|
||||
rm /lib/systemd/system/socat-smd11.service > /dev/null 2>&1
|
||||
rm /lib/systemd/system/socat-smd11-to-ttyIN.service > /dev/null 2>&1
|
||||
rm /lib/systemd/system/socat-smd11-from-ttyIN.service > /dev/null 2>&1
|
||||
rm /lib/systemd/system/socat-smd7.service > /dev/null 2>&1
|
||||
rm /lib/systemd/system/socat-smd7-to-ttyIN2.service > /dev/null 2>&1
|
||||
rm /lib/systemd/system/socat-smd7-to-ttyIN.service > /dev/null 2>&1
|
||||
rm /lib/systemd/system/socat-smd7-from-ttyIN.service > /dev/null 2>&1
|
||||
rm /lib/systemd/system/socat-smd7-from-ttyIN2.service > /dev/null 2>&1
|
||||
systemctl daemon-reload > /dev/null 2>&1
|
||||
rm -rf "$SOCAT_AT_DIR" > /dev/null 2>&1
|
||||
rm -rf "$SOCAT_AT_DIR" > /dev/null 2>&1
|
||||
rm -rf "/usrdata/micropython" > /dev/null 2>&1
|
||||
rm -rf "/usrdata/at-telnet" > /dev/null 2>&1
|
||||
echo -e "\033[0;32mAT Socat Bridge services removed!...\033[0m"
|
||||
fi
|
||||
|
||||
# Uninstall 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"
|
||||
# Uninstall the rest of Simpleadmin
|
||||
echo -e "\e[1;32mDo you want to uninstall the rest of Simpleadmin?\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."
|
||||
echo "Uninstalling the rest of Simpleadmin..."
|
||||
systemctl stop simpleadmin_httpd
|
||||
systemctl stop simpleadmin_generate_status
|
||||
rm -f /lib/systemd/system/simpleadmin_httpd.service
|
||||
rm -f /lib/systemd/system/simpleadmin_generate_status.service
|
||||
systemctl daemon-reload
|
||||
rm -rf "$SIMPLE_ADMIN_DIR"
|
||||
echo "The rest of Simpleadmin uninstalled."
|
||||
remount_ro
|
||||
fi
|
||||
|
||||
echo "Uninstallation process completed."
|
||||
}
|
||||
@@ -450,13 +532,13 @@ uninstall_simpleadmin_components() {
|
||||
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;32m1) Install/Update/Remove 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;;
|
||||
1) install_update_remove_tailscale;;
|
||||
2) configure_tailscale;;
|
||||
3) break;;
|
||||
*) echo "Invalid option";;
|
||||
@@ -465,17 +547,66 @@ tailscale_menu() {
|
||||
}
|
||||
|
||||
# Function to install, update, or remove Tailscale
|
||||
install_update_tailscale() {
|
||||
echo -e "\e[1;31m2) Installing tailscale from the $GITTREE branch\e[0m"
|
||||
ensure_entware_installed
|
||||
mkdir /usrdata/simpleupdates > /dev/null 2>&1
|
||||
mkdir /usrdata/simpleupdates/scripts > /dev/null 2>&1
|
||||
wget -O /usrdata/simpleupdates/scripts/update_tailscale.sh $GITROOT/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"
|
||||
install_update_remove_tailscale() {
|
||||
if [ -d "$TAILSCALE_DIR" ]; then
|
||||
echo "Tailscale is already installed."
|
||||
echo "1) Update Tailscale"
|
||||
echo "2) Remove Tailscale"
|
||||
read -p "Enter your choice: " tailscale_update_remove_choice
|
||||
|
||||
case $tailscale_update_remove_choice in
|
||||
1)
|
||||
echo "Updating Tailscale..."
|
||||
/usrdata/tailscale/tailscale update
|
||||
;;
|
||||
2)
|
||||
echo "Removing Tailscale..."
|
||||
remount_rw
|
||||
$TAILSCALE_DIR/tailscale down
|
||||
$TAILSCALE_DIR/tailscale logout
|
||||
systemctl stop tailscaled
|
||||
rm -f /lib/systemd/system/tailscaled.service
|
||||
systemctl daemon-reload
|
||||
rm -rf $TAILSCALE_DIR
|
||||
remount_ro
|
||||
echo "Tailscale removed successfully."
|
||||
;;
|
||||
*)
|
||||
echo "Invalid option";;
|
||||
esac
|
||||
else
|
||||
echo "Installing Tailscale..."
|
||||
remount_rw
|
||||
echo "Creating /usrdata/tailscale/"
|
||||
mkdir $TAILSCALE_DIR
|
||||
mkdir $TAILSCALE_SYSD_DIR
|
||||
echo "Downloading binary files..."
|
||||
cd /usrdata
|
||||
wget https://pkgs.tailscale.com/stable/tailscale_1.62.1_arm.tgz
|
||||
tar -xzf tailscale_1.62.1_arm.tgz
|
||||
cd /usrdata/tailscale_1.62.1_arm
|
||||
mv tailscale $TAILSCALE_DIR/tailscale
|
||||
mv tailscaled $TAILSCALE_DIR/tailscaled
|
||||
cd $TAILSCALE_DIR
|
||||
rm -rf /usrdata/tailscale_1.62.1_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 /usrdata/tailscale/tailscaled
|
||||
chmod +x /usrdata/tailscale/tailscale
|
||||
echo "Copy systemd units..."
|
||||
cp -rf /usrdata/tailscale/systemd/* /lib/systemd/system
|
||||
ln -sf /lib/systemd/system/tailscaled.service /lib/systemd/system/multi-user.target.wants/
|
||||
systemctl daemon-reload
|
||||
echo "Starting Tailscaled..."
|
||||
systemctl start tailscaled
|
||||
cd /
|
||||
remount_ro
|
||||
echo "Tailscale installed successfully."
|
||||
fi
|
||||
}
|
||||
|
||||
# Function to Configure Tailscale
|
||||
@@ -496,8 +627,8 @@ configure_tailscale() {
|
||||
1)
|
||||
remount_rw
|
||||
cd /lib/systemd/system/
|
||||
wget -O tailscale-webui.service $GITROOT/tailscale/systemd/tailscale-webui.service
|
||||
wget -O tailscale-webui-trigger.service $GITROOT/tailscale/systemd/tailscale-webui-trigger.service
|
||||
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"
|
||||
@@ -519,7 +650,7 @@ configure_tailscale() {
|
||||
remount_ro
|
||||
;;
|
||||
3) $TAILSCALE_DIR/tailscale up --accept-dns=false --reset;;
|
||||
4) $TAILSCALE_DIR/tailscale up --ssh --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;;
|
||||
@@ -706,61 +837,75 @@ WantedBy=multi-user.target" > "$cfun_service_path"
|
||||
fi
|
||||
}
|
||||
|
||||
install_ttyd() {
|
||||
echo -e "\e[1;34mStarting ttyd installation process...\e[0m"
|
||||
remount_rw
|
||||
ensure_entware_installed
|
||||
|
||||
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
|
||||
if [ -d "/usrdata/ttyd" ]; then
|
||||
echo -e "\e[1;34mttyd is already installed. Choose an option:\e[0m"
|
||||
echo -e "\e[1;34m1.) Update to ttyd 1.7.5 (DO NOT UPDATE WHILE USING ttyd! Use ADB or SSH instead)\e[0m"
|
||||
echo -e "\e[1;31m2.) Uninstall ttyd\e[0m"
|
||||
read -p "Enter your choice (1/2): " choice
|
||||
case $choice in
|
||||
1)
|
||||
echo -e "\e[1;31m2) Installing sshd from the $GITTREE branch\e[0m"
|
||||
echo -e "\e[1;34mUpdating ttyd...\e[0m"
|
||||
systemctl stop ttyd
|
||||
wget -O /usrdata/ttyd/ttyd https://github.com/tsl0922/ttyd/releases/download/1.7.5/ttyd.armhf && chmod +x /usrdata/ttyd/ttyd
|
||||
systemctl start ttyd
|
||||
echo -e "\e[1;32mttyd has been updated.\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;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"
|
||||
;;
|
||||
*)
|
||||
echo -e "\e[1;31mInvalid option. Please select 1 or 2.\e[0m"
|
||||
return 1
|
||||
echo -e "\e[1;31mInvalid option. Exiting.\e[0m"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
return
|
||||
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 $GITROOT/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"
|
||||
# Continue with installation if ttyd is not already installed.
|
||||
# Check for /usrdata/socat-at-bridge/atcmd, install if not installed
|
||||
if [ ! -f "/usrdata/socat-at-bridge/atcmd" ]; then
|
||||
echo -e "\e[1;34mDependency: atcmd command does not exist. Installing socat-at-bridge...\e[0m"
|
||||
install_update_at_socat
|
||||
if [ "$?" -ne 0 ]; then
|
||||
echo -e "\e[1;31mFailed to install/update atcmd. Please check the process.\e[0m"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
mount -o remount,rw /
|
||||
mkdir -p /usrdata/ttyd/scripts /usrdata/ttyd/systemd
|
||||
cd /usrdata/ttyd/
|
||||
wget -O ttyd https://github.com/tsl0922/ttyd/releases/download/1.7.4/ttyd.armhf && chmod +x ttyd
|
||||
wget -O scripts/ttyd.bash "https://raw.githubusercontent.com/$GITUSER/quectel-rgmii-toolkit/$GITTREE/ttyd/scripts/ttyd.bash" && chmod +x scripts/ttyd.bash
|
||||
wget -O systemd/ttyd.service "https://raw.githubusercontent.com/$GITUSER/quectel-rgmii-toolkit/$GITTREE/ttyd/systemd/ttyd.service"
|
||||
cp systemd/ttyd.service /lib/systemd/system/
|
||||
ln -sf /usrdata/ttyd/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 on port 443. Note: No TLS/SSL enabled yet.\e[0m"
|
||||
}
|
||||
|
||||
|
||||
|
||||
# Main menu
|
||||
|
||||
ARCH=$(uname -a)
|
||||
if echo "$ARCH" | grep -q "aarch64"; then
|
||||
cd /tmp && wget -O RM55x_rcPCIe_toolkit.sh http://git.ievo.top/iamromulan/quectel-rgmii-toolkit/SDXPINN/RM55x_rcPCIe_toolkit.sh && chmod +x RM55x_rcPCIe_toolkit.sh && ./RM55x_rcPCIe_toolkit.sh && cd /
|
||||
exit 0
|
||||
elif echo "$ARCH" | grep -q "armv7l"; then
|
||||
# Continue if architecture is armv7l
|
||||
echo "Architecture is armv7l, continuing..."
|
||||
else
|
||||
uname -a
|
||||
echo "Unsupported architecture."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
while true; do
|
||||
echo " .%+: "
|
||||
echo " .*@@@-. "
|
||||
@@ -829,19 +974,16 @@ echo " :+##+. "
|
||||
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)
|
||||
echo -e "\e[93m2) Install/Update/Uninstall Simple Admin\e[0m" # Yellow
|
||||
echo -e "\e[95m3) Simple Firewall Management\e[0m" # Light Purple
|
||||
echo -e "\e[94m4) Tailscale Management\e[0m" # Light Blue
|
||||
echo -e "\e[92m5) Install/Change or remove Daily Reboot Timer\e[0m" # Light Green
|
||||
echo -e "\e[91m6) Install/Uninstall CFUN 0 Fix\e[0m" # Light Red
|
||||
echo -e "\e[96m7) Install/Uninstall Entware/OPKG\e[0m" # Cyan (repeated color for additional options)
|
||||
echo -e "\e[96m8) Install/Update/Uninstall TTYd 1.7.4 (Uses port 443, No TLS/SSL)\e[0m" # Cyan
|
||||
echo -e "\e[92m9) Install Speedtest.net CLI app (speedtest command)\e[0m" # Light Green
|
||||
echo -e "\e[92m10) Install Fast.com CLI app (fast command)(tops out at 40Mbps)\e[0m" # Light Green
|
||||
echo -e "\e[93m11) Exit\e[0m" # Yellow (repeated color for exit option)
|
||||
read -p "Enter your choice: " choice
|
||||
|
||||
case $choice in
|
||||
@@ -849,97 +991,93 @@ echo " :+##+. "
|
||||
send_at_commands
|
||||
;;
|
||||
2)
|
||||
install_simple_admin
|
||||
if is_simple_admin_installed; then
|
||||
echo -e "\e[1;31mSimple Admin is already installed. It must be removed first\e[0m"
|
||||
echo -e "\e[1;32m1) Remove\e[0m" # Green
|
||||
echo -e "\e[0;33m2) Return to main menu\e[0m"
|
||||
read -p "Enter your choice: " simple_admin_choice
|
||||
case $simple_admin_choice in
|
||||
1) uninstall_simpleadmin_components;;
|
||||
2) break;;
|
||||
*) echo -e "\e[1;31mInvalid option\e[0m";;
|
||||
esac
|
||||
else
|
||||
echo -e "\e[1;32mInstalling Simple Admin...\e[0m"
|
||||
install_simple_admin
|
||||
fi
|
||||
;;
|
||||
3) set_simpleadmin_passwd
|
||||
;;
|
||||
4)
|
||||
set_root_passwd
|
||||
;;
|
||||
5)
|
||||
uninstall_simpleadmin_components
|
||||
;;
|
||||
6)
|
||||
configure_simple_firewall
|
||||
3)
|
||||
configure_simple_firewall
|
||||
;;
|
||||
|
||||
7)
|
||||
tailscale_menu
|
||||
;;
|
||||
8)
|
||||
manage_reboot_timer
|
||||
4)
|
||||
tailscale_menu
|
||||
;;
|
||||
5)
|
||||
manage_reboot_timer
|
||||
;;
|
||||
9)
|
||||
manage_cfun_fix
|
||||
6)
|
||||
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"
|
||||
7)
|
||||
echo -e "\e[1;32mInstalling Entware/OPKG\e[0m"
|
||||
cd /tmp && wget -O installentware.sh https://raw.githubusercontent.com/$GITUSER/quectel-rgmii-toolkit/$GITTREE/installentware.sh && chmod +x installentware.sh && ./installentware.sh && cd /
|
||||
;;
|
||||
12)
|
||||
echo -e "\e[1;32mInstalling fast.com CLI (fast command)\e[0m"
|
||||
8)
|
||||
install_ttyd
|
||||
;;
|
||||
9)
|
||||
echo -e "\e[1;32mInstalling Speedtest.net CLI (speedtest command)\e[0m"
|
||||
# Check for existing Entware/opkg installation, install if not installed
|
||||
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"
|
||||
fi
|
||||
echo -e "\e[1;32mInstalling Speedtest.net CLI (speedtest command)\e[0m"
|
||||
remount_rw
|
||||
mkdir /usrdata/root
|
||||
mkdir /usrdata/root
|
||||
mkdir /usrdata/root/bin
|
||||
cd /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"
|
||||
;;
|
||||
10)
|
||||
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
|
||||
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;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"
|
||||
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"
|
||||
11)
|
||||
echo -e "\e[1;32mGoodbye!\e[0m"
|
||||
break
|
||||
;;
|
||||
*)
|
||||
echo -e "\e[1;31mInvalid option\e[0m"
|
||||
*)
|
||||
echo -e "\e[1;31mInvalid option\e[0m"
|
||||
;;
|
||||
esac
|
||||
done
|
||||
@@ -1,5 +1,5 @@
|
||||
#!/bin/sh
|
||||
# Modified by iamromulan to set up a proper entware environment for Quectel RM5xx series m.2 modems
|
||||
# Modified by iamromlan to set up a proper entware environment for Quectel RM5xx series m.2 modems
|
||||
TYPE='generic'
|
||||
#|---------|-----------------|
|
||||
#| TARGET | Quectel Modem |
|
||||
@@ -17,6 +17,67 @@ PRE_OPKG_PATH=$(which opkg)
|
||||
# Remount filesystem as read-write
|
||||
mount -o remount,rw /
|
||||
|
||||
uninstall_entware() {
|
||||
echo -e '\033[31mInfo: Starting Entware/OPKG uninstallation...\033[0m'
|
||||
|
||||
# Stop services
|
||||
systemctl stop rc.unslung.service
|
||||
/opt/etc/init.d/rc.unslung stop
|
||||
rm /lib/systemd/system/multi-user.target.wants/rc.unslung.service
|
||||
rm /lib/systemd/system/rc.unslung.service
|
||||
|
||||
systemctl stop opt.mount
|
||||
rm /lib/systemd/system/multi-user.target.wants/start-opt-mount.service
|
||||
rm /lib/systemd/system/opt.mount
|
||||
rm /lib/systemd/system/start-opt-mount.service
|
||||
|
||||
# Unmount /opt if mounted
|
||||
mountpoint -q /opt && umount /opt
|
||||
|
||||
# Remove Entware installation directory
|
||||
rm -rf /usrdata/opt
|
||||
rm -rf /opt
|
||||
|
||||
# Reload systemctl daemon
|
||||
systemctl daemon-reload
|
||||
|
||||
# Optionally, clean up any modifications to /etc/profile or other system files
|
||||
# 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'
|
||||
}
|
||||
|
||||
# Check if /opt exists
|
||||
if [ -d /opt ]; then
|
||||
echo -e "\033[32mDo you want to uninstall Entware/OPKG first? It is already installed.\033[0m"
|
||||
echo -e "\033[32mThis will also resore your login process to Quectel Stock\033[0m"
|
||||
echo -e "\033[32m1) Yes\033[0m"
|
||||
echo -e "\033[32m2) No\033[0m"
|
||||
echo -e "\033[32m3) Cancel\033[0m"
|
||||
read -p "Select an option: " choice
|
||||
|
||||
case $choice in
|
||||
1)
|
||||
# Call the uninstall function
|
||||
uninstall_entware
|
||||
exit 0
|
||||
;;
|
||||
2)
|
||||
# Continue with the script
|
||||
echo "Continuing with the script..."
|
||||
;;
|
||||
3)
|
||||
echo "Canceling. Exiting script."
|
||||
exit 0
|
||||
;;
|
||||
*)
|
||||
echo "Invalid option. Please select 1, 2, or 3."
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
|
||||
create_opt_mount() {
|
||||
# Bind /usrdata/opt to /opt
|
||||
echo -e '\033[32mInfo: Setting up /opt mount to /usrdata/opt...\033[0m'
|
||||
@@ -57,13 +118,32 @@ EOF
|
||||
}
|
||||
|
||||
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"
|
||||
while true; do
|
||||
echo -e "\033[32mopkg already exists at: $PRE_OPKG_PATH\033[0m"
|
||||
echo -e "\033[32mDo you want to rename it to opkg_old?\033[0m"
|
||||
echo -e "\033[32m1) Yes (Highly Recommended)\033[0m"
|
||||
echo -e "\033[32m2) No (The opkg command may not work)\033[0m"
|
||||
read -p "Select an option (1 or 2): " user_choice
|
||||
|
||||
|
||||
case $user_choice in
|
||||
1)
|
||||
mv "$PRE_OPKG_PATH" "${PRE_OPKG_PATH}_old"
|
||||
echo "Factory/Already existing opkg has been renamed to opkg_old."
|
||||
break
|
||||
;;
|
||||
2)
|
||||
echo "Proceeding without renaming opkg."
|
||||
break
|
||||
;;
|
||||
*)
|
||||
echo "Invalid option. Please select 1 or 2."
|
||||
;;
|
||||
esac
|
||||
done
|
||||
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'
|
||||
@@ -130,9 +210,10 @@ systemctl start rc.unslung.service
|
||||
echo -e '\033[32mInfo: Congratulations!\033[0m'
|
||||
echo -e '\033[32mInfo: If there are no errors above then Entware was successfully initialized.\033[0m'
|
||||
echo -e '\033[32mInfo: Add /opt/bin & /opt/sbin to $PATH variable\033[0m'
|
||||
echo -e '\033[32mInfo: Run export PATH=/opt/bin:/opt/sbin:$PATH to do it for this session only\033[0m'
|
||||
echo -e '\033[32mInfo: opkg at /opt/bin will be linked to /bin but any package you install with opkg will not be automatically.\033[0m'
|
||||
ln -sf /opt/bin/opkg /bin
|
||||
echo -e '\033[32mInfo: Patching Quectel Login Binary\033[0m'
|
||||
opkg update && opkg install shadow-login shadow-passwd shadow-useradd
|
||||
opkg update && opkg install shadow-login shadow-passwd
|
||||
if [ "$?" -ne 0 ]; then
|
||||
echo -e "\e[1;31mPackage installation failed. Please check your internet connection and try again.\e[0m"
|
||||
exit 1
|
||||
@@ -153,15 +234,17 @@ opkg update && opkg install shadow-login shadow-passwd shadow-useradd
|
||||
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"
|
||||
echo -e "\e[1;31mPlease set your system login password.\e[0m"
|
||||
/usr/bin/passwd
|
||||
|
||||
# Install basic and useful utilites
|
||||
opkg install mc htop dfc lsof
|
||||
opkg install mc
|
||||
ln -sf /opt/bin/mc /bin
|
||||
opkg install htop
|
||||
ln -sf /opt/bin/htop /bin
|
||||
opkg install dfc
|
||||
ln -sf /opt/bin/dfc /bin
|
||||
opkg install lsof
|
||||
ln -sf /opt/bin/lsof /bin
|
||||
# Remount filesystem as read-only
|
||||
mount -o remount,ro /
|
||||
@@ -0,0 +1,28 @@
|
||||
#!/bin/bash
|
||||
|
||||
while true; do
|
||||
# Run AT+CGMM to get the modem model
|
||||
echo -en "AT+CGMM\r\n" | microcom -t 1000 /dev/ttyOUT > /tmp/modemmodel.txt
|
||||
sleep 2
|
||||
|
||||
# Run AT+CGCONTRDP once then proceed to while loop
|
||||
echo -en "AT+CGCONTRDP=1\r\n" | microcom -t 1000 /dev/ttyOUT > /tmp/apn.txt
|
||||
sleep 2
|
||||
|
||||
# Run AT+QUIMSLOT? to get the current sim slot
|
||||
echo -en "AT+QUIMSLOT?\r\n" | microcom -t 1000 /dev/ttyOUT > /tmp/simslot.txt
|
||||
sleep 2
|
||||
|
||||
# Send request to modem and wait 3 seconds for data
|
||||
echo -en "AT+QSPN;+CEREG=2;+CEREG?;+CEREG=0;+C5GREG=2;+C5GREG?;+C5GREG=0;+CSQ;+QENG=\"servingcell\";+QRSRP;+QCAINFO;+QNWPREFCFG=\"mode_pref\";+QTEMP\r\n" \
|
||||
| microcom -t 3000 /dev/ttyOUT > /tmp/modemstatus.txt
|
||||
if [ $? -eq 0 ]
|
||||
then
|
||||
# Parse
|
||||
if [ -f /tmp/modemstatus.txt ]
|
||||
then
|
||||
/usrdata/simpleadmin/scripts/modemstatus_parse.sh
|
||||
fi
|
||||
fi
|
||||
sleep 25 # Add a sleep to avoid CPU overload
|
||||
done
|
||||
540
old/original_main_repo/simpleadmin/scripts/modemstatus_parse.sh
Normal file
540
old/original_main_repo/simpleadmin/scripts/modemstatus_parse.sh
Normal file
@@ -0,0 +1,540 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Adapted to work with RJ45 / Quectel Board Dev
|
||||
# Quectel AT Parsing Original source ROOter2203
|
||||
# https://github.com/ofmodemsandmen/ROOterSource2203/blob/6636758b945ff16b6c5b54494de04b74b011c204/package/rooter/ext-rooter-basic/files/usr/lib/rooter/common/quecteldata.sh
|
||||
#
|
||||
|
||||
|
||||
rspr2rssi() {
|
||||
echo ${RSCP} ${BW_N} | awk '{printf "%.0f\n", (($1+10*log(12*$2)/log(10)))}'
|
||||
}
|
||||
|
||||
lte_bw() {
|
||||
BW=$(echo $BW | grep -o "[0-5]\{1\}")
|
||||
case $BW in
|
||||
"0")
|
||||
BW="1.4" ;;
|
||||
"1")
|
||||
BW="3" ;;
|
||||
"2"|"3"|"4"|"5")
|
||||
BW=$((($(echo $BW) - 1) * 5)) ;;
|
||||
esac
|
||||
}
|
||||
|
||||
nr_bw() {
|
||||
BW=$(echo $BW | grep -o "[0-9]\{1,2\}")
|
||||
case $BW in
|
||||
"0"|"1"|"2"|"3"|"4"|"5")
|
||||
BW=$((($(echo $BW) + 1) * 5)) ;;
|
||||
"6"|"7"|"8"|"9"|"10"|"11"|"12")
|
||||
BW=$((($(echo $BW) - 2) * 10)) ;;
|
||||
"13")
|
||||
BW="200" ;;
|
||||
"14")
|
||||
BW="400" ;;
|
||||
esac
|
||||
}
|
||||
|
||||
# Function to get the secondary LTE & NR5G bands
|
||||
get_secondary_bands_lte() {
|
||||
# Extract the LTE BANDs from SCC lines from /tmp/modemstatus.txt.
|
||||
# If there are multiple bands, they will be concatenated with <br/> tags.
|
||||
SC_BANDS=$(grep -o '"LTE BAND [0-9]\+"' /tmp/modemstatus.txt | tr -d '"' | sed '1d' | sed ':a;N;$!ba;s/\n/<br\/>/g')
|
||||
|
||||
# If there are no LTE bands or NR5G bands, set SC_BANDS to empty
|
||||
if [ -z "$SC_BANDS" ]; then
|
||||
SC_BANDS="-"
|
||||
fi
|
||||
|
||||
}
|
||||
|
||||
# Function to get the secondary NR5G bands for NR5G NSA
|
||||
get_secondary_bands_nsa() {
|
||||
# Extract the NR5G NSA BANDs from SCC lines from /tmp/modemstatus.txt.
|
||||
# If there are multiple bands, they will be concatenated with <br/> tags.
|
||||
SC_BANDS_NSA=$(grep -o '"NR5G BAND [0-9]\+"' /tmp/modemstatus.txt | tr -d '"' | sed ':a;N;$!ba;s/\n/<br\/>/g')
|
||||
echo $SC_BANDS_NSA > /tmp/scbands.txt
|
||||
|
||||
# If there are no NR5G NSA bands, set SC_BANDS_NSA to empty
|
||||
if [ -z "$SC_BANDS_NSA" ]; then
|
||||
SC_BANDS_NSA="-"
|
||||
fi
|
||||
}
|
||||
|
||||
get_secondary_bands_sa() {
|
||||
# Extract the NR5G SA BANDs from SCC lines from /tmp/modemstatus.txt.
|
||||
# If there are multiple bands, they will be concatenated with <br/> tags.
|
||||
SC_BANDS=$(grep -o '"NR5G BAND [0-9]\+"' /tmp/modemstatus.txt | tr -d '"' | sed '1d' | sed ':a;N;$!ba;s/\n/<br\/>/g')
|
||||
|
||||
# If there are no NR5G SA bands, set SC_BANDS to empty
|
||||
if [ -z "$SC_BANDS" ]; then
|
||||
SC_BANDS="-"
|
||||
fi
|
||||
}
|
||||
|
||||
# Get the modem model from /tmp/modemmodel.txt and parse it
|
||||
MODEM_MODEL=$(</tmp/modemmodel.txt)
|
||||
# Get the model name from the modem model (they either start with RG or RM)
|
||||
MODEM_MODEL=$(echo "$MODEM_MODEL" | grep -o "RG[^ ]\+\|RM[^ ]\+")
|
||||
|
||||
# Get the APN from /tmp/apn.txt and parse it
|
||||
APN=$(grep "^+CGCONTRDP" /tmp/apn.txt | awk -F',' '{gsub(/"/, "", $3); print $3}')
|
||||
|
||||
# Get the SIM slot from /tmp/simslot.txt and parse it
|
||||
# simslot.txt looks like this: +QUIMSLOT: 1
|
||||
SIMSLOT=$(</tmp/simslot.txt)
|
||||
SIMSLOT=$(echo "$SIMSLOT" | grep -o "[0-9]")
|
||||
# Append SIM before the SIM slot number
|
||||
SIMSLOT="SIM "$SIMSLOT
|
||||
|
||||
# Read File
|
||||
OX=$(</tmp/modemstatus.txt)
|
||||
|
||||
OX=$(echo $OX | tr 'a-z' 'A-Z')
|
||||
|
||||
RSRP=""
|
||||
RSRQ=""
|
||||
CHANNEL="-"
|
||||
ECIO="-"
|
||||
RSCP="-"
|
||||
ECIO1=" "
|
||||
RSCP1=" "
|
||||
MODE="-"
|
||||
MODTYPE="-"
|
||||
NETMODE="-"
|
||||
LBAND="-"
|
||||
PCI="-"
|
||||
CTEMP="-"
|
||||
SINR="-"
|
||||
COPS="-"
|
||||
COPS_MCC="-"
|
||||
COPS_MNC="-"
|
||||
CID=""
|
||||
CID5=""
|
||||
RAT=""
|
||||
QSPN=$(echo $OX | grep -o '+QSPN: "[^"]*","[^"]*","[^"]*",[^"]*,"[^"]*"' | cut -c 8-)
|
||||
# GET MCCMNC from the last field of QSPN
|
||||
MCCMNC=$(echo $QSPN | cut -d, -f5 | tr -d '"')
|
||||
PROVIDER=$(echo $QSPN | cut -d, -f1 | tr -d '"')
|
||||
PROVIDER_ID=$(echo $QSPN | cut -d, -f5 | tr -d '"')
|
||||
CSQ=$(echo $OX | grep -o "+CSQ: [0-9]\{1,2\}" | grep -o "[0-9]\{1,2\}")
|
||||
if [ "$CSQ" = "99" ]; then
|
||||
CSQ=""
|
||||
fi
|
||||
if [ -n "$CSQ" ]; then
|
||||
CSQ_PER=$(($CSQ * 100/31))"%"
|
||||
CSQ_RSSI=$((2 * CSQ - 113))" dBm"
|
||||
else
|
||||
CSQ="-"
|
||||
CSQ_PER="-"
|
||||
CSQ_RSSI="-"
|
||||
fi
|
||||
|
||||
NR_NSA=$(echo $OX | grep -o "+QENG:[ ]\?\"NR5G-NSA\",")
|
||||
NR_SA=$(echo $OX | grep -o "+QENG: \"SERVINGCELL\",[^,]\+,\"NR5G-SA\",\"[DFT]\{3\}\",")
|
||||
if [ -n "$NR_NSA" ]; then
|
||||
QENG=",,"$(echo $OX" " | grep -o "+QENG: \"LTE\".\+\"NR5G-NSA\"," | tr " " ",")
|
||||
if [ -z "$QENG5" ]; then
|
||||
# Fixed an issue where the last 2 digits were not included in the regex
|
||||
QENG5=$(echo $OX | grep -o "+QENG:[ ]\?\"NR5G-NSA\",[0-9]\{3\},[0-9]\{2,3\},[0-9]\{1,5\},-[0-9]\{2,3\},[-0-9]\{1,3\},-[0-9]\{2,3\},[0-9]\{1,6\},[0-9]\{1,3\},[0-9]\{1,3\},[0-9]\{1,3\}")
|
||||
if [ -n "$QENG5" ]; then
|
||||
QENG5=$QENG5",,"
|
||||
fi
|
||||
fi
|
||||
elif [ -n "$NR_SA" ]; then
|
||||
QENG=$(echo $NR_SA | tr " " ",")
|
||||
QENG5=$(echo $OX | grep -o "+QENG: \"SERVINGCELL\",[^,]\+,\"NR5G-SA\",\"[DFT]\{3\}\",[ 0-9]\{3,4\},[0-9]\{2,3\},[0-9A-F]\{1,10\},[0-9]\{1,5\},[0-9A-F]\{2,6\},[0-9]\{6,7\},[0-9]\{1,3\},[0-9]\{1,2\},-[0-9]\{2,5\},-[0-9]\{2,3\},[-0-9]\{1,3\}")
|
||||
else
|
||||
QENG=$(echo $OX" " | grep -o "+QENG: [^ ]\+ " | tr " " ",")
|
||||
fi
|
||||
QCA=$(echo $OX" " | grep -o "+QCAINFO: \"S[CS]\{2\}\".\+NWSCANMODE" | tr " " ",")
|
||||
QNSM=$(echo $OX | grep -o "+QCFG: \"NWSCANMODE\",[0-9]")
|
||||
QNWP=$(echo $OX | grep -o "+QNWPREFCFG: \"MODE_PREF\",[A-Z5:]\+" | cut -d, -f2)
|
||||
QTEMP=$(echo $OX | grep -o "+QTEMP: [0-9]\{1,3\}")
|
||||
if [ -z "$QTEMP" ]; then
|
||||
QTEMP=$(echo $OX | grep -o "+QTEMP:[ ]\?\"XO[_-]THERM[_-][^,]\+,[\"]\?[0-9]\{1,3\}" | grep -o "[0-9]\{1,3\}")
|
||||
fi
|
||||
if [ -z "$QTEMP" ]; then
|
||||
QTEMP=$(echo $OX | grep -o "+QTEMP:[ ]\?\"MDM-CORE-USR.\+[0-9]\{1,3\}\"" | cut -d\" -f4)
|
||||
fi
|
||||
if [ -z "$QTEMP" ]; then
|
||||
QTEMP=$(echo $OX | grep -o "+QTEMP:[ ]\?\"MDMSS.\+[0-9]\{1,3\}\"" | cut -d\" -f4)
|
||||
fi
|
||||
if [ -n "$QTEMP" ]; then
|
||||
CTEMP=$(echo $QTEMP | grep -o "[0-9]\{1,3\}")$(printf "\xc2\xb0")"C"
|
||||
fi
|
||||
RAT=$(echo $QENG | cut -d, -f4 | grep -o "[-A-Z5]\{3,7\}")
|
||||
|
||||
|
||||
rm -f /tmp/modnetwork
|
||||
case $RAT in
|
||||
"GSM")
|
||||
MODE="GSM"
|
||||
;;
|
||||
"WCDMA")
|
||||
MODE="WCDMA"
|
||||
CHANNEL=$(echo $QENG | cut -d, -f9)
|
||||
RSCP=$(echo $QENG | cut -d, -f12)
|
||||
RSCP="-"$(echo $RSCP | grep -o "[0-9]\{1,3\}")
|
||||
ECIO=$(echo $QENG | cut -d, -f13)
|
||||
ECIO="-"$(echo $ECIO | grep -o "[0-9]\{1,3\}")
|
||||
;;
|
||||
"LTE"|"CAT-M"|"CAT-NB")
|
||||
MODE=$(echo $QENG | cut -d, -f5 | grep -o "[DFT]\{3\}")
|
||||
if [ -n "$MODE" ]; then
|
||||
MODE="$RAT $MODE"
|
||||
else
|
||||
MODE="$RAT"
|
||||
fi
|
||||
get_secondary_bands_lte
|
||||
PCI=$(echo $QENG | cut -d, -f9)
|
||||
CHANNEL=$(echo $QENG | cut -d, -f10)
|
||||
LBAND=$(echo $QENG | cut -d, -f11 | grep -o "[0-9]\{1,3\}")
|
||||
BW=$(echo $QENG | cut -d, -f12)
|
||||
lte_bw
|
||||
BWU=$BW
|
||||
BW=$(echo $QENG | cut -d, -f13)
|
||||
lte_bw
|
||||
BWD=$BW
|
||||
if [ -z "$BWD" ]; then
|
||||
BWD="unknown"
|
||||
fi
|
||||
if [ -z "$BWU" ]; then
|
||||
BWU="unknown"
|
||||
fi
|
||||
if [ -n "$LBAND" ]; then
|
||||
PC_BAND="LTE BAND "$LBAND
|
||||
LBAND="B"$LBAND" (Bandwidth $BWD MHz Down | $BWU MHz Up)"
|
||||
fi
|
||||
RSRP=$(echo $QENG | cut -d, -f15 | grep -o "[0-9]\{1,3\}")
|
||||
if [ -n "$RSRP" ]; then
|
||||
RSCP="-"$RSRP
|
||||
RSRPLTE=$RSCP
|
||||
fi
|
||||
RSRQ=$(echo $QENG | cut -d, -f16 | grep -o "[0-9]\{1,3\}")
|
||||
if [ -n "$RSRQ" ]; then
|
||||
ECIO="-"$RSRQ
|
||||
fi
|
||||
RSSI=$(echo $QENG | cut -d, -f17 | grep -o "\-[0-9]\{1,3\}")
|
||||
if [ -n "$RSSI" ]; then
|
||||
CSQ_RSSI=$RSSI" dBm"
|
||||
fi
|
||||
SINRR=$(echo $QENG | cut -d, -f18 | grep -o "[0-9]\{1,3\}")
|
||||
if [ -n "$SINRR" ]; then
|
||||
if [ $SINRR -le 25 ]; then
|
||||
SINR=$((($(echo $SINRR) * 2) -20))" dB"
|
||||
fi
|
||||
fi
|
||||
if [ -n "$(echo $QENG | cut -d, -f21)" ]; then
|
||||
CQI=$(echo $QENG | cut -d, -f19 | grep "^[0-9]\+$")
|
||||
if [ -n "$SINR" -a -n "$CQI" -a "$CQI" != "0" ]; then
|
||||
SINR=$SINR" (CQI $CQI)"
|
||||
fi
|
||||
fi
|
||||
if [ -n "$NR_NSA" ]; then
|
||||
# Changed network mode to NR5G NSA for easy identification
|
||||
MODE="NR5G NSA"
|
||||
echo "0" > /tmp/modnetwork
|
||||
if [ -n "$QENG5" ]; then
|
||||
QENG5=$QENG5",,"
|
||||
get_secondary_bands_nsa
|
||||
# Append the SC_BANDS_NSA to SC_BANDS with <br /> tags
|
||||
SC_BANDS=$SC_BANDS"<br />"$SC_BANDS_NSA
|
||||
PCI="$PCI, "$(echo $QENG5 | cut -d, -f4)
|
||||
SCHV=$(echo $QENG5 | cut -d, -f8)
|
||||
SLBV=$(echo $QENG5 | cut -d, -f9) # Now correctly captures the NR band
|
||||
BW=$(echo $QENG5 | cut -d, -f10) # Now gets the correct BW
|
||||
if [ -n "$SLBV" ]; then
|
||||
LBAND=$LBAND"<br />n"$SLBV
|
||||
if [ -n "$BW" ]; then
|
||||
nr_bw
|
||||
LBAND=$LBAND" (Bandwidth $BW MHz)"
|
||||
fi
|
||||
if [ "$SCHV" -ge 123400 ]; then
|
||||
CHANNEL=$CHANNEL", "$SCHV
|
||||
else
|
||||
CHANNEL=$CHANNEL", -"
|
||||
fi
|
||||
else
|
||||
# removed the (unknown NR5G BAND) and replaced with No NR5G Band to avoid confusion
|
||||
LBAND=$LBAND"<br />No NR5G Band Detected"
|
||||
CHANNEL=$CHANNEL", -"
|
||||
fi
|
||||
RSCP=$RSCP" dBm<br />"$(echo $QENG5 | cut -d, -f5)
|
||||
SINRR=$(echo $QENG5 | cut -d, -f6 | grep -o "[0-9]\{1,3\}")
|
||||
if [ -n "$SINRR" ]; then
|
||||
if [ $SINRR -le 30 ]; then
|
||||
SINR=$SINR"<br />"$((($(echo $SINRR) * 2) -20))" dB"
|
||||
fi
|
||||
fi
|
||||
ECIO=$ECIO" (4G) dB<br />"$(echo $QENG5 | cut -d, -f7)" (5G) "
|
||||
fi
|
||||
fi
|
||||
if [ -z "$LBAND" ]; then
|
||||
LBAND="-"
|
||||
else
|
||||
if [ -n "$QCA" ]; then
|
||||
QCA=$(echo $QCA | grep -o "\"S[CS]\{2\}\"[-0-9A-Z,\"]\+")
|
||||
for QCAL in $(echo "$QCA"); do
|
||||
if [ $(echo "$QCAL" | cut -d, -f7) = "2" ]; then
|
||||
SCHV=$(echo $QCAL | cut -d, -f2 | grep -o "[0-9]\+")
|
||||
SRATP="B"
|
||||
if [ -n "$SCHV" ]; then
|
||||
CHANNEL="$CHANNEL, $SCHV"
|
||||
if [ "$SCHV" -gt 123400 ]; then
|
||||
SRATP="n"
|
||||
fi
|
||||
fi
|
||||
SLBV=$(echo $QCAL | cut -d, -f6 | grep -o "[0-9]\{1,2\}")
|
||||
if [ -n "$SLBV" ]; then
|
||||
LBAND=$LBAND"<br />"$SRATP$SLBV
|
||||
BWD=$(echo $QCAL | cut -d, -f3 | grep -o "[0-9]\{1,3\}")
|
||||
if [ -n "$BWD" ]; then
|
||||
UPDOWN=$(echo $QCAL | cut -d, -f13)
|
||||
case "$UPDOWN" in
|
||||
"UL" )
|
||||
CATYPE="CA"$(printf "\xe2\x86\x91") ;;
|
||||
"DL" )
|
||||
CATYPE="CA"$(printf "\xe2\x86\x93") ;;
|
||||
* )
|
||||
CATYPE="CA" ;;
|
||||
esac
|
||||
if [ $BWD -gt 14 ]; then
|
||||
LBAND=$LBAND" ("$CATYPE", Bandwidth "$(($(echo $BWD) / 5))" MHz)"
|
||||
else
|
||||
LBAND=$LBAND" ("$CATYPE", Bandwidth 1.4 MHz)"
|
||||
fi
|
||||
fi
|
||||
LBAND=$LBAND
|
||||
fi
|
||||
PCI="$PCI, "$(echo $QCAL | cut -d, -f8)
|
||||
fi
|
||||
done
|
||||
fi
|
||||
fi
|
||||
if [ $RAT = "CAT-M" ] || [ $RAT = "CAT-NB" ]; then
|
||||
LBAND="B$(echo $QENG | cut -d, -f11) ($RAT)"
|
||||
fi
|
||||
;;
|
||||
"NR5G-SA")
|
||||
MODE="NR5G-SA"
|
||||
echo "0" > /tmp/modnetwork
|
||||
if [ -n "$QENG5" ]; then
|
||||
MODE="$RAT $(echo $QENG5 | cut -d, -f4)"
|
||||
PCI=$(echo $QENG5 | cut -d, -f8)
|
||||
get_secondary_bands_sa
|
||||
# Apply | sed '1d' to NR_BAND
|
||||
# Temporarily removed the sed command for testing
|
||||
CHANNEL=$(echo $QENG5 | cut -d, -f10)
|
||||
LBAND=$(echo $QENG5 | cut -d, -f11)
|
||||
PC_BAND="NR5G BAND "$LBAND
|
||||
BW=$(echo $QENG5 | cut -d, -f12)
|
||||
nr_bw
|
||||
LBAND="n"$LBAND" (Bandwidth $BW MHz)"
|
||||
RSCP=$(echo $QENG5 | cut -d, -f13)
|
||||
ECIO=$(echo $QENG5 | cut -d, -f14)
|
||||
if [ "$CSQ_PER" = "-" ]; then
|
||||
BW_N=($BW * 5)
|
||||
RSSI=$(rspr2rssi)
|
||||
CSQ_PER=$((100 - (($RSSI + 51) * 100/-62)))"%"
|
||||
CSQ=$((($RSSI + 113) / 2))
|
||||
CSQ_RSSI=$RSSI" dBm"
|
||||
fi
|
||||
SINRR=$(echo $QENG5 | cut -d, -f15 | grep -o "[0-9]\{1,3\}")
|
||||
if [ -n "$SINRR" ]; then
|
||||
if [ $SINRR -le 30 ]; then
|
||||
SINR=$((($(echo $SINRR) * 2) -20))" dB"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
|
||||
QRSRP=$(echo "$OX" | grep -o "+QRSRP:[^,]\+,-[0-9]\{1,5\},-[0-9]\{1,5\},-[0-9]\{1,5\}[^ ]*")
|
||||
if [ -n "$QRSRP" ] && [ "$RAT" != "WCDMA" ]; then
|
||||
QRSRP1=$(echo $QRSRP | cut -d, -f1 | grep -o "[-0-9]\+")
|
||||
QRSRP2=$(echo $QRSRP | cut -d, -f2)
|
||||
QRSRP3=$(echo $QRSRP | cut -d, -f3)
|
||||
QRSRP4=$(echo $QRSRP | cut -d, -f4)
|
||||
QRSRPtype=$(echo $QRSRP | cut -d, -f5)
|
||||
if [ "$QRSRPtype" == "NR5G" ]; then
|
||||
if [ -n "$NR_SA" ]; then
|
||||
RSCP=$QRSRP1
|
||||
if [ -n "$QRSRP2" -a "$QRSRP2" != "-32768" ]; then
|
||||
RSCP1="RxD "$QRSRP2
|
||||
fi
|
||||
if [ -n "$QRSRP3" -a "$QRSRP3" != "-32768" -a "$QRSRP3" != "-44" ]; then
|
||||
RSCP=$RSCP" dBm<br />"$QRSRP3
|
||||
fi
|
||||
if [ -n "$QRSRP4" -a "$QRSRP4" != "-32768" -a "$QRSRP4" != "-44" ]; then
|
||||
RSCP1="RxD "$QRSRP4
|
||||
fi
|
||||
else
|
||||
RSCP=$RSRPLTE
|
||||
if [ -n "$QRSRP1" -a "$QRSRP1" != "-32768" -a "$QRSRP1" != "-44" ]; then
|
||||
RSCP=$RSCP" (4G) dBm<br />"$QRSRP1
|
||||
if [ -n "$QRSRP2" -a "$QRSRP2" != "-32768" -a "$QRSRP2" != "-44" ]; then
|
||||
RSCP="$RSCP, $QRSRP2"
|
||||
if [ -n "$QRSRP3" -a "$QRSRP3" != "-32768" -a "$QRSRP3" != "-44" ]; then
|
||||
RSCP="$RSCP, $QRSRP3"
|
||||
if [ -n "$QRSRP4" -a "$QRSRP4" != "-32768" -a "$QRSRP4" != "-44" ]; then
|
||||
RSCP="$RSCP, $QRSRP4"
|
||||
fi
|
||||
fi
|
||||
RSCP=$RSCP" (5G) "
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
elif [ "$QRSRP2$QRSRP3$QRSRP4" != "-44-44-44" -a -z "$QENG5" ]; then
|
||||
RSCP=$QRSRP1
|
||||
if [ "$QRSRP3$QRSRP4" == "-140-140" -o "$QRSRP3$QRSRP4" == "-44-44" -o "$QRSRP3$QRSRP4" == "-32768-32768" ]; then
|
||||
RSCP1="RxD "$(echo $QRSRP | cut -d, -f2)
|
||||
else
|
||||
RSCP=$RSCP" dBm (RxD "$QRSRP2" dBm)<br />"$QRSRP3
|
||||
RSCP1="RxD "$QRSRP4
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
QNSM=$(echo "$QNSM" | grep -o "[0-9]")
|
||||
if [ -n "$QNSM" ]; then
|
||||
MODTYPE="6"
|
||||
case $QNSM in
|
||||
"0" )
|
||||
NETMODE="1" ;;
|
||||
"1" )
|
||||
NETMODE="3" ;;
|
||||
"2"|"5" )
|
||||
NETMODE="5" ;;
|
||||
"3" )
|
||||
NETMODE="7" ;;
|
||||
esac
|
||||
fi
|
||||
if [ -n "$QNWP" ]; then
|
||||
MODTYPE="6"
|
||||
case $QNWP in
|
||||
"AUTO" )
|
||||
NETMODE="1" ;;
|
||||
"WCDMA" )
|
||||
NETMODE="5" ;;
|
||||
"LTE" )
|
||||
NETMODE="7" ;;
|
||||
"LTE:NR5G" )
|
||||
NETMODE="8" ;;
|
||||
"NR5G" )
|
||||
NETMODE="9" ;;
|
||||
esac
|
||||
fi
|
||||
|
||||
OX=$(echo "${OX//[ \"]/}")
|
||||
|
||||
REGV=$(echo "$OX" | grep -o "+C5GREG:2,[0-9],[A-F0-9]\{2,6\},[A-F0-9]\{5,10\},[0-9]\{1,2\}")
|
||||
if [ -n "$REGV" ]; then
|
||||
LAC5=$(echo "$REGV" | cut -d, -f3)
|
||||
LAC5=$LAC5" ($(printf "%d" 0x$LAC5))"
|
||||
CID5=$(echo "$REGV" | cut -d, -f4)
|
||||
CID5L=$(printf "%010X" 0x$CID5)
|
||||
RNC5=${CID5L:1:6}
|
||||
RNC5=$RNC5" ($(printf "%d" 0x$RNC5))"
|
||||
CID5=${CID5L:7:3}
|
||||
CID5="Short $(printf "%X" 0x$CID5) ($(printf "%d" 0x$CID5)), Long $(printf "%X" 0x$CID5L) ($(printf "%d" 0x$CID5L))"
|
||||
RAT=$(echo "$REGV" | cut -d, -f5)
|
||||
fi
|
||||
REGV=$(echo "$OX" | grep -o "+CEREG:2,[0-9],[A-F0-9]\{2,4\},[A-F0-9]\{5,8\}")
|
||||
REGFMT="3GPP"
|
||||
if [ -z "$REGV" ]; then
|
||||
REGV=$(echo "$OX" | grep -o "+CEREG:2,[0-9],[A-F0-9]\{2,4\},[A-F0-9]\{1,3\},[A-F0-9]\{5,8\}")
|
||||
REGFMT="SW"
|
||||
fi
|
||||
if [ -n "$REGV" ]; then
|
||||
LAC=$(echo "$REGV" | cut -d, -f3)
|
||||
LAC=$(printf "%04X" 0x$LAC)" ($(printf "%d" 0x$LAC))"
|
||||
if [ $REGFMT = "3GPP" ]; then
|
||||
CID=$(echo "$REGV" | cut -d, -f4)
|
||||
else
|
||||
CID=$(echo "$REGV" | cut -d, -f5)
|
||||
fi
|
||||
CIDL=$(printf "%08X" 0x$CID)
|
||||
RNC=${CIDL:1:5}
|
||||
RNC=$RNC" ($(printf "%d" 0x$RNC))"
|
||||
CID=${CIDL:6:2}
|
||||
CID="Short $(printf "%X" 0x$CID) ($(printf "%d" 0x$CID)), Long $(printf "%X" 0x$CIDL) ($(printf "%d" 0x$CIDL))"
|
||||
|
||||
else
|
||||
REGV=$(echo "$OX" | grep -o "+CREG:2,[0-9],[A-F0-9]\{2,4\},[A-F0-9]\{2,8\}")
|
||||
if [ -n "$REGV" ]; then
|
||||
LAC=$(echo "$REGV" | cut -d, -f3)
|
||||
CID=$(echo "$REGV" | cut -d, -f4)
|
||||
if [ ${#CID} -gt 4 ]; then
|
||||
LAC=$(printf "%04X" 0x$LAC)" ($(printf "%d" 0x$LAC))"
|
||||
CIDL=$(printf "%08X" 0x$CID)
|
||||
RNC=${CIDL:1:3}
|
||||
CID=${CIDL:4:4}
|
||||
CID="Short $(printf "%X" 0x$CID) ($(printf "%d" 0x$CID)), Long $(printf "%X" 0x$CIDL) ($(printf "%d" 0x$CIDL))"
|
||||
else
|
||||
LAC=""
|
||||
fi
|
||||
else
|
||||
LAC=""
|
||||
fi
|
||||
fi
|
||||
REGSTAT=$(echo "$REGV" | cut -d, -f2)
|
||||
if [ "$REGSTAT" == "5" -a "$COPS" != "-" ]; then
|
||||
COPS_MNC=$COPS_MNC" (Roaming)"
|
||||
fi
|
||||
if [ -n "$CID" -a -n "$CID5" ] && [ "$RAT" == "13" -o "$RAT" == "10" ]; then
|
||||
LAC="4G $LAC, 5G $LAC5"
|
||||
CID="4G $CID<br />5G $CID5"
|
||||
RNC="4G $RNC, 5G $RNC5"
|
||||
elif [ -n "$CID5" ]; then
|
||||
LAC=$LAC5
|
||||
CID=$CID5
|
||||
RNC=$RNC5
|
||||
fi
|
||||
if [ -z "$LAC" ]; then
|
||||
LAC="-"
|
||||
CID="-"
|
||||
RNC="-"
|
||||
fi
|
||||
|
||||
LUPDATE=$(date +%s)
|
||||
rm -fR /tmp/signal.txt
|
||||
MODEZ=$(echo $MODE | tr -d '"')
|
||||
{
|
||||
echo 'PROVIDER="'"$PROVIDER"'"'
|
||||
echo 'CSQ="'"$CSQ"'"'
|
||||
echo 'CSQ_PER="'"$CSQ_PER"'"'
|
||||
echo 'CSQ_RSSI="'"$CSQ_RSSI"'"'
|
||||
echo 'ECIO="'"$ECIO"'"'
|
||||
echo 'RSCP="'"$RSCP"'"'
|
||||
echo 'ECIO1="'"$ECIO1"'"'
|
||||
echo 'RSCP1="'"$RSCP1"'"'
|
||||
echo 'MODE="'"$MODEZ"'"'
|
||||
echo 'MODTYPE="'"$MODTYPE"'"'
|
||||
echo 'NETMODE="'"$NETMODE"'"'
|
||||
echo 'CHANNEL="'"$CHANNEL"'"'
|
||||
echo 'LBAND="'"$LBAND"'"'
|
||||
echo 'PC_BAND="'"$PC_BAND"'"'
|
||||
echo 'SC_BANDS="'"$SC_BANDS"'"'
|
||||
echo 'APN="'"$APN"'"'
|
||||
echo 'MODEM_MODEL="'"$MODEM_MODEL"'"'
|
||||
echo 'SIMSLOT="'"$SIMSLOT"'"'
|
||||
echo 'PCI="'"$PCI"'"'
|
||||
echo 'TEMP="'"$CTEMP"'"'
|
||||
echo 'SINR="'"$SINR"'"'
|
||||
echo 'LASTUPDATE="'"$LUPDATE"'"'
|
||||
echo 'COPS="'"$COPS"'"'
|
||||
echo 'COPS_MCC="'"$COPS_MCC"'"'
|
||||
echo 'COPS_MNC="'"$COPS_MNC"'"'
|
||||
echo 'MCCMNC="'"$MCCMNC"'"'
|
||||
echo 'LAC="'"$LAC"'"'
|
||||
echo 'LAC_NUM="'""'"'
|
||||
echo 'CID="'"$CID"'"'
|
||||
echo 'CID_NUM="'""'"'
|
||||
echo 'RNC="'"$RNC"'"'
|
||||
echo 'RNC_NUM="'""'"'
|
||||
} > /tmp/signal.txt
|
||||
|
||||
# Pregenerate JSON File
|
||||
/usrdata/simpleadmin/scripts/tojson.sh /tmp/signal.txt > /tmp/modemstatus.json
|
||||
48
old/original_main_repo/simpleadmin/scripts/tojson.sh
Normal file
48
old/original_main_repo/simpleadmin/scripts/tojson.sh
Normal file
@@ -0,0 +1,48 @@
|
||||
#!/bin/bash
|
||||
# sarav (hello@grity.com)
|
||||
# convert key=value to json
|
||||
# Created at Gritfy ( Devops Junction )
|
||||
# Updated by: dr-dolomite to make it more robust since it was failing on some casess
|
||||
|
||||
file_name="$1"
|
||||
|
||||
echo "{"
|
||||
last_line=$(wc -l < "$file_name")
|
||||
first_line=true
|
||||
|
||||
while IFS='=' read -r key value || [[ -n "$key" ]]; do
|
||||
# Skip empty lines and comments
|
||||
if [[ -z "$key" || "$key" == \#* ]]; then
|
||||
continue
|
||||
fi
|
||||
|
||||
# Trim leading and trailing whitespace from key and value
|
||||
key=$(echo "$key" | awk '{$1=$1};1')
|
||||
value=$(echo "$value" | awk '{$1=$1};1')
|
||||
|
||||
# Check if value includes double quotes inside it like: "value,"value"". If there is, remove the inner double quotes.
|
||||
if [[ "$value" == *\"* ]]; then
|
||||
value=$(echo "$value" | sed 's/\"//g')
|
||||
# enclose the value in double quotes again
|
||||
value="\"$value\""
|
||||
fi
|
||||
|
||||
# Check if value is empty, if so, skip printing this key-value pair
|
||||
if [[ -z "$value" ]]; then
|
||||
continue
|
||||
fi
|
||||
|
||||
# Print comma before each pair except for the first one
|
||||
if $first_line; then
|
||||
first_line=false
|
||||
else
|
||||
printf ','
|
||||
fi
|
||||
|
||||
# Print key-value pair in JSON format without surrounding double quotes on value
|
||||
printf ' "%s" : %s' "$key" "$value"
|
||||
|
||||
printf '\n'
|
||||
done < "$file_name"
|
||||
|
||||
echo "}"
|
||||
@@ -0,0 +1,9 @@
|
||||
[Unit]
|
||||
Description=Simpleadmin service to generate status from modem
|
||||
|
||||
[Service]
|
||||
ExecStart=/usrdata/simpleadmin/scripts/build_modem_status
|
||||
Restart=always
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
@@ -0,0 +1,11 @@
|
||||
[Unit]
|
||||
Description=SimpleAdmin httpd service
|
||||
After=network.target
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
ExecStart=/usr/sbin/httpd -f -h /usrdata/simpleadmin/www -p 8080
|
||||
ExecStop=/bin/kill -WINCH ${MAINPID}
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
352
old/original_main_repo/simpleadmin/www/atcommander.html
Normal file
352
old/original_main_repo/simpleadmin/www/atcommander.html
Normal file
@@ -0,0 +1,352 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<title>Simple Settings</title>
|
||||
|
||||
<script src="/js/alpinejs.min.js" defer></script>
|
||||
<link rel="stylesheet" href="/css/bulma.css" />
|
||||
<link rel="stylesheet" type="text/css" href="/css/admin.css" />
|
||||
<link rel="stylesheet" href="styles.css" />
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<!-- START NAV -->
|
||||
<nav class="navbar is-black" x-data="{ isOpen: false }">
|
||||
<div class="container">
|
||||
<div class="navbar-brand">
|
||||
<a class="navbar-item brand-text" href="/"> Simple Admin </a>
|
||||
<a
|
||||
role="button"
|
||||
class="navbar-burger burger"
|
||||
@click="isOpen = !isOpen"
|
||||
>
|
||||
<span aria-hidden="true"></span>
|
||||
<span aria-hidden="true"></span>
|
||||
<span aria-hidden="true"></span>
|
||||
</a>
|
||||
</div>
|
||||
<div
|
||||
id="navMenu"
|
||||
class="navbar-menu"
|
||||
:class="isOpen ? 'is-active' : ''"
|
||||
>
|
||||
<div class="navbar-start">
|
||||
<a class="navbar-item" href="/"> Connection Info </a>
|
||||
<a class="navbar-item" href="/atcommander.html"> AT Commands </a>
|
||||
<a class="navbar-item" href="/bandlock.html"> Simple Network </a>
|
||||
<a class="navbar-item" href="/ttl.html"> TTL Changer </a>
|
||||
<a class="navbar-item" href="/speedtest.html"> OpenSpeedtest </a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
<!-- END NAV -->
|
||||
<div class="container" x-data="atCommands()">
|
||||
<div class="columns">
|
||||
<div class="column is-12">
|
||||
<div class="columns">
|
||||
<div class="column is-4">
|
||||
<div class="card">
|
||||
<header class="card-header">
|
||||
<p class="card-header-title">AT Command</p>
|
||||
</header>
|
||||
<div class="card-content">
|
||||
<div class="content">
|
||||
<div class="field">
|
||||
<label class="label">AT Command</label>
|
||||
<div class="control">
|
||||
<input
|
||||
class="input"
|
||||
type="text"
|
||||
placeholder="ATI"
|
||||
x-model="atcmd"
|
||||
x-ref="atCmdInput"
|
||||
@keydown.enter="sendAtCommand()"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="field">
|
||||
<p class="control">
|
||||
<button
|
||||
class="button is-success"
|
||||
@click="sendAtCommand()"
|
||||
:disabled="isLoading"
|
||||
>
|
||||
Send AT Command
|
||||
</button>
|
||||
|
||||
<button
|
||||
class="button is-danger"
|
||||
@click="clearResponses()"
|
||||
:disabled="atCommandResponse === ''"
|
||||
>
|
||||
Clear
|
||||
</button>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="column is-8">
|
||||
<div class="card">
|
||||
<header class="card-header">
|
||||
<p class="card-header-title">AT Command Response</p>
|
||||
</header>
|
||||
<div class="card-content">
|
||||
<div class="content">
|
||||
<textarea
|
||||
class="textarea"
|
||||
placeholder="Multiple commands should be separated by a semicolon. Example: AT+CGMR;+GSN"
|
||||
rows="10"
|
||||
x-text="isLoading ? 'Fetching response, please wait...' : atCommandResponse"
|
||||
></textarea>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- START Useful Commands Section -->
|
||||
<div class="container" x-data="atCommands()">
|
||||
<div class="columns">
|
||||
<div class="column is-12">
|
||||
<div class="card">
|
||||
<header class="card-header">
|
||||
<p class="card-header-title">Useful One Click Commands</p>
|
||||
</header>
|
||||
<div class="card-content">
|
||||
<div class="content">
|
||||
<div style="display: flex; flex-direction: row; flex-wrap: wrap; margin-top: 1rem; justify-content: space-between;">
|
||||
<div class="field">
|
||||
<div class="control">
|
||||
<button
|
||||
class="button is-danger"
|
||||
@click="sendRebootCommand()"
|
||||
:disabled="isRebooting"
|
||||
>
|
||||
Reboot
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- <div class="field">
|
||||
<div class="control">
|
||||
<button
|
||||
class="button is-danger"
|
||||
@click="sendRebootCommand()"
|
||||
:disabled="isRebooting"
|
||||
>
|
||||
Reboot
|
||||
</button>
|
||||
</div>
|
||||
</div> -->
|
||||
</div>
|
||||
<p>Here are some useful commands:</p>
|
||||
<ul>
|
||||
<li>
|
||||
<!-- Open to another tab -->
|
||||
See <a href="https://github.com/iamromulan/RM520N-GL#at-commands" target="_blank" style="cursor: pointer;">https://github.com/iamromulan/RM520N-GL#at-commands</a> for
|
||||
more
|
||||
</li>
|
||||
<li>AT+CFUN=1,1 (reboot)</li>
|
||||
<li>
|
||||
AT+QMAPWAC? (get current status of auto connect, 0=disabled
|
||||
1=enabled)
|
||||
</li>
|
||||
<li>
|
||||
AT+QMAPWAC=1 (enable auto connect internet for ethernet)
|
||||
</li>
|
||||
<li>
|
||||
AT+QMAPWAC=0 (disable auto connect for ethernet; use when
|
||||
you want internet over usb to work; IPPT must be disabled)
|
||||
</li>
|
||||
<li>
|
||||
AT+QUIMSLOT? (get active sim slot; 1=Slot 1; 2=Slot 2)
|
||||
</li>
|
||||
<li>AT+QUIMSLOT=1 (switch to sim slot 1)</li>
|
||||
<li>AT+QUIMSLOT=2 (switch to sim slot 2)</li>
|
||||
<li>AT+CGDCONT? (Get active APN profle list 1 through 8)</li>
|
||||
<li>
|
||||
AT+CGDCONT=1,"IPV4V6","APNHERE" (Sets APN profle 1 to
|
||||
APNHERE using both IPV4 and IPV6)
|
||||
</li>
|
||||
<li>AT+GSN (Show current IMEI)</li>
|
||||
<li>AT+EGMR=1,7,"IMEIGOESHERE" (sets/repairs IMEI)</li>
|
||||
<li>AT+QCAINFO (Show all connected bands/CA info)</li>
|
||||
<li>
|
||||
AT+QNWPREFCFG="mode_pref" (Check what the current network
|
||||
search mode is set to)
|
||||
</li>
|
||||
<li>
|
||||
AT+QNWPREFCFG="mode_pref",AUTO (Set network search mode to
|
||||
automatic)
|
||||
</li>
|
||||
<li>
|
||||
AT+QNWPREFCFG="mode_pref",NR5G:LTE (Set network search mode
|
||||
to 5G/NR and 4G/LTE only)
|
||||
</li>
|
||||
<li>
|
||||
AT+QNWPREFCFG="mode_pref",NR5G (Set network search mode to
|
||||
5G/NR only)
|
||||
</li>
|
||||
<li>
|
||||
AT+QNWPREFCFG="mode_pref",LTE (Set network search mode to
|
||||
4G/LTE only)
|
||||
</li>
|
||||
<li>
|
||||
AT+QNWPREFCFG="nr5g_disable_mode" (Check to see if SA or NSA
|
||||
NR5G is disabled)
|
||||
</li>
|
||||
<li>
|
||||
AT+QNWPREFCFG="nr5g_disable_mode",0 (Enable Both SA and NSA
|
||||
5G/NR)
|
||||
</li>
|
||||
<li>
|
||||
AT+QNWPREFCFG="nr5g_disable_mode",1 (Disable SA 5G/NR only)
|
||||
</li>
|
||||
<li>
|
||||
AT+QNWPREFCFG="nr5g_disable_mode",2 (Disable NSA 5G/NR only)
|
||||
</li>
|
||||
<li>
|
||||
AT+QNWPREFCFG="nr5g_band" (Get current 5G/NR bandlock
|
||||
settings)
|
||||
</li>
|
||||
<li>
|
||||
AT+QNWPREFCFG="nr5g_band",1:2:3:4:5:6 (Example: Lock to
|
||||
5G/NR bands n1,n2,n3,n4,n5, and n6)
|
||||
</li>
|
||||
<li>
|
||||
AT+QNWPREFCFG="lte_band" (Get current 4G/LTE bandlock
|
||||
settings)
|
||||
</li>
|
||||
<li>
|
||||
AT+QNWPREFCFG="lte_band",1:2:3:4:5:6 (Example: Lock to
|
||||
4G/LTE bands 1,2,3,4,5, and 6)
|
||||
</li>
|
||||
<li>
|
||||
AT+QMAP="WWAN" (Show currently assigned IPv4 and IPv6 from
|
||||
the provider)
|
||||
</li>
|
||||
<li>
|
||||
AT+QMAP="LANIP" (Show current DHCP range and Gateway address
|
||||
for VLAN0)
|
||||
</li>
|
||||
<li>
|
||||
AT+QMAP="LANIP",IP_start_range,IP_end_range,Gateway_IP (Set
|
||||
IPv4 Start/End range and Gateway IP of DHCP for VLAN0)
|
||||
</li>
|
||||
<li>
|
||||
AT+QMAP="DHCPV4DNS","disable" (disable the onboard DNS
|
||||
proxy; recommended for IPPT)
|
||||
</li>
|
||||
<li>
|
||||
AT+QMAP="MPDN_rule",0,1,0,1,1,"FF:FF:FF:FF:FF:FF" (Turn on
|
||||
IP Passthrough for Ethernet)
|
||||
</li>
|
||||
<li>
|
||||
AT+QMAP="MPDN_rule",0 (turn off IPPT/clear MPDN rule 0;
|
||||
Remember to run AT+QMAPWAC=1 and reboot after)
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Loading modal -->
|
||||
<div x-show="isRebooting" class="modal-overlay">
|
||||
<div class="loading-modal">
|
||||
<div class="spinner"></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
|
||||
before refreshing the page.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
function atCommands() {
|
||||
return {
|
||||
isLoading: false,
|
||||
isRebooting: false,
|
||||
countdown: 40, // Total waiting time in seconds
|
||||
atcmd: null,
|
||||
defaultAtCommand: "ATI",
|
||||
atCommandResponse: "",
|
||||
sendAtCommand() {
|
||||
if (!this.atcmd) {
|
||||
// Use ATI as default command
|
||||
this.atcmd = "ATI";
|
||||
console.log(
|
||||
"AT Command is empty, using ATI as default command: ",
|
||||
this.atcmd
|
||||
);
|
||||
}
|
||||
this.isLoading = true;
|
||||
fetch(
|
||||
"/cgi-bin/get_atcommand?" +
|
||||
new URLSearchParams({
|
||||
atcmd: this.atcmd,
|
||||
})
|
||||
)
|
||||
.then((res) => {
|
||||
return res.text();
|
||||
})
|
||||
.then((data) => {
|
||||
this.atCommandResponse = data;
|
||||
this.isLoading = false;
|
||||
})
|
||||
.finally(() => {
|
||||
this.isLoading = false;
|
||||
});
|
||||
},
|
||||
clearResponses() {
|
||||
this.atCommandResponse = "";
|
||||
},
|
||||
sendRebootCommand() {
|
||||
this.atcmd = "AT+CFUN=1,1";
|
||||
this.isRebooting = true;
|
||||
console.log("Reboot command sent: ", this.atcmd);
|
||||
fetch(
|
||||
"/cgi-bin/get_atcommand?" +
|
||||
new URLSearchParams({
|
||||
atcmd: this.atcmd,
|
||||
})
|
||||
)
|
||||
.then((res) => {
|
||||
return res.text();
|
||||
})
|
||||
.then((data) => {
|
||||
this.atCommandResponse =
|
||||
"Rebooting... Please wait a few seconds before refreshing the page.";
|
||||
})
|
||||
.finally(() => {
|
||||
let timer = setInterval(() => {
|
||||
this.countdown--;
|
||||
if (this.countdown <= 0) {
|
||||
clearInterval(timer);
|
||||
this.isRebooting = false;
|
||||
}
|
||||
}, 1000); // Update countdown every second
|
||||
});
|
||||
},
|
||||
};
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
875
old/original_main_repo/simpleadmin/www/bandlock.html
Normal file
875
old/original_main_repo/simpleadmin/www/bandlock.html
Normal file
@@ -0,0 +1,875 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<title>Simple Network</title>
|
||||
|
||||
<script src="/js/alpinejs.min.js" defer></script>
|
||||
<link rel="stylesheet" href="/css/bulma.css" />
|
||||
<link rel="stylesheet" type="text/css" href="/css/admin.css" />
|
||||
<link rel="stylesheet" href="styles.css" />
|
||||
<style>
|
||||
.container {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
}
|
||||
.card-column {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<!-- START NAV -->
|
||||
<nav class="navbar is-black" x-data="{ isOpen: false }">
|
||||
<div class="container">
|
||||
<div class="navbar-brand">
|
||||
<a class="navbar-item brand-text" href="/"> Simple Admin </a>
|
||||
<a
|
||||
role="button"
|
||||
class="navbar-burger burger"
|
||||
@click="isOpen = !isOpen"
|
||||
>
|
||||
<span aria-hidden="true"></span>
|
||||
<span aria-hidden="true"></span>
|
||||
<span aria-hidden="true"></span>
|
||||
</a>
|
||||
</div>
|
||||
<div
|
||||
id="navMenu"
|
||||
class="navbar-menu"
|
||||
:class="isOpen ? 'is-active' : ''"
|
||||
>
|
||||
<div class="navbar-start">
|
||||
<a class="navbar-item" href="/"> Connection Info </a>
|
||||
<a class="navbar-item" href="/atcommander.html"> AT Commands </a>
|
||||
<a class="navbar-item" href="/bandlock.html"> Simple Network </a>
|
||||
<a class="navbar-item" href="/ttl.html"> TTL Changer </a>
|
||||
<a class="navbar-item" href="/speedtest.html"> OpenSpeedtest </a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
<!-- END NAV -->
|
||||
<div
|
||||
class="container"
|
||||
style="margin: auto"
|
||||
x-data="atCommands()"
|
||||
x-init="atCommands()"
|
||||
>
|
||||
<div class="columns is-multiline">
|
||||
<!-- First Box -->
|
||||
<div class="column is-8-tablet is-6-desktop card-column">
|
||||
<div class="card">
|
||||
<header class="card-header">
|
||||
<p class="card-header-title">Band Locking</p>
|
||||
</header>
|
||||
<div class="card-content">
|
||||
<!-- Create a drop down -->
|
||||
<div class="select is-primary">
|
||||
<select id="networkMode" x-model="networkMode">
|
||||
<option>Select Network Mode</option>
|
||||
<option>LTE</option>
|
||||
<option>NR5G-NSA</option>
|
||||
<option>NR5G-SA</option>
|
||||
</select>
|
||||
</div>
|
||||
<input
|
||||
class="input is-primary"
|
||||
type="text"
|
||||
placeholder="Example: 1,3,41"
|
||||
style="margin-top: 1rem"
|
||||
x-model="bandNumbers"
|
||||
/>
|
||||
|
||||
<div style="margin-top: 1rem; display: flex; flex-direction: row">
|
||||
<button
|
||||
class="button is-primary"
|
||||
@click="lockBands()"
|
||||
:disabled="isLocking"
|
||||
>
|
||||
Lock Bands
|
||||
</button>
|
||||
|
||||
<button
|
||||
class="button is-warning"
|
||||
style="margin-left: 1rem"
|
||||
@click="restoreBands()"
|
||||
:disabled="isLocking"
|
||||
>
|
||||
Restore Bands
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-footer" style="padding: 0.25rem">
|
||||
<p class="card-footer-item">
|
||||
Please first select your desired network band from the dropdown
|
||||
menu. To lock onto specific bands, please type the band numbers
|
||||
separated by commas (,) and then click the lock button.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Second Box -->
|
||||
<div class="column is-8-tablet is-6-desktop card-column">
|
||||
<div class="card">
|
||||
<header class="card-header">
|
||||
<p class="card-header-title">LTE and NR5G Cell Locking</p>
|
||||
</header>
|
||||
<div class="card-content">
|
||||
<div style="display: flex; flex-direction: row">
|
||||
<div class="select is-info">
|
||||
<select id="networkModeSelect" x-model="networkMode2">
|
||||
<option>Select Network Mode</option>
|
||||
<option>LTE</option>
|
||||
<option>NR5G-SA</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div
|
||||
id="numFreqContainer"
|
||||
style="margin-left: 1rem"
|
||||
x-show="networkMode2 == 'LTE'"
|
||||
>
|
||||
<input
|
||||
class="input is-info"
|
||||
type="number"
|
||||
id="numFreqInput"
|
||||
min="1"
|
||||
max="10"
|
||||
placeholder="1-10"
|
||||
x-model="cellNum"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="freqNumbersContainer"></div>
|
||||
|
||||
<!-- For NR5G-SA -->
|
||||
<div style="margin-top: 1rem" x-show="networkMode2 == 'NR5G-SA'">
|
||||
<div style="display: flex; flex-direction: row">
|
||||
<input
|
||||
class="input is-info"
|
||||
type="text"
|
||||
placeholder="EARFCN"
|
||||
x-model="earfcn1"
|
||||
/>
|
||||
<input
|
||||
class="input is-info"
|
||||
type="text"
|
||||
placeholder="PCI"
|
||||
x-model="pci1"
|
||||
style="margin-left: 1rem"
|
||||
/>
|
||||
<input
|
||||
class="input is-info"
|
||||
type="text"
|
||||
placeholder="SCS"
|
||||
x-model="scs"
|
||||
style="margin-left: 1rem"
|
||||
/>
|
||||
<input
|
||||
class="input is-info"
|
||||
type="text"
|
||||
placeholder="BAND"
|
||||
x-model="band"
|
||||
style="margin-left: 1rem"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div style="margin-top: 1rem; display: flex; flex-direction: row">
|
||||
<button
|
||||
class="button is-info"
|
||||
@click="cellLock()"
|
||||
:disabled="isLocking"
|
||||
>
|
||||
Lock Cell
|
||||
</button>
|
||||
|
||||
<button
|
||||
class="button is-warning"
|
||||
style="margin-left: 1rem"
|
||||
@click="restoreCell()"
|
||||
:disabled="isLocking"
|
||||
>
|
||||
Restore Cell
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-footer" style="padding: 0.25rem">
|
||||
<p class="card-footer-item">
|
||||
To utilize cell locking, first, select the network mode, then
|
||||
specify the number of cells you wish to lock onto (max 10) if
|
||||
you are using LTE. Next, input the EARFCN and PCI values for
|
||||
each cell number. If you are locking through NR5G-SA instead,
|
||||
simply fill up all the required parameters.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Third Box -->
|
||||
|
||||
<div class="column is-8-tablet is-6-desktop card-column">
|
||||
<div class="card">
|
||||
<header class="card-header">
|
||||
<p class="card-header-title">Network Utilities</p>
|
||||
</header>
|
||||
<div class="card-content">
|
||||
<div style="display: flex; flex-direction: column">
|
||||
<div>
|
||||
<p>Set Network APN</p>
|
||||
<div
|
||||
style="
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
margin-top: 0.5rem;
|
||||
"
|
||||
>
|
||||
<input
|
||||
class="input is-link"
|
||||
type="text"
|
||||
placeholder="APN"
|
||||
x-model="apnInput"
|
||||
/>
|
||||
<button
|
||||
class="button is-link"
|
||||
style="margin-left: 1rem"
|
||||
@click="setAPN()"
|
||||
:disabled="isLoading"
|
||||
>
|
||||
Set APN
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div style="margin-top: 1rem">
|
||||
<p>Set Preferred Network Mode</p>
|
||||
<div
|
||||
style="display: flex; flex-direction: row; margin-top: 0.5rem"
|
||||
>
|
||||
<div class="select is-info">
|
||||
<select id="prefNetworkMode" x-model="prefNetworkMode">
|
||||
<option>Select Network</option>
|
||||
<option>AUTO</option>
|
||||
<option>WCDMA</option>
|
||||
<option>LTE ONLY</option>
|
||||
<option>NR5G-NSA</option>
|
||||
<option>NR5G-SA</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<button
|
||||
class="button is-link"
|
||||
style="margin-left: 1rem"
|
||||
@click="setPrefNetwork()"
|
||||
:disabled="isLoading"
|
||||
>
|
||||
Set Network
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div style="margin-top: 1rem">
|
||||
<p>Set Sim Slot</p>
|
||||
<div
|
||||
style="display: flex; flex-direction: row; margin-top: 0.5rem"
|
||||
>
|
||||
<div class="select is-info">
|
||||
<select id="simSlot" x-model="simSlot">
|
||||
<option>Select Sim</option>
|
||||
<option>1</option>
|
||||
<option>2</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<button
|
||||
class="button is-link"
|
||||
style="margin-left: 1rem"
|
||||
@click="setSimSlot()"
|
||||
:disabled="isLoading"
|
||||
>
|
||||
Set Sim
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div style="margin-top: 1rem">
|
||||
<p>NR5G Mode Control</p>
|
||||
<div
|
||||
style="display: flex; flex-direction: row; margin-top: 0.5rem"
|
||||
>
|
||||
<div class="select is-info">
|
||||
<select id="nrMode" x-model="nrMode">
|
||||
<option>Select NR5G Mode</option>
|
||||
<option>Enable All</option>
|
||||
<option>Disable NSA</option>
|
||||
<option>Disable SA</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<button
|
||||
class="button is-link"
|
||||
style="margin-left: 1rem"
|
||||
@click="nr5GMode()"
|
||||
:disabled="isLoading"
|
||||
>
|
||||
Set Mode
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-footer" style="padding: 0.25rem">
|
||||
<p class="card-footer-item">
|
||||
This section allows you to set the APN, preferred network mode,
|
||||
and sim slot. Simply input the desired values and click the
|
||||
respective buttons to apply the changes. (Sim slot is only
|
||||
applicable for dual sim devices.)
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Fourth Box -->
|
||||
<div class="column is-8-tablet is-6-desktop card-column">
|
||||
<div class="card">
|
||||
<header class="card-header">
|
||||
<p class="card-header-title">Query Network Parameters</p>
|
||||
</header>
|
||||
<div class="card-content">
|
||||
<textarea
|
||||
class="textarea"
|
||||
rows="5"
|
||||
placeholder="Query Response"
|
||||
x-text=" isLoading ? 'Getting Response...' : queryCommandResponse"
|
||||
></textarea>
|
||||
|
||||
<div style="margin-top: 1.5rem">
|
||||
<p>Check Locked Bands</p>
|
||||
<div class="select is-info" style="margin-top: 0.5rem">
|
||||
<select id="lockedBands" x-model="lockedBands">
|
||||
<option>Locked Bands</option>
|
||||
<option>LTE</option>
|
||||
<option>NSA</option>
|
||||
<option>SA</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<button
|
||||
class="button is-link"
|
||||
style="margin-left: 1rem; margin-top: 0.5rem"
|
||||
@click="showLockedBands()"
|
||||
:disabled="isLoading"
|
||||
>
|
||||
Check Bands
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div style="margin-top: 1rem">
|
||||
<p>Check Cell Lock</p>
|
||||
<div class="select is-info" style="margin-top: 0.5rem">
|
||||
<select id="cellState" x-model="cellState">
|
||||
<option>Cell Lock</option>
|
||||
<option>LTE</option>
|
||||
<option>NR5G-SA</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<button
|
||||
class="button is-link"
|
||||
style="margin-left: 1rem; margin-top: 0.5rem"
|
||||
@click="showCellState()"
|
||||
:disabled="isLoading"
|
||||
>
|
||||
Check Cell
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div style="margin-top: 2rem">
|
||||
<p>Other Network Query</p>
|
||||
</div>
|
||||
<div class="buttons" style="margin-top: 0.5rem">
|
||||
<button
|
||||
class="button is-link mr-2"
|
||||
@click="showSupportedBands()"
|
||||
:disabled="isLoading"
|
||||
>
|
||||
Show Supported Bands
|
||||
</button>
|
||||
|
||||
<button
|
||||
class="button is-link mr-2"
|
||||
@click="showCurrentSim()"
|
||||
:disabled="isLoading"
|
||||
>
|
||||
Show Current Sim
|
||||
</button>
|
||||
|
||||
<button
|
||||
class="button is-link"
|
||||
@click="showPrefNetwork()"
|
||||
:disabled="isLoading"
|
||||
>
|
||||
Show Pref Network
|
||||
</button>
|
||||
|
||||
<button
|
||||
class="button is-link"
|
||||
@click="showCaInfo()"
|
||||
:disabled="isLoading"
|
||||
>
|
||||
Carrier Aggregation Info
|
||||
</button>
|
||||
|
||||
<button
|
||||
class="button is-link"
|
||||
@click="servingCellInfo()"
|
||||
:disabled="isLoading"
|
||||
>
|
||||
Serving Cell Info
|
||||
</button>
|
||||
|
||||
<button
|
||||
class="button is-link"
|
||||
@click="scanNeighbourCells()"
|
||||
:disabled="isLoading"
|
||||
>
|
||||
Scan Neighbour Cells
|
||||
</button>
|
||||
|
||||
<button
|
||||
class="button is-link"
|
||||
@click="scanNsaCells()"
|
||||
:disabled="isLoading"
|
||||
>
|
||||
Scan NSA Cells
|
||||
</button>
|
||||
|
||||
<button
|
||||
class="button is-link"
|
||||
@click="fullNetworkScan()"
|
||||
:disabled="isLoading"
|
||||
>
|
||||
Full Network Scan
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-footer" style="padding: 0.25rem">
|
||||
<p class="card-footer-item">
|
||||
This section allows you to query the network parameters. Simply
|
||||
click the respective buttons to view the network parameters.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Loading Modal for Locking Band -->
|
||||
<div x-show="isLocking" class="modal-overlay">
|
||||
<div class="loading-modal">
|
||||
<div class="spinner"></div>
|
||||
<div
|
||||
class="loading-text"
|
||||
style="display: flex; flex-direction: column"
|
||||
>
|
||||
<h3>Initializing Network...</h3>
|
||||
<p style="margin-top: 0.5rem">
|
||||
Please wait for
|
||||
<span x-text="countdown" style="font-weight: 500"></span> seconds.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div x-show="isError" class="modal-overlay">
|
||||
<div class="loading-modal">
|
||||
<div class="spinner"></div>
|
||||
<div
|
||||
class="loading-text"
|
||||
style="display: flex; flex-direction: column"
|
||||
>
|
||||
<h3>Request Error</h3>
|
||||
<p style="margin-top: 0.5rem">
|
||||
Please follow the instructions properly. Exiting in
|
||||
<span x-text="countdown" style="font-weight: 500"></span> seconds.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
function atCommands() {
|
||||
return {
|
||||
isLoading: false,
|
||||
isQuerying: false,
|
||||
isLocking: false,
|
||||
isError: false,
|
||||
countdown: 5, // Initial countdown value
|
||||
networkMode: null,
|
||||
networkMode2: null,
|
||||
bandNumbers: null,
|
||||
cellNum: null,
|
||||
earfcn1: null,
|
||||
pci1: null,
|
||||
earfcn2: null,
|
||||
pci2: null,
|
||||
earfcn3: null,
|
||||
pci3: null,
|
||||
earfcn4: null,
|
||||
pci4: null,
|
||||
earfcn5: null,
|
||||
pci5: null,
|
||||
earfcn6: null,
|
||||
pci6: null,
|
||||
earfcn7: null,
|
||||
pci7: null,
|
||||
earfcn8: null,
|
||||
pci8: null,
|
||||
earfcn9: null,
|
||||
pci9: null,
|
||||
earfcn10: null,
|
||||
pci10: null,
|
||||
band: null,
|
||||
scs: null,
|
||||
apnInput: null,
|
||||
prefNetworkMode: null,
|
||||
simSlot: null,
|
||||
nrMode: null,
|
||||
lockedBands: null,
|
||||
cellState: null,
|
||||
invalidCellNum: "",
|
||||
atCommandResponse: "",
|
||||
queryCommandResponse: "",
|
||||
lockBands() {
|
||||
if (!this.networkMode || !this.bandNumbers) {
|
||||
this.isError = true;
|
||||
this.startCountdown();
|
||||
console.error("Network mode and band numbers are required.");
|
||||
return;
|
||||
}
|
||||
|
||||
// Remove commas and replace with colons
|
||||
const parsedBandNumbers = this.bandNumbers.replace(/,/g, ":");
|
||||
|
||||
// Construct the atcmd based on the selected network mode
|
||||
let atcmd;
|
||||
switch (this.networkMode) {
|
||||
case "LTE":
|
||||
atcmd = `AT+QNWPREFCFG="lte_band",${parsedBandNumbers}`;
|
||||
console.log(atcmd);
|
||||
break;
|
||||
case "NR5G-NSA":
|
||||
atcmd = `AT+QNWPREFCFG="nsa_nr5g_band",${parsedBandNumbers}`;
|
||||
console.log(atcmd);
|
||||
break;
|
||||
case "NR5G-SA":
|
||||
atcmd = `AT+QNWPREFCFG="nr5g_band",${parsedBandNumbers}`;
|
||||
console.log(atcmd);
|
||||
break;
|
||||
default:
|
||||
console.error("Invalid network mode.");
|
||||
return;
|
||||
}
|
||||
|
||||
this.isLoading = true;
|
||||
fetch(
|
||||
"/cgi-bin/get_atcommand?" +
|
||||
new URLSearchParams({
|
||||
atcmd: atcmd,
|
||||
})
|
||||
)
|
||||
.then((res) => res.text())
|
||||
.then((data) => {
|
||||
this.atCommandResponse = data;
|
||||
this.isLocking = true;
|
||||
this.startCountdown();
|
||||
})
|
||||
.catch((error) => {
|
||||
this.isError = true;
|
||||
this.startCountdown();
|
||||
console.error("Error sending AT command:", error);
|
||||
})
|
||||
.finally(() => {
|
||||
this.isLoading = false;
|
||||
});
|
||||
},
|
||||
cellLock() {
|
||||
// Error handlers
|
||||
if (!this.networkMode2) {
|
||||
this.isError = true;
|
||||
this.startCountdown();
|
||||
console.error("Network mode is required.");
|
||||
return;
|
||||
}
|
||||
|
||||
// Construct the AT command based on the selected network mode
|
||||
let atcmd;
|
||||
|
||||
if (this.networkMode2 === "LTE") {
|
||||
if (parseInt(this.cellNum) > 10) {
|
||||
this.invalidCellNum = "Invalid";
|
||||
this.isError = true;
|
||||
this.startCountdown();
|
||||
console.error("Invalid frequency number.");
|
||||
return;
|
||||
}
|
||||
|
||||
this.isLocking = true;
|
||||
atcmd = `AT+QNWLOCK="common/4g",${this.cellNum}`;
|
||||
for (let i = 1; i <= parseInt(this.cellNum); i++) {
|
||||
atcmd += `,${this["earfcn" + i]},${this["pci" + i]}`;
|
||||
}
|
||||
console.log(atcmd);
|
||||
} else if (this.networkMode2 === "NR5G-SA") {
|
||||
this.isLocking = true;
|
||||
atcmd = `AT+QNWLOCK="common/5g",${this.pci1},${this.earfcn1},${this.scs},${this.band}`;
|
||||
console.log(atcmd);
|
||||
}
|
||||
|
||||
this.sendAtCommand(atcmd);
|
||||
},
|
||||
restoreBands() {
|
||||
const restoreCmd = 'AT+QNWPREFCFG="restore_band"';
|
||||
this.sendAtCommand(restoreCmd);
|
||||
},
|
||||
restoreCell() {
|
||||
const restoreCmd = 'AT+QNWLOCK="common/4g",0';
|
||||
this.sendAtCommand(restoreCmd);
|
||||
},
|
||||
setAPN() {
|
||||
const apnCmd = `AT+CGDCONT=1,"IPV4V6","${this.apnInput}"`;
|
||||
this.sendAtCommand(apnCmd);
|
||||
},
|
||||
setPrefNetwork() {
|
||||
// AT+QNWPREFCFG="mode_pref",<mode>
|
||||
let prefCmd;
|
||||
switch (this.prefNetworkMode) {
|
||||
case "AUTO":
|
||||
prefCmd = 'AT+QNWPREFCFG="mode_pref",AUTO';
|
||||
break;
|
||||
case "WCDMA":
|
||||
prefCmd = 'AT+QNWPREFCFG="mode_pref",WCDMA';
|
||||
break;
|
||||
case "LTE ONLY":
|
||||
prefCmd = 'AT+QNWPREFCFG="mode_pref",LTE';
|
||||
break;
|
||||
case "NR5G-NSA":
|
||||
prefCmd = 'AT+QNWPREFCFG="mode_pref",LTE:NR5G';
|
||||
break;
|
||||
case "NR5G-SA":
|
||||
prefCmd = 'AT+QNWPREFCFG="mode_pref",NR5G';
|
||||
break;
|
||||
default:
|
||||
console.error("Invalid network mode.");
|
||||
return;
|
||||
}
|
||||
this.sendAtCommand(prefCmd);
|
||||
},
|
||||
setSimSlot() {
|
||||
const simCmd = `AT+QUIMSLOT=${this.simSlot}`;
|
||||
this.sendAtCommand(simCmd);
|
||||
},
|
||||
nr5GMode() {
|
||||
let nrCmd;
|
||||
switch (this.nrMode) {
|
||||
case "Enable All":
|
||||
nrCmd = 'AT+QNWPREFCFG="nr5g_disable_mode",0';
|
||||
break;
|
||||
case "Disable NSA":
|
||||
nrCmd = 'AT+QNWPREFCFG="nr5g_disable_mode",2';
|
||||
break;
|
||||
case "Disable SA":
|
||||
nrCmd = 'AT+QNWPREFCFG="nr5g_disable_mode",1';
|
||||
break;
|
||||
default:
|
||||
console.error("Invalid NR5G mode.");
|
||||
return;
|
||||
}
|
||||
this.queryATCommand(nrCmd);
|
||||
},
|
||||
showLockedBands() {
|
||||
let lockedCmd;
|
||||
switch (this.lockedBands) {
|
||||
case "LTE":
|
||||
lockedCmd = 'AT+QNWPREFCFG="lte_band"';
|
||||
break;
|
||||
case "NSA":
|
||||
lockedCmd = 'AT+QNWPREFCFG="nsa_nr5g_band"';
|
||||
break;
|
||||
case "SA":
|
||||
lockedCmd = 'AT+QNWPREFCFG="nr5g_band"';
|
||||
break;
|
||||
default:
|
||||
console.error("Invalid network mode.");
|
||||
return;
|
||||
}
|
||||
this.queryATCommand(lockedCmd);
|
||||
},
|
||||
|
||||
showCellState() {
|
||||
let cellCmd;
|
||||
switch (this.cellState) {
|
||||
case "LTE":
|
||||
cellCmd = 'AT+QNWLOCK="common/4g"';
|
||||
break;
|
||||
case "NR5G-SA":
|
||||
cellCmd = 'AT+QNWLOCK="common/5g"';
|
||||
break;
|
||||
default:
|
||||
console.error("Invalid network mode.");
|
||||
return;
|
||||
}
|
||||
this.queryATCommand(cellCmd);
|
||||
},
|
||||
showSupportedBands() {
|
||||
const supportedCmd = 'AT+QNWPREFCFG="policy_band"';
|
||||
this.queryATCommand(supportedCmd);
|
||||
},
|
||||
showCurrentSim() {
|
||||
const simCmd = "AT+QUIMSLOT?";
|
||||
this.queryATCommand(simCmd);
|
||||
},
|
||||
showPrefNetwork() {
|
||||
const prefCmd = 'AT+QNWPREFCFG="mode_pref"';
|
||||
this.queryATCommand(prefCmd);
|
||||
},
|
||||
showCaInfo() {
|
||||
const caCmd = "AT+QCAINFO";
|
||||
this.queryATCommand(caCmd);
|
||||
},
|
||||
servingCellInfo() {
|
||||
const servingCmd = 'AT+QENG="servingcell"';
|
||||
this.queryATCommand(servingCmd);
|
||||
},
|
||||
scanNeighbourCells() {
|
||||
const scanCmd = 'AT+QENG="neighbourcell"';
|
||||
this.queryATCommand(scanCmd);
|
||||
},
|
||||
scanNsaCells() {
|
||||
const enableCmd = 'AT+QNWCFG="nr5g_meas_info",1';
|
||||
const queryScanCmd = 'AT+QNWCFG="nr5g_meas_info"';
|
||||
// Send the enable command first without getting the response
|
||||
fetch(
|
||||
"/cgi-bin/get_atcommand?" +
|
||||
new URLSearchParams({
|
||||
atcmd: enableCmd,
|
||||
})
|
||||
)
|
||||
.then(() => {
|
||||
console.log("Enable Success.");
|
||||
// Show a temporary loading query message
|
||||
this.queryCommandResponse =
|
||||
"Enabling NSA cell scan. Please wait...";
|
||||
this.queryATCommand(queryScanCmd);
|
||||
})
|
||||
.catch((error) => {
|
||||
this.isError = true;
|
||||
this.startCountdown();
|
||||
console.error("Error sending AT command:", error);
|
||||
});
|
||||
},
|
||||
fullNetworkScan() {
|
||||
const scanCmd = "AT+QSCAN=3,1";
|
||||
// Show a temporary loading query message
|
||||
this.queryCommandResponse =
|
||||
"Full network scan initiated. This takes about a minute. Please wait...";
|
||||
this.queryATCommand(scanCmd);
|
||||
},
|
||||
queryATCommand(atcmd) {
|
||||
this.isQuerying = true;
|
||||
fetch(
|
||||
"/cgi-bin/get_atcommand?" +
|
||||
new URLSearchParams({
|
||||
atcmd: atcmd,
|
||||
})
|
||||
)
|
||||
.then((res) => res.text())
|
||||
.then((data) => {
|
||||
this.queryCommandResponse = data;
|
||||
console.log(data);
|
||||
})
|
||||
.catch((error) => {
|
||||
this.isError = true;
|
||||
this.startCountdown();
|
||||
console.error("Error sending AT command:", error);
|
||||
})
|
||||
.finally(() => {
|
||||
this.isQuerying = false;
|
||||
});
|
||||
},
|
||||
sendAtCommand(atcmd) {
|
||||
this.isLoading = true;
|
||||
this.startCountdown();
|
||||
console.log(atcmd);
|
||||
fetch(
|
||||
"/cgi-bin/get_atcommand?" +
|
||||
new URLSearchParams({
|
||||
atcmd: atcmd,
|
||||
})
|
||||
)
|
||||
.then((res) => res.text())
|
||||
.then((data) => {
|
||||
this.atCommandResponse = data;
|
||||
console.log(data);
|
||||
})
|
||||
.catch((error) => {
|
||||
this.isError = true;
|
||||
this.startCountdown();
|
||||
console.error("Error sending AT command:", error);
|
||||
})
|
||||
.finally(() => {
|
||||
this.isLoading = false;
|
||||
});
|
||||
},
|
||||
startCountdown() {
|
||||
// Decrease countdown every second
|
||||
const interval = setInterval(() => {
|
||||
this.countdown--;
|
||||
if (this.countdown <= 0) {
|
||||
clearInterval(interval);
|
||||
// Reset values
|
||||
this.isLocking = false;
|
||||
this.isError = false;
|
||||
this.isLoading = false;
|
||||
this.isQuerying = false;
|
||||
this.countdown = 5;
|
||||
}
|
||||
}, 1000);
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
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 style="margin-top: 1rem" x-show="cellNum >= ${i} && networkMode2 == 'LTE'">
|
||||
<div style="display: flex; flex-direction: row">
|
||||
<input class="input is-info" type="text" placeholder="EARFCN" x-model="earfcn${i}" />
|
||||
<input class="input is-info" type="text" placeholder="PCI" x-model="pci${i}" style="margin-left: 1rem" />
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
return html;
|
||||
}
|
||||
|
||||
document
|
||||
.getElementById("numFreqInput")
|
||||
.addEventListener("input", function () {
|
||||
const cellNum = parseInt(this.value);
|
||||
freqNumbersContainer.innerHTML = generateFreqNumberInputs(cellNum);
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -13,11 +13,11 @@ if [ "${QUERY_STRING}" ]; then
|
||||
done
|
||||
fi
|
||||
|
||||
x=$(urldecode "$atcmd")
|
||||
MYATCMD=$(printf '%b\n' "${atcmd//%/\\x}")
|
||||
if [ -n "${MYATCMD}" ]; then
|
||||
# Initialize wait time to 200 ms
|
||||
wait_time=200
|
||||
x=$(urldecode "$atcmd")
|
||||
# Initialize wait time to 1 second
|
||||
wait_time=1000
|
||||
while true; do
|
||||
runcmd=$(echo -en "$x\r\n" | microcom -t $wait_time /dev/ttyOUT2)
|
||||
# Check if "OK" or "ERROR" is present in the response
|
||||
13
old/original_main_repo/simpleadmin/www/cgi-bin/get_csq
Normal file
13
old/original_main_repo/simpleadmin/www/cgi-bin/get_csq
Normal file
@@ -0,0 +1,13 @@
|
||||
#!/bin/bash
|
||||
|
||||
if [ ! -f /tmp/modemstatus.json ]
|
||||
then
|
||||
/usrdata/simpleadmin/scripts/modemstatus_parse.sh > /dev/null
|
||||
fi
|
||||
|
||||
runcmd=$(</tmp/modemstatus.json)
|
||||
|
||||
echo "Content-type: text/json"
|
||||
echo ""
|
||||
cat <<EOT
|
||||
$runcmd
|
||||
@@ -1,7 +1,7 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Check iptables for ttlvalue
|
||||
ttlvalue=$(/opt/bin/sudo /usr/sbin/iptables -w 5 -t mangle -vnL | grep TTL | awk '{print $13}' | head -n1)
|
||||
ttlvalue=$(iptables -t mangle -vnL | grep TTL | awk '{print $13}')
|
||||
ttlenabled=true;
|
||||
|
||||
# Set Variables
|
||||
@@ -16,5 +16,4 @@ cat <<EOT
|
||||
{
|
||||
"isEnabled": $ttlenabled,
|
||||
"ttl": $ttlvalue
|
||||
}
|
||||
EOT
|
||||
}
|
||||
61
old/original_main_repo/simpleadmin/www/cgi-bin/set_ttl
Normal file
61
old/original_main_repo/simpleadmin/www/cgi-bin/set_ttl
Normal file
@@ -0,0 +1,61 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Get query
|
||||
QUERY_STRING=$(echo "${QUERY_STRING}" | sed 's/;//g')
|
||||
|
||||
if [ "${QUERY_STRING}" ]; then
|
||||
|
||||
export IFS="&"
|
||||
for cmd in ${QUERY_STRING}; do
|
||||
|
||||
if [ "$(echo $cmd | grep '=')" ]; then
|
||||
key=$(echo $cmd | awk -F '=' '{print $1}')
|
||||
value=$(echo $cmd | awk -F '=' '{print $2}')
|
||||
eval $key=$value
|
||||
fi
|
||||
|
||||
done
|
||||
|
||||
fi
|
||||
|
||||
setTTL=$(printf '%b\n' "${ttlvalue//%/\\x}")
|
||||
|
||||
if [ -n "${setTTL}" ]; then
|
||||
# Stop Service To Remove Rules
|
||||
/usrdata/simplefirewall/ttl-override stop
|
||||
|
||||
# Check iptables is still set
|
||||
ttlcheck=$(iptables -t mangle -vnL | grep TTL | awk '{print $13}')
|
||||
|
||||
# If TTL is still set manually remove values
|
||||
if [ !-z "${ttlcheck}" ]; then
|
||||
iptables -t mangle -D POSTROUTING -o rmnet+ -j TTL --ttl-set ${ttlcheck} &>/dev/null || true
|
||||
ip6tables -t mangle -D POSTROUTING -o rmnet+ -j HL --hl-set ${ttlcheck} &>/dev/null || true
|
||||
fi
|
||||
|
||||
# Echo TTL to file
|
||||
echo $setTTL > /usrdata/simplefirewall/ttlvalue
|
||||
|
||||
# Set Start Service
|
||||
/usrdata/simplefirewall/ttl-override start
|
||||
fi
|
||||
|
||||
|
||||
|
||||
# Check iptables for ttlvalue
|
||||
ttlvalue=$(iptables -t mangle -vnL | grep TTL | awk '{print $13}')
|
||||
ttlenabled=true;
|
||||
|
||||
# Set Variables
|
||||
if [ -z "${ttlvalue}" ]; then
|
||||
ttlvalue=0
|
||||
ttlenabled=false
|
||||
fi
|
||||
|
||||
echo "Content-type: text/json"
|
||||
echo ""
|
||||
cat <<EOT
|
||||
{
|
||||
"isEnabled": $ttlenabled,
|
||||
"ttl": $ttlvalue
|
||||
}
|
||||
86
old/original_main_repo/simpleadmin/www/css/admin.css
Normal file
86
old/original_main_repo/simpleadmin/www/css/admin.css
Normal file
@@ -0,0 +1,86 @@
|
||||
:root{
|
||||
::-webkit-scrollbar{height:10px;width:10px}::-webkit-scrollbar-track{background:#efefef;border-radius:6px}::-webkit-scrollbar-thumb{background:#d5d5d5;border-radius:6px}::-webkit-scrollbar-thumb:hover{background:#c4c4c4}
|
||||
}
|
||||
html, body {
|
||||
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif;
|
||||
font-size: 16px;
|
||||
line-height: 1.5;
|
||||
height: 100%;
|
||||
background: #ECF0F3;
|
||||
}
|
||||
nav.navbar {
|
||||
border-top: 4px solid #276cda;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
.navbar-item.brand-text {
|
||||
font-weight: 300;
|
||||
}
|
||||
.navbar-item, .navbar-link {
|
||||
font-size: 14px;
|
||||
font-weight: 700;
|
||||
}
|
||||
.columns {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
margin-left: 0;
|
||||
}
|
||||
.menu-label {
|
||||
color: #8F99A3;
|
||||
letter-spacing: 1.3;
|
||||
font-weight: 700;
|
||||
}
|
||||
.menu-list a {
|
||||
color: #0F1D38;
|
||||
font-size: 14px;
|
||||
font-weight: 700;
|
||||
}
|
||||
.menu-list a:hover {
|
||||
background-color: transparent;
|
||||
color: #276cda;
|
||||
}
|
||||
.menu-list a.is-active {
|
||||
background-color: transparent;
|
||||
color: #276cda;
|
||||
font-weight: 700;
|
||||
}
|
||||
.card {
|
||||
box-shadow: 0px 2px 4px rgba(0, 0, 0, 0.18);
|
||||
margin-bottom: 2rem;
|
||||
}
|
||||
.card-header-title {
|
||||
color: #8F99A3;
|
||||
font-weight: 400;
|
||||
}
|
||||
.info-tiles {
|
||||
margin: 1rem 0;
|
||||
}
|
||||
.info-tiles .subtitle {
|
||||
font-weight: 300;
|
||||
color: #8F99A3;
|
||||
}
|
||||
.hero.welcome.is-info {
|
||||
background: #36D1DC;
|
||||
background: -webkit-linear-gradient(to right, #5B86E5, #36D1DC);
|
||||
background: linear-gradient(to right, #5B86E5, #36D1DC);
|
||||
}
|
||||
.hero.welcome .title, .hero.welcome .subtitle {
|
||||
color: hsl(192, 17%, 99%);
|
||||
}
|
||||
.card .content {
|
||||
font-size: 14px;
|
||||
}
|
||||
.card-footer-item {
|
||||
font-size: 14px;
|
||||
font-weight: 700;
|
||||
color: #8F99A3;
|
||||
}
|
||||
.card-footer-item:hover {
|
||||
}
|
||||
.card-table .table {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
.events-card .card-table {
|
||||
height: 330px;
|
||||
overflow-y: scroll;
|
||||
}
|
||||
|
||||
1
old/original_main_repo/simpleadmin/www/css/bulma.css
vendored
Normal file
1
old/original_main_repo/simpleadmin/www/css/bulma.css
vendored
Normal file
File diff suppressed because one or more lines are too long
284
old/original_main_repo/simpleadmin/www/index.html
Normal file
284
old/original_main_repo/simpleadmin/www/index.html
Normal file
@@ -0,0 +1,284 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<!-- change to a much simpler tab title -->
|
||||
<title>Simple Admin</title>
|
||||
|
||||
<script src="/js/alpinejs.min.js" defer></script>
|
||||
<link rel="stylesheet" href="/css/bulma.css" />
|
||||
<link rel="stylesheet" type="text/css" href="/css/admin.css" />
|
||||
<link rel="stylesheet" href="styles.css" />
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<!-- START NAV -->
|
||||
<nav class="navbar is-black" x-data="{ isOpen: false }">
|
||||
<div class="container">
|
||||
<div class="navbar-brand">
|
||||
<a class="navbar-item brand-text" href="/"> Simple Admin </a>
|
||||
<a
|
||||
role="button"
|
||||
class="navbar-burger burger"
|
||||
@click="isOpen = !isOpen"
|
||||
>
|
||||
<span aria-hidden="true"></span>
|
||||
<span aria-hidden="true"></span>
|
||||
<span aria-hidden="true"></span>
|
||||
</a>
|
||||
</div>
|
||||
<div
|
||||
id="navMenu"
|
||||
class="navbar-menu"
|
||||
:class="isOpen ? 'is-active' : ''"
|
||||
>
|
||||
<div class="navbar-start">
|
||||
<a class="navbar-item" href="/"> Connection Info </a>
|
||||
<a class="navbar-item" href="/atcommander.html"> AT Commands </a>
|
||||
<a class="navbar-item" href="/bandlock.html"> Simple Network </a>
|
||||
<a class="navbar-item" href="/ttl.html"> TTL Changer </a>
|
||||
<a class="navbar-item" href="/speedtest.html"> OpenSpeedtest </a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
<!-- END NAV -->
|
||||
<div class="container">
|
||||
<div class="columns">
|
||||
<div class="column is-12" x-data="getSignalData()" x-init="init()">
|
||||
<section class="hero is-info welcome is-small">
|
||||
<div class="hero-body">
|
||||
<div class="container">
|
||||
<!-- Fetches the correct Model Name -->
|
||||
<h1 class="title">
|
||||
<span x-text="csqData.MODEM_MODEL"></span> Connection
|
||||
Info
|
||||
</h1>
|
||||
<h2 class="subtitle">
|
||||
Data Updated: <span x-text="lastUpdate"></span>
|
||||
</h2>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<section class="info-tiles">
|
||||
<div class="tile is-ancestor has-text-centered">
|
||||
<div class="tile is-parent">
|
||||
<article class="tile is-child box">
|
||||
<!-- added APN -->
|
||||
<p class="title" x-text="csqData.APN"></p>
|
||||
<p class="subtitle">Current APN</p>
|
||||
<p
|
||||
class="title"
|
||||
style="margin-top: 1rem"
|
||||
x-html="csqData.SIMSLOT"
|
||||
></p>
|
||||
<p class="subtitle">Current SIM</p>
|
||||
</article>
|
||||
</div>
|
||||
<div class="tile is-parent">
|
||||
<article class="tile is-child box">
|
||||
<!-- added APN -->
|
||||
<p class="title" x-text="csqData.MODE"></p>
|
||||
<p class="subtitle">Network</p>
|
||||
<p
|
||||
class="title"
|
||||
x-text="csqData.PC_BAND"
|
||||
style="margin-top: 1rem"
|
||||
></p>
|
||||
<p class="subtitle">Primary Band</p>
|
||||
</article>
|
||||
</div>
|
||||
<!-- added primary band and secondary bands value -->
|
||||
<div class="tile is-parent">
|
||||
<article class="tile is-child box">
|
||||
<p class="title" x-html="csqData.SC_BANDS"></p>
|
||||
<p class="subtitle">Aggregated Bands</p>
|
||||
</article>
|
||||
</div>
|
||||
<div class="tile is-parent">
|
||||
<article class="tile is-child box">
|
||||
<p class="title" x-text="csqData.CSQ_PER"></p>
|
||||
<p class="subtitle">Signal Strength</p>
|
||||
<p
|
||||
class="title"
|
||||
x-text="csqData.TEMP"
|
||||
style="margin-top: 1rem"
|
||||
></p>
|
||||
<p class="subtitle">Modem Temperature</p>
|
||||
</article>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<div class="columns">
|
||||
<div class="column is-6">
|
||||
<div class="card events-card">
|
||||
<header class="card-header">
|
||||
<p class="card-header-title">Signal Information</p>
|
||||
</header>
|
||||
<div class="card-table">
|
||||
<div class="content">
|
||||
<table class="table is-fullwidth is-striped">
|
||||
<tbody>
|
||||
<tr>
|
||||
<th>Provider</th>
|
||||
<td x-text="csqData.PROVIDER"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>CSQ</th>
|
||||
<td x-text="csqData.CSQ"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Signal Strength</th>
|
||||
<td x-text="csqData.CSQ_PER"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>RSSI</th>
|
||||
<td x-text="csqData.CSQ_RSSI"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>
|
||||
ECIO<sup>3G</sup>/RSRQ<sup>4G</sup>/SS_RSRQ<sup
|
||||
>5G</sup
|
||||
>
|
||||
</th>
|
||||
<td x-html="csqData.ECIO"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>
|
||||
RSCP<sup>3G</sup>/RSRP<sup>4G</sup>/SS_RSRP<sup
|
||||
>5G</sup
|
||||
>
|
||||
</th>
|
||||
<td x-html="csqData.RSCP"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>SINR</th>
|
||||
<td x-html="csqData.SINR"></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="column is-6">
|
||||
<div class="card events-card">
|
||||
<header class="card-header">
|
||||
<p class="card-header-title">Cell Information</p>
|
||||
</header>
|
||||
<div class="card-table">
|
||||
<div class="content">
|
||||
<table class="table is-fullwidth is-striped">
|
||||
<tbody>
|
||||
<tr>
|
||||
<th>MCC MNC</th>
|
||||
<td>
|
||||
<span x-text="csqData.MCCMNC"></span>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>RNC<sup>3G</sup>/eNB ID<sup>4G/5G</sup></th>
|
||||
<td>
|
||||
<span x-text="csqData.RNC"></span>
|
||||
<span x-text="csqData.RNC_NUM"></span>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Lag<sup>3G</sup>/TAC<sup>4G/5G</sup></th>
|
||||
<td>
|
||||
<span x-text="csqData.LAC"></span>
|
||||
<span x-text="csqData.LAC_NUM"></span>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Cell ID</th>
|
||||
<td x-text="csqData.CID"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Band</th>
|
||||
<td x-html="csqData.LBAND"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Channel</th>
|
||||
<td x-text="csqData.CHANNEL"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>PCI</th>
|
||||
<td x-text="csqData.PCI"></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
function signalInfo() {
|
||||
return {
|
||||
isLoading: false,
|
||||
atcmd: 'AT+QSPN;+CEREG=2;+CEREG?;+CEREG=0;+C5GREG=2;+C5GREG?;+C5GREG=0;+CSQ;+QENG=\"servingcell\";+QRSRP;+QCAINFO;+QNWPREFCFG=\"mode_pref\";+QTEMP\r\n',
|
||||
atCommandResponse: null,
|
||||
refreshSignal() {
|
||||
this.isLoading = true; // Set loading state to true before fetching data
|
||||
fetch(
|
||||
"/cgi-bin/get_atcommand?" +
|
||||
new URLSearchParams({
|
||||
atcmd: this.atcmd,
|
||||
})
|
||||
)
|
||||
.then((res) => {
|
||||
return res.text();
|
||||
})
|
||||
.then((data) => {
|
||||
this.atCommandResponse = data;
|
||||
// Split the response into individual messages
|
||||
const messages = data.trim().split("\n\n");
|
||||
|
||||
// Convert the messages into a JSON file
|
||||
//TODO: Add the JSON conversion here
|
||||
|
||||
|
||||
// Log the parsed messages array as JSON to the console
|
||||
console.log(JSON.stringify(parsedMessages, null, 2));
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error("Something went wrong", error);
|
||||
})
|
||||
.finally(() => {
|
||||
this.isLoading = false; // Set loading state to false after fetching data
|
||||
});
|
||||
},
|
||||
};
|
||||
}
|
||||
function getSignalData() {
|
||||
return {
|
||||
csqData: {},
|
||||
lastUpdate: new Date().toLocaleString(),
|
||||
getcsq() {
|
||||
fetch("/cgi-bin/get_csq")
|
||||
.then((res) => res.json())
|
||||
.then((data) => {
|
||||
this.csqData = data;
|
||||
this.lastUpdate = new Date(
|
||||
data.LASTUPDATE * 1000
|
||||
).toLocaleString();
|
||||
});
|
||||
},
|
||||
init() {
|
||||
this.getcsq();
|
||||
setInterval(() => {
|
||||
this.getcsq();
|
||||
}, 30000);
|
||||
},
|
||||
};
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
81
old/original_main_repo/simpleadmin/www/speedtest.html
Normal file
81
old/original_main_repo/simpleadmin/www/speedtest.html
Normal file
@@ -0,0 +1,81 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<title>Speedtest</title>
|
||||
|
||||
<script src="/js/alpinejs.min.js" defer></script>
|
||||
<link rel="stylesheet" href="/css/bulma.css" />
|
||||
<link rel="stylesheet" type="text/css" href="/css/admin.css" />
|
||||
<link rel="stylesheet" href="styles.css" />
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<!-- START NAV -->
|
||||
<nav class="navbar is-black" x-data="{ isOpen: false }">
|
||||
<div
|
||||
class="container"
|
||||
>
|
||||
<div class="navbar-brand">
|
||||
<a class="navbar-item brand-text" href="/"> Simple Admin </a>
|
||||
<a
|
||||
role="button"
|
||||
class="navbar-burger burger"
|
||||
@click="isOpen = !isOpen"
|
||||
>
|
||||
<span aria-hidden="true"></span>
|
||||
<span aria-hidden="true"></span>
|
||||
<span aria-hidden="true"></span>
|
||||
</a>
|
||||
</div>
|
||||
<div
|
||||
id="navMenu"
|
||||
class="navbar-menu"
|
||||
:class="isOpen ? 'is-active' : ''"
|
||||
>
|
||||
<div class="navbar-start">
|
||||
<a class="navbar-item" href="/"> Connection Info </a>
|
||||
<a class="navbar-item" href="/atcommander.html"> AT Commands </a>
|
||||
<a class="navbar-item" href="/bandlock.html"> Simple Network </a>
|
||||
<a class="navbar-item" href="/ttl.html"> TTL Changer </a>
|
||||
<a class="navbar-item" href="/speedtest.html"> OpenSpeedtest </a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
<!-- END NAV -->
|
||||
<div class="container">
|
||||
<!--OST Widget code start-->
|
||||
<div style="text-align: right">
|
||||
<div style="min-height: 360px">
|
||||
<div
|
||||
style="
|
||||
width: 100%;
|
||||
height: 0;
|
||||
padding-bottom: 50%;
|
||||
position: relative;
|
||||
"
|
||||
>
|
||||
<iframe
|
||||
style="
|
||||
border: none;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
min-height: 360px;
|
||||
border: none;
|
||||
overflow: hidden !important;
|
||||
"
|
||||
src="//openspeedtest.com/speedtest"
|
||||
></iframe>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- OST Widget code end -->
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
48
old/original_main_repo/simpleadmin/www/styles.css
Normal file
48
old/original_main_repo/simpleadmin/www/styles.css
Normal file
@@ -0,0 +1,48 @@
|
||||
/* Google Poppins */
|
||||
@import url('https://fonts.googleapis.com/css2?family=Poppins:wght@300;400;500;600;700&display=swap');
|
||||
|
||||
*{
|
||||
font-family: 'Poppins', sans-serif;
|
||||
}
|
||||
|
||||
.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: 20px;
|
||||
border-radius: 10px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.spinner {
|
||||
border: 4px solid rgba(0, 0, 0, 0.1);
|
||||
border-left-color: #333;
|
||||
border-radius: 50%;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
animation: spin 1s linear infinite;
|
||||
margin: 0 auto 10px auto;
|
||||
}
|
||||
|
||||
.loading-text {
|
||||
font-size: 18px;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
@keyframes spin {
|
||||
to {
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
|
||||
132
old/original_main_repo/simpleadmin/www/ttl.html
Normal file
132
old/original_main_repo/simpleadmin/www/ttl.html
Normal file
@@ -0,0 +1,132 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>TTL Changer</title>
|
||||
|
||||
<script src="/js/alpinejs.min.js" defer></script>
|
||||
<link rel="stylesheet" href="/css/bulma.css">
|
||||
<link rel="stylesheet" type="text/css" href="/css/admin.css">
|
||||
<link rel="stylesheet" href="styles.css" />
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<!-- START NAV -->
|
||||
<nav class="navbar is-black" x-data="{ isOpen: false }">
|
||||
<div class="container">
|
||||
<div class="navbar-brand">
|
||||
<a class="navbar-item brand-text" href="/">
|
||||
Simple Admin
|
||||
</a>
|
||||
<a role="button" class="navbar-burger burger" @click="isOpen = !isOpen">
|
||||
<span aria-hidden="true"></span>
|
||||
<span aria-hidden="true"></span>
|
||||
<span aria-hidden="true"></span>
|
||||
</a>
|
||||
</div>
|
||||
<div id="navMenu" class="navbar-menu" :class="isOpen ? 'is-active' : ''">
|
||||
<div class="navbar-start">
|
||||
<a class="navbar-item" href="/"> Connection Info </a>
|
||||
<a class="navbar-item" href="/atcommander.html"> AT Commands </a>
|
||||
<a class="navbar-item" href="/bandlock.html"> Simple Network </a>
|
||||
<a class="navbar-item" href="/ttl.html"> TTL Changer </a>
|
||||
<a class="navbar-item" href="/speedtest.html"> OpenSpeedtest </a>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
<!-- END NAV -->
|
||||
<div class="container" x-data="ttlCommands()" x-init="init">
|
||||
<div class="columns">
|
||||
<div class="column is-12">
|
||||
<div class="columns">
|
||||
<div class="column is-8">
|
||||
<div class="card">
|
||||
<header class="card-header">
|
||||
<p class="card-header-title">
|
||||
TTL Enabler
|
||||
</p>
|
||||
</header>
|
||||
<div class="card-content">
|
||||
<div class="content">
|
||||
<p>
|
||||
<h2>TTL Status</h2> <br>
|
||||
TTL is <span class="tag is-large"
|
||||
:class="ttldata.isEnabled ? 'is-success' : 'is-danger'"
|
||||
x-text="ttldata.isEnabled == true ? 'ON' : 'OFF'"></span>
|
||||
<br />
|
||||
TTL Set to <span x-text="ttldata.ttl"></span>
|
||||
</p>
|
||||
<div class="field">
|
||||
<label class="label">Set TTL</label>
|
||||
<div class="control">
|
||||
<input class="input" type="number" placeholder="64" x-model="newTTL">
|
||||
</div>
|
||||
</div>
|
||||
<div class="field">
|
||||
<div class="control">
|
||||
<button class="button is-link" @click="setTTL()">Set TTL</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="column is-4">
|
||||
<div class="card">
|
||||
<header class="card-header">
|
||||
<p class="card-header-title">
|
||||
Common TTL For Providers
|
||||
</p>
|
||||
</header>
|
||||
<div class="card-content">
|
||||
<div class="content">
|
||||
<ul>
|
||||
<li>Magenta: 65</li>
|
||||
<li>Red: 88</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<script>
|
||||
|
||||
function ttlCommands() {
|
||||
return {
|
||||
isLoading: false,
|
||||
ttldata: null,
|
||||
newTTL: 0,
|
||||
init() {
|
||||
fetch('/cgi-bin/get_ttl_status')
|
||||
.then((res) => res.json())
|
||||
.then((data) => {
|
||||
this.ttldata = data
|
||||
});
|
||||
},
|
||||
setTTL() {
|
||||
fetch('/cgi-bin/set_ttl?' + new URLSearchParams({
|
||||
ttlvalue: this.newTTL,
|
||||
}))
|
||||
.then((res) => res.json())
|
||||
.then((data) => {
|
||||
this.ttldata = data
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
@@ -1,7 +1,7 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Define the ports you want to block
|
||||
PORTS=("80" "443") # Default ports, will be modified by the install script
|
||||
PORTS=("80" "8080" "8088" "443") # Default ports, will be modified by the install script
|
||||
|
||||
# First, allow specified ports on bridge0, eth0, and tailscale0
|
||||
for port in "${PORTS[@]}"; do
|
||||
@@ -3,7 +3,7 @@ Description=Socat Serial Emulation for smd11
|
||||
After=ql-netd.service
|
||||
|
||||
[Service]
|
||||
ExecStart=/usrdata/socat-at-bridge/socat-armel-static -d -d pty,link=/dev/ttyIN,raw,echo=0,group=20,perm=660 pty,link=/dev/ttyOUT,raw,echo=1,group=20,perm=660
|
||||
ExecStart=/usrdata/socat-at-bridge/socat-armel-static -d -d pty,link=/dev/ttyIN,raw,echo=0 pty,link=/dev/ttyOUT,raw,echo=1
|
||||
# Add a delay to prevent the clients from starting too early
|
||||
ExecStartPost=/bin/sleep 2s
|
||||
Restart=always
|
||||
@@ -3,7 +3,7 @@ Description=Socat Serial Emulation for smd7
|
||||
After=ql-netd.service
|
||||
|
||||
[Service]
|
||||
ExecStart=/usrdata/socat-at-bridge/socat-armel-static -d -d pty,link=/dev/ttyIN2,raw,echo=0,group=20,perm=660 pty,link=/dev/ttyOUT2,raw,echo=1,group=20,perm=660
|
||||
ExecStart=/usrdata/socat-at-bridge/socat-armel-static -d -d pty,link=/dev/ttyIN2,raw,echo=0 pty,link=/dev/ttyOUT2,raw,echo=1
|
||||
# Add a delay to prevent the clients from starting too early
|
||||
ExecStartPost=/bin/sleep 2s
|
||||
Restart=always
|
||||
101
old/original_main_repo/ttyd/scripts/ICCID_APN.sh
Normal file
101
old/original_main_repo/ttyd/scripts/ICCID_APN.sh
Normal file
@@ -0,0 +1,101 @@
|
||||
#!/bin/sh
|
||||
|
||||
# Configuration
|
||||
DEVICE_FILE="/dev/smd7"
|
||||
ICCID_FILE="/path/to/iccid_master_file" # Path to the ICCID-APN-IPType master file
|
||||
TMP_DIR="/tmp"
|
||||
TIMEOUT=4
|
||||
|
||||
# Start listening to device file
|
||||
start_listening() {
|
||||
cat "$DEVICE_FILE" > "$TMP_DIR/device_readout" &
|
||||
CAT_PID=$!
|
||||
}
|
||||
|
||||
# Send AT command
|
||||
send_at_command() {
|
||||
local command=$1
|
||||
echo -e "${command}\r" > "$DEVICE_FILE"
|
||||
}
|
||||
|
||||
# Wait for and process response
|
||||
wait_for_response() {
|
||||
local start_time=$(date +%s)
|
||||
local current_time
|
||||
local elapsed_time
|
||||
|
||||
while true; do
|
||||
if grep -q "OK" "$TMP_DIR/device_readout" || grep -q "ERROR" "$TMP_DIR/device_readout"; then
|
||||
RESPONSE=$(cat "$TMP_DIR/device_readout")
|
||||
echo "Response received: $RESPONSE"
|
||||
return 0
|
||||
fi
|
||||
current_time=$(date +%s)
|
||||
elapsed_time=$((current_time - start_time))
|
||||
if [ "$elapsed_time" -ge "$TIMEOUT" ]; then
|
||||
echo "Error: Response timed out."
|
||||
return 1
|
||||
fi
|
||||
sleep 1
|
||||
done
|
||||
}
|
||||
|
||||
# Cleanup function
|
||||
cleanup() {
|
||||
kill "$CAT_PID"
|
||||
wait "$CAT_PID" 2>/dev/null
|
||||
rm -f "$TMP_DIR/device_readout"
|
||||
}
|
||||
|
||||
# Function to send AT command and wait for response
|
||||
send_and_wait() {
|
||||
send_at_command "$1"
|
||||
wait_for_response
|
||||
}
|
||||
|
||||
# Function to update the APN
|
||||
update_apn() {
|
||||
local slot=$1
|
||||
local apn=$2
|
||||
local iptype=$3
|
||||
send_and_wait "AT+CGDCONT=$slot,\"$iptype\",\"$apn\""
|
||||
if [ $? -eq 0 ]; then
|
||||
echo "APN updated successfully."
|
||||
else
|
||||
echo "Failed to update APN."
|
||||
fi
|
||||
}
|
||||
|
||||
# Main Execution
|
||||
if [ -c "$DEVICE_FILE" ]; then
|
||||
start_listening
|
||||
|
||||
# Get ICCID
|
||||
send_and_wait "AT+CCID"
|
||||
ICCID=$(echo "$RESPONSE" | grep "+CCID" | cut -d ':' -f2 | tr -d '[:space:]')
|
||||
echo "ICCID: $ICCID"
|
||||
|
||||
# Check ICCID in master file
|
||||
if grep -q "$ICCID" "$ICCID_FILE"; then
|
||||
APN=$(grep "$ICCID" "$ICCID_FILE" | cut -d ',' -f2)
|
||||
IP_TYPE=$(grep "$ICCID" "$ICCID_FILE" | cut -d ',' -f3)
|
||||
IP_TYPE=${IP_TYPE:-"IPV4V6"} # Default to IPV4V6 if not specified
|
||||
|
||||
# Get current APN settings
|
||||
send_and_wait "AT+CGDCONT?"
|
||||
CURRENT_APN=$(echo "$RESPONSE" | grep "+CGDCONT: 1" | cut -d ',' -f3 | tr -d '"')
|
||||
|
||||
# Compare and update APN if necessary
|
||||
if [ "$APN" != "$CURRENT_APN" ]; then
|
||||
update_apn 1 "$APN" "$IP_TYPE"
|
||||
else
|
||||
echo "No APN update needed."
|
||||
fi
|
||||
else
|
||||
echo "ICCID not found in the master file."
|
||||
fi
|
||||
|
||||
cleanup
|
||||
else
|
||||
echo "Error: Device $DEVICE_FILE does not exist or is not a character special file."
|
||||
fi
|
||||
21
old/original_main_repo/ttyd/scripts/ICCIDfun.sh
Normal file
21
old/original_main_repo/ttyd/scripts/ICCIDfun.sh
Normal file
@@ -0,0 +1,21 @@
|
||||
edit_iccid_file() {
|
||||
local iccid_file="/path/to/iccid_master_file" # Path to the ICCID-APN-IPType master file
|
||||
|
||||
echo "Enter ICCID to add or edit:"
|
||||
read iccid
|
||||
echo "Enter APN for $iccid:"
|
||||
read apn
|
||||
echo "Enter IP Type (IPV4, IPV6, IPV4V6) for $iccid [Default: IPV4V6]:"
|
||||
read iptype
|
||||
iptype=${iptype:-"IPV4V6"} # Default to IPV4V6 if not specified
|
||||
|
||||
# Check if ICCID already exists
|
||||
if grep -q "$iccid" "$iccid_file"; then
|
||||
# Update existing ICCID's APN and IP Type
|
||||
sed -i "/$iccid/c\\$iccid,$apn,$iptype" "$iccid_file"
|
||||
else
|
||||
# Add new ICCID, APN, and IP Type
|
||||
echo "$iccid,$apn,$iptype" >> "$iccid_file"
|
||||
fi
|
||||
echo "ICCID file updated."
|
||||
}
|
||||
@@ -1,15 +1,9 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Check if /usrdata/socat-at-bridge/atcmd exists
|
||||
if [ -f "/usrdata/socat-at-bridge/atcmd" ]; then
|
||||
# Read the serial number
|
||||
serial_number=$(/usrdata/socat-at-bridge/atcmd 'AT+EGMR=0,5' | grep '+EGMR:' | cut -d '"' -f2)
|
||||
# Read the firmware revision
|
||||
firmware_revision=$(/usrdata/socat-at-bridge/atcmd 'AT+QGMR' | grep -o 'RM[0-9A-Z].*')
|
||||
else
|
||||
serial_number="UNKNOWN"
|
||||
firmware_revision="UNKNOWN"
|
||||
fi
|
||||
# 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)
|
||||
|
||||
echo "=============================================================="
|
||||
echo "=============================================================="
|
||||
@@ -90,7 +84,7 @@ echo " :@@@@@*. "
|
||||
echo " .=@@@@@- "
|
||||
echo " :+##+. "
|
||||
echo "=============================================================="
|
||||
echo "TTYd session file by iamromulan v1.1"
|
||||
echo "TTYd session file by iamromulan v1.0"
|
||||
echo "Firmware Revision: $firmware_revision"
|
||||
echo "Serial Number: $serial_number"
|
||||
echo "=============================================================="
|
||||
12
old/original_main_repo/ttyd/systemd/ttyd.service
Normal file
12
old/original_main_repo/ttyd/systemd/ttyd.service
Normal file
@@ -0,0 +1,12 @@
|
||||
[Unit]
|
||||
Description=TTYD Service
|
||||
After=network.target
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
ExecStartPre=/bin/sleep 5
|
||||
ExecStart=/usrdata/ttyd/ttyd -p 443 -t 'theme={"foreground":"white","background":"black"}' -t fontSize=25 --writable /usrdata/ttyd/scripts/ttyd.bash
|
||||
Restart=on-failure
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
@@ -1 +0,0 @@
|
||||
2
|
||||
@@ -1,7 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
#Path
|
||||
export PATH=/bin:/sbin:/usr/bin:/usr/sbin:/opt/bin:/opt/sbin:/usrdata/root/bin
|
||||
|
||||
#Post-login execution
|
||||
/usrdata/simpleadmin/console/menu/start_menu.sh
|
||||
@@ -1,150 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
CONFIG_FILE="/etc/data/mobileap_cfg.xml"
|
||||
|
||||
# Display Messages in Colors
|
||||
display_random_color() {
|
||||
local msg="$1"
|
||||
local colors=(33 34 35 36 37) # ANSI color codes for yellow, blue, magenta, cyan, white
|
||||
local num_colors=${#colors[@]}
|
||||
local random_color_index=$(($RANDOM % num_colors)) # Pick a random index from the colors array
|
||||
echo -e "\033[${colors[$random_color_index]}m$msg\033[0m"
|
||||
}
|
||||
|
||||
display_green() {
|
||||
echo -e "\033[0;32m$1\033[0m"
|
||||
}
|
||||
|
||||
display_red() {
|
||||
echo -e "\033[0;31m$1\033[0m"
|
||||
}
|
||||
|
||||
# Check and Install xml binary if not present
|
||||
check_and_install_xml() {
|
||||
if [ ! -f "/opt/bin/xml" ]; then
|
||||
echo "xml binary not found. Attempting to install xmlstarlet..."
|
||||
opkg update
|
||||
opkg install xmlstarlet
|
||||
# Verify installation
|
||||
if [ ! -f "/opt/bin/xml" ]; then
|
||||
echo "Failed to install xmlstarlet. Exiting..."
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
echo "xml binary is available."
|
||||
}
|
||||
|
||||
# Edit XML Value
|
||||
edit_xml_value() {
|
||||
local node="$1"
|
||||
local new_value="$2"
|
||||
/opt/bin/xml ed -L -u "$node" -v "$new_value" "$CONFIG_FILE"
|
||||
}
|
||||
|
||||
# Get Current XML Value
|
||||
get_current_value() {
|
||||
/opt/bin/xml sel -t -v "$1" "$CONFIG_FILE"
|
||||
}
|
||||
|
||||
# Enable/Disable Menu
|
||||
enable_disable_menu() {
|
||||
local node="$1"
|
||||
local current_value=$(get_current_value "$node")
|
||||
echo "Current status: $([ "$current_value" == "1" ] && echo "Enabled" || echo "Disabled")"
|
||||
echo "1. Enable"
|
||||
echo "2. Disable"
|
||||
read -p "Choose an option to toggle (1-2): " choice
|
||||
local new_value="$([ "$choice" == "1" ] && echo "1" || echo "0")"
|
||||
edit_xml_value "$node" "$new_value"
|
||||
display_green "After making changes, please reboot to have them take effect."
|
||||
}
|
||||
|
||||
# Edit Simple Value
|
||||
edit_simple_value() {
|
||||
local node="$1"
|
||||
local description="$2"
|
||||
local current=$(get_current_value "$node")
|
||||
echo "Current $description: $current"
|
||||
read -p "Enter new $description: " new_value
|
||||
edit_xml_value "$node" "$new_value"
|
||||
display_green "After making changes, please reboot to have them take effect."
|
||||
}
|
||||
|
||||
# Edit DHCP IP Range
|
||||
edit_dhcp_range() {
|
||||
local start_ip=$(get_current_value "//MobileAPLanCfg/DHCPCfg/StartIP")
|
||||
local end_ip=$(get_current_value "//MobileAPLanCfg/DHCPCfg/EndIP")
|
||||
echo "Current Start IP: $start_ip"
|
||||
echo "Current End IP: $end_ip"
|
||||
read -p "Enter new Start IP: " new_start_ip
|
||||
read -p "Enter new End IP: " new_end_ip
|
||||
edit_xml_value "//MobileAPLanCfg/DHCPCfg/StartIP" "$new_start_ip"
|
||||
edit_xml_value "//MobileAPLanCfg/DHCPCfg/EndIP" "$new_end_ip"
|
||||
display_green "After making changes, please reboot to have them take effect."
|
||||
}
|
||||
|
||||
# Reboot the system
|
||||
reboot_system() {
|
||||
echo "Rebooting system..."
|
||||
atcmd 'AT+CFUN=1,1' # Ensure this command is correct for your system
|
||||
echo "System reboot initiated. Good luck."
|
||||
}
|
||||
|
||||
# Main Menu
|
||||
main_menu() {
|
||||
while true; do
|
||||
clear
|
||||
display_red "Warning, these changes can break access over the network. Know what you are doing, and be prepared to use ADB to fix this just in case."
|
||||
echo "Configuration Menu"
|
||||
echo "------------------"
|
||||
display_green "1. Edit Gateway IPV4 Address"
|
||||
display_green "2. Edit Gateway URL"
|
||||
display_green "3. Edit LAN DHCP Start/End Range"
|
||||
display_green "4. Edit LAN Subnet Mask"
|
||||
display_green "5. Edit DHCPv6 Base address"
|
||||
display_green "6. Toggle IPv4 NAT"
|
||||
display_green "7. Toggle IPv6 NAT"
|
||||
display_green "8. Toggle DHCP Server"
|
||||
display_green "9. Toggle DHCPv4"
|
||||
display_green "10. Toggle DHCPv6"
|
||||
display_green "11. Toggle WAN Autoconnect"
|
||||
display_green "12. Toggle WAN AutoReconnect"
|
||||
display_green "13. Toggle Roaming"
|
||||
display_green "14. Toggle WAN DNSv4 Passthrough"
|
||||
display_green "15. Toggle WAN DNSv6 Passthrough"
|
||||
display_green "16. Toggle IPPT NAT/Ability to access gateway while in IPPT mode"
|
||||
display_green "17. Toggle UPnP"
|
||||
display_green "18. Reboot System"
|
||||
display_green "19. Exit"
|
||||
echo
|
||||
read -p "Select an option (1-19): " option
|
||||
|
||||
case "$option" in
|
||||
1) edit_simple_value "//MobileAPLanCfg/APIPAddr" "Gateway IPV4 Address";;
|
||||
2) edit_simple_value "//MobileAPLanCfg/GatewayURL" "Gateway URL";;
|
||||
3) edit_dhcp_range;;
|
||||
4) edit_simple_value "//MobileAPLanCfg/SubNetMask" "LAN Subnet Mask";;
|
||||
5) edit_simple_value "//MobileAPLanCfg/ULAIPv6BaseAddr" "DHCPv6 Base Address";;
|
||||
6) enable_disable_menu "//MobileAPNatCfg/IPv4NATDisable";;
|
||||
7) enable_disable_menu "//MobileAPNatv6Cfg/EnableIPv6NAT";;
|
||||
8) enable_disable_menu "//MobileAPLanCfg/EnableDHCPServer";;
|
||||
9) enable_disable_menu "//MobileAPLanCfg/EnableIPV4";;
|
||||
10) enable_disable_menu "//MobileAPLanCfg/EnableIPV6";;
|
||||
11) enable_disable_menu "//MobileAPWanCfg/AutoConnect";;
|
||||
12) enable_disable_menu "//MobileAPWanCfg/ReConnect";;
|
||||
13) enable_disable_menu "//MobileAPWanCfg/Roaming";;
|
||||
14) enable_disable_menu "//Dhcpv4Cfg/EnableDhcpv4Dns";;
|
||||
15) enable_disable_menu "//Dhcpv6Cfg/EnableDhcpv6Dns";;
|
||||
16) enable_disable_menu "//IPPassthroughFeatureWithNAT";;
|
||||
17) enable_disable_menu "//MobileAPSrvcCfg/UPnP";;
|
||||
18) reboot_system;;
|
||||
19) break;;
|
||||
*) echo "Invalid option. Please try again.";;
|
||||
esac
|
||||
done
|
||||
}
|
||||
|
||||
# Start by checking and installing xml if necessary, then mount filesystem as rw and run the menu
|
||||
mount -o remount,rw /
|
||||
check_and_install_xml
|
||||
main_menu
|
||||
@@ -1,129 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
SIMPLE_FIREWALL_DIR="/usrdata/simplefirewall"
|
||||
SIMPLE_FIREWALL_SCRIPT="$SIMPLE_FIREWALL_DIR/simplefirewall.sh"
|
||||
SIMPLE_FIREWALL_SYSTEMD_DIR="$SIMPLE_FIREWALL_DIR/systemd"
|
||||
|
||||
# Display Messages in Colors
|
||||
display_random_color() {
|
||||
local msg="$1"
|
||||
local colors=(33 34 35 36 37) # ANSI color codes for yellow, blue, magenta, cyan, white
|
||||
local num_colors=${#colors[@]}
|
||||
local random_color_index=$(($RANDOM % num_colors)) # Pick a random index from the colors array
|
||||
echo -e "\033[${colors[$random_color_index]}m$msg\033[0m"
|
||||
}
|
||||
|
||||
display_green() {
|
||||
echo -e "\033[0;32m$1\033[0m"
|
||||
}
|
||||
|
||||
display_red() {
|
||||
echo -e "\033[0;31m$1\033[0m"
|
||||
}
|
||||
|
||||
set_portblocks() {
|
||||
current_ports_line=$(grep '^PORTS=' "$SIMPLE_FIREWALL_SCRIPT")
|
||||
ports=$(echo "$current_ports_line" | cut -d'=' -f2 | tr -d '()' | tr ' ' '\n' | grep -o '[0-9]\+')
|
||||
echo -e "\e[1;32mCurrent configured ports:\e[0m"
|
||||
echo "$ports" | awk '{print NR") "$0}'
|
||||
|
||||
while true; do
|
||||
echo -e "\e[1;32mEnter a port number to add/remove, or type 'done' or 'exit' to finish:\e[0m"
|
||||
read port
|
||||
if [ "$port" = "done" ] || [ "$port" = "exit" ]; then
|
||||
if [ "$port" = "exit" ]; then
|
||||
echo -e "\e[1;31mExiting without making changes...\e[0m"
|
||||
return
|
||||
fi
|
||||
break
|
||||
elif ! echo "$port" | grep -qE '^[0-9]+$'; then
|
||||
echo -e "\e[1;31mInvalid input: Please enter a numeric value.\e[0m"
|
||||
elif echo "$ports" | grep -q "^$port\$"; then
|
||||
ports=$(echo "$ports" | grep -v "^$port\$")
|
||||
echo -e "\e[1;32mPort $port removed.\e[0m"
|
||||
else
|
||||
ports=$(echo "$ports"; echo "$port" | grep -o '[0-9]\+')
|
||||
echo -e "\e[1;32mPort $port added.\e[0m"
|
||||
fi
|
||||
done
|
||||
|
||||
if [ "$port" != "exit" ]; then
|
||||
new_ports_line="PORTS=($(echo "$ports" | tr '\n' ' '))"
|
||||
sed -i "s/$current_ports_line/$new_ports_line/" "$SIMPLE_FIREWALL_SCRIPT"
|
||||
fi
|
||||
}
|
||||
|
||||
set_ttl(){
|
||||
# TTL configuration code
|
||||
ttl_value=$(cat /usrdata/simplefirewall/ttlvalue)
|
||||
if [ "$ttl_value" -eq 0 ]; then
|
||||
echo -e "\e[1;31mTTL is not set.\e[0m"
|
||||
else
|
||||
echo -e "\e[1;32mTTL value is set to $ttl_value.\e[0m"
|
||||
fi
|
||||
|
||||
echo -e "\e[1;31mType 'exit' to cancel.\e[0m"
|
||||
read -p "What do you want the TTL value to be: " new_ttl_value
|
||||
if [ "$new_ttl_value" = "exit" ]; then
|
||||
echo -e "\e[1;31mExiting TTL configuration...\e[0m"
|
||||
return
|
||||
elif ! echo "$new_ttl_value" | grep -qE '^[0-9]+$'; then
|
||||
echo -e "\e[1;31mInvalid input: Please enter a numeric value.\e[0m"
|
||||
return
|
||||
else
|
||||
/usrdata/simplefirewall/ttl-override stop
|
||||
echo "$new_ttl_value" > /usrdata/simplefirewall/ttlvalue
|
||||
/usrdata/simplefirewall/ttl-override start
|
||||
echo -e "\033[0;32mTTL value updated to $new_ttl_value.\033[0m"
|
||||
fi
|
||||
}
|
||||
|
||||
# function to configure the fetures of simplefirewall
|
||||
simple_firewall_menu() {
|
||||
if [ ! -f "$SIMPLE_FIREWALL_SCRIPT" ]; then
|
||||
display_random_color "Simplefirewall is not installed, would you like to install it?"
|
||||
display_green "1) Yes"
|
||||
display_red "2) No"
|
||||
read -p "Enter your choice (1-2): " install_choice
|
||||
|
||||
case $install_choice in
|
||||
1)
|
||||
install_simple_firewall
|
||||
;;
|
||||
2)
|
||||
return
|
||||
;;
|
||||
*)
|
||||
display_red "Invalid choice. Please select either 1 or 2."
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
|
||||
display_random_color "Configure Simple Firewall:"
|
||||
display_green "1) Configure incoming port block"
|
||||
display_green "2) Configure TTL"
|
||||
display_green "3) Exit to Main Menu"
|
||||
read -p "Enter your choice (1-2): " menu_choice
|
||||
|
||||
case $menu_choice in
|
||||
1)
|
||||
set_portblocks
|
||||
;;
|
||||
2)
|
||||
set_ttl
|
||||
;;
|
||||
3)
|
||||
return
|
||||
;;
|
||||
*)
|
||||
echo -e "\e[1;31mInvalid choice. Please select either 1 or 2.\e[0m"
|
||||
;;
|
||||
esac
|
||||
|
||||
systemctl restart simplefirewall
|
||||
echo -e "\e[1;32mFirewall configuration updated.\e[0m"
|
||||
}
|
||||
|
||||
# Main execution
|
||||
mount -o remount,rw /
|
||||
simple_firewall_menu
|
||||
@@ -1,118 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Define executable files path
|
||||
MENU_SH=/usrdata/simpleadmin/console/menu
|
||||
|
||||
# Display Messages in Colors
|
||||
display_random_color() {
|
||||
local msg="$1"
|
||||
local colors=(33 34 35 36 37) # ANSI color codes for yellow, blue, magenta, cyan, white
|
||||
local num_colors=${#colors[@]}
|
||||
local random_color_index=$(($RANDOM % num_colors)) # Pick a random index from the colors array
|
||||
echo -e "\033[${colors[$random_color_index]}m$msg\033[0m"
|
||||
}
|
||||
|
||||
display_green() {
|
||||
echo -e "\033[0;32m$1\033[0m"
|
||||
}
|
||||
|
||||
display_red() {
|
||||
echo -e "\033[0;31m$1\033[0m"
|
||||
}
|
||||
|
||||
# Menus
|
||||
|
||||
toolkit_menu() {
|
||||
while true; do
|
||||
display_random_color "Run a Toolkit version"
|
||||
display_green "Select an option:"
|
||||
echo "------------------"
|
||||
display_green "1. Get and run the Toolkit"
|
||||
display_random_color "2. Get and run the Development/unstable Toolkit"
|
||||
display_random_color "3. Exit (Enter Root Shell)"
|
||||
echo
|
||||
read -p "Select an option (1-3): " option
|
||||
|
||||
case "$option" in
|
||||
1) cd /tmp && wget -O RMxxx_rgmii_toolkit.sh https://raw.githubusercontent.com/iamromulan/quectel-rgmii-toolkit/SDXLEMUR/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-SDXLEMUR/RMxxx_rgmii_toolkit.sh && chmod +x RMxxx_rgmii_toolkit.sh && ./RMxxx_rgmii_toolkit.sh && cd / ;;
|
||||
3) break ;;
|
||||
*) echo "Invalid option. Please try again." ;;
|
||||
esac
|
||||
done
|
||||
}
|
||||
|
||||
apps_menu() {
|
||||
while true; do
|
||||
display_random_color "Run a modem App"
|
||||
display_green "Select an option:"
|
||||
echo "------------------"
|
||||
display_random_color "1. Open File Browser/Editor (mc)"
|
||||
display_random_color "2. View Used/Available space"
|
||||
display_random_color "3. Open Task Manager/View CPU Load"
|
||||
display_random_color "4. Run speedtest.net test"
|
||||
display_random_color "5. Run fast.com test (30Mbps max)"
|
||||
display_green "6. Go Back"
|
||||
echo
|
||||
read -p "Select an option (1-6): " option
|
||||
|
||||
case "$option" in
|
||||
1) mc ;;
|
||||
2) dfc ;;
|
||||
3) htop ;;
|
||||
4) speedtest ;;
|
||||
5) fast ;;
|
||||
6) break ;;
|
||||
*) echo "Invalid option. Please try again." ;;
|
||||
esac
|
||||
done
|
||||
}
|
||||
|
||||
settings_menu() {
|
||||
while true; do
|
||||
display_random_color "Welcome to" && display_green "iamromulan's" && display_random_color "Simple Console Menu"
|
||||
display_green "Select an option:"
|
||||
echo "------------------"
|
||||
display_green "1. LAN Settings"
|
||||
display_green "2. simplefirewall settings (TTL and Port Block)"
|
||||
display_green "3. Change simpleadmin (admin) password"
|
||||
display_green "4. Change root password (shell/ssh/console)"
|
||||
display_green "5. Go back"
|
||||
echo
|
||||
read -p "Select an option (1-5): " option
|
||||
|
||||
case "$option" in
|
||||
1) $MENU_SH/LAN_settings.sh ;;
|
||||
2) $MENU_SH/sfirewall_settings.sh ;;
|
||||
3) simplepasswd ;;
|
||||
4) passwd ;;
|
||||
5) break ;;
|
||||
*) echo "Invalid option. Please try again." ;;
|
||||
esac
|
||||
done
|
||||
}
|
||||
|
||||
main_menu() {
|
||||
while true; do
|
||||
display_green "Welcome to iamromulan's Simple Console Menu"
|
||||
display_green "To get back to this from the root shell, just type 'menu'"
|
||||
display_green "Select an option:"
|
||||
echo "------------------"
|
||||
display_random_color "1. Apps"
|
||||
display_random_color "2. Settings"
|
||||
display_random_color "3. Toolkit"
|
||||
display_random_color "4. Exit (Enter Root Shell)"
|
||||
echo
|
||||
read -p "Select an option (1-4): " option
|
||||
|
||||
case "$option" in
|
||||
1) apps_menu ;;
|
||||
2) settings_menu ;;
|
||||
3) toolkit_menu ;;
|
||||
4) break ;;
|
||||
*) echo "Invalid option. Please try again." ;;
|
||||
esac
|
||||
done
|
||||
}
|
||||
|
||||
main_menu
|
||||
@@ -1,27 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Define the command to execute when the ethernet port breaks
|
||||
command_to_execute="/usrdata/socat-at-bridge/atcmd 'AT+CFUN=1,1'"
|
||||
|
||||
# Define the monitoring function
|
||||
watch() {
|
||||
while true; do
|
||||
# Extract the last 60 lines of dmesg and count the specific pattern occurrences
|
||||
count=$(dmesg | tail -60 | grep -e "eth0: cmd = 0xff, should be 0x47" -e "eth0: pci link is down" | grep -c "eth0")
|
||||
|
||||
# Check if the count of patterns is 4 or more
|
||||
if [ "$count" -ge 4 ]; then
|
||||
echo "Condition met, executing command..."
|
||||
eval "$command_to_execute"
|
||||
# Optionally, add a break here if you want the script to stop after executing the command
|
||||
# break
|
||||
fi
|
||||
|
||||
# Sleep for 3 seconds before checking again
|
||||
sleep 3
|
||||
done
|
||||
}
|
||||
|
||||
# Initial delay before starting monitoring
|
||||
sleep 30
|
||||
watch
|
||||
@@ -1,28 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Define the hostname or IP address to ping
|
||||
HOSTNAME="google.com"
|
||||
|
||||
# Number of pings to attempt
|
||||
PING_COUNT=6
|
||||
|
||||
# Initialize a counter for successful pings
|
||||
success_count=0
|
||||
|
||||
# Attempt to ping the specified number of times
|
||||
for i in $(seq 1 $PING_COUNT); do
|
||||
# Ping the hostname with a timeout of 1 second per ping
|
||||
if ping -c 1 -W 1 $HOSTNAME &> /dev/null; then
|
||||
((success_count++))
|
||||
else
|
||||
echo "Ping attempt $i failed."
|
||||
fi
|
||||
done
|
||||
|
||||
# Check if all pings failed
|
||||
if [ $success_count -eq 0 ]; then
|
||||
echo "All $PING_COUNT ping attempts failed, executing AT command."
|
||||
/bin/atcmd 'AT+CFUN=1,1'
|
||||
else
|
||||
echo "$success_count out of $PING_COUNT ping attempts were successful."
|
||||
fi
|
||||
@@ -1,14 +0,0 @@
|
||||
[Unit]
|
||||
Description=Ping Watchdog Service
|
||||
Wants=network.target
|
||||
After=network.target
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
ExecStartPre=/bin/sleep 60 # Sleep for 60 seconds to ensure the network is ready
|
||||
ExecStart=/usrdata/simpleadmin/console/services/ping_watchdog.sh
|
||||
Restart=on-failure
|
||||
RestartSec=30s
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
Binary file not shown.
@@ -1,47 +0,0 @@
|
||||
server.modules = (
|
||||
"mod_redirect",
|
||||
"mod_cgi",
|
||||
"mod_proxy",
|
||||
"mod_openssl",
|
||||
"mod_authn_file",
|
||||
)
|
||||
|
||||
server.username = "www-data"
|
||||
server.groupname = "dialout"
|
||||
|
||||
server.port = 80
|
||||
server.document-root = "/usrdata/simpleadmin/www"
|
||||
index-file.names = ( "index.html" )
|
||||
|
||||
auth.backend = "htpasswd"
|
||||
auth.backend.htpasswd.userfile = "/opt/etc/.htpasswd"
|
||||
|
||||
$SERVER["socket"] == "0.0.0.0:443" {
|
||||
ssl.engine = "enable"
|
||||
ssl.privkey= "/usrdata/simpleadmin/server.key"
|
||||
ssl.pemfile= "/usrdata/simpleadmin/server.crt"
|
||||
ssl.acme-tls-1 = "/etc/simpleadmin/dehydrated/tls-alpn-01"
|
||||
ssl.openssl.ssl-conf-cmd = ("MinProtocol" => "TLSv1.2") # (lighttpd 1.4.56 default; recommended to accept only TLSv1.2 and TLSv1.3)
|
||||
auth.require = ( "/" => (
|
||||
"method" => "basic",
|
||||
"realm" => "Authorized users only",
|
||||
"require" => "valid-user"
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
# Redirect everything to https
|
||||
$HTTP["scheme"] == "http" {
|
||||
url.redirect = ("" => "https://${url.authority}${url.path}${qsa}")
|
||||
}
|
||||
|
||||
# Anything in /cgi-bin will be run as a script
|
||||
$HTTP["url"] =~ "/cgi-bin/" {
|
||||
cgi.assign = ( "" => "" )
|
||||
}
|
||||
|
||||
# Handle proxy to ttyd if it's running
|
||||
$HTTP["url"] =~ "(^/console)" {
|
||||
proxy.header = ("map-urlpath" => ( "/console" => "/" ), "upgrade" => "enable" )
|
||||
proxy.server = ( "" => ("" => ( "host" => "127.0.0.1", "port" => 8080 )))
|
||||
}
|
||||
@@ -1,60 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
# Function to create and run the Watchcat script
|
||||
create_and_run_watchcat_script() {
|
||||
local ip=$1
|
||||
local timeout=$2
|
||||
local failure_count=$3
|
||||
local script_path="/usrdata/simpleadmin/script/watchcat.sh"
|
||||
|
||||
# Create the script with the watchcat logic
|
||||
sudo cat << EOF > $script_path
|
||||
#!/bin/sh
|
||||
|
||||
failures=0
|
||||
|
||||
while :; do
|
||||
if ping -c 1 $ip > /dev/null 2>&1; then
|
||||
failures=0
|
||||
else
|
||||
failures=\$((failures + 1))
|
||||
if [ "\$failures" -ge "$failure_count" ]; then
|
||||
echo "Rebooting system due to \$failures consecutive ping failures."
|
||||
/sbin/reboot
|
||||
exit 0
|
||||
fi
|
||||
fi
|
||||
sleep $timeout
|
||||
done
|
||||
EOF
|
||||
|
||||
# Make the watchcat script executable
|
||||
chmod +x $script_path
|
||||
|
||||
# Create a JSON to be fetched later
|
||||
echo "{\"enabled\": true, \"track_ip\": \"$ip\", \"ping_timeout\": $timeout, \"ping_failure_count\": $failure_count}" > /usrdata/simpleadmin/script/watchcat.json
|
||||
|
||||
# Check if the script was created successfully
|
||||
if [ -f "$script_path" ]; then
|
||||
# Make the script executable
|
||||
chmod +x "$script_path"
|
||||
|
||||
# Run the script in the background
|
||||
# nohup /bin/sh "$script_path" &
|
||||
/bin/sh "$script_path" &
|
||||
|
||||
echo "Watchcat script created and running."
|
||||
else
|
||||
echo "Failed to create the Watchcat script."
|
||||
echo "Please check the script path: $script_path"
|
||||
fi
|
||||
}
|
||||
|
||||
# Check if the script is called with the required parameters
|
||||
if [ "$#" -ne 3 ]; then
|
||||
echo "Usage: $0 <IP> <timeout> <failure_count>"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Call the function with the provided arguments
|
||||
create_and_run_watchcat_script "$1" "$2" "$3"
|
||||
@@ -1,32 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
# Function to remove the Watchcat script and JSON file
|
||||
remove_watchcat_script() {
|
||||
local script_path="/usrdata/simpleadmin/script/watchcat.sh"
|
||||
local json_path="/usrdata/simpleadmin/script/watchcat.json"
|
||||
|
||||
# Mount as read-write
|
||||
mount -o remount,rw /
|
||||
|
||||
# Remove the watchcat script if it exists
|
||||
if [ -f "$script_path" ]; then
|
||||
rm "$script_path"
|
||||
echo "Removed $script_path"
|
||||
else
|
||||
echo "$script_path does not exist"
|
||||
fi
|
||||
|
||||
# Remove the JSON file if it exists
|
||||
if [ -f "$json_path" ]; then
|
||||
rm "$json_path"
|
||||
echo "Removed $json_path"
|
||||
else
|
||||
echo "$json_path does not exist"
|
||||
fi
|
||||
|
||||
# Mount as read-only
|
||||
mount -o remount,ro /
|
||||
}
|
||||
|
||||
# Call the function to remove the scripts
|
||||
remove_watchcat_script
|
||||
@@ -1,43 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
# Check if the required parameters are provided
|
||||
if [ "$#" -ne 2 ]; then
|
||||
echo "Usage: $0 <enable|disable> <ttl_value>"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Assign the provided parameters to variables
|
||||
mode="$1"
|
||||
ttl_value="$2"
|
||||
|
||||
# Check if iptables is still set
|
||||
ttlcheck=$(/opt/bin/sudo /usr/sbin/iptables -w 5 -t mangle -vnL | grep TTL | awk '{print $13}')
|
||||
|
||||
# If TTL is still set, manually remove values
|
||||
if [ ! -z "${ttlcheck}" ]; then
|
||||
/opt/bin/sudo /usr/sbin/iptables -w 5 -t mangle -D POSTROUTING -o rmnet+ -j TTL --ttl-set "${ttlcheck}" &>/dev/null || true
|
||||
/opt/bin/sudo /usr/sbin/ip6tables -w 5 -t mangle -D POSTROUTING -o rmnet+ -j HL --hl-set "${ttlcheck}" &>/dev/null || true
|
||||
fi
|
||||
|
||||
# Handle the enable/disable mode
|
||||
case "${mode}" in
|
||||
enable)
|
||||
# Echo TTL to file
|
||||
echo "${ttl_value}" > /usrdata/simplefirewall/ttlvalue
|
||||
|
||||
# Set Start Service
|
||||
/opt/bin/sudo /usrdata/simplefirewall/ttl-override start
|
||||
;;
|
||||
disable)
|
||||
# Remove TTL value file
|
||||
rm -f /usrdata/simplefirewall/ttlvalue
|
||||
|
||||
# Stop the service
|
||||
/opt/bin/sudo /usrdata/simplefirewall/ttl-override stop
|
||||
;;
|
||||
*)
|
||||
echo "Invalid mode: ${mode}"
|
||||
echo "Usage: $0 <enable|disable> <ttl_value>"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
@@ -1,5 +0,0 @@
|
||||
#/bin/bash
|
||||
|
||||
echo -e "\e[1;31mPlease set your simpleadmin (User: admin) web login password.\e[0m"
|
||||
/usrdata/root/bin/htpasswd -c /opt/etc/.htpasswd admin
|
||||
echo -e "\e[1;32mPassword set.\e[0m"
|
||||
@@ -1,14 +0,0 @@
|
||||
[Unit]
|
||||
Description=Lighttpd Daemon
|
||||
After=network.target opt.mount
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
PIDFile=/opt/var/run/lighttpd.pid
|
||||
ExecStartPre=/opt/sbin/lighttpd -tt -f /usrdata/simpleadmin/lighttpd.conf
|
||||
ExecStart=/opt/sbin/lighttpd -D -f /usrdata/simpleadmin/lighttpd.conf
|
||||
ExecReload=/bin/kill -USR1 $MAINPID
|
||||
Restart=on-failure
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
@@ -1,12 +0,0 @@
|
||||
[Unit]
|
||||
Description=TTYD Service
|
||||
After=network.target
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
ExecStartPre=/bin/sleep 5
|
||||
ExecStart=/usrdata/simpleadmin/console/ttyd -i 127.0.0.1 -p 8080 -t 'theme={"foreground":"white","background":"black"}' -t fontSize=25 --writable /usrdata/simpleadmin/console/ttyd.bash
|
||||
Restart=on-failure
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
@@ -1,19 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
# This script will ping 8.8.8.8 and return the result
|
||||
# If the ping is successful, it will return "OK"
|
||||
# If the ping fails, it will return "ERROR"
|
||||
|
||||
# Send the ping command and store the output
|
||||
ping_output=$(ping -c 1 8.8.8.8)
|
||||
|
||||
# Check if the output contains "0% packet loss"
|
||||
if echo "$ping_output" | grep -q "0% packet loss"; then
|
||||
echo "Content-type: text/plain"
|
||||
echo ""
|
||||
echo "OK"
|
||||
else
|
||||
echo "Content-type: text/plain"
|
||||
echo ""
|
||||
echo "ERROR"
|
||||
fi
|
||||
@@ -1,11 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Execute the uptime command and store the result
|
||||
uptime_output=$(uptime)
|
||||
|
||||
# Set header for plain text content
|
||||
echo "Content-Type: text/plain"
|
||||
echo ""
|
||||
|
||||
# Output the uptime result
|
||||
echo "$uptime_output"
|
||||
@@ -1,17 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Content type header
|
||||
echo "Content-type: application/json"
|
||||
echo ""
|
||||
|
||||
# This script fetches the watchCat parameters from the /tmp/watchcat.json and returns it as JSON
|
||||
# Example content of /tmp/watchcat:
|
||||
# {"watchcat": {"enabled": true, "track_ip": "1.1.1.1", "ping_timeout": 30, "ping_failure_count": 10}}
|
||||
|
||||
# Check if the file exists
|
||||
if [ -f /tmp/watchcat.json ]; then
|
||||
cat /tmp/watchcat.json
|
||||
else
|
||||
# return an empty JSON object
|
||||
echo "{}"
|
||||
fi
|
||||
@@ -1,31 +0,0 @@
|
||||
#!/bin/bash
|
||||
QUERY_STRING=$(echo "${QUERY_STRING}" | sed 's/;//g')
|
||||
urldecode() {
|
||||
local data
|
||||
data="${*//+/ }"
|
||||
echo -e "${data//%/\\x}"
|
||||
}
|
||||
|
||||
if [ "${QUERY_STRING}" ]; then
|
||||
export IFS="&"
|
||||
for cmd in ${QUERY_STRING}; do
|
||||
if [[ "$cmd" == *=* ]]; then
|
||||
key=$(echo "$cmd" | awk -F '=' '{print $1}')
|
||||
value=$(echo "$cmd" | awk -F '=' '{print $2}')
|
||||
eval "$key"="$(urldecode "$value")"
|
||||
fi
|
||||
done
|
||||
fi
|
||||
|
||||
phone_number="$number"
|
||||
message_encoded="$msg"
|
||||
|
||||
|
||||
send_at_command() {
|
||||
local cmd=$1
|
||||
echo -en "$cmd\r" | microcom -t 100 /dev/ttyOUT2
|
||||
}
|
||||
|
||||
send_at_command "AT+CMGS=\"$phone_number\","$Command""
|
||||
runcmd=$((echo -en "$message_encoded"; echo -en "\x1A") | microcom -t 500 /dev/ttyOUT2)
|
||||
echo "$runcmd"
|
||||
@@ -1,64 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Debug log function
|
||||
log_debug() {
|
||||
local message="$1"
|
||||
debug_logs+=("$message")
|
||||
}
|
||||
|
||||
# Initialize debug logs array
|
||||
declare -a debug_logs=()
|
||||
|
||||
# Get query
|
||||
QUERY_STRING=$(echo "${QUERY_STRING}" | sed 's/;//g')
|
||||
if [ "${QUERY_STRING}" ]; then
|
||||
export IFS="&"
|
||||
for cmd in ${QUERY_STRING}; do
|
||||
if [ "$(echo $cmd | grep '=')" ]; then
|
||||
key=$(echo $cmd | awk -F '=' '{print $1}')
|
||||
value=$(echo $cmd | awk -F '=' '{print $2}')
|
||||
eval $key=$value
|
||||
log_debug "Received parameter: $key=$value"
|
||||
fi
|
||||
done
|
||||
fi
|
||||
|
||||
setTTL=$(printf '%b\n' "${ttlvalue//%/\\x}")
|
||||
if [ -n "${setTTL}" ]; then
|
||||
log_debug "Stopping service to remove rules"
|
||||
/usrdata/simplefirewall/ttl-override stop
|
||||
|
||||
# Convert ttlvalue to integer
|
||||
if [ "${ttlvalue}" ]; then
|
||||
ttlvalue_int=$(echo "${ttlvalue}" | sed 's/[^0-9]//g')
|
||||
log_debug "Converted ttlvalue to integer: $ttlvalue_int"
|
||||
fi
|
||||
|
||||
# Call the sh script with the appropriate parameters
|
||||
if [ "${ttlvalue_int}" != 0 ]; then
|
||||
log_debug "Enabling TTL with value: ${setTTL}"
|
||||
/usrdata/simpleadmin/script/ttl_script.sh enable "${setTTL}"
|
||||
commandRan="/usrdata/simpleadmin/script/ttl_script.sh enable ${setTTL}"
|
||||
ttlenabled=true
|
||||
ttlvalue=$ttlvalue_int
|
||||
elif [ "${ttlvalue_int}" = 0 ]; then
|
||||
log_debug "Disabling TTL"
|
||||
/usrdata/simpleadmin/script/ttl_script.sh disable 0
|
||||
commandRan="/usrdata/simpleadmin/script/ttl_script.sh disable 0"
|
||||
ttlenabled=false
|
||||
ttlvalue=0
|
||||
fi
|
||||
|
||||
log_debug "Starting service to apply rules"
|
||||
/usrdata/simplefirewall/ttl-override start
|
||||
fi
|
||||
|
||||
echo "Content-type: text/text"
|
||||
echo ""
|
||||
cat <<EOT
|
||||
{
|
||||
"debug_logs": [
|
||||
$(printf '"%s",' "${debug_logs[@]}")
|
||||
]
|
||||
}
|
||||
EOT
|
||||
@@ -1,125 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
QUERY_STRING=$(echo "${QUERY_STRING}" | sed 's/;//g')
|
||||
function urldecode() { : "${*//+/ }"; echo -e "${_//%/\\x}"; }
|
||||
|
||||
if [ "${QUERY_STRING}" ]; then
|
||||
export IFS="&"
|
||||
for cmd in ${QUERY_STRING}; do
|
||||
if [[ "$cmd" == *"="* ]]; then
|
||||
key=$(echo $cmd | awk -F '=' '{print $1}')
|
||||
value=$(echo $cmd | awk -F '=' '{print $2}')
|
||||
eval $key=$(urldecode $value)
|
||||
fi
|
||||
done
|
||||
fi
|
||||
|
||||
if [ -z "$status" ] || [ -z "$IpDNS" ] || [ -z "$cooldown" ] || [ -z "$failures" ] || [ -z "$action" ]; then
|
||||
response="Missing parameters. Please provide the following parameters: IpDNS, cooldown, failures, action."
|
||||
echo "Content-type: text/plain"
|
||||
echo ""
|
||||
echo "$response"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ "$status" == "enabled" ]; then
|
||||
watch_script="/usrdata/simpleadmin/script/watchat.sh"
|
||||
mount -o remount,rw /
|
||||
|
||||
cat <<EOF > $watch_script
|
||||
#!/bin/bash
|
||||
|
||||
ip_or_dns="$IpDNS"
|
||||
cooldown=$cooldown
|
||||
action="$action"
|
||||
fail_count=0
|
||||
max_failures=$failures
|
||||
|
||||
# Process the action variable.
|
||||
|
||||
# Create a JSON file containing the parameters of the script
|
||||
echo -n '{"ip_or_dns":"$ip_or_dns","cooldown":$cooldown,"action":"$action","fail_count":$fail_count,"max_failures":$max_failures}' > /tmp/watchatParams.json
|
||||
|
||||
|
||||
while true; do
|
||||
if ping -c 1 -W 1 \$ip_or_dns > /dev/null; then
|
||||
fail_count=0
|
||||
echo "Success at \$(date)" >> /tmp/watchat.log
|
||||
# Convert /tmp/watchat.log to json format
|
||||
echo -n '{"log":[' > /tmp/watchat.json
|
||||
cat /tmp/watchat.log | sed 's/$/,/' | tr -d '\n' | sed 's/,$//' >> /tmp/watchat.json
|
||||
echo -n ']}' >> /tmp/watchat.json
|
||||
else
|
||||
((fail_count++))
|
||||
if [ \$fail_count -ge \$max_failures ]; then
|
||||
case "\$action" in
|
||||
reboot)
|
||||
echo "Rebooting system..."
|
||||
/sbin/reboot
|
||||
;;
|
||||
switch_sim)
|
||||
echo "Switching SIM..."
|
||||
echo -ne "AT+CNMI=2,1\r" > /dev/ttyOUT2
|
||||
sleep 1
|
||||
echo "Switching SIM at \$(date)" >> /tmp/watchat.log
|
||||
;;
|
||||
none)
|
||||
echo "No action taken."
|
||||
echo "No action taken at \$(date)" >> /tmp/watchat.log
|
||||
;;
|
||||
*)
|
||||
echo "Unknown action: \$action"
|
||||
;;
|
||||
esac
|
||||
# Reset fail count
|
||||
fail_count=0
|
||||
fi
|
||||
fi
|
||||
echo "Fail count: \$fail_count at \$(date)" >> /tmp/watchat.log
|
||||
# Convert /tmp/watchat.log to json format
|
||||
echo -n '{"log":[' > /tmp/watchat.json
|
||||
cat /tmp/watchat.log | sed 's/$/,/' | tr -d '\n' | sed 's/,$//' >> /tmp/watchat.json
|
||||
echo -n ']}' >> /tmp/watchat.json
|
||||
sleep \$cooldown
|
||||
done
|
||||
EOF
|
||||
|
||||
chmod +x $watch_script
|
||||
|
||||
cat <<EOF > /lib/systemd/system/watchcat.service
|
||||
[Unit]
|
||||
Description=Ping Watcher Service
|
||||
|
||||
[Service]
|
||||
ExecStart=$watch_script
|
||||
Restart=always
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
EOF
|
||||
|
||||
ln -s /lib/systemd/system/watchcat.service /etc/systemd/system/multi-user.target.wants/watchcat.service
|
||||
|
||||
systemctl daemon-reload
|
||||
systemctl start watchcat.service
|
||||
|
||||
response="Script created at $watch_script and made executable. Service created and started."
|
||||
|
||||
elif [ "$status" == "disabled" ]; then
|
||||
watch_script="/usrdata/simpleadmin/script/watchat.sh"
|
||||
rm -f $watch_script
|
||||
|
||||
systemctl stop watchcat.service
|
||||
rm -f /lib/systemd/system/watchcat.service
|
||||
rm -f /etc/systemd/system/multi-user.target.wants/watchcat.service
|
||||
|
||||
systemctl daemon-reload
|
||||
|
||||
response="Script removed at $watch_script. Service stopped and removed."
|
||||
else
|
||||
response="Invalid status. Please provide either enabled or disabled."
|
||||
fi
|
||||
|
||||
echo "Content-type: text/plain"
|
||||
echo ""
|
||||
echo "$response"
|
||||
@@ -1,26 +0,0 @@
|
||||
#!/bin/bash
|
||||
QUERY_STRING=$(echo "${QUERY_STRING}" | sed 's/;//g')
|
||||
function urldecode() { : "${*//+/ }"; echo -e "${_//%/\\x}"; }
|
||||
|
||||
if [ "${QUERY_STRING}" ]; then
|
||||
export IFS="&"
|
||||
for cmd in ${QUERY_STRING}; do
|
||||
if [ "$(echo $cmd | grep '=')" ]; then
|
||||
key=$(echo $cmd | awk -F '=' '{print $1}')
|
||||
value=$(echo $cmd | awk -F '=' '{print $2}')
|
||||
eval $key=$value
|
||||
fi
|
||||
done
|
||||
fi
|
||||
|
||||
x=$(urldecode "$atcmd")
|
||||
MYATCMD=$(printf '%b\n' "${atcmd//%/\\x}")
|
||||
if [ -n "${MYATCMD}" ]; then
|
||||
# Capture the response and remove ANSI color codes using awk
|
||||
runcmd=$(atcmd '$x' | awk '{ gsub(/\x1B\[[0-9;]*[mG]/, "") }1')
|
||||
fi
|
||||
|
||||
echo "Content-type: text/plain"
|
||||
echo $x
|
||||
echo ""
|
||||
echo "$runcmd"
|
||||
@@ -1,72 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Decode URL-encoded strings
|
||||
function urldecode() {
|
||||
local data=${1//+/ }
|
||||
printf '%b' "${data//%/\\x}"
|
||||
}
|
||||
|
||||
# Parse QUERY_STRING
|
||||
QUERY_STRING=$(echo "${QUERY_STRING}" | sed 's/;//g')
|
||||
if [ "${QUERY_STRING}" ]; then
|
||||
export IFS="&"
|
||||
for cmd in ${QUERY_STRING}; do
|
||||
if [[ "$cmd" == *"="* ]]; then
|
||||
key=$(echo $cmd | awk -F '=' '{print $1}')
|
||||
value=$(echo $cmd | awk -F '=' '{print $2}')
|
||||
eval $key=$(urldecode $value)
|
||||
fi
|
||||
done
|
||||
fi
|
||||
|
||||
# Set default values
|
||||
WATCHCAT_ENABLED=${WATCHCAT_ENABLED:-"disable"}
|
||||
TRACK_IP=${TRACK_IP:-"1.1.1.1"}
|
||||
PING_TIMEOUT=${PING_TIMEOUT:-30}
|
||||
PING_FAILURE_COUNT=${PING_FAILURE_COUNT:-3}
|
||||
|
||||
# Validate input
|
||||
if ! [[ "$WATCHCAT_ENABLED" =~ ^(enable|disable)$ ]]; then
|
||||
echo "Content-type: text/plain"
|
||||
echo ""
|
||||
echo "Invalid value for WATCHCAT_ENABLED. Use 'enable' or 'disable'."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if ! [[ "$TRACK_IP" =~ ^([0-9]{1,3}\.){3}[0-9]{1,3}$ ]]; then
|
||||
echo "Content-type: text/plain"
|
||||
echo ""
|
||||
echo "Invalid IP address format for TRACK_IP."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if ! [[ "$PING_TIMEOUT" =~ ^[0-9]+$ ]] || [ "$PING_TIMEOUT" -le 0 ]; then
|
||||
echo "Content-type: text/plain"
|
||||
echo ""
|
||||
echo "PING_TIMEOUT must be a positive integer."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if ! [[ "$PING_FAILURE_COUNT" =~ ^[0-9]+$ ]] || [ "$PING_FAILURE_COUNT" -le 0 ]; then
|
||||
echo "Content-type: text/plain"
|
||||
echo ""
|
||||
echo "PING_FAILURE_COUNT must be a positive integer."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Implement the Watchcat logic
|
||||
if [ "$WATCHCAT_ENABLED" == "enable" ]; then
|
||||
echo "Content-type: text/plain"
|
||||
echo ""
|
||||
echo "Watchcat is enabled. Tracking IP: $TRACK_IP, Ping timeout: $PING_TIMEOUT seconds, Ping failure count: $PING_FAILURE_COUNT"
|
||||
# Call the create script here and use the needed parameters
|
||||
sudo /usrdata/simpleadmin/script/create_watchcat.sh "$TRACK_IP" "$PING_TIMEOUT" "$PING_FAILURE_COUNT"
|
||||
else
|
||||
echo "Content-type: text/plain"
|
||||
echo ""
|
||||
echo "Watchcat is disabled."
|
||||
# Call the remove script here
|
||||
sudo /usrdata/simpleadmin/script/remove_watchcat.sh
|
||||
fi
|
||||
|
||||
exit 0
|
||||
6143
simpleadmin/www/css/all.min.css
vendored
6143
simpleadmin/www/css/all.min.css
vendored
File diff suppressed because it is too large
Load Diff
6
simpleadmin/www/css/bootstrap.min.css
vendored
6
simpleadmin/www/css/bootstrap.min.css
vendored
File diff suppressed because one or more lines are too long
@@ -1,173 +0,0 @@
|
||||
/* import poppins */
|
||||
/* poppins-300 - latin */
|
||||
@font-face {
|
||||
font-display: swap; /* Check https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/font-display for other options. */
|
||||
font-family: 'Poppins';
|
||||
font-style: normal;
|
||||
font-weight: 300;
|
||||
src: url('../fonts/poppins-v23-latin-300.woff2') format('woff2'); /* Chrome 36+, Opera 23+, Firefox 39+, Safari 12+, iOS 10+ */
|
||||
}
|
||||
/* poppins-300italic - latin */
|
||||
@font-face {
|
||||
font-display: swap; /* Check https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/font-display for other options. */
|
||||
font-family: 'Poppins';
|
||||
font-style: italic;
|
||||
font-weight: 300;
|
||||
src: url('../fonts/poppins-v23-latin-300italic.woff2') format('woff2'); /* Chrome 36+, Opera 23+, Firefox 39+, Safari 12+, iOS 10+ */
|
||||
}
|
||||
/* poppins-regular - latin */
|
||||
@font-face {
|
||||
font-display: swap; /* Check https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/font-display for other options. */
|
||||
font-family: 'Poppins';
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
src: url('../fonts/poppins-v23-latin-regular.woff2') format('woff2'); /* Chrome 36+, Opera 23+, Firefox 39+, Safari 12+, iOS 10+ */
|
||||
}
|
||||
/* poppins-italic - latin */
|
||||
@font-face {
|
||||
font-display: swap; /* Check https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/font-display for other options. */
|
||||
font-family: 'Poppins';
|
||||
font-style: italic;
|
||||
font-weight: 400;
|
||||
src: url('../fonts/poppins-v23-latin-italic.woff2') format('woff2'); /* Chrome 36+, Opera 23+, Firefox 39+, Safari 12+, iOS 10+ */
|
||||
}
|
||||
/* poppins-500 - latin */
|
||||
@font-face {
|
||||
font-display: swap; /* Check https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/font-display for other options. */
|
||||
font-family: 'Poppins';
|
||||
font-style: normal;
|
||||
font-weight: 500;
|
||||
src: url('../fonts/poppins-v23-latin-500.woff2') format('woff2'); /* Chrome 36+, Opera 23+, Firefox 39+, Safari 12+, iOS 10+ */
|
||||
}
|
||||
/* poppins-500italic - latin */
|
||||
@font-face {
|
||||
font-display: swap; /* Check https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/font-display for other options. */
|
||||
font-family: 'Poppins';
|
||||
font-style: italic;
|
||||
font-weight: 500;
|
||||
src: url('../fonts/poppins-v23-latin-500italic.woff2') format('woff2'); /* Chrome 36+, Opera 23+, Firefox 39+, Safari 12+, iOS 10+ */
|
||||
}
|
||||
/* poppins-600 - latin */
|
||||
@font-face {
|
||||
font-display: swap; /* Check https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/font-display for other options. */
|
||||
font-family: 'Poppins';
|
||||
font-style: normal;
|
||||
font-weight: 600;
|
||||
src: url('../fonts/poppins-v23-latin-600.woff2') format('woff2'); /* Chrome 36+, Opera 23+, Firefox 39+, Safari 12+, iOS 10+ */
|
||||
}
|
||||
/* poppins-600italic - latin */
|
||||
@font-face {
|
||||
font-display: swap; /* Check https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/font-display for other options. */
|
||||
font-family: 'Poppins';
|
||||
font-style: italic;
|
||||
font-weight: 600;
|
||||
src: url('../fonts/poppins-v23-latin-600italic.woff2') format('woff2'); /* Chrome 36+, Opera 23+, Firefox 39+, Safari 12+, iOS 10+ */
|
||||
}
|
||||
/* poppins-700 - latin */
|
||||
@font-face {
|
||||
font-display: swap; /* Check https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/font-display for other options. */
|
||||
font-family: 'Poppins';
|
||||
font-style: normal;
|
||||
font-weight: 700;
|
||||
src: url('../fonts/poppins-v23-latin-700.woff2') format('woff2'); /* Chrome 36+, Opera 23+, Firefox 39+, Safari 12+, iOS 10+ */
|
||||
}
|
||||
/* poppins-700italic - latin */
|
||||
@font-face {
|
||||
font-display: swap; /* Check https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/font-display for other options. */
|
||||
font-family: 'Poppins';
|
||||
font-style: italic;
|
||||
font-weight: 700;
|
||||
src: url('../fonts/poppins-v23-latin-700italic.woff2') format('woff2'); /* Chrome 36+, Opera 23+, Firefox 39+, Safari 12+, iOS 10+ */
|
||||
}
|
||||
/* import fontawesome icons */
|
||||
@import url("./all.min.css");
|
||||
|
||||
* {
|
||||
font-family: "Poppins", sans-serif;
|
||||
}
|
||||
|
||||
.custom-checkbox .form-check-input {
|
||||
margin-right: 1px;
|
||||
}
|
||||
|
||||
.modal-overlay {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-color: rgba(0, 0, 0, 0.5);
|
||||
z-index: 1000;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.loading-modal {
|
||||
background-color: #fff;
|
||||
padding: 3rem;
|
||||
border-radius: 10px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.loading-text {
|
||||
font-size: 18px;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.loader {
|
||||
width: 64px;
|
||||
height: 64px;
|
||||
border: 3px dotted #000;
|
||||
border-style: solid solid dotted dotted;
|
||||
border-radius: 50%;
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
box-sizing: border-box;
|
||||
animation: rotation 2s linear infinite;
|
||||
margin-bottom: 2rem;
|
||||
}
|
||||
|
||||
.loader::after {
|
||||
content: "";
|
||||
box-sizing: border-box;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
right: 0;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
margin: auto;
|
||||
border: 3px dotted #0b5ed7;
|
||||
border-style: solid solid dotted;
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
border-radius: 50%;
|
||||
animation: rotationBack 1s linear infinite;
|
||||
transform-origin: center center;
|
||||
}
|
||||
|
||||
@keyframes rotation {
|
||||
0% {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
100% {
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
@keyframes rotationBack {
|
||||
0% {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
100% {
|
||||
transform: rotate(-360deg);
|
||||
}
|
||||
}
|
||||
|
||||
.is-warning {
|
||||
background-color: #ffb70f !important;
|
||||
color: #000 !important;
|
||||
}
|
||||
|
||||
.is-medium {
|
||||
font-weight: 600;
|
||||
}
|
||||
@@ -1,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. 2025
|
||||
</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>
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 15 KiB |
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
File diff suppressed because it is too large
Load Diff
7
simpleadmin/www/js/bootstrap.bundle.min.js
vendored
7
simpleadmin/www/js/bootstrap.bundle.min.js
vendored
File diff suppressed because one or more lines are too long
@@ -1,37 +0,0 @@
|
||||
// Function to toggle dark mode
|
||||
const toggleDarkMode = () => {
|
||||
const html = document.querySelector('html');
|
||||
const currentTheme = html.getAttribute('data-bs-theme');
|
||||
|
||||
if (currentTheme === 'dark') {
|
||||
html.removeAttribute('data-bs-theme');
|
||||
darkModeToggle.textContent = '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);
|
||||
@@ -1,37 +0,0 @@
|
||||
const freqNumbersContainer = document.getElementById(
|
||||
"freqNumbersContainer"
|
||||
);
|
||||
|
||||
function generateFreqNumberInputs(num) {
|
||||
let html = "";
|
||||
const maxFields = Math.min(num, 10); // Limit to a maximum of 10 fields
|
||||
for (let i = 1; i <= maxFields; i++) {
|
||||
html += `
|
||||
<div class="input-group mb-3" x-show="cellNum >= ${i} && networkModeCell == 'LTE'">
|
||||
<input
|
||||
type="text"
|
||||
aria-label="EARFCN"
|
||||
placeholder="EARFCN"
|
||||
class="form-control"
|
||||
x-model="earfcn${i}"
|
||||
/>
|
||||
<input
|
||||
type="text"
|
||||
aria-label="PCI"
|
||||
placeholder="PCI"
|
||||
class="form-control"
|
||||
x-model="pci${i}"
|
||||
/>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
return html;
|
||||
}
|
||||
|
||||
document.addEventListener("DOMContentLoaded", function () {
|
||||
const cellNumInput = document.querySelector("[aria-label='NumCells']");
|
||||
cellNumInput.addEventListener("input", function () {
|
||||
const cellNum = parseInt(this.value);
|
||||
freqNumbersContainer.innerHTML = generateFreqNumberInputs(cellNum);
|
||||
});
|
||||
});
|
||||
@@ -1,99 +0,0 @@
|
||||
function parseCurrentSettings(rawdata) {
|
||||
const data = rawdata;
|
||||
|
||||
const lines = data.split("\n");
|
||||
console.log(lines);
|
||||
|
||||
// Remove QUIMSLOT and only take 1 or 2
|
||||
this.sim = lines
|
||||
.find(
|
||||
(line) => line.includes("QUIMSLOT: 1") || line.includes("QUIMSLOT: 2")
|
||||
)
|
||||
.split(":")[1]
|
||||
// remove spaces
|
||||
.replace(/\s/g, "");
|
||||
// .replace(/\"/g, "");
|
||||
|
||||
try {
|
||||
this.apn = lines
|
||||
.find((line) => line.includes("+CGCONTRDP: 1"))
|
||||
.split(",")[2]
|
||||
.replace(/\"/g, "");
|
||||
} catch (error) {
|
||||
this.apn = "Failed fetching APN";
|
||||
}
|
||||
|
||||
this.cellLock4GStatus = lines
|
||||
.find((line) => line.includes('+QNWLOCK: "common/4g"'))
|
||||
.split(",")[1]
|
||||
.replace(/\"/g, "");
|
||||
|
||||
this.cellLock5GStatus = lines
|
||||
.find((line) => line.includes('+QNWLOCK: "common/5g"'))
|
||||
.split(",")[1]
|
||||
.replace(/\"/g, "");
|
||||
|
||||
this.prefNetwork = lines
|
||||
.find((line) => line.includes('+QNWPREFCFG: "mode_pref"'))
|
||||
.split(",")[1]
|
||||
.replace(/\"/g, "");
|
||||
|
||||
this.nrModeControlStatus = lines
|
||||
.find((line) => line.includes('+QNWPREFCFG: "nr5g_disable_mode"'))
|
||||
.split(",")[1]
|
||||
.replace(/\"/g, "");
|
||||
|
||||
this.apnIP = lines
|
||||
.find((line) => line.includes("+CGDCONT: 1"))
|
||||
.split(",")[1]
|
||||
.replace(/\"/g, "");
|
||||
|
||||
try {
|
||||
const PCCbands = lines
|
||||
.find((line) => line.includes('+QCAINFO: "PCC"'))
|
||||
.split(",")[3]
|
||||
.replace(/\"/g, "");
|
||||
|
||||
// Loop over all QCAINFO: "SCC" lines and get the bands
|
||||
try {
|
||||
const SCCbands = lines
|
||||
.filter((line) => line.includes('+QCAINFO: "SCC"'))
|
||||
.map((line) => line.split(",")[3].replace(/\"/g, ""))
|
||||
.join(", ");
|
||||
this.bands = `${PCCbands}, ${SCCbands}`;
|
||||
} catch (error) {
|
||||
this.bands = PCCbands;
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
this.bands = "Failed fetching bands";
|
||||
}
|
||||
|
||||
if (this.cellLock4GStatus == 1 && this.cellLock5GStatus == 1) {
|
||||
this.cellLockStatus = "Locked to 4G and 5G";
|
||||
} else if (this.cellLock4GStatus == 1) {
|
||||
this.cellLockStatus = "Locked to 4G";
|
||||
} else if (this.cellLock5GStatus == 1) {
|
||||
this.cellLockStatus = "Locked to 5G";
|
||||
} else {
|
||||
this.cellLockStatus = "Not Locked";
|
||||
}
|
||||
|
||||
if (this.nrModeControlStatus == 0) {
|
||||
this.nrModeControlStatus = "Not Disabled";
|
||||
} else if (this.nrModeControlStatus == 1) {
|
||||
this.nrModeControlStatus = "SA Disabled";
|
||||
} else {
|
||||
this.nrModeControlStatus = "NSA Disabled";
|
||||
}
|
||||
|
||||
return {
|
||||
sim: sim,
|
||||
apn: apn,
|
||||
apnIP: apnIP,
|
||||
cellLockStatus: cellLockStatus,
|
||||
prefNetwork: prefNetwork,
|
||||
nrModeControl: nrModeControlStatus,
|
||||
bands: bands,
|
||||
};
|
||||
}
|
||||
@@ -1,81 +0,0 @@
|
||||
function populateCheckboxes(lte_band, nsa_nr5g_band, nr5g_band, locked_lte_bands, locked_nsa_bands, locked_sa_bands, cellLock) {
|
||||
var checkboxesForm = document.getElementById("checkboxForm");
|
||||
var selectedMode = document.getElementById("networkModeBand").value;
|
||||
var bands;
|
||||
var prefix;
|
||||
|
||||
// Determine bands and prefix based on selected network mode
|
||||
if (selectedMode === "LTE") {
|
||||
bands = lte_band;
|
||||
prefix = "B";
|
||||
} else if (selectedMode === "NSA") {
|
||||
bands = nsa_nr5g_band;
|
||||
prefix = "N";
|
||||
} else if (selectedMode === "SA") {
|
||||
bands = nr5g_band;
|
||||
prefix = "N";
|
||||
}
|
||||
|
||||
checkboxesForm.innerHTML = ""; // Clear existing checkboxes
|
||||
|
||||
// Store the locked bands in arrays
|
||||
var locked_lte_bands_array = locked_lte_bands.split(":");
|
||||
var locked_nsa_bands_array = locked_nsa_bands.split(":");
|
||||
var locked_sa_bands_array = locked_sa_bands.split(":");
|
||||
|
||||
var isBandLocked = function(band) {
|
||||
if (selectedMode === "LTE" && locked_lte_bands_array.includes(band)) {
|
||||
return true;
|
||||
}
|
||||
if (selectedMode === "NSA" && locked_nsa_bands_array.includes(band)) {
|
||||
return true;
|
||||
}
|
||||
if (selectedMode === "SA" && locked_sa_bands_array.includes(band)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
var fragment = document.createDocumentFragment();
|
||||
|
||||
if (bands !== null && bands !== "0") {
|
||||
var bandsArray = bands.split(":");
|
||||
var currentRow;
|
||||
|
||||
bandsArray.forEach(function(band, index) {
|
||||
if (index % 5 === 0) {
|
||||
currentRow = document.createElement("div");
|
||||
currentRow.className = "row mb-2 mx-auto"; // Add margin bottom for spacing
|
||||
fragment.appendChild(currentRow);
|
||||
}
|
||||
|
||||
var checkboxDiv = document.createElement("div");
|
||||
checkboxDiv.className = "form-check form-check-reverse col-2"; // Each checkbox takes a column
|
||||
var checkboxInput = document.createElement("input");
|
||||
checkboxInput.className = "form-check-input";
|
||||
checkboxInput.type = "checkbox";
|
||||
checkboxInput.id = "inlineCheckbox" + band;
|
||||
checkboxInput.value = band;
|
||||
checkboxInput.autocomplete = "off";
|
||||
checkboxInput.checked = isBandLocked(band);
|
||||
|
||||
var checkboxLabel = document.createElement("label");
|
||||
checkboxLabel.className = "form-check-label";
|
||||
checkboxLabel.htmlFor = "inlineCheckbox" + band;
|
||||
checkboxLabel.innerText = prefix + band;
|
||||
|
||||
checkboxDiv.appendChild(checkboxInput);
|
||||
checkboxDiv.appendChild(checkboxLabel);
|
||||
currentRow.appendChild(checkboxDiv);
|
||||
});
|
||||
} else {
|
||||
// Create a text saying that no bands are available
|
||||
var noBandsText = document.createElement("p");
|
||||
noBandsText.className = "text-center";
|
||||
noBandsText.innerText = "No supported bands available";
|
||||
fragment.appendChild(noBandsText);
|
||||
}
|
||||
|
||||
checkboxesForm.appendChild(fragment);
|
||||
addCheckboxListeners(cellLock);
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,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="sendATCommand()"
|
||||
/>
|
||||
<div id="atCommandInputHelper" class="form-text">
|
||||
Seperate multiple commands with comma (,).
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="d-grid gap-2 d-md-flex justify-content-md-start"
|
||||
>
|
||||
<button
|
||||
class="btn btn-primary me-md-2"
|
||||
type="button"
|
||||
@click="sendATCommand()"
|
||||
:disabled="isLoading"
|
||||
>
|
||||
Submit
|
||||
</button>
|
||||
<button
|
||||
class="btn btn-danger"
|
||||
type="button"
|
||||
@click="clearResponses()"
|
||||
:disabled="isClean"
|
||||
>
|
||||
Clear
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<div class="card">
|
||||
<div class="card-header">One Click Utilities</div>
|
||||
<div class="card-body">
|
||||
<div class="card-text">
|
||||
<div class="table-responsive">
|
||||
<table class="table">
|
||||
<tbody>
|
||||
<tr>
|
||||
<th scope="row">Reboot</th>
|
||||
<td>
|
||||
<button
|
||||
type="submit"
|
||||
class="btn btn-danger"
|
||||
@click="showRebootModal()"
|
||||
:disabled="isLoading"
|
||||
>
|
||||
Reboot
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">Reset AT Commands Settings</th>
|
||||
<td>
|
||||
<button
|
||||
type="submit"
|
||||
class="btn btn-danger"
|
||||
@click="resetATCommands()"
|
||||
:disabled="isLoading"
|
||||
>
|
||||
Reset
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">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>
|
||||
@@ -1,421 +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];
|
||||
// Maximum world wide phone number length is 17 (North Korea), UTF-16BE Hex string comes back at 48+ for US Number, min length is 3.
|
||||
// When 3 digit SMS short code is used the result is a 12 length string (which we then need to check if the sender hex starts with 003 or 002B(+))
|
||||
// This check is probably completley unecessary but I have no data on how the modems behave with different firmware(whether support for CSCS="UCS2" is available).
|
||||
const sender = senderHex.length > 11 && (senderHex.startsWith('002B') || senderHex.startsWith('003')) ? this.convertHexToText(senderHex) : senderHex;
|
||||
const dateStr = match[3].replace(/\+\d{2}$/, "");
|
||||
const date = this.parseCustomDate(dateStr);
|
||||
if (isNaN(date)) {
|
||||
console.error(`Invalid Date: ${dateStr}`);
|
||||
continue;
|
||||
}
|
||||
const startIndex = cmglRegex.lastIndex;
|
||||
const endIndex = data.indexOf("+CMGL:", startIndex) !== -1 ? data.indexOf("+CMGL:", startIndex) : data.length;
|
||||
const messageHex = data.substring(startIndex, endIndex).trim();
|
||||
const message = /^[0-9a-fA-F]+$/.test(messageHex) ? this.convertHexToText(messageHex) : messageHex;
|
||||
if (lastIndex !== null && this.messages[lastIndex].sender === sender && (date - this.messages[lastIndex].date) / 1000 <= 1) {
|
||||
this.messages[lastIndex].text += " " + message;
|
||||
this.messages[lastIndex].indices.push(index);
|
||||
this.dates[lastIndex] = this.formatDate(date);
|
||||
} else {
|
||||
this.messageIndices.push([index]);
|
||||
this.senders.push(sender);
|
||||
this.dates.push(this.formatDate(date));
|
||||
this.messages.push({ text: message, sender: sender, date: date, indices: [index] });
|
||||
lastIndex = this.messages.length - 1;
|
||||
}
|
||||
}
|
||||
while ((match = cscaRegex.exec(data)) !== null) {
|
||||
const serviceCenterHex = match[1];
|
||||
const serviceCenter = this.convertHexToText(serviceCenterHex);
|
||||
this.serviceCenters.push(serviceCenter);
|
||||
}
|
||||
},
|
||||
|
||||
// 将十六进制转换为文本(假设使用 UTF-16BE 编码)
|
||||
convertHexToText(hex) {
|
||||
const bytes = new Uint8Array(hex.match(/.{1,2}/g).map(byte => parseInt(byte, 16)));
|
||||
return new TextDecoder('utf-16be').decode(bytes);
|
||||
},
|
||||
|
||||
// 自定义解析日期函数
|
||||
parseCustomDate(dateStr) {
|
||||
const [datePart, timePart] = dateStr.split(',');
|
||||
const [day, month, year] = datePart.split('/').map(part => parseInt(part, 10));
|
||||
const [hour, minute, second] = timePart.split(':').map(part => parseInt(part, 10));
|
||||
|
||||
// 将日期转换为标准格式的日期对象
|
||||
return new Date(Date.UTC(2000 + year, month - 1, day, hour, minute, second));
|
||||
},
|
||||
|
||||
// 自定义格式化日期函数
|
||||
formatDate(date) {
|
||||
const year = date.getUTCFullYear() - 2000;
|
||||
const month = (date.getUTCMonth() + 1).toString().padStart(2, '0');
|
||||
const day = date.getUTCDate().toString().padStart(2, '0');
|
||||
const hour = date.getUTCHours().toString().padStart(2, '0');
|
||||
const minute = date.getUTCMinutes().toString().padStart(2, '0');
|
||||
const second = date.getUTCSeconds().toString().padStart(2, '0');
|
||||
return `${day}/${month}/${year},${hour}:${minute}:${second}`;
|
||||
},
|
||||
|
||||
// 删除选中的短信
|
||||
deleteSelectedSMS() {
|
||||
if (this.selectedMessages.length === 0) {
|
||||
console.warn("没有选中的短信");
|
||||
return;
|
||||
}
|
||||
if (!this.messageIndices || this.messageIndices.length === 0) {
|
||||
console.error("短信索引未正确初始化或为空");
|
||||
return;
|
||||
}
|
||||
|
||||
// 检查是否全选
|
||||
const isAllSelected = this.selectedMessages.length === this.messages.length;
|
||||
|
||||
if (isAllSelected) {
|
||||
// 如果全选,则调用删除所有短信的方法
|
||||
this.deleteAllSMS();
|
||||
} else {
|
||||
// 否则,删除选中的短信
|
||||
const indicesToDelete = [];
|
||||
this.selectedMessages.forEach(index => {
|
||||
indicesToDelete.push(...this.messages[index].indices);
|
||||
});
|
||||
if (indicesToDelete.length === 0) {
|
||||
console.warn("没有有效的短信索引");
|
||||
return;
|
||||
}
|
||||
|
||||
// 拼接 AT 命令
|
||||
const atCommands = indicesToDelete.map((index, i) => i === 0 ? `AT+CMGD=${index}` : `+CMGD=${index}`).join(';');
|
||||
fetch(`/cgi-bin/get_atcommand?${new URLSearchParams({ atcmd: atCommands })}`)
|
||||
.finally(() => {
|
||||
this.selectedMessages = [];
|
||||
this.requestSMS();
|
||||
});
|
||||
}
|
||||
},
|
||||
// 删除所有短信
|
||||
deleteAllSMS() {
|
||||
fetch(`/cgi-bin/get_atcommand?${new URLSearchParams({ atcmd: "AT+CMGD=,4" })}`)
|
||||
.finally(() => {
|
||||
this.init();
|
||||
});
|
||||
},
|
||||
// 发送短信
|
||||
encodeUCS2(input) {
|
||||
let output = '';
|
||||
for (let i = 0; i < input.length; i++) {
|
||||
const hex = input.charCodeAt(i).toString(16).toUpperCase().padStart(4, '0');
|
||||
output += hex;
|
||||
}
|
||||
return output;
|
||||
},
|
||||
|
||||
async sendSMS() {
|
||||
let phoneNumberWithCountryCode;
|
||||
if (this.phoneNumber.length < 11) {
|
||||
phoneNumberWithCountryCode = this.phoneNumber;
|
||||
} else {
|
||||
const serviceCenterPrefix = this.serviceCenters[0].substring(0, 3);
|
||||
phoneNumberWithCountryCode = `${serviceCenterPrefix}${this.phoneNumber}`;
|
||||
}
|
||||
const encodedPhoneNumber = this.encodeUCS2(phoneNumberWithCountryCode);
|
||||
const messageSegments = this.splitMessage(this.messageToSend, 70); // 将消息分段
|
||||
const uid = Math.floor(Math.random() * 256); // 生成随机的UID
|
||||
const totalSegments = messageSegments.length;
|
||||
let allSegmentsSent = true;
|
||||
let errorCode = null;
|
||||
for (let i = 0; i < totalSegments; i++) {
|
||||
const segment = messageSegments[i];
|
||||
const encodedMessage = this.encodeUCS2(segment);
|
||||
const currentSegment = i + 1;
|
||||
const Command = `${uid},${currentSegment},${totalSegments}`;
|
||||
const params = new URLSearchParams({
|
||||
number: encodedPhoneNumber,
|
||||
msg: encodedMessage,
|
||||
Command: Command
|
||||
});
|
||||
try {
|
||||
const response = await fetch(`/cgi-bin/send_sms?${params.toString()}`);
|
||||
const data = await response.text();
|
||||
console.log("Response from server:", data);
|
||||
|
||||
// 检查返回的数据中是否包含 '+CMS ERROR'
|
||||
if (data.includes('+CMS ERROR')) {
|
||||
errorCode = data.match(/\+CMS ERROR: (\d+)/)?.[1];
|
||||
console.error("SMS send error:", data);
|
||||
allSegmentsSent = false;
|
||||
break; // 停止发送剩余的段
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Fetch error:", error);
|
||||
allSegmentsSent = false;
|
||||
break; // 停止发送剩余的段
|
||||
}
|
||||
}
|
||||
if (allSegmentsSent) {
|
||||
this.showNotification("SMS sent successfully!");
|
||||
} else {
|
||||
this.showNotification(`SMS sending failed!: ${errorCode}`);
|
||||
}
|
||||
},
|
||||
|
||||
splitMessage(message, length) {
|
||||
const segments = [];
|
||||
for (let i = 0; i < message.length; i += length) {
|
||||
segments.push(message.substring(i, i + length));
|
||||
}
|
||||
return segments;
|
||||
},
|
||||
|
||||
showNotification(message, type) {
|
||||
const notification = document.getElementById('notification');
|
||||
notification.innerText = message;
|
||||
notification.className = `alert alert-${type}`;
|
||||
notification.style.display = 'block';
|
||||
setTimeout(() => {
|
||||
notification.style.display = 'none';
|
||||
}, 3000); // 3秒后自动关闭
|
||||
},
|
||||
|
||||
// 初始化
|
||||
// Initialize
|
||||
init() {
|
||||
this.clearData();
|
||||
this.requestSMS();
|
||||
},
|
||||
|
||||
// 全选/取消全选
|
||||
// Select all/deselect all
|
||||
toggleAll(event) {
|
||||
this.selectedMessages = event.target.checked ? this.messages.map((_, index) => index) : [];
|
||||
}
|
||||
};
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
@@ -1,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>
|
||||
@@ -1,351 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en" data-bs-theme="light">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<title>Simple Admin</title>
|
||||
<!-- <link
|
||||
href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css"
|
||||
rel="stylesheet"
|
||||
integrity="sha384-QWTKZyjpPEjISv5WaRU9OFeRpok6YctnYmDr5pNlyT2bRjXh0JMhjY6hW+ALEwIH"
|
||||
crossorigin="anonymous"
|
||||
/> -->
|
||||
<!-- Import all the bootstrap css files from css folder -->
|
||||
<link rel="stylesheet" href="css/styles.css" />
|
||||
<link rel="stylesheet" href="css/bootstrap.min.css" />
|
||||
|
||||
<!-- Logo -->
|
||||
<link rel="simpleadmin-logo" href="favicon.ico" />
|
||||
|
||||
<!-- Import BootStrap Javascript -->
|
||||
<script src="js/bootstrap.bundle.min.js"></script>
|
||||
<script src="js/alpinejs.min.js" defer></script>
|
||||
|
||||
<style>
|
||||
.form-switch .form-check-input {
|
||||
width: 2.4em;
|
||||
height: 1.2em;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<main>
|
||||
<div class="container my-4" x-data="simpleWatchCat()">
|
||||
<nav class="navbar navbar-expand-lg mt-2">
|
||||
<div class="container-fluid">
|
||||
<a class="navbar-brand" href="/"
|
||||
><span class="mb-0 h4">Simple Admin</span></a
|
||||
>
|
||||
<button
|
||||
class="navbar-toggler"
|
||||
type="button"
|
||||
data-bs-toggle="collapse"
|
||||
data-bs-target="#navbarText"
|
||||
aria-controls="navbarText"
|
||||
aria-expanded="false"
|
||||
aria-label="Toggle navigation"
|
||||
>
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
<div class="collapse navbar-collapse" id="navbarText">
|
||||
<ul class="navbar-nav me-auto mb-2 ml-4 mb-lg-0">
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="/">Home</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="/network.html">Simple Network</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a
|
||||
class="nav-link active"
|
||||
href="/settings.html"
|
||||
aria-current="page"
|
||||
>Simple Settings</a
|
||||
>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="/sms.html">SMS</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="/console">Console</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="/deviceinfo.html"
|
||||
>Device Information</a
|
||||
>
|
||||
</li>
|
||||
</ul>
|
||||
<span class="navbar-text">
|
||||
<button class="btn btn-link text-reset" id="darkModeToggle">
|
||||
Dark Mode
|
||||
</button>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
<div class="row mt-3 mb-4">
|
||||
<div class="col">
|
||||
<div class="card">
|
||||
<div class="card-header">Simple Watchcat</div>
|
||||
<div class="card-body">
|
||||
<div class="card-text">
|
||||
<div class="row mt-3 mb-5 align-content-center mx-4">
|
||||
<div class="col">
|
||||
<div class="mt-3">
|
||||
<label> Enable Watchcat </label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-5">
|
||||
<div class="mt-2">
|
||||
<div class="form-check form-switch form-switch-lg">
|
||||
<input
|
||||
class="form-check-input"
|
||||
type="checkbox"
|
||||
role="switch"
|
||||
id="watchCatSwitch"
|
||||
x-model="watchCatStatus"
|
||||
:disabled="!isFormComplete"
|
||||
x:onchange="setWatchCatSettings"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row mt-3 mb-3 align-items-center mx-4">
|
||||
<div class="col">
|
||||
<div class="mt-3 mb-4">
|
||||
<label> Track IP </label>
|
||||
</div>
|
||||
|
||||
<div class="mt-3 mb-4">
|
||||
<label> Ping Request Timeout </label>
|
||||
</div>
|
||||
|
||||
<div class="mt-3 mb-4">
|
||||
<label> Ping Failure Amount </label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-5">
|
||||
<div class="mt-3 mb-4">
|
||||
<select
|
||||
class="form-select"
|
||||
aria-label="Select Site to Ping"
|
||||
x-model="trackIP"
|
||||
>
|
||||
<option selected>Select IP</option>
|
||||
<option value="1.1.1.1">1.1.1.1</option>
|
||||
<option value="8.8.8.8">8.8.8.8</option>
|
||||
<option value="9.9.9.9">9.9.9.9</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="mt-3 mb-4">
|
||||
<input
|
||||
type="number"
|
||||
class="form-control"
|
||||
aria-label="Ping Timeout"
|
||||
aria-describedby="inputGroup-sizing-default"
|
||||
placeholder="Enter Ping Timeout in Seconds."
|
||||
x-model="pingTimeout"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="mt-3 mb-4">
|
||||
<input
|
||||
type="number"
|
||||
class="form-control"
|
||||
aria-label="Sizing example input"
|
||||
aria-describedby="inputGroup-sizing-default"
|
||||
placeholder="Enter Ping Failure Amount."
|
||||
x-model="pingFailureCount"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- <div class="row mt-3 mb-5 align-content-center mx-4">
|
||||
<div class="col">
|
||||
<div class="mt-3">
|
||||
<label>Sim Auto Switch</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-5">
|
||||
<div class="mt-2">
|
||||
<div class="form-check form-switch form-switch-lg">
|
||||
<input
|
||||
class="form-check-input"
|
||||
type="checkbox"
|
||||
role="switch"
|
||||
id="simAutoSwitch"
|
||||
x-model="simAutoSwitchStatus"
|
||||
disabled
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div> -->
|
||||
|
||||
<!-- <div class="row mt-3 mb-3 align-items-center mx-4">
|
||||
<div class="col">
|
||||
<div class="mt-3 mb-4">
|
||||
<label> Select Preferred SIM </label>
|
||||
</div>
|
||||
|
||||
<div class="mt-3 mb-4">
|
||||
<label> SIM 1 APN </label>
|
||||
</div>
|
||||
|
||||
<div class="mt-3 mb-4">
|
||||
<label> SIM 2 APN </label>
|
||||
</div>
|
||||
|
||||
<div class="mt-3 mb-4">
|
||||
<label> Failover Interval </label>
|
||||
</div>
|
||||
|
||||
<div class="mt-3 mb-4">
|
||||
<label> Scheduled SIM Hot Swap</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-5">
|
||||
<div class="mt-3 mb-3">
|
||||
<select
|
||||
class="form-select"
|
||||
aria-label="Select Sim"
|
||||
x-model="preferredSim"
|
||||
>
|
||||
<option selected>Select SIM</option>
|
||||
<option value="1">SIM 1</option>
|
||||
<option value="2">SIM 2</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="mt-3 mb-3">
|
||||
<input
|
||||
type="number"
|
||||
class="form-control"
|
||||
aria-label="SIM 1 APN"
|
||||
aria-describedby="inputGroup-sizing-default"
|
||||
placeholder="Input APN for SIM 1. (Optional)"
|
||||
x-model="sim1APN"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="mt-3 mb-3">
|
||||
<input
|
||||
type="number"
|
||||
class="form-control"
|
||||
aria-label="SIM 2 APN"
|
||||
aria-describedby="inputGroup-sizing-default"
|
||||
placeholder="Input APN for SIM 2. (Optional)"
|
||||
x-model="sim2APN"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="mt-3 mb-3 d-flex align-items-center">
|
||||
<select
|
||||
class="form-select"
|
||||
aria-label="Failover Interval"
|
||||
>
|
||||
<option selected>Failover Interval</option>
|
||||
<option value="5">5</option>
|
||||
<option value="10">10</option>
|
||||
<option value="15">15</option>
|
||||
<option value="20">20</option>
|
||||
</select>
|
||||
<label class="mx-3">Minutes</label>
|
||||
</div>
|
||||
|
||||
<div class="mt-3 mb-3">
|
||||
<input
|
||||
type="time"
|
||||
class="form-control"
|
||||
aria-label="Scheduled SIM Hot Swap"
|
||||
aria-describedby="inputGroup-sizing-default"
|
||||
x-model="scheduledSIMHotSwap"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div> -->
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-footer">
|
||||
<!-- Setting a low ping timeout and ping failure count may cause
|
||||
intermittent disconnections due to high sensitivity. <br />
|
||||
Select appropriate values for both based on your needs.<br /> -->
|
||||
Still under development. Coming soon...
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mt-3 mb-3">
|
||||
<div class="col">
|
||||
<div class="card">
|
||||
<div class="card-header">Simple Watchcat Logs</div>
|
||||
<div class="card-body">
|
||||
<div class="card-text">
|
||||
<div class="form-floating">
|
||||
<textarea
|
||||
class="form-control"
|
||||
placeholder="Leave a comment here"
|
||||
id="floatingTextarea2"
|
||||
style="height: 100px"
|
||||
x-text="response"
|
||||
readonly
|
||||
></textarea>
|
||||
<label for="floatingTextarea2">Logs Here</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
<script src="js/dark-mode.js"></script>
|
||||
<script>
|
||||
function simpleWatchCat() {
|
||||
return {
|
||||
watchCatStatus: false,
|
||||
trackIP: "",
|
||||
pingTimeout: "",
|
||||
pingFailureCount: "",
|
||||
response: "",
|
||||
|
||||
setWatchCatSettings() {
|
||||
fetch(
|
||||
"/cgi-bin/watchcat_maker?" +
|
||||
new URLSearchParams({
|
||||
WATCHCAT_ENABLED: this.watchCatStatus,
|
||||
TRACK_IP: this.trackIP,
|
||||
PING_TIMEOUT: this.pingTimeout,
|
||||
PING_FAILURE_COUNT: this.pingFailureCount,
|
||||
})
|
||||
)
|
||||
.then((response) => response.text()) // Convert response to text
|
||||
.then((data) => {
|
||||
this.response = data; // Store the response data
|
||||
console.log(data); // Log the response for debugging
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error("Error:", error); // Handle any errors
|
||||
this.response = "An error occurred.";
|
||||
});
|
||||
},
|
||||
|
||||
// Computed property to check if the form is complete
|
||||
get isFormComplete() {
|
||||
return (
|
||||
this.trackIP !== "" &&
|
||||
this.pingTimeout !== "" &&
|
||||
this.pingFailureCount !== ""
|
||||
);
|
||||
},
|
||||
};
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1 +0,0 @@
|
||||
2
|
||||
@@ -1 +0,0 @@
|
||||
2
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user