Files
Alpine_5G/scripts/modem-status-at.sh
nearxos 160ad641ce Add web GUI, docs, scripts, and 5G router config
- Web app (Flask): status, config, firewall, logs, users, restart
- Docs: AT commands, deploy, DNS, quickstart, web GUI
- Scripts: connect, deploy, diag, healthcheck, modem-status, speedtest, status, troubleshoot
- Init and iptables: 5g-router, 5g-webgui, rules.v4
- CHANGELOG, TODO, REVISION; config and README updates
2026-02-02 09:38:23 +02:00

106 lines
4.2 KiB
Bash
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/bin/sh
# Alpine 5G Router modem status via AT commands (AT_COMMANDS_REFERENCE.md)
# Outputs JSON. Used by Web GUI /api/status.
# Rev: 2 (see REVISION in repo root)
CONFIG="/etc/5g-router.conf"
AT_PORT="${AT_PORT:-/dev/ttyUSB1}"
[ -f "$CONFIG" ] && . "$CONFIG"
get_at() {
_cmd="$1"
_wait="${2:-1}"
timeout $((_wait + 2)) sh -c "
cat $AT_PORT 2>/dev/null &
_p=\$!
sleep 0.3
echo -e '${_cmd}\r' > $AT_PORT
sleep $_wait
kill \$_p 2>/dev/null
" 2>/dev/null
}
json_str() { printf '"%s"' "$(echo "$1" | sed 's/\\/\\\\/g; s/"/\\"/g; s/\r//g' | tr '\n' ' ')"; }
# Probe port: send AT, return 0 if we see OK
try_at_port() {
_port="$1"
[ ! -c "$_port" ] && return 1
_out=$(timeout 4 sh -c "
cat $_port 2>/dev/null &
_p=\$!
sleep 0.3
echo -e 'AT\r' > $_port
sleep 1
kill \$_p 2>/dev/null
" 2>/dev/null)
echo "$_out" | grep -q 'OK' && return 0 || return 1
}
# Use configured port if it exists and is a char device; else try common Fibocom AT ports
if [ ! -c "$AT_PORT" ]; then
for p in /dev/ttyUSB0 /dev/ttyUSB1 /dev/ttyUSB2; do
if try_at_port "$p"; then
AT_PORT="$p"
break
fi
done
fi
[ ! -c "$AT_PORT" ] && echo '{}' && exit 0
# Disable command echo so we get only response lines (ATE0); avoids parsing "AT+CGMI" as manufacturer
get_at "ATE0" 1 >/dev/null 2>&1
sleep 0.2
# Query AT commands (reference: AT_COMMANDS_REFERENCE.md)
r_cgmi=$(get_at "AT+CGMI" 1)
r_cgmm=$(get_at "AT+CGMM" 1)
r_cgmr=$(get_at "AT+CGMR" 1)
r_cgsn=$(get_at "AT+CGSN" 1)
r_csq=$(get_at "AT+CSQ" 1)
r_creg=$(get_at "AT+CREG?" 1)
r_cereg=$(get_at "AT+CEREG?" 1)
r_usbmode=$(get_at "AT+GTUSBMODE?" 1)
r_ccid=$(get_at "AT+CCID" 1)
r_cops=$(get_at "AT+COPS?" 1)
r_cgpaddr=$(get_at "AT+CGPADDR=1" 1)
# Parse (skip echoed command lines: lines starting with AT or +)
manufacturer=$(echo "$r_cgmi" | grep -vE '^AT|^\+' | grep -oE '^[A-Za-z0-9 ].*' | head -1 | sed 's/\r$//; s/^ *//; s/ *$//')
model=$(echo "$r_cgmm" | grep -vE '^AT|^\+' | grep -oE '^[A-Za-z0-9\-].*' | head -1 | sed 's/\r$//; s/^ *//; s/ *$//')
revision=$(echo "$r_cgmr" | grep -vE '^(AT|OK|\+)' | head -1 | sed 's/\r$//; s/^ *//; s/ *$//')
imei=$(echo "$r_cgsn" | grep -oE '[0-9]{15}' | head -1)
csq=$(echo "$r_csq" | grep "+CSQ:" | grep -oE '[0-9]+' | head -1)
creg=$(echo "$r_creg" | grep "+CREG:" | head -1)
cereg=$(echo "$r_cereg" | grep "+CEREG:" | head -1)
usb_mode=$(echo "$r_usbmode" | grep "+GTUSBMODE:" | grep -oE '[0-9]+' | head -1)
iccid=$(echo "$r_ccid" | grep "+CCID:" | sed 's/+CCID:[[:space:]]*//; s/\r$//; s/"//g' | head -1)
cops=$(echo "$r_cops" | grep "+COPS:" | sed 's/+COPS:[[:space:]]*//; s/\r$//' | head -1)
modem_ip=$(echo "$r_cgpaddr" | grep "+CGPADDR:" | grep -oE '[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+' | head -1)
# Registration: CREG 0,1 = registered home, 0,5 = registered roaming; CEREG same
creg_status=""
case "$creg" in *",1"*) creg_status="registered_home";; *",5"*) creg_status="registered_roaming";; *",2"*) creg_status="searching";; *",0"*) creg_status="not_registered";; *) creg_status="unknown";; esac
cereg_status=""
case "$cereg" in *",1"*) cereg_status="registered_home";; *",5"*) cereg_status="registered_roaming";; *",2"*) cereg_status="searching";; *",0"*) cereg_status="not_registered";; *) cereg_status="unknown";; esac
# Operator name from +COPS: 0,0,"Vodafone",7
operator_name=$(echo "$cops" | sed -n 's/.*"\([^"]*\)".*/\1/p')
# Build JSON (no jq)
printf '{\n'
printf ' "at_port": '; json_str "$AT_PORT"; printf ',\n'
printf ' "manufacturer": '; json_str "${manufacturer:-}"; printf ',\n'
printf ' "model": '; json_str "${model:-}"; printf ',\n'
printf ' "revision": '; json_str "${revision:-}"; printf ',\n'
printf ' "imei": '; json_str "${imei:-}"; printf ',\n'
printf ' "signal_csq": %s,\n' "${csq:-null}"
printf ' "creg_status": '; json_str "$creg_status"; printf ',\n'
printf ' "cereg_status": '; json_str "$cereg_status"; printf ',\n'
printf ' "usb_mode": '; json_str "${usb_mode:-}"; printf ',\n'
printf ' "iccid": '; json_str "${iccid:-}"; printf ',\n'
printf ' "operator": '; json_str "${operator_name:-}"; printf ',\n'
printf ' "modem_ip": '; json_str "${modem_ip:-}"; printf '\n'
printf '}\n'