Initial Merge
This commit is contained in:
42
README.md
42
README.md
@@ -1,3 +1,41 @@
|
|||||||
# GL-XE300
|
# LTE Recovery Script for GL-XE300_V1.0 Router Board
|
||||||
|
|
||||||
|
This script resets and brings up a Quectel EP06-A LTE modem using `uqmi`.
|
||||||
|
|
||||||
|
## What It Does
|
||||||
|
|
||||||
|
- Kills stuck `uqmi` processes
|
||||||
|
- Stops the active PDP session (with timeout)
|
||||||
|
- Blanks and restores the APN
|
||||||
|
- Forces `raw_ip=Y` mode
|
||||||
|
- Brings interface down and up cleanly
|
||||||
|
- Confirms WAN is working (IP + route + ping)
|
||||||
|
|
||||||
|
## Why I Made This
|
||||||
|
|
||||||
|
Most LTE recovery tools are locked behind vendor-specific web GUIs.
|
||||||
|
This script is built for **OpenWRT 24.10.0** and is intended for users running **command-line only** with no GUI.
|
||||||
|
|
||||||
|
Use cases include:
|
||||||
|
|
||||||
|
- Deployments where modem control must be done over shell
|
||||||
|
- Cron-based or watchdog-based recovery without manual intervention
|
||||||
|
- Off-grid or solar-powered systems where the LTE radio is **only active at certain times of day**
|
||||||
|
|
||||||
|
If you're running raw OpenWRT and want reliable LTE recovery on CLI, this is for you.
|
||||||
|
|
||||||
|
## Requirements
|
||||||
|
|
||||||
|
System must be flashed to **OpenWRT 24.10.0** with the **Quectel EP06-A** modem installed.
|
||||||
|
Assumes modem interface is named `wwan` and located at `/dev/cdc-wdm0`.
|
||||||
|
|
||||||
|
The script uses an APN of `mobile`, which is valid for **EIOT Club SIM cards** as of this commit.
|
||||||
|
This SIM was selected for its plug-and-play compatibility with OpenWRT and `uqmi`, requiring no manual registration or configuration.
|
||||||
|
|
||||||
|
Assumes WAN port has internet access during the first run so the required packages can be installed.
|
||||||
|
|
||||||
|
Install required packages:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
opkg update && opkg install uqmi ip-full iputils-ping uci
|
||||||
|
|
||||||
OpenWRT scripts and workflows for the GL.iNet Puli / CSG M106. With a few upgrades, this 4G LTE gateway router punches well above its weight class: 512GB of storage, 6 GPIOs plus UART, GNSS and USB 2.0 port for everything else (audio output to 3.5mm, external Wi-Fi hardware, BLE, etc.)
|
|
||||||
178
lte_recover.sh
Normal file
178
lte_recover.sh
Normal file
@@ -0,0 +1,178 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
# ✅ Function: Check if we have a usable WAN link
|
||||||
|
wait_for_data_connection() {
|
||||||
|
echo "[RAIDBOT] ⏳ Waiting for usable WAN link (IP + route)..."
|
||||||
|
for i in $(seq 1 20); do
|
||||||
|
IP=$(ip -4 -o addr show dev wwan0 | awk '{print $4}')
|
||||||
|
if [ -n "$IP" ]; then
|
||||||
|
if ip r | grep -q "default via"; then
|
||||||
|
if ip route get 8.8.8.8 2>/dev/null | grep -q "dev wwan0"; then
|
||||||
|
echo "[RAIDBOT] ✅ WAN is up. IP: $IP"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
echo "[RAIDBOT] ...not ready yet ($i/20)"
|
||||||
|
sleep 2
|
||||||
|
done
|
||||||
|
echo "[RAIDBOT] ❌ Timed out waiting for usable link."
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# ✅ Function: Wait until the interface is truly down
|
||||||
|
wait_for_down() {
|
||||||
|
echo "[RAIDBOT] ⏳ Waiting for wwan0 to go down..."
|
||||||
|
for i in $(seq 1 10); do
|
||||||
|
ip a show dev wwan0 | grep -q "inet " || {
|
||||||
|
echo "[RAIDBOT] ✅ Interface down confirmed."
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
sleep 3
|
||||||
|
done
|
||||||
|
echo "[RAIDBOT] ⚠️ Interface may still be up."
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# ✅ Function: Wait until modem detaches from PDP session
|
||||||
|
wait_for_detach() {
|
||||||
|
echo "[RAIDBOT] ⏳ Waiting for modem to detach from network..."
|
||||||
|
for i in $(seq 1 10); do
|
||||||
|
STATUS=$(uqmi -d /dev/cdc-wdm0 --get-data-status 2>/dev/null | grep '"connected"' || true)
|
||||||
|
if [ -z "$STATUS" ]; then
|
||||||
|
echo "[RAIDBOT] ✅ Modem detached from PDP session."
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
echo "[RAIDBOT] ...still attached ($i/10)"
|
||||||
|
sleep 2
|
||||||
|
done
|
||||||
|
echo "[RAIDBOT] ⚠️ Timed out waiting for modem to detach."
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# ✅ Function: Hang-proof stop-network
|
||||||
|
safe_stop_network() {
|
||||||
|
STATUS=$(uqmi -d /dev/cdc-wdm0 --get-data-status 2>/dev/null | grep '"connected"' || true)
|
||||||
|
if [ -z "$STATUS" ]; then
|
||||||
|
echo "[RAIDBOT] ⚠️ Modem already disconnected — skipping stop-network."
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "[RAIDBOT] 🔻 Issuing stop-network with timeout guard..."
|
||||||
|
|
||||||
|
(
|
||||||
|
uqmi -d /dev/cdc-wdm0 --stop-network 0xffffffff --autoconnect
|
||||||
|
) &
|
||||||
|
STOP_PID=$!
|
||||||
|
|
||||||
|
for i in $(seq 1 10); do
|
||||||
|
if ! kill -0 $STOP_PID 2>/dev/null; then
|
||||||
|
echo "[RAIDBOT] ✅ stop-network completed (in ${i}s)"
|
||||||
|
wait_for_detach
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
echo "[RAIDBOT] ...waiting for stop-network to finish ($i/10)"
|
||||||
|
sleep 1
|
||||||
|
done
|
||||||
|
|
||||||
|
echo "[RAIDBOT] ❌ stop-network hung — killing process..."
|
||||||
|
kill -9 $STOP_PID 2>/dev/null
|
||||||
|
wait $STOP_PID 2>/dev/null
|
||||||
|
echo "[RAIDBOT] ⚠️ stop-network force killed — skipping wait_for_detach."
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# ✅ Function: Kill stuck uqmi and verify
|
||||||
|
kill_uqmi_safely() {
|
||||||
|
echo "[RAIDBOT] 🔪 Killing any stuck uqmi processes..."
|
||||||
|
killall -9 uqmi 2>/dev/null
|
||||||
|
for i in $(seq 1 5); do
|
||||||
|
if ! pgrep uqmi >/dev/null; then
|
||||||
|
echo "[RAIDBOT] ✅ uqmi process gone."
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
echo "[RAIDBOT] ...still cleaning up ($i/5)"
|
||||||
|
sleep 1
|
||||||
|
done
|
||||||
|
echo "[RAIDBOT] ⚠️ uqmi process may still be running!"
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# ✅ Function: Set APN and confirm it
|
||||||
|
set_apn_and_confirm() {
|
||||||
|
local apn_value="$1"
|
||||||
|
echo "[RAIDBOT] 📡 Setting APN to '$apn_value'..."
|
||||||
|
uci set network.wwan.apn="$apn_value"
|
||||||
|
uci commit network
|
||||||
|
|
||||||
|
for i in $(seq 1 5); do
|
||||||
|
CURRENT_APN=$(uci get network.wwan.apn 2>/dev/null)
|
||||||
|
if [ "$CURRENT_APN" = "$apn_value" ]; then
|
||||||
|
echo "[RAIDBOT] ✅ APN is now '$CURRENT_APN'."
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
echo "[RAIDBOT] ...verifying APN ($i/5)"
|
||||||
|
sleep 1
|
||||||
|
done
|
||||||
|
|
||||||
|
echo "[RAIDBOT] ⚠️ APN setting failed (wanted '$apn_value', got '$CURRENT_APN')."
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# ✅ Function: Set raw_ip=Y and confirm it
|
||||||
|
set_raw_ip_mode() {
|
||||||
|
echo "[RAIDBOT] ⚙️ Setting raw_ip=Y..."
|
||||||
|
echo Y > /sys/class/net/wwan0/qmi/raw_ip
|
||||||
|
|
||||||
|
for i in $(seq 1 5); do
|
||||||
|
RAW=$(cat /sys/class/net/wwan0/qmi/raw_ip 2>/dev/null || echo "unknown")
|
||||||
|
if [ "$RAW" = "Y" ]; then
|
||||||
|
echo "[RAIDBOT] ✅ raw_ip confirmed as 'Y'."
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
echo "[RAIDBOT] ...verifying raw_ip ($i/5)"
|
||||||
|
sleep 1
|
||||||
|
done
|
||||||
|
|
||||||
|
echo "[RAIDBOT] ⚠️ raw_ip mode failed to set (still '$RAW')."
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# --- Recovery Sequence Begins ---
|
||||||
|
|
||||||
|
kill_uqmi_safely
|
||||||
|
|
||||||
|
safe_stop_network
|
||||||
|
|
||||||
|
set_apn_and_confirm ''
|
||||||
|
set_raw_ip_mode
|
||||||
|
|
||||||
|
echo "[RAIDBOT] 🛑 ifdown wwan (blank run)..."
|
||||||
|
ifdown wwan
|
||||||
|
wait_for_down
|
||||||
|
|
||||||
|
echo "[RAIDBOT] 🚀 Bringing up blank APN..."
|
||||||
|
ifup wwan
|
||||||
|
if wait_for_data_connection; then
|
||||||
|
echo "[RAIDBOT] 🔻 Re-stopping PDP (post-blank)..."
|
||||||
|
safe_stop_network
|
||||||
|
else
|
||||||
|
echo "[RAIDBOT] ⚠️ Skipping post-blank PDP stop — WAN never came up."
|
||||||
|
fi
|
||||||
|
|
||||||
|
set_apn_and_confirm 'mobile'
|
||||||
|
set_raw_ip_mode
|
||||||
|
|
||||||
|
echo "[RAIDBOT] 🛑 ifdown wwan (real APN)..."
|
||||||
|
ifdown wwan
|
||||||
|
wait_for_down
|
||||||
|
|
||||||
|
echo "[RAIDBOT] 🚀 Bringing up real APN (mobile)..."
|
||||||
|
ifup wwan
|
||||||
|
if ! wait_for_data_connection; then
|
||||||
|
echo "[RAIDBOT] ❌ Final APN bring-up failed — WAN still unreachable."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "[RAIDBOT] 🌐 Final ping test..."
|
||||||
|
ping -c3 8.8.8.8
|
||||||
Reference in New Issue
Block a user