LTE watchdog для WBC2-4G на Wiren Board: рабочий вариант
Как и обещал, выкладываю рабочий вариант LTE watchdog, который я сейчас использую на контроллерах Wiren Board с модемом WBC2-4G.
Исходная проблема была такая: LTE-связь периодически пропадала, при этом по dmesg было видно, что это не просто обрыв сотовой сети, а модем переподнимался как USB-устройство. После такого отвала связь сама стабильно не восстанавливалась, помогала только перезагрузка контроллера.
После установки watchdog проблема не повторяется уже больше 10 дней. Сейчас это решение используется на нескольких контроллерах.
Что делает watchdog
Скрипт запускается через systemd timer каждые 2 минуты.
Логика восстановления такая:
-
Проверить наличие активного GSM-профиля.
-
Проверить наличие
/dev/ttyUSB*. -
Проверить доступность интернета через
ping. -
Если связи нет — переподнять активный GSM-профиль.
-
Если не помогло — попробовать
wb-gsm-sim1иwb-gsm-sim2. -
Если не помогло — перезапустить
ModemManager. -
Если не помогло — выполнить power-cycle LTE-модема через
wb-gsm. -
Если несколько циклов подряд не дали результата — перезагрузить контроллер.
1. Установка скрипта
Создать файл:
nano /usr/local/sbin/lte-watchdog.sh
Содержимое:
#!/bin/bash
set -u
LOGTAG="lte-watchdog"
FAIL_FILE="/var/tmp/lte-watchdog-fails"
SIM1_CONN="wb-gsm-sim1"
SIM2_CONN="wb-gsm-sim2"
MAX_FAILS_BEFORE_REBOOT=5
PING_TARGETS=("1.1.1.1" "8.8.8.8")
log() {
logger -t "$LOGTAG" "$1"
echo "$(date '+%F %T') $1"
}
get_active_gsm_connection() {
nmcli -t -f DEVICE,TYPE,STATE,CONNECTION dev status \
| awk -F: '$2=="gsm" && $3=="connected" {print $4; exit}'
}
get_available_gsm_connections() {
nmcli -t -f NAME,TYPE con show \
| awk -F: '$2=="gsm" {print $1}'
}
internet_ok() {
for target in "${PING_TARGETS[@]}"; do
if ping -c 2 -W 5 "$target" >/dev/null 2>&1; then
return 0
fi
done
return 1
}
reset_fails() {
echo 0 > "$FAIL_FILE"
}
inc_fails() {
local n=0
if [ -f "$FAIL_FILE" ]; then
n=$(cat "$FAIL_FILE" 2>/dev/null || echo 0)
fi
n=$((n + 1))
echo "$n" > "$FAIL_FILE"
echo "$n"
}
connection_exists() {
nmcli con show "$1" >/dev/null 2>&1
}
restart_connection() {
local conn="$1"
if ! connection_exists "$conn"; then
log "Connection $conn does not exist, skipping"
return 1
fi
log "Restarting GSM connection: $conn"
nmcli con down "$conn" >/dev/null 2>&1
sleep 10
nmcli con up "$conn" >/dev/null 2>&1
sleep 45
if internet_ok; then
log "Internet restored using $conn"
reset_fails
return 0
fi
log "Connection $conn did not restore internet"
return 1
}
try_all_gsm_connections() {
local active_conn="$1"
# Сначала пробуем активный профиль, если он известен
if [ -n "$active_conn" ]; then
restart_connection "$active_conn" && return 0
fi
# Затем пробуем стандартные профили SIM1/SIM2
for conn in "$SIM1_CONN" "$SIM2_CONN"; do
if [ "$conn" != "$active_conn" ]; then
restart_connection "$conn" && return 0
fi
done
# Затем пробуем любые другие GSM-профили, если они есть
while read -r conn; do
[ -z "$conn" ] && continue
[ "$conn" = "$SIM1_CONN" ] && continue
[ "$conn" = "$SIM2_CONN" ] && continue
[ "$conn" = "$active_conn" ] && continue
restart_connection "$conn" && return 0
done < <(get_available_gsm_connections)
return 1
}
modemmanager_recovery() {
local active_conn="$1"
log "Restarting ModemManager"
systemctl restart ModemManager
sleep 35
if [ -n "$active_conn" ]; then
nmcli con up "$active_conn" >/dev/null 2>&1
sleep 45
if internet_ok; then
log "Internet restored after ModemManager restart using $active_conn"
reset_fails
return 0
fi
fi
try_all_gsm_connections "$active_conn" && return 0
return 1
}
wbgsm_power_cycle() {
local active_conn="$1"
log "Power-cycling LTE modem via wb-gsm"
systemctl stop wb-gsm
sleep 25
systemctl start wb-gsm
sleep 80
if [ -n "$active_conn" ]; then
nmcli con up "$active_conn" >/dev/null 2>&1
sleep 45
if internet_ok; then
log "Internet restored after wb-gsm power cycle using $active_conn"
reset_fails
return 0
fi
fi
try_all_gsm_connections "$active_conn" && return 0
return 1
}
check_ttyusb_presence() {
if ls /dev/ttyUSB* >/dev/null 2>&1; then
return 0
fi
log "No /dev/ttyUSB* devices found. Restarting ModemManager and wb-gsm"
systemctl restart ModemManager
sleep 25
systemctl restart wb-gsm
sleep 80
return 1
}
main() {
local active_conn
local fails
active_conn="$(get_active_gsm_connection || true)"
if [ -n "$active_conn" ]; then
log "Active GSM connection: $active_conn"
else
log "No active GSM connection detected"
fi
check_ttyusb_presence
if internet_ok; then
reset_fails
exit 0
fi
log "Internet check failed"
if try_all_gsm_connections "$active_conn"; then
exit 0
fi
if modemmanager_recovery "$active_conn"; then
exit 0
fi
if wbgsm_power_cycle "$active_conn"; then
exit 0
fi
fails=$(inc_fails)
log "LTE still unavailable after full recovery cycle. Consecutive fails: $fails"
if [ "$fails" -ge "$MAX_FAILS_BEFORE_REBOOT" ]; then
log "Too many LTE failures. Rebooting controller"
reboot
fi
exit 1
}
main "$@"
Сделать исполняемым:
chmod +x /usr/local/sbin/lte-watchdog.sh
2. systemd service
Создать файл:
nano /etc/systemd/system/lte-watchdog.service
Содержимое:
[Unit]
Description=LTE watchdog for WBC2-4G with SIM1/SIM2 support
After=NetworkManager.service ModemManager.service wb-gsm.service
Wants=NetworkManager.service ModemManager.service wb-gsm.service
[Service]
Type=oneshot
ExecStart=/usr/local/sbin/lte-watchdog.sh
Nice=10
3. systemd timer
Создать файл:
nano /etc/systemd/system/lte-watchdog.timer
Содержимое:
[Unit]
Description=Run LTE watchdog every 2 minutes
[Timer]
OnBootSec=5min
OnUnitActiveSec=2min
AccuracySec=30s
Persistent=true
Unit=lte-watchdog.service
[Install]
WantedBy=timers.target
4. Включить watchdog
systemctl daemon-reload
systemctl enable --now lte-watchdog.timer
Проверить timer:
systemctl status lte-watchdog.timer --no-pager
systemctl list-timers | grep lte-watchdog
Ручной запуск watchdog:
systemctl start lte-watchdog.service
Посмотреть логи:
journalctl -t lte-watchdog --since "1 hour ago" --no-pager
или:
journalctl -u lte-watchdog.service -n 100 --no-pager
5. Настройка под свои профили
В скрипте используются стандартные имена GSM-профилей:
SIM1_CONN="wb-gsm-sim1"
SIM2_CONN="wb-gsm-sim2"
Если у вас профили называются иначе, нужно поменять эти переменные.
Проверить профили:
nmcli con show | grep -E 'gsm|wb-gsm'
Проверить активное GSM-устройство:
nmcli dev status
6. Диагностика модема
Полезные команды:
mmcli -m wbc || mmcli -m any
nmcli dev status
nmcli con show
systemctl status ModemManager --no-pager
systemctl status wb-gsm --no-pager
Посмотреть USB-события:
dmesg -T | grep -Ei "usb|ttyUSB|option|rndis|wbc|modem|disconnect|reset|timeout" | tail -100
7. Что можно изменить
Интервал запуска задаётся в timer:
OnUnitActiveSec=2min
Количество неудачных циклов перед reboot:
MAX_FAILS_BEFORE_REBOOT=5
Адреса проверки интернета:
PING_TARGETS=("1.1.1.1" "8.8.8.8")
Если reboot как крайняя мера не нужен, можно закомментировать строку:
reboot
или сильно увеличить:
MAX_FAILS_BEFORE_REBOOT=20
8. Результат
На моих объектах это решение работает больше 10 дней. До установки watchdog LTE-связь на части контроллеров могла пропадать почти ежедневно и требовала ручной перезагрузки WB. После установки watchdog ручное вмешательство больше не требовалось.
Понимаю, что если ядро теряет USB-соединение с модемом, первопричина может быть на уровне питания, USB-хоста, модема, прошивки или драйвера. Но для удалённых объектов, где LTE является единственным каналом связи, такой watchdog оказался практичным способом автоматического восстановления доступности контроллера.