30 Commits

Author SHA1 Message Date
Cameron Thompson
0d962f3130 Merge pull request #171 from 1alessandro1/patch-3
fix typo
2025-06-01 13:34:22 -04:00
1alessandro1
6bf2d640c3 fix typo 2025-06-01 08:58:26 +02:00
Cameron Thompson
1d91aebcc8 Update README.md 2025-05-14 21:28:19 -04:00
Cameron Thompson
0b1f3b22d8 Update Branch name 2024-11-08 18:52:35 -08:00
Cameron Thompson
7ed145d7bc Archive Simpleadmin 1.0 2024-10-30 03:22:39 +00:00
Cameron Thompson
74d7d3f3ef Reduce README to skeleton
Temporary redirection readme
More to come
2024-10-30 03:17:45 +00:00
Cameron Thompson
3962c5cf5a Hot fix: Broken download link for bandlock.html 2024-05-10 16:17:04 -04:00
Cameron Thompson
67a9ddfff8 Update RMxxx_rgmii_toolkit.sh 2024-04-13 13:08:56 -04:00
Cameron Thompson
84439e332e Fixed entware not being fully installed
-Login binary takeover will now happen when installing entware
-You can set your password at this point as well
2024-04-12 23:51:00 -04:00
Cameron Thompson
4446e6287e Update RMxxx_rgmii_toolkit.sh
Disable dev branch install for now
2024-04-12 09:43:47 -04:00
Cameron Thompson
0f7f5a258c Update ttl.html
fix nav
2024-04-12 09:40:49 -04:00
Cameron Thompson
766e6c5457 Update speedtest.html
fix nav
2024-04-12 09:39:53 -04:00
Cameron Thompson
5546c9e3ac Update index.html
fix nav
2024-04-12 09:39:28 -04:00
Cameron Thompson
2fa9596106 Update bandlock.html
fix nav
2024-04-12 09:38:47 -04:00
Cameron Thompson
cadd1fbb8b Update atcommander.html
Fix Nav
2024-04-12 09:38:05 -04:00
Cameron Thompson
d18e3be937 Re-add useful AT commands section for now 2024-04-03 21:05:08 -04:00
Cameron Thompson
47dded4538 Update README.md 2024-03-31 03:01:12 -04:00
Cameron Thompson
9ac6bdf597 Update bandlock.html 2024-03-31 02:31:32 -04:00
Cameron Thompson
16bb998c72 Updated to install the new bandlock.html 2024-03-31 02:28:33 -04:00
Cameron Thompson
20e2aca705 Major Toolkit Update
New: simple settings for band locking, cell locking, and other settable settings.

New: Tailscale and ttyd now get the binaries directly from their sources

Updated: tailscale and ttyd versions

Updated: simpleadmin is now installed by downloading each file individually and directly to the spot it needs to be in

Removed: TTL Only and No at commands versions of simpleadmin. If anyone needs this please open an issue.
2024-03-31 01:50:44 -04:00
Cameron Thompson
de74eecd77 Update ttyd source to 1.75
https://github.com/tsl0922/ttyd/releases/tag/1.7.5
2024-03-28 00:18:27 -04:00
iamromulan
c01c9e88e0 Sync stable Changes with development
-NSA and SA stats now show correctly
-Entware is now considered out of BETA
-ttyd installation process improved
-Added install option for speedtest and fast CLI commands

Co-Authored-By: Russel Yasol <73575327+dr-dolomite@users.noreply.github.com>
2024-03-26 01:57:29 -04:00
Cameron Thompson
36e3ff1da3 Fixed TTYd not starting at boot 2024-03-19 20:01:53 -07:00
iamromulan
dea33f9ad9 Sync changes with development
Co-Authored-By: Russel Yasol <73575327+dr-dolomite@users.noreply.github.com>
2024-03-18 00:02:30 -04:00
Cameron Thompson
f44eba7d4d Update README.md 2024-03-17 22:05:09 -04:00
Cameron Thompson
0669bfc693 Update README.md 2024-03-17 22:04:00 -04:00
Cameron Thompson
898482b80f Update main README.md 2024-03-17 21:54:34 -04:00
Cameron Thompson
3ee103c3dd Update README.md
Fix spacing issue
2024-03-17 21:32:06 -04:00
Cameron Thompson
0231ac55b2 Merge pull request #11 from tarunVreddy/patch-1
Fixed SA band aggregation
2024-03-17 13:09:38 -04:00
Tarun Reddy
977cd261bc Fixed SA band aggregation
Parsing failed with more than one band used in SA mode. This does not allow for more than 3 bands in NSA or 2 bands in SA. Relevant for better towers and better rm521 modems.
2024-03-17 07:19:46 -06:00
50 changed files with 2015 additions and 546 deletions

178
README.md
View File

@@ -1,147 +1,61 @@
# RGMII Toolkit
Software deployment Toolkit for Quectel RM5xxx series 5G modems utilizing an m.2 to RJ45 adapter (RGMII)
#### [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
# Quectel Application Processor Repository (repo to be renamed soon)
Current Branch: **Main**
# 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.
**My goal** is for this to also include any new useful scripts or software for this modem and others that support RGMII mode.
## Screenshots
# Branches
![Home Page](https://github.com/iamromulan/quectel-rgmii-configuration-notes/blob/main/images/iamromulansimpleindex.png?raw=true)
![AT Commands](https://github.com/iamromulan/quectel-rgmii-configuration-notes/blob/main/images/iamromulanatcommands.png?raw=true)
![TTL](https://github.com/iamromulan/quectel-rgmii-configuration-notes/blob/main/images/iamromulansimpleTTL.png?raw=true)
![Toolkit](https://github.com/iamromulan/quectel-rgmii-configuration-notes/blob/main/images/iamromulantoolkit.png?raw=true)
## 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
## 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 /
```
## Development/Testing/Unstable
**Or, if you want to stay in the modems shell when you are done**
> :bulb: Open pull requests pointed to these branches.
```
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:**
![Toolkit](https://github.com/iamromulan/quectel-rgmii-configuration-notes/blob/main/images/iamromulantoolkit.png?raw=true)
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.
## Tailscale Installation and Config
- [SDXLEMUR and SDXPRAIRIE platforms (QTI Linux system armv7 32-bit)](https://github.com/iamromulan/quectel-rgmii-toolkit/tree/development-SDXLEMUR)
> :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
- [SDXPINN platform OpenWRT system armv8-A 64-bit](https://github.com/iamromulan/quectel-rgmii-toolkit/tree/development-SDXPINN)
![Toolkit](https://github.com/iamromulan/quectel-rgmii-configuration-notes/blob/main/images/tailscalemenu.png?raw=true)
## Temporary/Experimental/Overhaul branches
**Press 1, wait for it to install. This is a very large file for the system so give it some time.**
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.
**Once done and it says Tailscale installed successfully press 2/enter to configure it.**
- [OVERHAUL: SDXLEMUR and SDXPRAIRIE platforms (QTI Linux system armv7 32-bit)](https://github.com/iamromulan/quectel-rgmii-toolkit/tree/overhaul-SDXLEMUR)
![Toolkit](https://github.com/iamromulan/quectel-rgmii-configuration-notes/blob/main/images/tailscaleconfig.png?raw=true)
If you want to, enable the Tailscale Web UI on port 8088 for configuration from the browser later by **pressing 1/enter**.
To do it in the toolkit:
First time connecting you'll be given a link to login with
- Press 3 to just connect only.
- Press 4 to connect and enable SSH access (remote command line) over tailscale.
- Press 5 to reconnect with SSH off while connected with SSH on
- Press 6 to disconnect
- Press 7 to Logout
That's it! From another device running tailscale you should be able to access your modem through the IP assigned to it by your tailnet. To access SSH from another device on the tailnet, open a terminal/command prompt and type
tailscale ssh root@(IP or Hostname)
IP or Hostname being the IP or hostname assigned to it in your tailnet
- Note that your SSH client must be able to give you a link to sign in with upon connecting. That's how the session is authorized. Works fine in Windows CMD or on Android use JuiceSSH.
## Advanced/Beta
### Entware/OPKG installation
- 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!
### 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)

View 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
![Toolkit](https://github.com/iamromulan/quectel-rgmii-configuration-notes/blob/main/images/iamromulantoolkit.png?raw=true)
![Home Page](https://github.com/iamromulan/quectel-rgmii-configuration-notes/blob/main/images/iamromulansimpleindex.png?raw=true)
![AT Commands](https://github.com/iamromulan/quectel-rgmii-configuration-notes/blob/main/images/iamromulanatcommands.png?raw=true)
![AT Commands](https://github.com/iamromulan/quectel-rgmii-configuration-notes/blob/main/images/iamromulansimplenetwork.png?raw=true)
![TTL](https://github.com/iamromulan/quectel-rgmii-configuration-notes/blob/main/images/iamromulansimpleTTL.png?raw=true)
![TTL](https://github.com/iamromulan/quectel-rgmii-configuration-notes/blob/main/images/iamromulanspeedtest.png?raw=true)
## 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:**
![Toolkit](https://github.com/iamromulan/quectel-rgmii-configuration-notes/blob/main/images/iamromulantoolkit.png?raw=true)
## Tailscale Installation and Config
> :warning: Your modem must already be connected to the internet for this to install
### Installation:
Open up the toolkit main menu and **press 4** to enter the Tailscale menu
![Toolkit](https://github.com/iamromulan/quectel-rgmii-configuration-notes/blob/main/images/tailscalemenu.png?raw=true)
**Press 1, wait for it to install. This is a very large file for the system so give it some time.**
**Once done and it says Tailscale installed successfully press 2/enter to configure it.**
![Toolkit](https://github.com/iamromulan/quectel-rgmii-configuration-notes/blob/main/images/tailscaleconfig.png?raw=true)
If you want to, enable the Tailscale Web UI on port 8088 for configuration from the browser later by **pressing 1/enter**.
To do it in the toolkit:
First time connecting you'll be given a link to login with
- Press 3 to just connect only.
- Press 4 to connect and enable SSH access (remote command line) over tailscale.
- Press 5 to reconnect with SSH off while connected with SSH on
- Press 6 to disconnect
- Press 7 to Logout
That's it! From another device running tailscale you should be able to access your modem through the IP assigned to it by your tailnet. To access SSH from another device on the tailnet, open a terminal/command prompt and type
tailscale ssh root@(IP or Hostname)
IP or Hostname being the IP or hostname assigned to it in your tailnet
- Note that your SSH client must be able to give you a link to sign in with upon connecting. That's how the session is authorized. Works fine in Windows CMD or on Android use JuiceSSH.
### 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)

View File

@@ -11,12 +11,6 @@ SIMPLE_ADMIN_DIR="/usrdata/simpleadmin"
SIMPLE_FIREWALL_DIR="/usrdata/simplefirewall"
SIMPLE_FIREWALL_SCRIPT="$SIMPLE_FIREWALL_DIR/simplefirewall.sh"
SIMPLE_FIREWALL_SYSTEMD_DIR="$SIMPLE_FIREWALL_DIR/systemd"
SIMPLE_FIREWALL_SERVICE="/lib/systemd/system/simplefirewall.service"
GITHUB_URL="https://github.com/$GITUSER/quectel-rgmii-toolkit/archive/refs/heads/$GITTREE.zip"
GITHUB_SIMPADMIN_FULL_URL="https://github.com/$GITUSER/quectel-rgmii-toolkit/archive/refs/heads/simpleadminfull.zip"
GITHUB_SIMPADMIN_NOCMD_URL="https://github.com/$GITUSER/quectel-rgmii-toolkit/archive/refs/heads/simpleadminnoatcmds.zip"
GITHUB_SIMPADMIN_TTL_URL="https://github.com/$GITUSER/quectel-rgmii-toolkit/archive/refs/heads/simpleadminttlonly.zip"
GITHUB_SIMPADMIN_TEST_URL="https://github.com/$GITUSER/quectel-rgmii-toolkit/archive/refs/heads/simpleadmintest.zip"
TAILSCALE_DIR="/usrdata/tailscale/"
TAILSCALE_SYSD_DIR="/usrdata/tailscale/systemd"
# AT Command Script Variables and Functions
@@ -103,6 +97,70 @@ send_at_commands() {
fi
}
ensure_entware_installed() {
remount_rw
if [ ! -f "/opt/bin/opkg" ]; then
echo -e "\e[1;32mInstalling Entware/OPKG\e[0m"
cd /tmp && wget -O installentware.sh "https://raw.githubusercontent.com/$GITUSER/quectel-rgmii-toolkit/$GITTREE/installentware.sh" && chmod +x installentware.sh && ./installentware.sh
if [ "$?" -ne 0 ]; then
echo -e "\e[1;31mEntware/OPKG installation failed. Please check your internet connection or the repository URL.\e[0m"
exit 1
fi
cd /
else
echo -e "\e[1;32mEntware/OPKG is already installed.\e[0m"
if [ "$(readlink /bin/login)" != "/opt/bin/login" ]; then
opkg update && opkg install shadow-login shadow-passwd shadow-useradd
if [ "$?" -ne 0 ]; then
echo -e "\e[1;31mPackage installation failed. Please check your internet connection and try again.\e[0m"
exit 1
fi
# Replace the login and passwd binaries and set home for root to a writable directory
rm /opt/etc/shadow
rm /opt/etc/passwd
cp /etc/shadow /opt/etc/
cp /etc/passwd /opt/etc
mkdir -p /usrdata/root/bin
touch /usrdata/root/.profile
echo "# Set PATH for all shells" > /usrdata/root/.profile
echo "export PATH=/bin:/usr/sbin:/usr/bin:/sbin:/opt/sbin:/opt/bin:/usrdata/root/bin" >> /usrdata/root/.profile
chmod +x /usrdata/root/.profile
sed -i '1s|/home/root:/bin/sh|/usrdata/root:/bin/bash|' /opt/etc/passwd
rm /bin/login /usr/bin/passwd
ln -sf /opt/bin/login /bin
ln -sf /opt/bin/passwd /usr/bin/
ln -sf /opt/bin/useradd /usr/bin/
echo -e "\e[1;31mPlease set the root password.\e[0m"
/usr/bin/passwd
# Install basic and useful utilities
opkg install mc htop dfc lsof
ln -sf /opt/bin/mc /bin
ln -sf /opt/bin/htop /bin
ln -sf /opt/bin/dfc /bin
ln -sf /opt/bin/lsof /bin
fi
if [ ! -f "/usrdata/root/.profile" ]; then
opkg update && opkg install shadow-useradd
mkdir -p /usrdata/root/bin
touch /usrdata/root/.profile
echo "# Set PATH for all shells" > /usrdata/root/.profile
echo "export PATH=/bin:/usr/sbin:/usr/bin:/sbin:/opt/sbin:/opt/bin:/usrdata/root/bin" >> /usrdata/root/.profile
chmod +x /usrdata/root/.profile
sed -i '1s|/home/root:/bin/sh|/usrdata/root:/bin/bash|' /opt/etc/passwd
fi
fi
if [ ! -f "/opt/sbin/useradd" ]; then
echo "useradd does not exist. Installing shadow-useradd..."
opkg install shadow-useradd
else
echo "useradd already exists. Continuing..."
fi
}
# Check if Simple Admin is installed
is_simple_admin_installed() {
[ -d "$SIMPLE_ADMIN_DIR" ] && return 0 || return 1
@@ -310,97 +368,77 @@ configure_simple_firewall() {
install_simple_admin() {
while true; do
echo -e "\e[1;32mWhat version of Simple Admin do you want to install? This will start a webserver on port 8080\e[0m"
echo -e "\e[1;32m1) Full Install\e[0m"
echo -e "\e[1;34m2) No AT Commands, List only\e[0m"
echo -e "\e[1;33m3) TTL Only\e[0m"
echo -e "\e[1;31m4) Install Test Build (work in progress/not ready yet)\e[0m"
echo -e "\e[0;33m5) Return to Main Menu\e[0m"
echo -e "\e[1;32m1) Stable current version, (Main Branch)\e[0m"
echo -e "\e[1;31m2) Install Test Build (Development Branch)\e[0m"
echo -e "\e[0;33m3) Return to Main Menu\e[0m"
echo -e "\e[1;32mSelect your choice: \e[0m"
read choice
case $choice in
1)
install_update_at_socat
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
cd $TMP_DIR
wget $GITHUB_SIMPADMIN_FULL_URL -O simpleadminfull.zip
unzip -o simpleadminfull.zip
cp -Rf quectel-rgmii-toolkit-simpleadminfull/simpleadmin/ $USRDATA_DIR
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 "Cleaning up..."
rm /tmp/simpleadminfull.zip
rm -rf /tmp/quectel-rgmii-toolkit-simpleadminfull/
echo -e "\e[1;32msimpleadmin has been installed and is now ready for use!\e[0m"
break
;;
2)
install_update_at_socat
install_simple_firewall
remount_rw
cd $TMP_DIR
wget $GITHUB_SIMPADMIN_NOCMD_URL -O simpleadminnoatcmds.zip
unzip -o simpleadminnoatcmds.zip
cp -Rf quectel-rgmii-toolkit-simpleadminnoatcmds/simpleadmin/ $USRDATA_DIR
chmod +x $SIMPLE_ADMIN_DIR/scripts/*
chmod +x $SIMPLE_ADMIN_DIR/www/cgi-bin/*
cp -rf $SIMPLE_ADMIN_DIR/systemd/* /lib/systemd/system
systemctl daemon-reload
ln -sf /lib/systemd/system/simpleadmin_httpd.service /lib/systemd/system/multi-user.target.wants/
ln -sf /lib/systemd/system/simpleadmin_generate_status.service /lib/systemd/system/multi-user.target.wants/
systemctl start simpleadmin_generate_status
systemctl start simpleadmin_httpd
remount_ro
echo "Cleaning up..."
rm /tmp/simpleadminnoatcmds.zip
rm -rf /tmp/quectel-rgmii-toolkit-simpleadminnoatcmds/
break
echo -e "\e[1;31m2) Development Branch is currently not ready. Major updates coming soon!!\e[0m"
;;
3)
install_simple_firewall
remount_rw
cd $TMP_DIR
wget $GITHUB_SIMPADMIN_TTL_URL -O simpleadminttlonly.zip
unzip -o simpleadminttlonly.zip
cp -Rf quectel-rgmii-toolkit-simpleadminttlonly/simpleadmin/ $USRDATA_DIR
chmod +x $SIMPLE_ADMIN_DIR/www/cgi-bin/*
cp -rf $SIMPLE_ADMIN_DIR/systemd/* /lib/systemd/system
systemctl daemon-reload
ln -sf /lib/systemd/system/simpleadmin_httpd.service /lib/systemd/system/multi-user.target.wants/
systemctl start simpleadmin_httpd
remount_ro
echo "Cleaning up..."
rm /tmp/simpleadminttlonly.zip
rm -rf /tmp/quectel-rgmii-toolkit-simpleadminttlonly/
break
;;
4)
install_update_at_socat
install_simple_firewall
remount_rw
cd $TMP_DIR
wget $GITHUB_SIMPADMIN_TEST_URL -O simpleadmintest.zip
unzip -o simpleadmintest.zip
cp -Rf quectel-rgmii-toolkit-simpleadmintest/simpleadmin/ $USRDATA_DIR
chmod +x $SIMPLE_ADMIN_DIR/scripts/*
chmod +x $SIMPLE_ADMIN_DIR/www/cgi-bin/*
cp -rf $SIMPLE_ADMIN_DIR/systemd/* /lib/systemd/system
systemctl daemon-reload
ln -sf /lib/systemd/system/simpleadmin_httpd.service /lib/systemd/system/multi-user.target.wants/
ln -sf /lib/systemd/system/simpleadmin_generate_status.service /lib/systemd/system/multi-user.target.wants/
systemctl start simpleadmin_generate_status
systemctl start simpleadmin_httpd
remount_ro
break
;;
5)
3)
echo "Returning to main menu..."
break
;;
@@ -542,11 +580,15 @@ install_update_remove_tailscale() {
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
echo "Downloading binary: /usrdata/tailscale/tailscaled"
wget https://raw.githubusercontent.com/$GITUSER/quectel-rgmii-toolkit/main/tailscale/tailscaled
echo "Downloading binary: /usrdata/tailscale/tailscale"
wget https://raw.githubusercontent.com/$GITUSER/quectel-rgmii-toolkit/main/tailscale/tailscale
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
@@ -795,60 +837,74 @@ WantedBy=multi-user.target" > "$cfun_service_path"
fi
}
# Function for TTYd install
install_ttyd() {
echo -e "\e[1;34mStarting ttyd installation process...\e[0m"
remount_rw
ensure_entware_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 [ -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;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;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. Exiting.\e[0m"
exit 1
;;
esac
return
fi
# 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;31mEntware/OPKG installation failed. Please check your internet connection or the repository URL.\e[0m"
echo -e "\e[1;31mFailed to install/update atcmd. Please check the process.\e[0m"
exit 1
fi
cd /
else
echo -e "\e[1;32mEntware/OPKG is already installed.\e[0m"
fi
mount -o remount,rw /
opkg update && opkg install shadow-login shadow-passwd
if [ "$?" -ne 0 ]; then
echo -e "\e[1;31mPackage installation failed. Please check your internet connection and try again.\e[0m"
exit 1
fi
# Replacing the login and passwd binaries
rm /opt/etc/shadow
cp /etc/shadow /opt/etc/
rm /bin/login /usr/bin/passwd
ln -sf /opt/bin/login /bin
ln -sf /opt/bin/passwd /usr/bin/
echo -e "\e[1;31mPlease set your system login password.\e[0m"
/usr/bin/passwd
# Setting up ttyd
mkdir -p /usrdata/ttyd/scripts /usrdata/ttyd/systemd
cd /usrdata/ttyd/
wget -O ttyd "https://raw.githubusercontent.com/$GITUSER/quectel-rgmii-toolkit/$GITTREE/ttyd/ttyd" && chmod +x ttyd
wget -O 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 /lib/systemd/system/ttyd.service /etc/systemd/system/multi-user.target.wants/
ln -sf /usrdata/ttyd/ttyd /bin
# Enabling and starting ttyd service
systemctl daemon-reload
systemctl enable ttyd
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;32mInstall Complete! ttyd server is up on port 443. Note: No TLS/SSL enabled yet.\e[0m"
echo -e "\e[1;32mInstallation Complete! ttyd server is up on port 443. Note: No TLS/SSL enabled yet.\e[0m"
}
# Main menu
while true; do
echo " .%+: "
@@ -923,9 +979,11 @@ echo " :+##+. "
echo -e "\e[94m4) Tailscale Management\e[0m" # Light Blue
echo -e "\e[92m5) Install/Change or remove Daily Reboot Timer\e[0m" # Light Green
echo -e "\e[91m6) Install/Uninstall CFUN 0 Fix\e[0m" # Light Red
echo -e "\e[96m7) Install Entware/OPKG (BETA/Advanced)\e[0m" # Cyan (repeated color for additional options)
echo -e "\e[96m8) Install TTYd (BETA,443,No TLS/SSL)\e[0m" # Cyan
echo -e "\e[93m9) Exit\e[0m" # Yellow (repeated color for exit option)
echo -e "\e[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
@@ -963,13 +1021,58 @@ echo " :+##+. "
;;
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 /
cd /tmp && wget -O installentware.sh https://raw.githubusercontent.com/$GITUSER/quectel-rgmii-toolkit/$GITTREE/installentware.sh && chmod +x installentware.sh && ./installentware.sh && cd /
;;
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/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
remount_ro
echo -e "\e[1;32mFast.com CLI (speedtest command) installed!!\e[0m"
echo -e "\e[1;32mTry running the command 'fast'\e[0m"
echo -e "\e[1;32mThe fast.com test tops out at 40Mbps on the modem\e[0m"
;;
11)
echo -e "\e[1;32mGoodbye!\e[0m"
break
;;

View File

@@ -1,7 +1,8 @@
#!/bin/sh
# Modified by iamromlan to set up a proper entware environment for Quectel RM5xx series m.2 modems
TYPE='generic'
#|---------|-----------------|
#| TARGET | Quectel Modem |
#| ARCH | armv7sf-k3.2 |
#| LOADER | ld-linux.so.3 |
#| GLIBC | 2.27 |
@@ -41,7 +42,9 @@ uninstall_entware() {
systemctl daemon-reload
# Optionally, clean up any modifications to /etc/profile or other system files
# This step depends on the specific changes made by the user or the installation script
# 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'
}
@@ -49,6 +52,7 @@ uninstall_entware() {
# 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"
@@ -209,6 +213,38 @@ echo -e '\033[32mInfo: Add /opt/bin & /opt/sbin to $PATH variable\033[0m'
echo -e '\033[32mInfo: Run export PATH=/opt/bin:/opt/sbin:$PATH to do it for this session only\033[0m'
echo -e '\033[32mInfo: opkg at /opt/bin will be linked to /bin but any package you install with opkg will not be automatically.\033[0m'
ln -sf /opt/bin/opkg /bin
opkg update
opkg update && opkg install shadow-login shadow-passwd
if [ "$?" -ne 0 ]; then
echo -e "\e[1;31mPackage installation failed. Please check your internet connection and try again.\e[0m"
exit 1
fi
# Replace the login and passwd binaries and set home for root to a writable directory
rm /opt/etc/shadow
rm /opt/etc/passwd
cp /etc/shadow /opt/etc/
cp /etc/passwd /opt/etc
mkdir /usrdata/root
mkdir /usrdata/root/bin
touch /usrdata/root/.profile
echo "# Set PATH for all shells" > /usrdata/root/.profile
echo "export PATH=/bin:/usr/sbin:/usr/bin:/sbin:/opt/sbin:/opt/bin:/usrdata/root/bin" >> /usrdata/root/.profile
chmod +x /usrdata/root/.profile
sed -i '1s|/home/root:/bin/sh|/usrdata/root:/bin/bash|' /opt/etc/passwd
rm /bin/login /usr/bin/passwd
ln -sf /opt/bin/login /bin
ln -sf /opt/bin/passwd /usr/bin/
echo -e "\e[1;31mPlease set your system login password.\e[0m"
/usr/bin/passwd
# Install basic and useful utilites
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 /

View File

@@ -6,16 +6,16 @@ while true; do
sleep 2
# Run AT+CGCONTRDP once then proceed to while loop
echo -en "AT+CGCONTRDP\r\n" | microcom -t 1000 /dev/ttyOUT > /tmp/apn.txt
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 5 seconds for data
# 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 5000 /dev/ttyOUT > /tmp/modemstatus.txt
| microcom -t 3000 /dev/ttyOUT > /tmp/modemstatus.txt
if [ $? -eq 0 ]
then
# Parse

View File

@@ -36,25 +36,41 @@ nr_bw() {
esac
}
# Function to get the secondary LTE bands
get_secondary_bands() {
# Extract LTE BANDs from SCC lines
SCC_BANDS=$(echo "$OX" | grep '+QCAINFO: "SCC"' | grep -o '"LTE BAND [0-9]\+"' | tr -d '"' | sed '1d')
# Extract NR5G BANDs from SCC lines
NR_BAND=$(echo "$OX" | grep '+QCAINFO: "SCC"' | grep -o '"NR5G BAND [0-9]\+"' | tr -d '"')
# Check if both SCC and NR bands are non-empty
if [ -n "$SCC_BANDS" ] && [ -n "$NR_BAND" ]; then
# Concatenate LTE BANDs with NR5G BANDs
SC_BANDS="$SCC_BANDS<br />$NR_BAND"
else
# Set SC_BANDS to the non-empty variable or empty if both are empty
SC_BANDS="${SCC_BANDS}${NR_BAND}"
# 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
# Get the PCI value. For example: 264 based on this +QCAINFO: "PCC",1775,75,"LTE BAND 3",1,264,-103,-13,-71,0
MAIN_PCI=$(echo "$OX" | grep '+QCAINFO: "PCC"' | grep -o ',[0-9]\{1,5\},' | tr -d ',')
}
# 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
@@ -63,8 +79,7 @@ MODEM_MODEL=$(</tmp/modemmodel.txt)
MODEM_MODEL=$(echo "$MODEM_MODEL" | grep -o "RG[^ ]\+\|RM[^ ]\+")
# Get the APN from /tmp/apn.txt and parse it
APN=$(</tmp/apn.txt)
APN=$(echo "$APN" | grep -o '"[^"]*"' | head -n1 | tr -d '"')
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
@@ -115,8 +130,7 @@ else
CSQ_PER="-"
CSQ_RSSI="-"
fi
get_secondary_bands
# End of QCAINFO
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
@@ -173,6 +187,7 @@ case $RAT in
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\}")
@@ -218,11 +233,14 @@ case $RAT in
fi
fi
if [ -n "$NR_NSA" ]; then
MODE="LTE/NR EN-DC"
# Changed network mode to NR5G NSA for easy identification
MODE="NR5G NSA"
echo "0" > /tmp/modnetwork
if [ -n "$QENG5" ]; then
QENG5=$QENG5",,"
# Append the initial PCI value rather than overwriting it
get_secondary_bands_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
@@ -305,6 +323,9 @@ case $RAT in
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

View File

@@ -8,6 +8,7 @@ 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
@@ -19,15 +20,29 @@ while IFS='=' read -r key value || [[ -n "$key" ]]; do
key=$(echo "$key" | awk '{$1=$1};1')
value=$(echo "$value" | awk '{$1=$1};1')
# Print key-value pair in JSON format without surrounding double quotes on value
printf ' "%s" : %s' "$key" "$value"
# 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 not the last line, add comma
if [ $((++current_line)) -lt "$last_line" ]; then
# 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 "}"
echo "}"

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

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

View File

@@ -0,0 +1,35 @@
#!/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
MYATCMD=$(printf '%b\n' "${atcmd//%/\\x}")
if [ -n "${MYATCMD}" ]; then
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
if [[ $runcmd =~ "OK" ]] || [[ $runcmd =~ "ERROR" ]]; then
break # Exit the loop if "OK" or "ERROR" is found
fi
# If neither "OK" nor "ERROR" is found, increment wait time by 1 second
((wait_time++))
done
fi
echo "Content-type: text/plain"
echo $x
echo ""
echo $runcmd

View File

@@ -10,6 +10,7 @@
<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>
@@ -17,7 +18,7 @@
<nav class="navbar is-black" x-data="{ isOpen: false }">
<div class="container">
<div class="navbar-brand">
<a class="navbar-item brand-text" href="/"> Quectel Simple Admin </a>
<a class="navbar-item brand-text" href="/"> Simple Admin </a>
<a
role="button"
class="navbar-burger burger"
@@ -36,7 +37,9 @@
<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>
@@ -50,7 +53,7 @@
<div class="container">
<!-- Fetches the correct Model Name -->
<h1 class="title">
Quectel <span x-text="csqData.MODEM_MODEL"></span> Connection
<span x-text="csqData.MODEM_MODEL"></span> Connection
Info
</h1>
<h2 class="subtitle">
@@ -217,28 +220,65 @@
</div>
<script>
function getSignalData() {
function signalInfo() {
return {
csqData: {},
lastUpdate: new Date().toLocaleString(),
getcsq() {
fetch("/cgi-bin/get_csq")
.then((res) => res.json())
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.csqData = data;
this.lastUpdate = new Date(
data.LASTUPDATE * 1000
).toLocaleString();
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
});
},
init() {
this.getcsq();
setInterval(() => {
this.getcsq();
}, 30000);
},
};
}
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>

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

View 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);
}
}

View File

@@ -5,11 +5,12 @@
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>RM5xxx TTL Changer</title>
<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>
@@ -19,7 +20,7 @@
<div class="container">
<div class="navbar-brand">
<a class="navbar-item brand-text" href="/">
Quectel Simple Admin
Simple Admin
</a>
<a role="button" class="navbar-burger burger" @click="isOpen = !isOpen">
<span aria-hidden="true"></span>
@@ -29,15 +30,11 @@
</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="/ttl.html">
TTL Changer
</a>
<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>
@@ -58,16 +55,17 @@
<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>
<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">
<input class="input" type="number" placeholder="64" x-model="newTTL">
</div>
</div>
<div class="field">
@@ -130,4 +128,5 @@
}
</script>
</body>
</html>
</html>

View File

@@ -10,24 +10,15 @@ setup_device() {
-echoctl -echoke noflsh -ixon -crtscts
}
# Prepare the device for communication
setup_device
echo -e "\033[0;36mType 'exit' to end the session.\033[0m"
while true; do
echo -en "\033[0;36mEnter AT Command: \033[0m"
read user_input
if [[ "$user_input" == "exit" ]]; then
echo -e "\033[0;32mExiting...\033[0m"
break
fi
# Function to send AT command and capture the output
send_at_command() {
local command="$1"
# Clear the device buffer before sending a new command
echo -n > $DEVICE
# Send the AT command
echo -e "$user_input\r" > $DEVICE
# Send the AT command, preserving the integrity of the input
echo -e "$command\r" > $DEVICE
# Use a temporary file to capture the command output
tmpfile=$(mktemp)
@@ -52,4 +43,27 @@ while true; do
# Clean up
rm "$tmpfile"
done
}
# Prepare the device for communication
setup_device
# Check if an AT command is provided as an argument
if [ $# -gt 0 ]; then
# Concatenate all arguments to handle commands with spaces and/or quotes correctly
FULL_CMD="$*"
send_at_command "$FULL_CMD"
else
echo -e "\033[0;36mType 'exit' to end the session.\033[0m"
while true; do
echo -en "\033[0;36mEnter AT Command: \033[0m"
read user_input
if [[ "$user_input" == "exit" ]]; then
echo -e "\033[0;32mExiting...\033[0m"
break
fi
send_at_command "$user_input"
done
fi

View File

@@ -1,7 +1,9 @@
#!/bin/bash
# Read the serial number and remove the last two digits
serial_number=$(cat /sys/devices/soc0/serial_number | sed 's/..$//')
# 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 "=============================================================="
@@ -82,9 +84,10 @@ echo " :@@@@@*. "
echo " .=@@@@@- "
echo " :+##+. "
echo "=============================================================="
echo "Test ttyd startup file by iamromulan V0.1"
echo "quectel-ID: $serial_number"
echo "TTYd session file by iamromulan v1.0"
echo "Firmware Revision: $firmware_revision"
echo "Serial Number: $serial_number"
echo "=============================================================="
# Start a login session
exec /bin/login
exec /bin/login

View File

@@ -1,179 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>RM5xxx AT Commands</title>
<script src="/js/alpinejs.min.js" defer></script>
<link rel="stylesheet" href="/css/bulma.css">
<link rel="stylesheet" type="text/css" href="/css/admin.css">
</head>
<body>
<!-- START NAV -->
<nav class="navbar is-black" x-data="{ isOpen: false }">
<div class="container">
<div class="navbar-brand">
<a class="navbar-item brand-text" href="/">
Quectel 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="/ttl.html">
TTL Changer
</a>
</div>
</div>
</div>
</nav>
<!-- END NAV -->
<div class="container" x-data="atCommands()">
<div class="columns">
<div class="column is-12">
<div class="columns">
<div class="column is-4">
<div class="card">
<header class="card-header">
<p class="card-header-title">
AT Command
</p>
</header>
<div class="card-content">
<div class="content">
<div class="field">
<label class="label">AT Command</label>
<div class="control">
<input class="input" type="text" placeholder="ATI" x-model="atcmd">
</div>
</div>
<div class="field">
<p class="control">
<button class="button is-success" @click="sendAtCommand()">
Send AT Command
</button>
</p>
</div>
</div>
</div>
</div>
</div>
<div class="column is-8">
<div class="card">
<header class="card-header">
<p class="card-header-title">
ATI Response
</p>
</header>
<div class="card-content">
<div class="content">
<textarea class="textarea" placeholder="ATI Responses Will Appear Here" rows="10"
x-text="atCommandResponse"></textarea>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- START Useful Commands Section -->
<div class="container">
<div class="columns">
<div class="column is-12">
<div class="card">
<header class="card-header">
<p class="card-header-title">
Useful Commands
</p>
</header>
<div class="card-content">
<div class="content">
<!-- Add your useful commands content here -->
<p>Here are some useful commands:</p>
<ul>
<li>See https://github.com/iamromulan/RM520N-GL#at-commands for more </li>
<li>AT+CFUN=1,1 (reboot)</li>
<li>AT+QMAPWAC? (get current status of auto connect, 0=disabled 1=enabled)</li>
<li>AT+QMAPWAC=1 (enable auto connect internet for ethernet)</li>
<li>AT+QMAPWAC=0 (disable auto connect for ethernet; use when you want internet over usb to work; IPPT must be disabled)</li>
<li>AT+QUIMSLOT? (get active sim slot; 1=Slot 1; 2=Slot 2)</li>
<li>AT+QUIMSLOT=1 (switch to sim slot 1)</li>
<li>AT+QUIMSLOT=2 (switch to sim slot 2)</li>
<li>AT+CGDCONT? (Get active APN profle list 1 through 8)</li>
<li>AT+CGDCONT=1,"IPV4V6","APNHERE" (Sets APN profle 1 to APNHERE using both IPV4 and IPV6)</li>
<li>AT+GSN (Show current IMEI)</li>
<li>AT+EGMR=1,7,"IMEIGOESHERE" (sets/repairs IMEI)</li>
<li>AT+QCAINFO (Show all connected bands/CA info)</li>
<li>AT+QNWPREFCFG="mode_pref" (Check what the current network search mode is set to)</li>
<li>AT+QNWPREFCFG="mode_pref",AUTO (Set network search mode to automatic)</li>
<li>AT+QNWPREFCFG="mode_pref",NR5G:LTE (Set network search mode to 5G/NR and 4G/LTE only)</li>
<li>AT+QNWPREFCFG="mode_pref",NR5G (Set network search mode to 5G/NR only)</li>
<li>AT+QNWPREFCFG="mode_pref",LTE (Set network search mode to 4G/LTE only)</li>
<li>AT+QNWPREFCFG="nr5g_disable_mode" (Check to see if SA or NSA NR5G is disabled)</li>
<li>AT+QNWPREFCFG="nr5g_disable_mode",0 (Enable Both SA and NSA 5G/NR)</li>
<li>AT+QNWPREFCFG="nr5g_disable_mode",1 (Disable SA 5G/NR only)</li>
<li>AT+QNWPREFCFG="nr5g_disable_mode",2 (Disable NSA 5G/NR only)</li>
<li>AT+QNWPREFCFG="nr5g_band" (Get current 5G/NR bandlock settings)</li>
<li>AT+QNWPREFCFG="nr5g_band",1:2:3:4:5:6 (Example: Lock to 5G/NR bands n1,n2,n3,n4,n5, and n6)</li>
<li>AT+QNWPREFCFG="lte_band" (Get current 4G/LTE bandlock settings)</li>
<li>AT+QNWPREFCFG="lte_band",1:2:3:4:5:6 (Example: Lock to 4G/LTE bands 1,2,3,4,5, and 6)</li>
<li>AT+QMAP="WWAN" (Show currently assigned IPv4 and IPv6 from the provider)</li>
<li>AT+QMAP="LANIP" (Show current DHCP range and Gateway address for VLAN0)</li>
<li>AT+QMAP="LANIP",IP_start_range,IP_end_range,Gateway_IP (Set IPv4 Start/End range and Gateway IP of DHCP for VLAN0)</li>
<li>AT+QMAP="DHCPV4DNS","disable" (disable the onboard DNS proxy; recommended for IPPT)</li>
<li>AT+QMAP="MPDN_rule",0,1,0,1,1,"FF:FF:FF:FF:FF:FF" (Turn on IP Passthrough for Ethernet)</li>
<li>AT+QMAP="MPDN_rule",0 (turn off IPPT/clear MPDN rule 0; Remember to run AT+QMAPWAC=1 and reboot after)</li>
</ul>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- END Useful Commands Section -->
<script>
function atCommands() {
return {
isLoading: false,
atcmd: null,
atCommandResponse: null,
sendAtCommand() {
fetch('/cgi-bin/get_atcommand?' + new URLSearchParams({
atcmd: this.atcmd,
}))
.then((res) => {
return res.text();
})
.then((data) => {
this.atCommandResponse = data;
this.isLoading = false;
})
},
}
}
</script>
</body>
</html>

View File

@@ -1,29 +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
MYATCMD=$(printf '%b\n' "${atcmd//%/\\x}")
if [ -n "${MYATCMD}" ]; then
x=$(urldecode "$atcmd")
runcmd=$(echo -en "$x\r\n" | microcom -t 2000 /dev/ttyOUT2)
fi
echo "Content-type: text/plain"
echo $x
echo ""
echo $runcmd

Binary file not shown.

Binary file not shown.

BIN
ttyd/ttyd

Binary file not shown.