🎉 Sync 2026-06-28 20:31:01

This commit is contained in:
github-actions[bot] committed 2026-06-28 20:31:01 +08:00
1 parent c1ac066adb
commit 38fe5fc408
24 files changed
+279 -227

No files matched your search

+63
View File
@@ -0,0 +1,63 @@
#!/bin/sh
# SIM slot switcher - schedule handler
# Called by cron, generated by /etc/init.d/ssw
# by Konstantine Shevlakov at <shevlakov@132lan.ru> 2025
NODE="SW SIM SCHED"
get_vars() {
for d in modem sim; do
for s in gpio value; do
eval "${d}_${s}=$(uci -q get ssw.${d}.${s} 2>/dev/null)"
done
done
}
reload_iface() {
local iface
iface=$(uci show network | awk -F'[.]' '/devices/{gsub("'\''",""); print $2}' | tail -1)
[ -n "$iface" ] && ifup "$iface"
}
sw_sim() {
local cur_sim next_sim
cur_sim=$(cat /sys/class/gpio/"$sim_gpio"/value)
case "$cur_sim" in
0) next_sim=1 ;;
1) next_sim=0 ;;
*) logger -t "$NODE" "ERROR: unexpected sim gpio value: $cur_sim"; exit 1 ;;
esac
logger -t "$NODE" "Switching SIM: slot $cur_sim -> slot $next_sim"
echo "0" > /sys/class/gpio/"$modem_gpio"/value
echo "$next_sim" > /sys/class/gpio/"$sim_gpio"/value
if [ "$modem_value" = "1" ]; then
sleep 2
echo "1" > /sys/class/gpio/"$modem_gpio"/value
if [ -x /etc/init.d/smstools3 ]; then
/etc/init.d/smstools3 restart
fi
fi
sleep 5 && reload_iface &
}
sw_revert() {
local cur_sim
cur_sim=$(cat /sys/class/gpio/"$sim_gpio"/value)
if [ "$cur_sim" != "$sim_value" ]; then
logger -t "$NODE" "Reverting SIM to default slot $sim_value"
sw_sim
else
logger -t "$NODE" "SIM already on default slot $sim_value, nothing to do"
fi
}
# --- main ---
get_vars
case "$1" in
revert) sw_revert ;;
*) sw_sim ;;
esac
+2 -188
View File
@@ -58,18 +58,6 @@ get_vars(){
[ -n "$interval" ] || interval=60
[ -n "$times_rsrp" ] || times_rsrp=5
# Schedule variables
sched_enable=$(uci -q get ssw.schedule.enable 2>/dev/null)
sched_time_on=$(uci -q get ssw.schedule.time_on 2>/dev/null)
sched_duration=$(uci -q get ssw.schedule.duration 2>/dev/null)
sched_apn=$(uci -q get ssw.schedule.apn 2>/dev/null)
sched_period=$(uci -q get ssw.schedule.period 2>/dev/null)
sched_period_days=$(uci -q get ssw.schedule.period_days 2>/dev/null)
sched_weekday=$(uci -q get ssw.schedule.weekday 2>/dev/null)
[ -n "$sched_duration" ] || sched_duration=0
[ -n "$sched_period" ] || sched_period=daily
[ -n "$sched_period_days" ] || sched_period_days=1
[ -n "$sched_weekday" ] || sched_weekday=1
}
# SIM Switch
@@ -92,163 +80,6 @@ sw_sim(){
set > /tmp/apn.ssw
}
# Revert rule switch (failover)
sw_rule(){
if [ -f /tmp/ssw.vars ]; then
. /tmp/ssw.vars
fi
if [ "$cur_sim" -ne "$sim_value" ]; then
if [ "$(date +%s)" -gt "$SWDATE" ]; then
logger -t "$NODE" "Revert to default SIM slot with $apn"
sw_sim
fi
fi
}
# Schedule: revert to default SIM after duration
sched_revert(){
[ -f /tmp/ssw_sched.vars ] && . /tmp/ssw_sched.vars
if [ -n "$SCHED_REVERT_AT" ] && [ "$(date +%s)" -ge "$SCHED_REVERT_AT" ]; then
cur_sim=$(cat /sys/class/gpio/$sim_gpio/value)
if [ "$cur_sim" -ne "$sim_value" ]; then
logger -t "$NODE" "Schedule: reverting to default SIM slot"
iface=$(uci show network | awk -F [.] '/devices/{gsub("'\''","");print $2}' | tail -1)
uci set network.$iface.apn="${apn1:-internet}"
uci commit network
reload_config network
sw_sim && sleep 20 && reload_iface &
fi
rm -f /tmp/ssw_sched.vars
logger -t "$NODE" "Schedule: revert done, schedule state cleared"
fi
}
# Check if today matches the configured schedule period.
# Returns 0 (true) if the switch should fire today, 1 otherwise.
sched_day_match(){
today=$(date +%Y%m%d)
now_dow=$(date +%w) # 0=Sun .. 6=Sat
case "$sched_period" in
daily)
return 0
;;
weekly)
[ "$now_dow" = "$sched_weekday" ] && return 0
return 1
;;
interval)
# Read the date of the last successful switch from persistent state.
# We keep it in /tmp/ssw_sched_last.date so it survives across
# the daemon's iterations but resets on reboot (intentional —
# after reboot the interval counter restarts from today).
last_date=""
[ -f /tmp/ssw_sched_last.date ] && last_date=$(cat /tmp/ssw_sched_last.date)
if [ -z "$last_date" ]; then
# First run ever (or after reboot): trigger today.
return 0
fi
# Calculate elapsed days between last_date and today (YYYYMMDD arithmetic).
# Use date to convert both to unix timestamps then divide.
ts_last=$(date -d "$last_date" +%s 2>/dev/null)
[ -z "$ts_last" ] && ts_last=$(date -jf "%Y%m%d" "$last_date" +%s 2>/dev/null)
ts_now=$(date +%s)
elapsed_days=$(( (ts_now - ts_last) / 86400 ))
[ "$elapsed_days" -ge "$sched_period_days" ] && return 0
return 1
;;
*)
# Unknown period — treat as daily
return 0
;;
esac
}
# Schedule: switch to reserve SIM at configured time
check_schedule(){
[ "$sched_enable" = "1" ] || return
[ -n "$sched_time_on" ] || return
# Handle pending revert first — takes priority over new switch logic.
if [ -f /tmp/ssw_sched.vars ]; then
sched_revert
return
fi
# Parse HH:MM (strip leading zeros to avoid octal)
sched_h=$(echo "$sched_time_on" | cut -d: -f1 | sed 's/^0*//')
sched_m=$(echo "$sched_time_on" | cut -d: -f2 | sed 's/^0*//')
[ -z "$sched_h" ] && sched_h=0
[ -z "$sched_m" ] && sched_m=0
now_h=$(date +%H | sed 's/^0*//')
now_m=$(date +%M | sed 's/^0*//')
[ -z "$now_h" ] && now_h=0
[ -z "$now_m" ] && now_m=0
# Check time window: [sched_time .. sched_time + ceil(interval/60)) minutes
now_total=$(( now_h * 60 + now_m ))
sched_total=$(( sched_h * 60 + sched_m ))
interval_min=$(( interval / 60 + 1 ))
diff=$(( now_total - sched_total ))
# Not in the time window yet
if [ "$diff" -lt 0 ] || [ "$diff" -ge "$interval_min" ]; then
return
fi
# Check if the period condition is met (daily / weekly / every N days)
sched_day_match || return
# Check if we already fired today (prevents re-triggering within the same window)
today=$(date +%Y%m%d)
if [ -f /tmp/ssw_sched_fired.date ]; then
fired=$(cat /tmp/ssw_sched_fired.date)
[ "$fired" = "$today" ] && return
fi
# All conditions met — switch to reserve SIM
cur_sim=$(cat /sys/class/gpio/$sim_gpio/value)
if [ "$cur_sim" -ne "$sim_value" ]; then
# Already on reserve SIM (e.g. failover active), skip but record the day.
logger -t "$NODE" "Schedule: already on reserve SIM, skipping switch"
echo "$today" > /tmp/ssw_sched_fired.date
return
fi
logger -t "$NODE" "Schedule: switching to reserve SIM (period=$sched_period, time=$sched_time_on)"
iface=$(uci show network | awk -F [.] '/devices/{gsub("'\''","");print $2}' | tail -1)
apn_use="${sched_apn:-${apn2:-internet}}"
uci set network.$iface.apn="$apn_use"
uci commit network
reload_config network
sw_sim && sleep 20 && reload_iface &
# Record fire date (suppress re-trigger within same day/window)
echo "$today" > /tmp/ssw_sched_fired.date
# For interval mode: record as the last successful switch date
if [ "$sched_period" = "interval" ]; then
echo "$today" > /tmp/ssw_sched_last.date
fi
# Arm the revert timer if duration > 0
if [ "$sched_duration" -gt 0 ]; then
revert_at=$(( $(date +%s) + sched_duration * 60 ))
echo "SCHED_REVERT_AT=$revert_at" > /tmp/ssw_sched.vars
logger -t "$NODE" "Schedule: will revert to default SIM in ${sched_duration} min"
else
logger -t "$NODE" "Schedule: no auto-revert configured"
fi
}
# Check interface state via mwan3
monitor_mwan3(){
iface=$(uci show network | awk -F [.] '/devices/{print $2}')
@@ -268,10 +99,10 @@ monitor_rsrp(){
CRSRP=$(echo "$SIGNAL" | jsonfilter -e '@["modem"][*]["5g"]["rsrp"]' | awk '{printf "%.0f\n", $1}')
fi
if [ $CRSRP -ne 0 ]; then
if [ -n "$CRSRP" ] && [ "$CRSRP" -ne "0" ]; then
echo $CRSRP >> /tmp/ssw_rsrp.var
fi
if [ $cnt -eq $times_rsrp ]; then
if [ "$cnt" -eq "$times_rsrp" ]; then
RSRP=$(awk '{sum+=$1} END { printf "%.0f\n", sum/NR }' /tmp/ssw_rsrp.var)
cat /dev/null > /tmp/ssw_rsrp.var
if [ $RSRP -lt $rsrp ]; then
@@ -297,9 +128,6 @@ while true; do
get_vars
sleep $interval
# Schedule check runs every iteration, independently of failover
check_schedule
if [ "$enable" = "1" ]; then
cur_sim=$(cat /sys/class/gpio/$sim_gpio/value)
monitor_rsrp
@@ -333,22 +161,8 @@ while true; do
uci commit network
reload_config network
if [ "$revert" = "1" ]; then
if [ "$cur_sim" -eq "$sim_value" ]; then
FBT=${FBT:=$((($interval+$times_rsrp)*2))}
FBT=$(($FBT*2))
SWDATE=$((`date +%s`+$FBT))
echo "FBT=$FBT" > /tmp/ssw.vars
echo SWDATE=$SWDATE >> /tmp/ssw.vars
logger -t "$NODE" "Back to default SIM-slot after $(date -d @${SWDATE})"
fi
fi
sw_sim && sleep 20 && reload_iface &
fi
if [ "$revert" = "1" ]; then
sw_rule && sleep 20 && reload_iface &
fi
cnt=0
else
cnt=$(($cnt+1))