first commit
This commit is contained in:
1
files/files/crond-root
Normal file
1
files/files/crond-root
Normal file
@@ -0,0 +1 @@
|
||||
*/1 * * * * /root/wifidebug.sh
|
||||
1
files/files/crond-root-scroll24
Normal file
1
files/files/crond-root-scroll24
Normal file
@@ -0,0 +1 @@
|
||||
*/20 * * * * /root/scroll24.sh --allbymyself
|
||||
8
files/files/filter_1vap_id0.jq
Normal file
8
files/files/filter_1vap_id0.jq
Normal file
@@ -0,0 +1,8 @@
|
||||
# enable+lbd on index 0 (no touching others)
|
||||
( . as $root
|
||||
| ( $root.wireless.radios[$r].vaps // [] ) as $v
|
||||
| if ($v | length) >= 1 then
|
||||
.wireless.radios[$r].vaps[0].enabled = true
|
||||
| .wireless.radios[$r].vaps[0].lbd = true
|
||||
else . end )
|
||||
|
||||
11
files/files/filter_1vap_id1.jq
Normal file
11
files/files/filter_1vap_id1.jq
Normal file
@@ -0,0 +1,11 @@
|
||||
# enable+lbd on index 1 (Policy B)
|
||||
( . as $root
|
||||
| ( $root.wireless.radios[$r].vaps // [] ) as $v
|
||||
| if ($v | length) >= 2 then
|
||||
.wireless.radios[$r].vaps[1].enabled = true
|
||||
| .wireless.radios[$r].vaps[1].lbd = true
|
||||
else
|
||||
( .wireless.radios[$r].vaps[1].enabled = true
|
||||
| .wireless.radios[$r].vaps[1].lbd = true )
|
||||
end )
|
||||
|
||||
9
files/files/filter_2vaps_0_1.jq
Normal file
9
files/files/filter_2vaps_0_1.jq
Normal file
@@ -0,0 +1,9 @@
|
||||
# keep 0 (enable+lbd), disable 1
|
||||
( . as $root
|
||||
| ( $root.wireless.radios[$r].vaps // [] ) as $v
|
||||
| if ($v | length) >= 2 then
|
||||
.wireless.radios[$r].vaps[0].enabled = true
|
||||
| .wireless.radios[$r].vaps[0].lbd = true
|
||||
| .wireless.radios[$r].vaps[1].enabled = false
|
||||
else . end )
|
||||
|
||||
9
files/files/filter_2vaps_1_0.jq
Normal file
9
files/files/filter_2vaps_1_0.jq
Normal file
@@ -0,0 +1,9 @@
|
||||
# layout 1,0 -> same outcome: keep 0 (enable+lbd), disable 1
|
||||
( . as $root
|
||||
| ( $root.wireless.radios[$r].vaps // [] ) as $v
|
||||
| if ($v | length) >= 2 then
|
||||
.wireless.radios[$r].vaps[0].enabled = true
|
||||
| .wireless.radios[$r].vaps[0].lbd = true
|
||||
| .wireless.radios[$r].vaps[1].enabled = false
|
||||
else . end )
|
||||
|
||||
371
files/files/scroll24.sh
Normal file
371
files/files/scroll24.sh
Normal file
@@ -0,0 +1,371 @@
|
||||
#!/bin/sh
|
||||
# wifiscan24.sh — 2.4 GHz channel scout for ath1 (BusyBox-safe)
|
||||
# Default: probe 1/6/11 (+ current), print recommendation, restore original.
|
||||
#
|
||||
# Flags:
|
||||
# --goforit : scan + apply best, policy prefers 1/6/11, verify
|
||||
# --force : as above, but pre-reset AP (disable/enable) before applying
|
||||
# --allbymyself : try like --goforit; if apply fails, auto-bounce AP and retry once
|
||||
# --keepbadchannels : allow 2–5 or 7–10 if they win (only matters with goforit/force/allbymyself)
|
||||
# --chan <N> : override — switch directly to channel N (ignores scan & policy)
|
||||
# works alone (no reset) or with --force (preflight reset)
|
||||
# --deep : deeper scan (longer dwell); works with apply modes
|
||||
#
|
||||
# Score: score = 7*OBSSavg + 3*CUavg (lower is better)
|
||||
# Ties: lower OBSSmax → lower (more negative) noise → lower CUavg
|
||||
#
|
||||
# Apply policy:
|
||||
# By default apply only to {1,6,11}. To allow middle channels {2..5,7..10} add --keepbadchannels
|
||||
sleep 20
|
||||
|
||||
IFACE="${IFACE:-ath1}"
|
||||
CHANNELS="${CHANNELS:-1 6 11}"
|
||||
CSA_BEACONS="${CSA_BEACONS:-10}" # CSA duration (~1s at default beacon interval)
|
||||
WAIT_AFTER_SWITCH="${WAIT_AFTER_SWITCH:-2}" # settle time after CSA during scan/apply
|
||||
SAMPLES="${SAMPLES:-5}" # samples per channel
|
||||
SLEEP_BETWEEN="${SLEEP_BETWEEN:-1}" # seconds between samples
|
||||
|
||||
# Deep-scan presets (used only with --deep)
|
||||
DEEP_WAIT="2"
|
||||
DEEP_SAMPLES="10"
|
||||
DEEP_SLEEP="1"
|
||||
|
||||
GOOD_CH_SET="1 6 11" # policy-preferred set
|
||||
|
||||
GOFORIT=0
|
||||
FORCE=0
|
||||
ALLBY=0
|
||||
DEEP=0
|
||||
KEEPBAD=0
|
||||
OVERRIDE_CH=""
|
||||
|
||||
# ---- arg parse ----
|
||||
while [ $# -gt 0 ]; do
|
||||
case "$1" in
|
||||
--goforit|--go|--apply) GOFORIT=1 ;;
|
||||
--force) FORCE=1 ;;
|
||||
--allbymyself) ALLBY=1 ;;
|
||||
--deep) DEEP=1 ;;
|
||||
--keepbadchannels) KEEPBAD=1 ;;
|
||||
--chan)
|
||||
shift
|
||||
[ -n "$1" ] || { echo "Error: --chan requires a channel number." >&2; exit 1; }
|
||||
OVERRIDE_CH="$1"
|
||||
;;
|
||||
-h|--help)
|
||||
cat <<EOF
|
||||
Usage: $0 [--goforit|--force|--allbymyself] [--keepbadchannels] [--deep] [--chan N]
|
||||
|
||||
Apply modes (choose one):
|
||||
--goforit scan + apply best (policy prefers 1/6/11), verify
|
||||
--force as above, but pre-reset AP before applying
|
||||
--allbymyself like --goforit; if apply fails, auto-bounce AP and retry once
|
||||
|
||||
Extras:
|
||||
--keepbadchannels allow 2–5/7–10 if they win (only with apply modes)
|
||||
--deep deeper scan dwell (more stable numbers)
|
||||
--chan N override: switch immediately to channel N (ignores scan & policy)
|
||||
EOF
|
||||
exit 0
|
||||
;;
|
||||
*)
|
||||
echo "Unknown option: $1" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
shift
|
||||
done
|
||||
|
||||
# If multiple apply flags passed, pick strongest precedence: FORCE > ALLBY > GOFORIT
|
||||
if [ "$FORCE" -eq 1 ]; then
|
||||
GOFORIT=0
|
||||
ALLBY=0
|
||||
elif [ "$ALLBY" -eq 1 ]; then
|
||||
GOFORIT=0
|
||||
fi
|
||||
|
||||
# Deep dwell
|
||||
if [ "$DEEP" -eq 1 ]; then
|
||||
WAIT_AFTER_SWITCH="$DEEP_WAIT"
|
||||
SAMPLES="$DEEP_SAMPLES"
|
||||
SLEEP_BETWEEN="$DEEP_SLEEP"
|
||||
fi
|
||||
|
||||
# ---- helpers ----
|
||||
freq_from_ch() { ch="$1"; [ "$ch" -eq 14 ] && { echo 2484; return; }; echo $((2412 + 5*(ch-1))); }
|
||||
ch_from_freq() { f="$1"; [ "$f" -eq 2484 ] && { echo 14; return; }; echo $(( (f-2412)/5 + 1 )); }
|
||||
|
||||
valid_ch() {
|
||||
case "$1" in
|
||||
''|*[!0-9]*) return 1 ;;
|
||||
*) [ "$1" -ge 1 ] && [ "$1" -le 14 ] ;;
|
||||
esac
|
||||
}
|
||||
|
||||
in_good_set() {
|
||||
case " $GOOD_CH_SET " in
|
||||
*" $1 "*) return 0 ;;
|
||||
*) return 1 ;;
|
||||
esac
|
||||
}
|
||||
|
||||
get_current_freq() {
|
||||
f="$(hostapd_cli -i "$IFACE" status 2>/dev/null | awk -F= '/^freq=/{print $2; exit}')"
|
||||
[ -n "$f" ] || f="$(wifitool "$IFACE" get_rrmutil 2>/dev/null | awk -F': *' '/^channel/{print $2; exit}')"
|
||||
echo "$f"
|
||||
}
|
||||
|
||||
measure_once() {
|
||||
# prints: "chan_util obss_util noise"
|
||||
wifitool "$IFACE" get_rrmutil 2>/dev/null | awk -F': *' '
|
||||
/^chan util/ {cu=$2+0}
|
||||
/^obss util/ {ob=$2+0}
|
||||
/^noise floor/ {nf=$2+0}
|
||||
END {printf "%d %d %d\n", cu, ob, nf}
|
||||
'
|
||||
}
|
||||
|
||||
# CSA wrapper (quiet)
|
||||
do_csa() {
|
||||
hostapd_cli -i "$IFACE" chan_switch "$CSA_BEACONS" "$1" ht bandwidth=20 blocktx >/dev/null 2>&1
|
||||
}
|
||||
|
||||
# Verify helper
|
||||
verify_freq() {
|
||||
target="$1"
|
||||
sleep "$WAIT_AFTER_SWITCH"
|
||||
cur="$(get_current_freq)"
|
||||
[ "$cur" = "$target" ]
|
||||
}
|
||||
|
||||
# Self-bounce helper
|
||||
ap_bounce() {
|
||||
hostapd_cli -i "$IFACE" disable >/dev/null 2>&1
|
||||
sleep 2
|
||||
hostapd_cli -i "$IFACE" enable >/dev/null 2>&1
|
||||
sleep 2
|
||||
}
|
||||
|
||||
# ---- prereqs ----
|
||||
command -v hostapd_cli >/dev/null 2>&1 || { echo "hostapd_cli not found"; exit 1; }
|
||||
command -v wifitool >/dev/null 2>&1 || { echo "wifitool not found"; exit 1; }
|
||||
|
||||
orig_freq="$(get_current_freq)"; orig_ch="$(ch_from_freq "$orig_freq")"
|
||||
|
||||
# ---------- OVERRIDE PATH: --chan N ----------
|
||||
if [ -n "$OVERRIDE_CH" ]; then
|
||||
valid_ch "$OVERRIDE_CH" || { echo "Invalid channel: $OVERRIDE_CH (expected 1..14)"; exit 1; }
|
||||
target_freq="$(freq_from_ch "$OVERRIDE_CH")"
|
||||
if [ "$target_freq" = "$orig_freq" ]; then
|
||||
echo "Already on channel $OVERRIDE_CH ($target_freq MHz). No switch needed."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [ "$FORCE" -eq 1 ]; then
|
||||
echo "Pre-resetting AP before override…"
|
||||
ap_bounce
|
||||
fi
|
||||
|
||||
echo "Applying override: hostapd_cli -i $IFACE chan_switch $CSA_BEACONS $target_freq ht bandwidth=20 blocktx"
|
||||
do_csa "$target_freq"
|
||||
if verify_freq "$target_freq"; then
|
||||
echo "Switched to ch $OVERRIDE_CH ($target_freq MHz)."
|
||||
exit 0
|
||||
else
|
||||
echo "Override failed to take effect. Try: --chan $OVERRIDE_CH --force"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
# ---------- SCAN PATH ----------
|
||||
# unique set incl. current
|
||||
unique=""; add(){ case " $unique " in *" $1 "*) : ;; *) unique="$unique $1";; esac; }
|
||||
for c in $CHANNELS; do add "$c"; done; add "$orig_ch"
|
||||
|
||||
echo "Interface: $IFACE"
|
||||
echo "Original: ch $orig_ch ($orig_freq MHz)"
|
||||
[ "$DEEP" -eq 1 ] && echo "Mode: deep scan (WAIT=$WAIT_AFTER_SWITCH s, SAMPLES=$SAMPLES, SLEEP=$SLEEP_BETWEEN s)"
|
||||
echo "Testing: $unique"
|
||||
echo
|
||||
|
||||
tmp="$(mktemp)"
|
||||
RESTORE=1
|
||||
cleanup() {
|
||||
if [ "$RESTORE" = 1 ]; then
|
||||
do_csa "$orig_freq"
|
||||
fi
|
||||
rm -f "$tmp"
|
||||
}
|
||||
trap 'cleanup' EXIT INT TERM
|
||||
|
||||
measure_channel() {
|
||||
ch="$1"; freq="$(freq_from_ch "$ch")"
|
||||
curf="$(get_current_freq)"
|
||||
if [ "$curf" != "$freq" ]; then
|
||||
do_csa "$freq"
|
||||
sleep "$WAIT_AFTER_SWITCH"
|
||||
fi
|
||||
|
||||
cu_min=9999; cu_max=0; cu_sum=0
|
||||
ob_min=9999; ob_max=0; ob_sum=0
|
||||
nf_min=9999; nf_max=-9999; nf_sum=0
|
||||
|
||||
i=0
|
||||
while [ "$i" -lt "$SAMPLES" ]; do
|
||||
set -- $(measure_once) # $1=cu $2=ob $3=nf
|
||||
cu="$1"; ob="$2"; nf="$3"
|
||||
|
||||
[ "$cu" -lt "$cu_min" ] && cu_min="$cu"; [ "$cu" -gt "$cu_max" ] && cu_max="$cu"; cu_sum=$((cu_sum+cu))
|
||||
[ "$ob" -lt "$ob_min" ] && ob_min="$ob"; [ "$ob" -gt "$ob_max" ] && ob_max="$ob"; ob_sum=$((ob_sum+ob))
|
||||
[ "$nf" -lt "$nf_min" ] && nf_min="$nf"; [ "$nf" -gt "$nf_max" ] && nf_max="$nf"; nf_sum=$((nf_sum+nf))
|
||||
|
||||
i=$((i+1))
|
||||
[ "$i" -lt "$SAMPLES" ] && sleep "$SLEEP_BETWEEN"
|
||||
done
|
||||
|
||||
cu_avg=$((cu_sum / SAMPLES)); ob_avg=$((ob_sum / SAMPLES)); nf_avg=$((nf_sum / SAMPLES))
|
||||
|
||||
printf "ch %2d (%4d MHz): OBSS min/avg/max=%3d/%3d/%3d CHutil min/avg/max=%3d/%3d/%3d Noise avg=%4d dBm\n" \
|
||||
"$ch" "$freq" "$ob_min" "$ob_avg" "$ob_max" "$cu_min" "$cu_avg" "$cu_max" "$nf_avg"
|
||||
|
||||
# machine line: ch ob_avg cu_avg ob_max nf_avg
|
||||
echo "__RESULT__ $ch $ob_avg $cu_avg $ob_max $nf_avg"
|
||||
}
|
||||
|
||||
# Measure all
|
||||
for ch in $unique; do
|
||||
out="$(measure_channel "$ch")"
|
||||
printf "%s\n" "$out" | head -n 1
|
||||
printf "%s\n" "$out" | awk '/^__RESULT__/ {print}' >>"$tmp"
|
||||
done
|
||||
|
||||
# Pick best overall and best among 1/6/11
|
||||
best_any_ch=""; best_any_score=999999; best_any_obmax=9999; best_any_nf=0; best_any_cu=9999
|
||||
best_good_ch=""; best_good_score=999999; best_good_obmax=9999; best_good_nf=0; best_good_cu=9999
|
||||
|
||||
while read -r _ ch ob cu obmax nf; do
|
||||
score=$(( 7*ob + 3*cu ))
|
||||
|
||||
# overall best
|
||||
if [ "$score" -lt "$best_any_score" ]; then
|
||||
best_any_score="$score"; best_any_ch="$ch"; best_any_obmax="$obmax"; best_any_nf="$nf"; best_any_cu="$cu"
|
||||
elif [ "$score" -eq "$best_any_score" ]; then
|
||||
# Tie-breaker without command groups — ash-safe
|
||||
if [ "$obmax" -lt "$best_any_obmax" ]; then
|
||||
best_any_ch="$ch"; best_any_obmax="$obmax"; best_any_nf="$nf"; best_any_cu="$cu"
|
||||
elif [ "$obmax" -eq "$best_any_obmax" ]; then
|
||||
if [ "$nf" -lt "$best_any_nf" ]; then
|
||||
best_any_ch="$ch"; best_any_obmax="$obmax"; best_any_nf="$nf"; best_any_cu="$cu"
|
||||
elif [ "$nf" -eq "$best_any_nf" ] && [ "$cu" -lt "$best_any_cu" ]; then
|
||||
best_any_ch="$ch"; best_any_obmax="$obmax"; best_any_nf="$nf"; best_any_cu="$cu"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
# best among 1/6/11
|
||||
if in_good_set "$ch"; then
|
||||
if [ "$score" -lt "$best_good_score" ]; then
|
||||
best_good_score="$score"; best_good_ch="$ch"; best_good_obmax="$obmax"; best_good_nf="$nf"; best_good_cu="$cu"
|
||||
elif [ "$score" -eq "$best_good_score" ]; then
|
||||
# Tie-breaker without command groups — ash-safe
|
||||
if [ "$obmax" -lt "$best_good_obmax" ]; then
|
||||
best_good_ch="$ch"; best_good_obmax="$obmax"; best_good_nf="$nf"; best_good_cu="$cu"
|
||||
elif [ "$obmax" -eq "$best_good_obmax" ]; then
|
||||
if [ "$nf" -lt "$best_good_nf" ]; then
|
||||
best_good_ch="$ch"; best_good_obmax="$obmax"; best_good_nf="$nf"; best_good_cu="$cu"
|
||||
elif [ "$nf" -eq "$best_good_nf" ] && [ "$cu" -lt "$best_good_cu" ]; then
|
||||
best_good_ch="$ch"; best_good_obmax="$obmax"; best_good_nf="$nf"; best_good_cu="$cu"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
done <"$tmp"
|
||||
|
||||
best_any_freq="$(freq_from_ch "$best_any_ch")"
|
||||
best_good_freq=""; [ -n "$best_good_ch" ] && best_good_freq="$(freq_from_ch "$best_good_ch")"
|
||||
|
||||
echo
|
||||
echo ">>> Best by score: ch $best_any_ch ($best_any_freq MHz) [score=${best_any_score} = 7*OBSSavg + 3*CUavg]"
|
||||
|
||||
# Apply target by policy
|
||||
apply_ch=""; apply_freq=""; note="policy prefers 1/6/11"
|
||||
if [ "$KEEPBAD" -eq 1 ]; then
|
||||
apply_ch="$best_any_ch"; apply_freq="$best_any_freq"; note="--keepbadchannels set (allow 2–5/7–10)"
|
||||
else
|
||||
if [ -n "$best_good_ch" ]; then
|
||||
apply_ch="$best_good_ch"; apply_freq="$best_good_freq"
|
||||
else
|
||||
apply_ch="$best_any_ch"; apply_freq="$best_any_freq"; note="no scorable 1/6/11; falling back to overall best"
|
||||
fi
|
||||
fi
|
||||
|
||||
echo ">>> Policy target (apply): ch $apply_ch ($apply_freq MHz) [$note]"
|
||||
[ "$apply_freq" = "$orig_freq" ] && APPLY_SAME=1 || APPLY_SAME=0
|
||||
|
||||
# ---------- APPLY SECTION ----------
|
||||
if [ "$GOFORIT" -eq 1 ] || [ "$FORCE" -eq 1 ] || [ "$ALLBY" -eq 1 ]; then
|
||||
if [ "$APPLY_SAME" -eq 1 ]; then
|
||||
echo "Already on the policy target channel. No switch needed."
|
||||
RESTORE=0
|
||||
exit 0
|
||||
fi
|
||||
fi
|
||||
|
||||
# Common apply attempt
|
||||
try_apply_once() {
|
||||
tgt="$1"
|
||||
echo "Applying (no reset): hostapd_cli -i $IFACE chan_switch $CSA_BEACONS $tgt ht bandwidth=20 blocktx"
|
||||
do_csa "$tgt"
|
||||
if verify_freq "$tgt"; then
|
||||
return 0
|
||||
fi
|
||||
return 1
|
||||
}
|
||||
|
||||
if [ "$FORCE" -eq 1 ]; then
|
||||
echo "Pre-resetting AP (force)…"
|
||||
ap_bounce
|
||||
echo "Applying after reset: hostapd_cli -i $IFACE chan_switch $CSA_BEACONS $apply_freq ht bandwidth=20 blocktx"
|
||||
do_csa "$apply_freq"
|
||||
if verify_freq "$apply_freq"; then
|
||||
echo "Switched to ch $apply_ch ($apply_freq MHz) after AP reset."
|
||||
RESTORE=0
|
||||
exit 0
|
||||
else
|
||||
echo "Unable to switch automatically at this time. Keeping the original channel."
|
||||
exit 1
|
||||
fi
|
||||
elif [ "$ALLBY" -eq 1 ]; then
|
||||
# First: normal CSA
|
||||
if try_apply_once "$apply_freq"; then
|
||||
echo "Switched to ch $apply_ch ($apply_freq MHz)."
|
||||
RESTORE=0
|
||||
exit 0
|
||||
fi
|
||||
# Second: bounce then retry once
|
||||
echo "Apply failed; self-bouncing AP and retrying once…"
|
||||
ap_bounce
|
||||
if try_apply_once "$apply_freq"; then
|
||||
echo "Switched to ch $apply_ch ($apply_freq MHz) after self-bounce."
|
||||
RESTORE=0
|
||||
exit 0
|
||||
fi
|
||||
echo "Retry after self-bounce also failed. Keeping the original channel."
|
||||
exit 1
|
||||
elif [ "$GOFORIT" -eq 1 ]; then
|
||||
if try_apply_once "$apply_freq"; then
|
||||
echo "Switched to ch $apply_ch ($apply_freq MHz)."
|
||||
RESTORE=0
|
||||
exit 0
|
||||
fi
|
||||
echo "Cannot switch now; the radio needs a brief reset. Re-run with --allbymyself or --force${KEEPBAD:+ --keepbadchannels}."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# ---------- SCAN-ONLY ----------
|
||||
echo "Scan-only mode."
|
||||
echo "To apply (prefer 1/6/11): $0 --goforit"
|
||||
echo "To self-heal on failure: $0 --allbymyself"
|
||||
echo "To apply with reset: $0 --force"
|
||||
echo "To allow middle chans: add --keepbadchannels with one of the above"
|
||||
echo "To override to a chan: $0 --chan N (optionally add --force)"
|
||||
421
files/files/wifidebug.sh
Normal file
421
files/files/wifidebug.sh
Normal file
@@ -0,0 +1,421 @@
|
||||
#!/bin/sh
|
||||
|
||||
#sleep $((RANDOM % 18 + 3))
|
||||
|
||||
SCRIPTVERSION=17
|
||||
|
||||
delay=$(( ( $(hexdump -n2 -e '/2 "%u"' /dev/urandom) % 18 ) + 3 ))
|
||||
#echo "Sleeping for $delay seconds..."
|
||||
sleep $delay
|
||||
|
||||
# Get hostname
|
||||
HOSTNAME=$(cat /proc/sys/kernel/hostname)
|
||||
|
||||
FWVER=$(cat /etc/banner | grep rev | awk '{ print $1 }')
|
||||
|
||||
# ===========================================================
|
||||
# GPS coordinates management (locks, timeout, 0/0 fallback)
|
||||
# - Writes /tmp/gps_coordinates with:
|
||||
# longitude: <lon 6 decimals>
|
||||
# latitude: <lat 6 decimals>
|
||||
# - Uses /tmp/gps_coordinates.<epoch>.lock (expires 10m)
|
||||
# - Tracks retries in /tmp/gps_timeout (stop after 3)
|
||||
# - On any retrieval attempt (success/fail) -> exit cycle
|
||||
# ===========================================================
|
||||
|
||||
COORD_FILE="/tmp/gps_coordinates"
|
||||
TIMEOUT_FILE="/tmp/gps_timeout"
|
||||
LOCK_MAX_AGE_MIN=10 # minutes
|
||||
RETRIEVE_MAX_WAIT=480 # seconds (8 minutes)
|
||||
LOCATION_LON="0.000000"
|
||||
LOCATION_LAT="0.000000"
|
||||
|
||||
# Helper: parse existing coords file (if any)
|
||||
read_coords_file() {
|
||||
if [ -f "$COORD_FILE" ]; then
|
||||
# Expect two lines: "longitude: X" and "latitude: Y"
|
||||
local lon lat
|
||||
lon=$(awk -F': *' '/^longitude:/ {print $2; exit}' "$COORD_FILE")
|
||||
lat=$(awk -F': *' '/^latitude:/ {print $2; exit}' "$COORD_FILE")
|
||||
# Validate numeric and ranges; format to 6 decimals
|
||||
if echo "$lon" | awk 'BEGIN{ok=0} /^[+-]?[0-9]*\.?[0-9]+$/ {ok=1} END{exit !ok}'; then
|
||||
if echo "$lat" | awk 'BEGIN{ok=0} /^[+-]?[0-9]*\.?[0-9]+$/ {ok=1} END{exit !ok}'; then
|
||||
if awk -v a="$lat" -v b="$lon" 'BEGIN{exit !(a>=-90 && a<=90 && b>=-180 && b<=180)}'; then
|
||||
LOCATION_LON=$(awk -v x="$lon" 'BEGIN{printf "%.6f", x+0}')
|
||||
LOCATION_LAT=$(awk -v x="$lat" 'BEGIN{printf "%.6f", x+0}')
|
||||
return 0
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
return 1
|
||||
}
|
||||
|
||||
# If coords exist and valid -> proceed; else attempt retrieval logic
|
||||
if read_coords_file; then
|
||||
:
|
||||
else
|
||||
# Check retry threshold
|
||||
GTO=0
|
||||
if [ -f "$TIMEOUT_FILE" ]; then
|
||||
GTO=$(cat "$TIMEOUT_FILE" 2>/dev/null | awk '/^[0-9]+$/ {print $0; exit}')
|
||||
[ -z "$GTO" ] && GTO=0
|
||||
fi
|
||||
|
||||
if [ "$GTO" -ge 3 ]; then
|
||||
# Give up trying; ensure coords file exists with 0/0 and exit this cycle
|
||||
printf "longitude: %.6f\nlatitude: %.6f\n" 0 0 > "${COORD_FILE}.tmp"
|
||||
mv "${COORD_FILE}.tmp" "$COORD_FILE"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Clean up stale locks (>10 minutes)
|
||||
find /tmp -maxdepth 1 -type f -name 'gps_coordinates.*.lock' -mmin +"$LOCK_MAX_AGE_MIN" -exec rm -f {} \; 2>/dev/null
|
||||
|
||||
# If any non-stale lock remains, skip this run
|
||||
for f in /tmp/gps_coordinates.*.lock; do
|
||||
[ -e "$f" ] || continue
|
||||
# Found an active (<=10m) lock; skip this cycle
|
||||
exit 0
|
||||
done
|
||||
|
||||
# Create fresh lock and start retrieval
|
||||
NOWTS=$(date +%s)
|
||||
LOCK_FILE="/tmp/gps_coordinates.${NOWTS}.lock"
|
||||
: > "$LOCK_FILE" 2>/dev/null
|
||||
|
||||
CAND="/tmp/gps_candidate.$$"
|
||||
(
|
||||
gpspipe -r | awk -F, '
|
||||
# -------- THE ONLY CHANGE IS HERE: use deglen+1 for minutes --------
|
||||
function dm2dd(dm, hemi, deglen, deg, min, dd) {
|
||||
if (dm=="" || hemi=="") return ""
|
||||
deglen = (hemi=="N" || hemi=="S") ? 2 : 3
|
||||
deg = substr(dm, 1, deglen) + 0
|
||||
min = substr(dm, deglen+1) + 0
|
||||
dd = deg + (min / 60.0)
|
||||
return (hemi=="S" || hemi=="W") ? -dd : dd
|
||||
}
|
||||
# Wait for first valid RMC (A)
|
||||
/^\$..RMC/ && $3=="A" {
|
||||
lat = dm2dd($4, $5)
|
||||
lon = dm2dd($6, $7)
|
||||
if (lat != "" && lon != "") {
|
||||
printf("%.6f %.6f\n", lon, lat)
|
||||
exit
|
||||
}
|
||||
}
|
||||
' > "$CAND"
|
||||
) &
|
||||
GPID=$!
|
||||
|
||||
# Wait up to RETRIEVE_MAX_WAIT seconds for candidate to appear
|
||||
waited=0
|
||||
while [ "$waited" -lt "$RETRIEVE_MAX_WAIT" ]; do
|
||||
if [ -s "$CAND" ]; then
|
||||
break
|
||||
fi
|
||||
sleep 1
|
||||
waited=$((waited+1))
|
||||
done
|
||||
|
||||
success=0
|
||||
if [ -s "$CAND" ]; then
|
||||
set -- $(head -n1 "$CAND" 2>/dev/null)
|
||||
cand_lon="$1"
|
||||
cand_lat="$2"
|
||||
if awk -v a="$cand_lat" -v b="$cand_lon" 'BEGIN{ok=(a!="" && b!=""); if (!ok) exit 1; exit !(a>=-90 && a<=90 && b>=-180 && b<=180)}'
|
||||
then
|
||||
printf "longitude: %.6f\nlatitude: %.6f\n" "$cand_lon" "$cand_lat" > "${COORD_FILE}.tmp"
|
||||
mv "${COORD_FILE}.tmp" "$COORD_FILE"
|
||||
echo 0 > "$TIMEOUT_FILE"
|
||||
success=1
|
||||
fi
|
||||
fi
|
||||
|
||||
# Cleanup background gpspipe if still running
|
||||
kill "$GPID" 2>/dev/null
|
||||
sleep 1
|
||||
kill -9 "$GPID" 2>/dev/null
|
||||
|
||||
# Remove lock and temp
|
||||
rm -f "$LOCK_FILE" "$CAND" 2>/dev/null
|
||||
|
||||
# Exit this cycle after any retrieval attempt (success or fail)
|
||||
if [ "$success" -eq 1 ]; then
|
||||
exit 0
|
||||
else
|
||||
printf "longitude: %.6f\nlatitude: %.6f\n" 0 0 > "${COORD_FILE}.tmp"
|
||||
mv "${COORD_FILE}.tmp" "$COORD_FILE"
|
||||
GTO=$((GTO+1))
|
||||
echo "$GTO" > "$TIMEOUT_FILE"
|
||||
exit 0
|
||||
fi
|
||||
fi
|
||||
|
||||
# At this point, LOCATION_LON/LOCATION_LAT are set (from file or default 0/0)
|
||||
|
||||
# Get OBSS utilization value from wifitool
|
||||
ATH0_OBSS_UTIL=$(wifitool ath0 get_rrmutil | awk '/obss util/ { print $4 }')
|
||||
ATH1_OBSS_UTIL=$(wifitool ath1 get_rrmutil | awk '/obss util/ { print $4 }')
|
||||
ATH0_CH_UTIL=$(cfg80211tool ath0 get_chutil | awk -F ':' '{ print $2 }')
|
||||
ATH1_CH_UTIL=$(cfg80211tool ath1 get_chutil | awk -F ':' '{ print $2 }')
|
||||
|
||||
# -----------------------------------------------------------
|
||||
# Count connected (real) clients on ath0 and ath1
|
||||
# -----------------------------------------------------------
|
||||
|
||||
get_usercount() {
|
||||
IFACE=$1
|
||||
hostapd_cli -i "$IFACE" all_sta 2>/dev/null | awk '
|
||||
/^[0-9a-f]{2}(:[0-9a-f]{2}){5}$/ {mac=$0; next}
|
||||
/flags=/ {
|
||||
auth = (index($0, "AUTH") > 0)
|
||||
assoc = (index($0, "ASSOC") > 0)
|
||||
authorized = (index($0, "AUTHORIZED") > 0)
|
||||
}
|
||||
/rx_packets=/ {rx_packets=$1; sub("rx_packets=", "", rx_packets)}
|
||||
/tx_packets=/ {tx_packets=$1; sub("tx_packets=", "", tx_packets)}
|
||||
/inactive_msec=/ {inactive=$1; sub("inactive_msec=", "", inactive)}
|
||||
/connected_time=/ {
|
||||
connected=$1; sub("connected_time=", "", connected)
|
||||
if (auth && assoc && authorized &&
|
||||
rx_packets+0 > 0 && tx_packets+0 > 0 &&
|
||||
inactive+0 < 5000 && connected+0 > 60) {
|
||||
count++
|
||||
}
|
||||
}
|
||||
END { print count+0 }
|
||||
'
|
||||
}
|
||||
|
||||
ATH0_USERCOUNT=$(get_usercount ath0)
|
||||
ATH1_USERCOUNT=$(get_usercount ath1)
|
||||
|
||||
# -----------------------------------------------------------
|
||||
# Get IP/MAC for br-wan
|
||||
# -----------------------------------------------------------
|
||||
|
||||
MACADDRESS=$(ip link show br-wan | awk '/link\/ether/ {print $2}')
|
||||
IPADDR_MASK=$(ip -4 addr show br-wan | awk '/inet / {print $2}' | head -n 1)
|
||||
IPADDRESS=${IPADDR_MASK%/*}
|
||||
IPMASK=${IPADDR_MASK#*/}
|
||||
|
||||
# -----------------------------------------------------------
|
||||
# Get LLDP neighbor switch
|
||||
NEIGH_SW=$(grep ikeja /tmp/run/lldp_server.json | grep -E "\-sc|\-as" -m1 | sed -E 's/.*"system_name": "([^"]+)".*/\1/')
|
||||
|
||||
# -----------------------------------------------------------
|
||||
# Get default GW
|
||||
DEFGW=$(ip route show | grep default | awk '{ print $3 }')
|
||||
|
||||
# -----------------------------------------------------------
|
||||
|
||||
# Run once per iface and reuse the buffer
|
||||
ATH0_RAW="$(apstats -v -i ath0 2>/dev/null)"
|
||||
ATH1_RAW="$(apstats -v -i ath1 2>/dev/null)"
|
||||
|
||||
# ---- ath0 (read from ATH0_RAW) ----
|
||||
ATH0_TXDP=$(printf '%s\n' "$ATH0_RAW" | grep -m 1 "Tx Data Packets " | awk '{ print $NF }')
|
||||
ATH0_RXDP=$(printf '%s\n' "$ATH0_RAW" | grep -m 1 "Rx Data Packets" | awk '{ print $NF }')
|
||||
ATH0_TXUDP=$(printf '%s\n' "$ATH0_RAW" | grep "Tx Unicast Data Packets" | awk '{ print $NF }')
|
||||
ATH0_TXMBDP=$(printf '%s\n' "$ATH0_RAW" | grep "Tx Multi/Broadcast Data Packets" | awk '{ print $NF }')
|
||||
ATH0_TXMDP=$(printf '%s\n' "$ATH0_RAW" | grep "Tx multicast Data Packets" | awk '{ print $NF }')
|
||||
ATH0_TXBDP=$(printf '%s\n' "$ATH0_RAW" | grep "Tx Broadcast Data Packets" | awk '{ print $NF }')
|
||||
ATH0_TXFLR=$(printf '%s\n' "$ATH0_RAW" | grep "Tx failures" | awk '{ print $NF }')
|
||||
ATH0_PCKERR=$(printf '%s\n' "$ATH0_RAW" | grep "Packets Errored" | awk '{ print $NF }')
|
||||
ATH0_RETR=$(printf '%s\n' "$ATH0_RAW" | grep "Retries" | awk '{ print $NF }')
|
||||
ATH0_BCNSUC=$(printf '%s\n' "$ATH0_RAW" | grep "Beacon success" | awk '{ print $NF }')
|
||||
ATH0_BCNFLR=$(printf '%s\n' "$ATH0_RAW" | grep "Beacon failed" | awk '{ print $NF }')
|
||||
|
||||
ATH0_TXRATE=$(echo "$ATH0_RAW" | awk -F'=' '/^Average Tx Rate/{gsub(/[^0-9]/,"",$2); print ($2==""?0:$2); exit}')
|
||||
ATH0_RXRATE=$(echo "$ATH0_RAW" | awk -F'=' '/^Average Rx Rate/{gsub(/[^0-9]/,"",$2); print ($2==""?0:$2); exit}')
|
||||
|
||||
# ---- ath1 (read from ATH1_RAW) ----
|
||||
ATH1_TXDP=$(printf '%s\n' "$ATH1_RAW" | grep -m 1 "Tx Data Packets " | awk '{ print $NF }')
|
||||
ATH1_RXDP=$(printf '%s\n' "$ATH1_RAW" | grep -m 1 "Rx Data Packets" | awk '{ print $NF }')
|
||||
ATH1_TXUDP=$(printf '%s\n' "$ATH1_RAW" | grep "Tx Unicast Data Packets" | awk '{ print $NF }')
|
||||
ATH1_TXMBDP=$(printf '%s\n' "$ATH1_RAW" | grep "Tx Multi/Broadcast Data Packets" | awk '{ print $NF }')
|
||||
ATH1_TXMDP=$(printf '%s\n' "$ATH1_RAW" | grep "Tx multicast Data Packets" | awk '{ print $NF }')
|
||||
ATH1_TXBDP=$(printf '%s\n' "$ATH1_RAW" | grep "Tx Broadcast Data Packets" | awk '{ print $NF }')
|
||||
ATH1_TXFLR=$(printf '%s\n' "$ATH1_RAW" | grep "Tx failures" | awk '{ print $NF }')
|
||||
ATH1_PCKERR=$(printf '%s\n' "$ATH1_RAW" | grep "Packets Errored" | awk '{ print $NF }')
|
||||
ATH1_RETR=$(printf '%s\n' "$ATH1_RAW" | grep "Retries" | awk '{ print $NF }')
|
||||
ATH1_BCNSUC=$(printf '%s\n' "$ATH1_RAW" | grep "Beacon success" | awk '{ print $NF }')
|
||||
ATH1_BCNFLR=$(printf '%s\n' "$ATH1_RAW" | grep "Beacon failed" | awk '{ print $NF }')
|
||||
|
||||
ATH1_TXRATE=$(echo "$ATH1_RAW" | awk -F'=' '/^Average Tx Rate/{gsub(/[^0-9]/,"",$2); print ($2==""?0:$2); exit}')
|
||||
ATH1_RXRATE=$(echo "$ATH1_RAW" | awk -F'=' '/^Average Rx Rate/{gsub(/[^0-9]/,"",$2); print ($2==""?0:$2); exit}')
|
||||
|
||||
# -----------------------------------------------------------
|
||||
# channels
|
||||
# -----------------------------------------------------------
|
||||
|
||||
ATH0_CH_NMBR=$(iw dev ath0 info | grep MHz | awk '{ print $2 }')
|
||||
ATH0_CH_WIDTH=$(iw dev ath0 info | grep MHz | awk '{ print $6 }')
|
||||
ATH0_CH_CNTR=$(iw dev ath0 info | grep MHz | awk '{ print $(NF-1) }')
|
||||
|
||||
ATH1_CH_NMBR=$(iw dev ath1 info | grep MHz | awk '{ print $2 }')
|
||||
ATH1_CH_WIDTH=$(iw dev ath1 info | grep MHz | awk '{ print $6 }')
|
||||
ATH1_CH_CNTR=$(iw dev ath1 info | grep MHz | awk '{ print $(NF-1) }')
|
||||
|
||||
# --- ath1 RSSI buckets (gold/silver/bronze/trash) ---
|
||||
ATH1_USGLD=0; ATH1_USSLV=0; ATH1_USBRN=0; ATH1_USTRS=0
|
||||
_assigns="$(
|
||||
(
|
||||
exec 2>/dev/null
|
||||
hostapd_cli -i ath1 all_sta \
|
||||
| grep 'AUTHORIZED' -B1 -A12 \
|
||||
| grep -E '([[:xdigit:]]{2}:){5}[[:xdigit:]]{2}|^signal=' \
|
||||
| awk '
|
||||
BEGIN { g=0; s=0; b=0; t=0 }
|
||||
/^[0-9A-Fa-f]{2}(:[0-9A-Fa-f]{2}){5}$/ { next }
|
||||
/^signal=/ {
|
||||
sig=$0; sub(/^signal=[[:space:]]*/,"",sig); sig+=0
|
||||
if (sig>=-65 && sig<=-20) g++
|
||||
else if (sig>=-75 && sig<=-66) s++
|
||||
else if (sig>=-85 && sig<=-76) b++
|
||||
else if (sig>=-200 && sig<=-86) t++
|
||||
}
|
||||
END {
|
||||
printf "ATH1_USGLD=%d\nATH1_USSLV=%d\nATH1_USBRN=%d\nATH1_USTRS=%d\n", g+0, s+0, b+0, t+0
|
||||
}
|
||||
'
|
||||
) || true
|
||||
)"
|
||||
if printf '%s\n' "$_assigns" | awk -F= '
|
||||
NR==1 && $1=="ATH1_USGLD" && $2 ~ /^[0-9]+$/ {ok1=1}
|
||||
NR==2 && $1=="ATH1_USSLV" && $2 ~ /^[0-9]+$/ {ok2=1}
|
||||
NR==3 && $1=="ATH1_USBRN" && $2 ~ /^[0-9]+$/ {ok3=1}
|
||||
NR==4 && $1=="ATH1_USTRS" && $2 ~ /^[0-9]+$/ {ok4=1}
|
||||
END{ exit !(ok1&&ok2&&ok3&&ok4) }
|
||||
'; then
|
||||
eval "$_assigns"
|
||||
fi
|
||||
case "$ATH1_USGLD" in (''|*[!0-9]*) ATH1_USGLD=0;; esac
|
||||
case "$ATH1_USSLV" in (''|*[!0-9]*) ATH1_USSLV=0;; esac
|
||||
case "$ATH1_USBRN" in (''|*[!0-9]*) ATH1_USBRN=0;; esac
|
||||
case "$ATH1_USTRS" in (''|*[!0-9]*) ATH1_USTRS=0;; esac
|
||||
|
||||
# --- ath0 RSSI buckets (gold/silver/bronze/trash) ---
|
||||
ATH0_USGLD=0; ATH0_USSLV=0; ATH0_USBRN=0; ATH0_USTRS=0
|
||||
_assigns="$(
|
||||
(
|
||||
exec 2>/dev/null
|
||||
hostapd_cli -i ath0 all_sta \
|
||||
| grep 'AUTHORIZED' -B1 -A12 \
|
||||
| grep -E '([[:xdigit:]]{2}:){5}[[:xdigit:]]{2}|^signal=' \
|
||||
| awk '
|
||||
BEGIN { g=0; s=0; b=0; t=0 }
|
||||
/^[0-9A-Fa-f]{2}(:[0-9A-Fa-f]{2}){5}$/ { next }
|
||||
/^signal=/ {
|
||||
sig=$0; sub(/^signal=[[:space:]]*/,"",sig); sig+=0
|
||||
if (sig>=-65 && sig<=-20) g++
|
||||
else if (sig>=-75 && sig<=-66) s++
|
||||
else if (sig>=-85 && sig<=-76) b++
|
||||
else if (sig>=-200 && sig<=-86) t++
|
||||
}
|
||||
END {
|
||||
printf "ATH0_USGLD=%d\nATH0_USSLV=%d\nATH0_USBRN=%d\nATH0_USTRS=%d\n", g+0, s+0, b+0, t+0
|
||||
}
|
||||
'
|
||||
) || true
|
||||
)"
|
||||
if printf '%s\n' "$_assigns" | awk -F= '
|
||||
NR==1 && $1=="ATH0_USGLD" && $2 ~ /^[0-9]+$/ {ok1=1}
|
||||
NR==2 && $1=="ATH0_USSLV" && $2 ~ /^[0-9]+$/ {ok2=1}
|
||||
NR==3 && $1=="ATH0_USBRN" && $2 ~ /^[0-9]+$/ {ok3=1}
|
||||
NR==4 && $1=="ATH0_USTRS" && $2 ~ /^[0-9]+$/ {ok4=1}
|
||||
END{ exit !(ok1&&ok2&&ok3&&ok4) }
|
||||
'; then
|
||||
eval "$_assigns"
|
||||
fi
|
||||
case "$ATH0_USGLD" in (''|*[!0-9]*) ATH0_USGLD=0;; esac
|
||||
case "$ATH0_USSLV" in (''|*[!0-9]*) ATH0_USSLV=0;; esac
|
||||
case "$ATH0_USBRN" in (''|*[!0-9]*) ATH0_USBRN=0;; esac
|
||||
case "$ATH0_USTRS" in (''|*[!0-9]*) ATH0_USTRS=0;; esac
|
||||
|
||||
# -----------------------------------------------------------
|
||||
# FCS totals/errored
|
||||
# -----------------------------------------------------------
|
||||
|
||||
WIFISTATS_ATH0_FCSOK=$(wifistats wifi0 2 | grep fcs_ok | awk '{ print $3 }')
|
||||
WIFISTATS_ATH0_FCSERR=$(wifistats wifi0 2 | grep fcs_err | awk '{ print $3 }')
|
||||
|
||||
WIFISTATS_ATH1_FCSOK=$(wifistats wifi1 2 | grep fcs_ok | awk '{ print $3 }')
|
||||
WIFISTATS_ATH1_FCSERR=$(wifistats wifi1 2 | grep fcs_err | awk '{ print $3 }')
|
||||
|
||||
# 10-hex-char uuid for correlation (shared between the two parts)
|
||||
UUID=$(hexdump -n5 -e '5/1 "%02x"' /dev/urandom)
|
||||
|
||||
# ------------------------
|
||||
# Part 1: ath0 + shared (+ GPS)
|
||||
# ------------------------
|
||||
MSG1="hostname=${HOSTNAME} \
|
||||
uuid=${UUID} part=1 \
|
||||
scrver=${SCRIPTVERSION} \
|
||||
ath0_ch_nmbr=${ATH0_CH_NMBR} \
|
||||
ath0_ch_width=${ATH0_CH_WIDTH} \
|
||||
ath0_ch_cntr=${ATH0_CH_CNTR} \
|
||||
ath0_obss_util=${ATH0_OBSS_UTIL} \
|
||||
ath0_chutil=${ATH0_CH_UTIL} \
|
||||
ath0_txdp=${ATH0_TXDP} \
|
||||
ath0_rxdp=${ATH0_RXDP} \
|
||||
ath0_txudp=${ATH0_TXUDP} \
|
||||
ath0_txmbdp=${ATH0_TXMBDP} \
|
||||
ath0_txmdp=${ATH0_TXMDP} \
|
||||
ath0_txbdp=${ATH0_TXBDP} \
|
||||
ath0_txflr=${ATH0_TXFLR} \
|
||||
ath0_txrate=${ATH0_TXRATE} \
|
||||
ath0_rxrate=${ATH0_RXRATE} \
|
||||
ath0_pckerr=${ATH0_PCKERR} \
|
||||
ath0_retr=${ATH0_RETR} \
|
||||
ath0_bcnsuc=${ATH0_BCNSUC} \
|
||||
ath0_bcnflr=${ATH0_BCNFLR} \
|
||||
ath0_usercount=${ATH0_USERCOUNT} \
|
||||
ath0_usgld=${ATH0_USGLD} \
|
||||
ath0_usslv=${ATH0_USSLV} \
|
||||
ath0_usbrn=${ATH0_USBRN} \
|
||||
ath0_ustrs=${ATH0_USTRS} \
|
||||
ath0_fcsok=${WIFISTATS_ATH0_FCSOK} \
|
||||
ath0_fcserr=${WIFISTATS_ATH0_FCSERR} \
|
||||
fw_ver=${FWVER} ipaddress=${IPADDRESS} ipmask=${IPMASK} defgw=${DEFGW} macaddress=${MACADDRESS} neigh_switch=${NEIGH_SW} \
|
||||
location.lat=${LOCATION_LAT} location.lon=${LOCATION_LON}"
|
||||
|
||||
# ------------------------
|
||||
# Part 2: ath1 only
|
||||
# ------------------------
|
||||
MSG2="hostname=${HOSTNAME} \
|
||||
uuid=${UUID} part=2 \
|
||||
scrver=${SCRIPTVERSION} \
|
||||
ath1_ch_nmbr=${ATH1_CH_NMBR} \
|
||||
ath1_ch_width=${ATH1_CH_WIDTH} \
|
||||
ath1_ch_cntr=${ATH1_CH_CNTR} \
|
||||
ath1_obss_util=${ATH1_OBSS_UTIL} \
|
||||
ath1_chutil=${ATH1_CH_UTIL} \
|
||||
ath1_txdp=${ATH1_TXDP} \
|
||||
ath1_rxdp=${ATH1_RXDP} \
|
||||
ath1_txudp=${ATH1_TXUDP} \
|
||||
ath1_txmbdp=${ATH1_TXMBDP} \
|
||||
ath1_txmdp=${ATH1_TXMDP} \
|
||||
ath1_txbdp=${ATH1_TXBDP} \
|
||||
ath1_txflr=${ATH1_TXFLR} \
|
||||
ath1_txrate=${ATH1_TXRATE} \
|
||||
ath1_rxrate=${ATH1_RXRATE} \
|
||||
ath1_pckerr=${ATH1_PCKERR} \
|
||||
ath1_retr=${ATH1_RETR} \
|
||||
ath1_bcnsuc=${ATH1_BCNSUC} \
|
||||
ath1_bcnflr=${ATH1_BCNFLR} \
|
||||
ath1_usercount=${ATH1_USERCOUNT} \
|
||||
ath1_usgld=${ATH1_USGLD} \
|
||||
ath1_usslv=${ATH1_USSLV} \
|
||||
ath1_usbrn=${ATH1_USBRN} \
|
||||
ath1_ustrs=${ATH1_USTRS} \
|
||||
ath1_fcsok=${WIFISTATS_ATH1_FCSOK} \
|
||||
ath1_fcserr=${WIFISTATS_ATH1_FCSERR} \
|
||||
fw_ver=${FWVER} ipaddress=${IPADDRESS} ipmask=${IPMASK} defgw=${DEFGW} macaddress=${MACADDRESS} neigh_switch=${NEIGH_SW} \
|
||||
location.lat=${LOCATION_LAT} location.lon=${LOCATION_LON}"
|
||||
|
||||
# Send messages via syslog (two separate lines, same tag)
|
||||
logger -t "debug|${HOSTNAME}" "$MSG1"
|
||||
logger -t "debug|${HOSTNAME}" "$MSG2"
|
||||
294
files/files/wifidebug12.sh
Normal file
294
files/files/wifidebug12.sh
Normal file
@@ -0,0 +1,294 @@
|
||||
#!/bin/sh
|
||||
|
||||
#sleep $((RANDOM % 18 + 3))
|
||||
|
||||
SCRIPTVERSION=12
|
||||
|
||||
delay=$(( ( $(hexdump -n2 -e '/2 "%u"' /dev/urandom) % 18 ) + 3 ))
|
||||
#echo "Sleeping for $delay seconds..."
|
||||
sleep $delay
|
||||
|
||||
# Get hostname
|
||||
HOSTNAME=$(cat /proc/sys/kernel/hostname)
|
||||
|
||||
FWVER=$(cat /etc/banner | grep rev | awk '{ print $1 }')
|
||||
|
||||
# Get OBSS utilization value from wifitool
|
||||
ATH0_OBSS_UTIL=$(wifitool ath0 get_rrmutil | awk '/obss util/ { print $4 }')
|
||||
ATH1_OBSS_UTIL=$(wifitool ath1 get_rrmutil | awk '/obss util/ { print $4 }')
|
||||
ATH0_CH_UTIL=$(cfg80211tool ath0 get_chutil | awk -F ':' '{ print $2 }')
|
||||
ATH1_CH_UTIL=$(cfg80211tool ath1 get_chutil | awk -F ':' '{ print $2 }')
|
||||
|
||||
# -----------------------------------------------------------
|
||||
# Count connected (real) clients on ath0 and ath1
|
||||
# -----------------------------------------------------------
|
||||
|
||||
get_usercount() {
|
||||
IFACE=$1
|
||||
hostapd_cli -i "$IFACE" all_sta 2>/dev/null | awk '
|
||||
/^[0-9a-f]{2}(:[0-9a-f]{2}){5}$/ {mac=$0; next}
|
||||
/flags=/ {
|
||||
auth = (index($0, "AUTH") > 0)
|
||||
assoc = (index($0, "ASSOC") > 0)
|
||||
authorized = (index($0, "AUTHORIZED") > 0)
|
||||
}
|
||||
/rx_packets=/ {rx_packets=$1; sub("rx_packets=", "", rx_packets)}
|
||||
/tx_packets=/ {tx_packets=$1; sub("tx_packets=", "", tx_packets)}
|
||||
/inactive_msec=/ {inactive=$1; sub("inactive_msec=", "", inactive)}
|
||||
/connected_time=/ {
|
||||
connected=$1; sub("connected_time=", "", connected)
|
||||
if (auth && assoc && authorized &&
|
||||
rx_packets+0 > 0 && tx_packets+0 > 0 &&
|
||||
inactive+0 < 5000 && connected+0 > 60) {
|
||||
count++
|
||||
}
|
||||
}
|
||||
END { print count+0 }
|
||||
'
|
||||
}
|
||||
|
||||
ATH0_USERCOUNT=$(get_usercount ath0)
|
||||
ATH1_USERCOUNT=$(get_usercount ath1)
|
||||
|
||||
# -----------------------------------------------------------
|
||||
# Get IP/MAC for br-wan
|
||||
# -----------------------------------------------------------
|
||||
|
||||
# MAC address
|
||||
MACADDRESS=$(ip link show br-wan | awk '/link\/ether/ {print $2}')
|
||||
|
||||
# IP address and mask (CIDR)
|
||||
IPADDR_MASK=$(ip -4 addr show br-wan | awk '/inet / {print $2}' | head -n 1)
|
||||
|
||||
# Split into IP and mask separately (optional)
|
||||
IPADDRESS=${IPADDR_MASK%/*}
|
||||
IPMASK=${IPADDR_MASK#*/}
|
||||
|
||||
# -----------------------------------------------------------
|
||||
# Get LLDP neighbor switch
|
||||
#
|
||||
|
||||
NEIGH_SW=$(grep ikeja /tmp/run/lldp_server.json | grep -E "\-sc|\-as" -m1 | sed -E 's/.*"system_name": "([^"]+)".*/\1/')
|
||||
|
||||
# -----------------------------------------------------------
|
||||
# Get default GW
|
||||
# -----------------------------------------------------------
|
||||
|
||||
DEFGW=$(ip route show | grep default | awk '{ print $3 }')
|
||||
|
||||
# -----------------------------------------------------------
|
||||
|
||||
# Run once per iface and reuse the buffer
|
||||
ATH0_RAW="$(apstats -v -i ath0 2>/dev/null)"
|
||||
ATH1_RAW="$(apstats -v -i ath1 2>/dev/null)"
|
||||
|
||||
# ---- ath0 (read from ATH0_RAW) ----
|
||||
ATH0_TXDP=$(printf '%s\n' "$ATH0_RAW" | grep -m 1 "Tx Data Packets " | awk '{ print $NF }')
|
||||
ATH0_RXDP=$(printf '%s\n' "$ATH0_RAW" | grep -m 1 "Rx Data Packets" | awk '{ print $NF }')
|
||||
ATH0_TXUDP=$(printf '%s\n' "$ATH0_RAW" | grep "Tx Unicast Data Packets" | awk '{ print $NF }')
|
||||
ATH0_TXMBDP=$(printf '%s\n' "$ATH0_RAW" | grep "Tx Multi/Broadcast Data Packets" | awk '{ print $NF }')
|
||||
ATH0_TXMDP=$(printf '%s\n' "$ATH0_RAW" | grep "Tx multicast Data Packets" | awk '{ print $NF }')
|
||||
ATH0_TXBDP=$(printf '%s\n' "$ATH0_RAW" | grep "Tx Broadcast Data Packets" | awk '{ print $NF }')
|
||||
ATH0_TXFLR=$(printf '%s\n' "$ATH0_RAW" | grep "Tx failures" | awk '{ print $NF }')
|
||||
ATH0_PCKERR=$(printf '%s\n' "$ATH0_RAW" | grep "Packets Errored" | awk '{ print $NF }')
|
||||
ATH0_RETR=$(printf '%s\n' "$ATH0_RAW" | grep "Retries" | awk '{ print $NF }')
|
||||
ATH0_BCNSUC=$(printf '%s\n' "$ATH0_RAW" | grep "Beacon success" | awk '{ print $NF }')
|
||||
ATH0_BCNFLR=$(printf '%s\n' "$ATH0_RAW" | grep "Beacon failed" | awk '{ print $NF }')
|
||||
|
||||
ATH0_TXRATE=$(echo "$ATH0_RAW" | awk -F'=' '/^Average Tx Rate/{gsub(/[^0-9]/,"",$2); print ($2==""?0:$2); exit}')
|
||||
ATH0_RXRATE=$(echo "$ATH0_RAW" | awk -F'=' '/^Average Rx Rate/{gsub(/[^0-9]/,"",$2); print ($2==""?0:$2); exit}')
|
||||
|
||||
|
||||
# ---- ath1 (read from ATH1_RAW) ----
|
||||
ATH1_TXDP=$(printf '%s\n' "$ATH1_RAW" | grep -m 1 "Tx Data Packets " | awk '{ print $NF }')
|
||||
ATH1_RXDP=$(printf '%s\n' "$ATH1_RAW" | grep -m 1 "Rx Data Packets" | awk '{ print $NF }')
|
||||
ATH1_TXUDP=$(printf '%s\n' "$ATH1_RAW" | grep "Tx Unicast Data Packets" | awk '{ print $NF }')
|
||||
ATH1_TXMBDP=$(printf '%s\n' "$ATH1_RAW" | grep "Tx Multi/Broadcast Data Packets" | awk '{ print $NF }')
|
||||
ATH1_TXMDP=$(printf '%s\n' "$ATH1_RAW" | grep "Tx multicast Data Packets" | awk '{ print $NF }')
|
||||
ATH1_TXBDP=$(printf '%s\n' "$ATH1_RAW" | grep "Tx Broadcast Data Packets" | awk '{ print $NF }')
|
||||
ATH1_TXFLR=$(printf '%s\n' "$ATH1_RAW" | grep "Tx failures" | awk '{ print $NF }')
|
||||
ATH1_PCKERR=$(printf '%s\n' "$ATH1_RAW" | grep "Packets Errored" | awk '{ print $NF }')
|
||||
ATH1_RETR=$(printf '%s\n' "$ATH1_RAW" | grep "Retries" | awk '{ print $NF }')
|
||||
ATH1_BCNSUC=$(printf '%s\n' "$ATH1_RAW" | grep "Beacon success" | awk '{ print $NF }')
|
||||
ATH1_BCNFLR=$(printf '%s\n' "$ATH1_RAW" | grep "Beacon failed" | awk '{ print $NF }')
|
||||
|
||||
ATH1_TXRATE=$(echo "$ATH1_RAW" | awk -F'=' '/^Average Tx Rate/{gsub(/[^0-9]/,"",$2); print ($2==""?0:$2); exit}')
|
||||
ATH1_RXRATE=$(echo "$ATH1_RAW" | awk -F'=' '/^Average Rx Rate/{gsub(/[^0-9]/,"",$2); print ($2==""?0:$2); exit}')
|
||||
|
||||
|
||||
|
||||
# -----------------------------------------------------------
|
||||
# channels
|
||||
# -----------------------------------------------------------
|
||||
|
||||
ATH0_CH_NMBR=$(iw dev ath0 info | grep MHz | awk '{ print $2 }')
|
||||
ATH0_CH_WIDTH=$(iw dev ath0 info | grep MHz | awk '{ print $6 }')
|
||||
ATH0_CH_CNTR=$(iw dev ath0 info | grep MHz | awk '{ print $(NF-1) }')
|
||||
|
||||
ATH1_CH_NMBR=$(iw dev ath1 info | grep MHz | awk '{ print $2 }')
|
||||
ATH1_CH_WIDTH=$(iw dev ath1 info | grep MHz | awk '{ print $6 }')
|
||||
ATH1_CH_CNTR=$(iw dev ath1 info | grep MHz | awk '{ print $(NF-1) }')
|
||||
|
||||
|
||||
# --- ath1 RSSI buckets (gold/silver/bronze/trash) ---
|
||||
ATH1_USGLD=0; ATH1_USSLV=0; ATH1_USBRN=0; ATH1_USTRS=0
|
||||
|
||||
_assigns="$(
|
||||
(
|
||||
exec 2>/dev/null
|
||||
hostapd_cli -i ath1 all_sta \
|
||||
| grep 'AUTHORIZED' -B1 -A12 \
|
||||
| grep -E '([[:xdigit:]]{2}:){5}[[:xdigit:]]{2}|^signal=' \
|
||||
| awk '
|
||||
BEGIN { g=0; s=0; b=0; t=0 }
|
||||
/^[0-9A-Fa-f]{2}(:[0-9A-Fa-f]{2}){5}$/ { next }
|
||||
/^signal=/ {
|
||||
sig=$0; sub(/^signal=[[:space:]]*/,"",sig); sig+=0
|
||||
if (sig>=-65 && sig<=-20) g++
|
||||
else if (sig>=-75 && sig<=-66) s++
|
||||
else if (sig>=-85 && sig<=-76) b++
|
||||
else if (sig>=-200 && sig<=-86) t++
|
||||
}
|
||||
END {
|
||||
printf "ATH1_USGLD=%d\nATH1_USSLV=%d\nATH1_USBRN=%d\nATH1_USTRS=%d\n", g+0, s+0, b+0, t+0
|
||||
}
|
||||
'
|
||||
) || true
|
||||
)"
|
||||
|
||||
# apply only if well-formed; otherwise keep zeros
|
||||
if printf '%s\n' "$_assigns" | awk -F= '
|
||||
NR==1 && $1=="ATH1_USGLD" && $2 ~ /^[0-9]+$/ {ok1=1}
|
||||
NR==2 && $1=="ATH1_USSLV" && $2 ~ /^[0-9]+$/ {ok2=1}
|
||||
NR==3 && $1=="ATH1_USBRN" && $2 ~ /^[0-9]+$/ {ok3=1}
|
||||
NR==4 && $1=="ATH1_USTRS" && $2 ~ /^[0-9]+$/ {ok4=1}
|
||||
END{ exit !(ok1&&ok2&&ok3&&ok4) }
|
||||
'; then
|
||||
eval "$_assigns"
|
||||
fi
|
||||
|
||||
# final sanitize
|
||||
case "$ATH1_USGLD" in (''|*[!0-9]*) ATH1_USGLD=0;; esac
|
||||
case "$ATH1_USSLV" in (''|*[!0-9]*) ATH1_USSLV=0;; esac
|
||||
case "$ATH1_USBRN" in (''|*[!0-9]*) ATH1_USBRN=0;; esac
|
||||
case "$ATH1_USTRS" in (''|*[!0-9]*) ATH1_USTRS=0;; esac
|
||||
|
||||
########
|
||||
|
||||
# --- ath0 RSSI buckets (gold/silver/bronze/trash) ---
|
||||
ATH0_USGLD=0; ATH0_USSLV=0; ATH0_USBRN=0; ATH0_USTRS=0
|
||||
|
||||
_assigns="$(
|
||||
(
|
||||
exec 2>/dev/null
|
||||
hostapd_cli -i ath0 all_sta \
|
||||
| grep 'AUTHORIZED' -B1 -A12 \
|
||||
| grep -E '([[:xdigit:]]{2}:){5}[[:xdigit:]]{2}|^signal=' \
|
||||
| awk '
|
||||
BEGIN { g=0; s=0; b=0; t=0 }
|
||||
/^[0-9A-Fa-f]{2}(:[0-9A-Fa-f]{2}){5}$/ { next }
|
||||
/^signal=/ {
|
||||
sig=$0; sub(/^signal=[[:space:]]*/,"",sig); sig+=0
|
||||
if (sig>=-65 && sig<=-20) g++
|
||||
else if (sig>=-75 && sig<=-66) s++
|
||||
else if (sig>=-85 && sig<=-76) b++
|
||||
else if (sig>=-200 && sig<=-86) t++
|
||||
}
|
||||
END {
|
||||
printf "ATH0_USGLD=%d\nATH0_USSLV=%d\nATH0_USBRN=%d\nATH0_USTRS=%d\n", g+0, s+0, b+0, t+0
|
||||
}
|
||||
'
|
||||
) || true
|
||||
)"
|
||||
# apply only if well-formed; otherwise keep zeros
|
||||
if printf '%s\n' "$_assigns" | awk -F= '
|
||||
NR==1 && $1=="ATH0_USGLD" && $2 ~ /^[0-9]+$/ {ok1=1}
|
||||
NR==2 && $1=="ATH0_USSLV" && $2 ~ /^[0-9]+$/ {ok2=1}
|
||||
NR==3 && $1=="ATH0_USBRN" && $2 ~ /^[0-9]+$/ {ok3=1}
|
||||
NR==4 && $1=="ATH0_USTRS" && $2 ~ /^[0-9]+$/ {ok4=1}
|
||||
END{ exit !(ok1&&ok2&&ok3&&ok4) }
|
||||
'; then
|
||||
eval "$_assigns"
|
||||
fi
|
||||
|
||||
# final sanitize
|
||||
case "$ATH0_USGLD" in (''|*[!0-9]*) ATH0_USGLD=0;; esac
|
||||
case "$ATH0_USSLV" in (''|*[!0-9]*) ATH0_USSLV=0;; esac
|
||||
case "$ATH0_USBRN" in (''|*[!0-9]*) ATH0_USBRN=0;; esac
|
||||
case "$ATH0_USTRS" in (''|*[!0-9]*) ATH0_USTRS=0;; esac
|
||||
|
||||
# -----------------------------------------------------------
|
||||
# FCS totals/errored
|
||||
# -----------------------------------------------------------
|
||||
|
||||
WIFISTATS_ATH0_FCSOK=$(wifistats wifi0 2 | grep fcs_ok | awk '{ print $3 }')
|
||||
WIFISTATS_ATH0_FCSERR=$(wifistats wifi0 2 | grep fcs_err | awk '{ print $3 }')
|
||||
|
||||
WIFISTATS_ATH1_FCSOK=$(wifistats wifi1 2 | grep fcs_ok | awk '{ print $3 }')
|
||||
WIFISTATS_ATH1_FCSERR=$(wifistats wifi1 2 | grep fcs_err | awk '{ print $3 }')
|
||||
|
||||
|
||||
|
||||
# -----------------------------------------------------------
|
||||
# Build message
|
||||
# -----------------------------------------------------------
|
||||
|
||||
MSG="hostname=${HOSTNAME} \
|
||||
scrver=${SCRIPTVERSION} \
|
||||
ath1_ch_nmbr=${ATH1_CH_NMBR} \
|
||||
ath1_ch_width=${ATH1_CH_WIDTH} \
|
||||
ath1_ch_cntr=${ATH1_CH_CNTR} \
|
||||
ath1_obss_util=${ATH1_OBSS_UTIL} \
|
||||
ath1_chutil=${ATH1_CH_UTIL} \
|
||||
ath1_txdp=${ATH1_TXDP} \
|
||||
ath1_rxdp=${ATH1_RXDP} \
|
||||
ath1_txudp=${ATH1_TXUDP} \
|
||||
ath1_txmbdp=${ATH1_TXMBDP} \
|
||||
ath1_txmdp=${ATH1_TXMDP} \
|
||||
ath1_txbdp=${ATH1_TXBDP} \
|
||||
ath1_txflr=${ATH1_TXFLR} \
|
||||
ath1_txrate=${ATH1_TXRATE} \
|
||||
ath1_rxrate=${ATH1_RXRATE} \
|
||||
ath1_pckerr=${ATH1_PCKERR} \
|
||||
ath1_retr=${ATH1_RETR} \
|
||||
ath1_bcnsuc=${ATH1_BCNSUC} \
|
||||
ath1_bcnflr=${ATH1_BCNFLR} \
|
||||
ath1_usercount=${ATH1_USERCOUNT} \
|
||||
ath1_usgld=${ATH1_USGLD} \
|
||||
ath1_usslv=${ATH1_USSLV} \
|
||||
ath1_usbrn=${ATH1_USBRN} \
|
||||
ath1_ustrs=${ATH1_USTRS} \
|
||||
ath1_fcsok=${WIFISTATS_ATH1_FCSOK} \
|
||||
ath1_fcserr=${WIFISTATS_ATH1_FCSERR} \
|
||||
ath0_ch_nmbr=${ATH0_CH_NMBR} \
|
||||
ath0_ch_width=${ATH0_CH_WIDTH} \
|
||||
ath0_ch_cntr=${ATH0_CH_CNTR} \
|
||||
ath0_obss_util=${ATH0_OBSS_UTIL} \
|
||||
ath0_chutil=${ATH0_CH_UTIL} \
|
||||
ath0_txdp=${ATH0_TXDP} \
|
||||
ath0_rxdp=${ATH0_RXDP} \
|
||||
ath0_txudp=${ATH0_TXUDP} \
|
||||
ath0_txmbdp=${ATH0_TXMBDP} \
|
||||
ath0_txmdp=${ATH0_TXMDP} \
|
||||
ath0_txbdp=${ATH0_TXBDP} \
|
||||
ath0_txflr=${ATH0_TXFLR} \
|
||||
ath0_txrate=${ATH0_TXRATE} \
|
||||
ath0_rxrate=${ATH0_RXRATE} \
|
||||
ath0_pckerr=${ATH0_PCKERR} \
|
||||
ath0_retr=${ATH0_RETR} \
|
||||
ath0_bcnsuc=${ATH0_BCNSUC} \
|
||||
ath0_bcnflr=${ATH0_BCNFLR} \
|
||||
ath0_usercount=${ATH0_USERCOUNT} \
|
||||
ath0_usgld=${ATH0_USGLD} \
|
||||
ath0_usslv=${ATH0_USSLV} \
|
||||
ath0_usbrn=${ATH0_USBRN} \
|
||||
ath0_ustrs=${ATH0_USTRS} \
|
||||
ath0_fcsok=${WIFISTATS_ATH0_FCSOK} \
|
||||
ath0_fcserr=${WIFISTATS_ATH0_FCSERR} \
|
||||
fw_ver=${FWVER} ipaddress=${IPADDRESS} ipmask=${IPMASK} defgw=${DEFGW} macaddress=${MACADDRESS} neigh_switch=${NEIGH_SW}"
|
||||
|
||||
|
||||
|
||||
# Send message via syslog
|
||||
logger -t "debug|${HOSTNAME}" "$MSG"
|
||||
|
||||
420
files/files/wifidebug16.sh
Normal file
420
files/files/wifidebug16.sh
Normal file
@@ -0,0 +1,420 @@
|
||||
#!/bin/sh
|
||||
|
||||
#sleep $((RANDOM % 18 + 3))
|
||||
|
||||
SCRIPTVERSION=16
|
||||
|
||||
delay=$(( ( $(hexdump -n2 -e '/2 "%u"' /dev/urandom) % 18 ) + 3 ))
|
||||
#echo "Sleeping for $delay seconds..."
|
||||
sleep $delay
|
||||
|
||||
# Get hostname
|
||||
HOSTNAME=$(cat /proc/sys/kernel/hostname)
|
||||
|
||||
FWVER=$(cat /etc/banner | grep rev | awk '{ print $1 }')
|
||||
|
||||
# ===========================================================
|
||||
# GPS coordinates management (locks, timeout, 0/0 fallback)
|
||||
# - Writes /tmp/gps_coordinates with:
|
||||
# longitude: <lon 6 decimals>
|
||||
# latitude: <lat 6 decimals>
|
||||
# - Uses /tmp/gps_coordinates.<epoch>.lock (expires 10m)
|
||||
# - Tracks retries in /tmp/gps_timeout (stop after 3)
|
||||
# - On any retrieval attempt (success/fail) -> exit cycle
|
||||
# ===========================================================
|
||||
|
||||
COORD_FILE="/tmp/gps_coordinates"
|
||||
TIMEOUT_FILE="/tmp/gps_timeout"
|
||||
LOCK_MAX_AGE_MIN=10 # minutes
|
||||
RETRIEVE_MAX_WAIT=480 # seconds (8 minutes)
|
||||
LOCATION_LON="0.000000"
|
||||
LOCATION_LAT="0.000000"
|
||||
|
||||
# Helper: parse existing coords file (if any)
|
||||
read_coords_file() {
|
||||
if [ -f "$COORD_FILE" ]; then
|
||||
# Expect two lines: "longitude: X" and "latitude: Y"
|
||||
local lon lat
|
||||
lon=$(awk -F': *' '/^longitude:/ {print $2; exit}' "$COORD_FILE")
|
||||
lat=$(awk -F': *' '/^latitude:/ {print $2; exit}' "$COORD_FILE")
|
||||
# Validate numeric and ranges; format to 6 decimals
|
||||
if echo "$lon" | awk 'BEGIN{ok=0} /^[+-]?[0-9]*\.?[0-9]+$/ {ok=1} END{exit !ok}'; then
|
||||
if echo "$lat" | awk 'BEGIN{ok=0} /^[+-]?[0-9]*\.?[0-9]+$/ {ok=1} END{exit !ok}'; then
|
||||
if awk -v a="$lat" -v b="$lon" 'BEGIN{exit !(a>=-90 && a<=90 && b>=-180 && b<=180)}'; then
|
||||
LOCATION_LON=$(awk -v x="$lon" 'BEGIN{printf "%.6f", x+0}')
|
||||
LOCATION_LAT=$(awk -v x="$lat" 'BEGIN{printf "%.6f", x+0}')
|
||||
return 0
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
return 1
|
||||
}
|
||||
|
||||
# If coords exist and valid -> proceed; else attempt retrieval logic
|
||||
if read_coords_file; then
|
||||
:
|
||||
else
|
||||
# Check retry threshold
|
||||
GTO=0
|
||||
if [ -f "$TIMEOUT_FILE" ]; then
|
||||
GTO=$(cat "$TIMEOUT_FILE" 2>/dev/null | awk '/^[0-9]+$/ {print $0; exit}')
|
||||
[ -z "$GTO" ] && GTO=0
|
||||
fi
|
||||
|
||||
if [ "$GTO" -ge 3 ]; then
|
||||
# Give up trying; ensure coords file exists with 0/0 and exit this cycle
|
||||
printf "longitude: %.6f\nlatitude: %.6f\n" 0 0 > "${COORD_FILE}.tmp"
|
||||
mv "${COORD_FILE}.tmp" "$COORD_FILE"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Clean up stale locks (>10 minutes)
|
||||
find /tmp -maxdepth 1 -type f -name 'gps_coordinates.*.lock' -mmin +"$LOCK_MAX_AGE_MIN" -exec rm -f {} \; 2>/dev/null
|
||||
|
||||
# If any non-stale lock remains, skip this run
|
||||
for f in /tmp/gps_coordinates.*.lock; do
|
||||
[ -e "$f" ] || continue
|
||||
# Found an active (<=10m) lock; skip this cycle
|
||||
exit 0
|
||||
done
|
||||
|
||||
# Create fresh lock and start retrieval
|
||||
NOWTS=$(date +%s)
|
||||
LOCK_FILE="/tmp/gps_coordinates.${NOWTS}.lock"
|
||||
: > "$LOCK_FILE" 2>/dev/null
|
||||
|
||||
CAND="/tmp/gps_candidate.$$"
|
||||
(
|
||||
gpspipe -r | awk -F, '
|
||||
# -------- THE ONLY CHANGE IS HERE: use deglen+1 for minutes --------
|
||||
function dm2dd(dm, hemi, deglen, deg, min, dd) {
|
||||
if (dm=="" || hemi=="") return ""
|
||||
deglen = (hemi=="N" || hemi=="S") ? 2 : 3
|
||||
deg = substr(dm, 1, deglen) + 0
|
||||
min = substr(dm, deglen+1) + 0
|
||||
dd = deg + (min / 60.0)
|
||||
return (hemi=="S" || hemi=="W") ? -dd : dd
|
||||
}
|
||||
# Wait for first valid RMC (A)
|
||||
/^\$..RMC/ && $3=="A" {
|
||||
lat = dm2dd($4, $5)
|
||||
lon = dm2dd($6, $7)
|
||||
if (lat != "" && lon != "") {
|
||||
printf("%.6f %.6f\n", lon, lat)
|
||||
exit
|
||||
}
|
||||
}
|
||||
' > "$CAND"
|
||||
) &
|
||||
GPID=$!
|
||||
|
||||
# Wait up to RETRIEVE_MAX_WAIT seconds for candidate to appear
|
||||
waited=0
|
||||
while [ "$waited" -lt "$RETRIEVE_MAX_WAIT" ]; do
|
||||
if [ -s "$CAND" ]; then
|
||||
break
|
||||
fi
|
||||
sleep 1
|
||||
waited=$((waited+1))
|
||||
done
|
||||
|
||||
success=0
|
||||
if [ -s "$CAND" ]; then
|
||||
set -- $(head -n1 "$CAND" 2>/dev/null)
|
||||
cand_lon="$1"
|
||||
cand_lat="$2"
|
||||
if awk -v a="$cand_lat" -v b="$cand_lon" 'BEGIN{ok=(a!="" && b!=""); if (!ok) exit 1; exit !(a>=-90 && a<=90 && b>=-180 && b<=180)}'
|
||||
then
|
||||
printf "longitude: %.6f\nlatitude: %.6f\n" "$cand_lon" "$cand_lat" > "${COORD_FILE}.tmp"
|
||||
mv "${COORD_FILE}.tmp" "$COORD_FILE"
|
||||
echo 0 > "$TIMEOUT_FILE"
|
||||
success=1
|
||||
fi
|
||||
fi
|
||||
|
||||
# Cleanup background gpspipe if still running
|
||||
kill "$GPID" 2>/dev/null
|
||||
sleep 1
|
||||
kill -9 "$GPID" 2>/dev/null
|
||||
|
||||
# Remove lock and temp
|
||||
rm -f "$LOCK_FILE" "$CAND" 2>/dev/null
|
||||
|
||||
# Exit this cycle after any retrieval attempt (success or fail)
|
||||
if [ "$success" -eq 1 ]; then
|
||||
exit 0
|
||||
else
|
||||
printf "longitude: %.6f\nlatitude: %.6f\n" 0 0 > "${COORD_FILE}.tmp"
|
||||
mv "${COORD_FILE}.tmp" "$COORD_FILE"
|
||||
GTO=$((GTO+1))
|
||||
echo "$GTO" > "$TIMEOUT_FILE"
|
||||
exit 0
|
||||
fi
|
||||
fi
|
||||
|
||||
# At this point, LOCATION_LON/LOCATION_LAT are set (from file or default 0/0)
|
||||
|
||||
# Get OBSS utilization value from wifitool
|
||||
ATH0_OBSS_UTIL=$(wifitool ath0 get_rrmutil | awk '/obss util/ { print $4 }')
|
||||
ATH1_OBSS_UTIL=$(wifitool ath1 get_rrmutil | awk '/obss util/ { print $4 }')
|
||||
ATH0_CH_UTIL=$(cfg80211tool ath0 get_chutil | awk -F ':' '{ print $2 }')
|
||||
ATH1_CH_UTIL=$(cfg80211tool ath1 get_chutil | awk -F ':' '{ print $2 }')
|
||||
|
||||
# -----------------------------------------------------------
|
||||
# Count connected (real) clients on ath0 and ath1
|
||||
# -----------------------------------------------------------
|
||||
|
||||
get_usercount() {
|
||||
IFACE=$1
|
||||
hostapd_cli -i "$IFACE" all_sta 2>/dev/null | awk '
|
||||
/^[0-9a-f]{2}(:[0-9a-f]{2}){5}$/ {mac=$0; next}
|
||||
/flags=/ {
|
||||
auth = (index($0, "AUTH") > 0)
|
||||
assoc = (index($0, "ASSOC") > 0)
|
||||
authorized = (index($0, "AUTHORIZED") > 0)
|
||||
}
|
||||
/rx_packets=/ {rx_packets=$1; sub("rx_packets=", "", rx_packets)}
|
||||
/tx_packets=/ {tx_packets=$1; sub("tx_packets=", "", tx_packets)}
|
||||
/inactive_msec=/ {inactive=$1; sub("inactive_msec=", "", inactive)}
|
||||
/connected_time=/ {
|
||||
connected=$1; sub("connected_time=", "", connected)
|
||||
if (auth && assoc && authorized &&
|
||||
rx_packets+0 > 0 && tx_packets+0 > 0 &&
|
||||
inactive+0 < 5000 && connected+0 > 60) {
|
||||
count++
|
||||
}
|
||||
}
|
||||
END { print count+0 }
|
||||
'
|
||||
}
|
||||
|
||||
ATH0_USERCOUNT=$(get_usercount ath0)
|
||||
ATH1_USERCOUNT=$(get_usercount ath1)
|
||||
|
||||
# -----------------------------------------------------------
|
||||
# Get IP/MAC for br-wan
|
||||
# -----------------------------------------------------------
|
||||
|
||||
MACADDRESS=$(ip link show br-wan | awk '/link\/ether/ {print $2}')
|
||||
IPADDR_MASK=$(ip -4 addr show br-wan | awk '/inet / {print $2}' | head -n 1)
|
||||
IPADDRESS=${IPADDR_MASK%/*}
|
||||
IPMASK=${IPADDR_MASK#*/}
|
||||
|
||||
# -----------------------------------------------------------
|
||||
# Get LLDP neighbor switch
|
||||
NEIGH_SW=$(grep ikeja /tmp/run/lldp_server.json | grep -E "\-sc|\-as" -m1 | sed -E 's/.*"system_name": "([^"]+)".*/\1/')
|
||||
|
||||
# -----------------------------------------------------------
|
||||
# Get default GW
|
||||
DEFGW=$(ip route show | grep default | awk '{ print $3 }')
|
||||
|
||||
# -----------------------------------------------------------
|
||||
|
||||
# Run once per iface and reuse the buffer
|
||||
ATH0_RAW="$(apstats -v -i ath0 2>/dev/null)"
|
||||
ATH1_RAW="$(apstats -v -i ath1 2>/dev/null)"
|
||||
|
||||
# ---- ath0 (read from ATH0_RAW) ----
|
||||
ATH0_TXDP=$(printf '%s\n' "$ATH0_RAW" | grep -m 1 "Tx Data Packets " | awk '{ print $NF }')
|
||||
ATH0_RXDP=$(printf '%s\n' "$ATH0_RAW" | grep -m 1 "Rx Data Packets" | awk '{ print $NF }')
|
||||
ATH0_TXUDP=$(printf '%s\n' "$ATH0_RAW" | grep "Tx Unicast Data Packets" | awk '{ print $NF }')
|
||||
ATH0_TXMBDP=$(printf '%s\n' "$ATH0_RAW" | grep "Tx Multi/Broadcast Data Packets" | awk '{ print $NF }')
|
||||
ATH0_TXMDP=$(printf '%s\n' "$ATH0_RAW" | grep "Tx multicast Data Packets" | awk '{ print $NF }')
|
||||
ATH0_TXBDP=$(printf '%s\n' "$ATH0_RAW" | grep "Tx Broadcast Data Packets" | awk '{ print $NF }')
|
||||
ATH0_TXFLR=$(printf '%s\n' "$ATH0_RAW" | grep "Tx failures" | awk '{ print $NF }')
|
||||
ATH0_PCKERR=$(printf '%s\n' "$ATH0_RAW" | grep "Packets Errored" | awk '{ print $NF }')
|
||||
ATH0_RETR=$(printf '%s\n' "$ATH0_RAW" | grep "Retries" | awk '{ print $NF }')
|
||||
ATH0_BCNSUC=$(printf '%s\n' "$ATH0_RAW" | grep "Beacon success" | awk '{ print $NF }')
|
||||
ATH0_BCNFLR=$(printf '%s\n' "$ATH0_RAW" | grep "Beacon failed" | awk '{ print $NF }')
|
||||
|
||||
ATH0_TXRATE=$(echo "$ATH0_RAW" | awk -F'=' '/^Average Tx Rate/{gsub(/[^0-9]/,"",$2); print ($2==""?0:$2); exit}')
|
||||
ATH0_RXRATE=$(echo "$ATH0_RAW" | awk -F'=' '/^Average Rx Rate/{gsub(/[^0-9]/,"",$2); print ($2==""?0:$2); exit}')
|
||||
|
||||
# ---- ath1 (read from ATH1_RAW) ----
|
||||
ATH1_TXDP=$(printf '%s\n' "$ATH1_RAW" | grep -m 1 "Tx Data Packets " | awk '{ print $NF }')
|
||||
ATH1_RXDP=$(printf '%s\n' "$ATH1_RAW" | grep -m 1 "Rx Data Packets" | awk '{ print $NF }')
|
||||
ATH1_TXUDP=$(printf '%s\n' "$ATH1_RAW" | grep "Tx Unicast Data Packets" | awk '{ print $NF }')
|
||||
ATH1_TXMBDP=$(printf '%s\n' "$ATH1_RAW" | grep "Tx Multi/Broadcast Data Packets" | awk '{ print $NF }')
|
||||
ATH1_TXMDP=$(printf '%s\n' "$ATH1_RAW" | grep "Tx multicast Data Packets" | awk '{ print $NF }')
|
||||
ATH1_TXBDP=$(printf '%s\n' "$ATH1_RAW" | grep "Tx Broadcast Data Packets" | awk '{ print $NF }')
|
||||
ATH1_TXFLR=$(printf '%s\n' "$ATH1_RAW" | grep "Tx failures" | awk '{ print $NF }')
|
||||
ATH1_PCKERR=$(printf '%s\n' "$ATH1_RAW" | grep "Packets Errored" | awk '{ print $NF }')
|
||||
ATH1_RETR=$(printf '%s\n' "$ATH1_RAW" | grep "Retries" | awk '{ print $NF }')
|
||||
ATH1_BCNSUC=$(printf '%s\n' "$ATH1_RAW" | grep "Beacon success" | awk '{ print $NF }')
|
||||
ATH1_BCNFLR=$(printf '%s\n' "$ATH1_RAW" | grep "Beacon failed" | awk '{ print $NF }')
|
||||
|
||||
ATH1_TXRATE=$(echo "$ATH1_RAW" | awk -F'=' '/^Average Tx Rate/{gsub(/[^0-9]/,"",$2); print ($2==""?0:$2); exit}')
|
||||
ATH1_RXRATE=$(echo "$ATH1_RAW" | awk -F'=' '/^Average Rx Rate/{gsub(/[^0-9]/,"",$2); print ($2==""?0:$2); exit}')
|
||||
|
||||
# -----------------------------------------------------------
|
||||
# channels
|
||||
# -----------------------------------------------------------
|
||||
|
||||
ATH0_CH_NMBR=$(iw dev ath0 info | grep MHz | awk '{ print $2 }')
|
||||
ATH0_CH_WIDTH=$(iw dev ath0 info | grep MHz | awk '{ print $6 }')
|
||||
ATH0_CH_CNTR=$(iw dev ath0 info | grep MHz | awk '{ print $(NF-1) }')
|
||||
|
||||
ATH1_CH_NMBR=$(iw dev ath1 info | grep MHz | awk '{ print $2 }')
|
||||
ATH1_CH_WIDTH=$(iw dev ath1 info | grep MHz | awk '{ print $6 }')
|
||||
ATH1_CH_CNTR=$(iw dev ath1 info | grep MHz | awk '{ print $(NF-1) }')
|
||||
|
||||
# --- ath1 RSSI buckets (gold/silver/bronze/trash) ---
|
||||
ATH1_USGLD=0; ATH1_USSLV=0; ATH1_USBRN=0; ATH1_USTRS=0
|
||||
_assigns="$(
|
||||
(
|
||||
exec 2>/dev/null
|
||||
hostapd_cli -i ath1 all_sta \
|
||||
| grep 'AUTHORIZED' -B1 -A12 \
|
||||
| grep -E '([[:xdigit:]]{2}:){5}[[:xdigit:]]{2}|^signal=' \
|
||||
| awk '
|
||||
BEGIN { g=0; s=0; b=0; t=0 }
|
||||
/^[0-9A-Fa-f]{2}(:[0-9A-Fa-f]{2}){5}$/ { next }
|
||||
/^signal=/ {
|
||||
sig=$0; sub(/^signal=[[:space:]]*/,"",sig); sig+=0
|
||||
if (sig>=-65 && sig<=-20) g++
|
||||
else if (sig>=-75 && sig<=-66) s++
|
||||
else if (sig>=-85 && sig<=-76) b++
|
||||
else if (sig>=-200 && sig<=-86) t++
|
||||
}
|
||||
END {
|
||||
printf "ATH1_USGLD=%d\nATH1_USSLV=%d\nATH1_USBRN=%d\nATH1_USTRS=%d\n", g+0, s+0, b+0, t+0
|
||||
}
|
||||
'
|
||||
) || true
|
||||
)"
|
||||
if printf '%s\n' "$_assigns" | awk -F= '
|
||||
NR==1 && $1=="ATH1_USGLD" && $2 ~ /^[0-9]+$/ {ok1=1}
|
||||
NR==2 && $1=="ATH1_USSLV" && $2 ~ /^[0-9]+$/ {ok2=1}
|
||||
NR==3 && $1=="ATH1_USBRN" && $2 ~ /^[0-9]+$/ {ok3=1}
|
||||
NR==4 && $1=="ATH1_USTRS" && $2 ~ /^[0-9]+$/ {ok4=1}
|
||||
END{ exit !(ok1&&ok2&&ok3&&ok4) }
|
||||
'; then
|
||||
eval "$_assigns"
|
||||
fi
|
||||
case "$ATH1_USGLD" in (''|*[!0-9]*) ATH1_USGLD=0;; esac
|
||||
case "$ATH1_USSLV" in (''|*[!0-9]*) ATH1_USSLV=0;; esac
|
||||
case "$ATH1_USBRN" in (''|*[!0-9]*) ATH1_USBRN=0;; esac
|
||||
case "$ATH1_USTRS" in (''|*[!0-9]*) ATH1_USTRS=0;; esac
|
||||
|
||||
# --- ath0 RSSI buckets (gold/silver/bronze/trash) ---
|
||||
ATH0_USGLD=0; ATH0_USSLV=0; ATH0_USBRN=0; ATH0_USTRS=0
|
||||
_assigns="$(
|
||||
(
|
||||
exec 2>/dev/null
|
||||
hostapd_cli -i ath0 all_sta \
|
||||
| grep 'AUTHORIZED' -B1 -A12 \
|
||||
| grep -E '([[:xdigit:]]{2}:){5}[[:xdigit:]]{2}|^signal=' \
|
||||
| awk '
|
||||
BEGIN { g=0; s=0; b=0; t=0 }
|
||||
/^[0-9A-Fa-f]{2}(:[0-9A-Fa-f]{2}){5}$/ { next }
|
||||
/^signal=/ {
|
||||
sig=$0; sub(/^signal=[[:space:]]*/,"",sig); sig+=0
|
||||
if (sig>=-65 && sig<=-20) g++
|
||||
else if (sig>=-75 && sig<=-66) s++
|
||||
else if (sig>=-85 && sig<=-76) b++
|
||||
else if (sig>=-200 && sig<=-86) t++
|
||||
}
|
||||
END {
|
||||
printf "ATH0_USGLD=%d\nATH0_USSLV=%d\nATH0_USBRN=%d\nATH0_USTRS=%d\n", g+0, s+0, b+0, t+0
|
||||
}
|
||||
'
|
||||
) || true
|
||||
)"
|
||||
if printf '%s\n' "$_assigns" | awk -F= '
|
||||
NR==1 && $1=="ATH0_USGLD" && $2 ~ /^[0-9]+$/ {ok1=1}
|
||||
NR==2 && $1=="ATH0_USSLV" && $2 ~ /^[0-9]+$/ {ok2=1}
|
||||
NR==3 && $1=="ATH0_USBRN" && $2 ~ /^[0-9]+$/ {ok3=1}
|
||||
NR==4 && $1=="ATH0_USTRS" && $2 ~ /^[0-9]+$/ {ok4=1}
|
||||
END{ exit !(ok1&&ok2&&ok3&&ok4) }
|
||||
'; then
|
||||
eval "$_assigns"
|
||||
fi
|
||||
case "$ATH0_USGLD" in (''|*[!0-9]*) ATH0_USGLD=0;; esac
|
||||
case "$ATH0_USSLV" in (''|*[!0-9]*) ATH0_USSLV=0;; esac
|
||||
case "$ATH0_USBRN" in (''|*[!0-9]*) ATH0_USBRN=0;; esac
|
||||
case "$ATH0_USTRS" in (''|*[!0-9]*) ATH0_USTRS=0;; esac
|
||||
|
||||
# -----------------------------------------------------------
|
||||
# FCS totals/errored
|
||||
# -----------------------------------------------------------
|
||||
|
||||
WIFISTATS_ATH0_FCSOK=$(wifistats wifi0 2 | grep fcs_ok | awk '{ print $3 }')
|
||||
WIFISTATS_ATH0_FCSERR=$(wifistats wifi0 2 | grep fcs_err | awk '{ print $3 }')
|
||||
|
||||
WIFISTATS_ATH1_FCSOK=$(wifistats wifi1 2 | grep fcs_ok | awk '{ print $3 }')
|
||||
WIFISTATS_ATH1_FCSERR=$(wifistats wifi1 2 | grep fcs_err | awk '{ print $3 }')
|
||||
|
||||
# 10-hex-char uuid for correlation (shared between the two parts)
|
||||
UUID=$(hexdump -n5 -e '5/1 "%02x"' /dev/urandom)
|
||||
|
||||
# ------------------------
|
||||
# Part 1: ath0 + shared (+ GPS)
|
||||
# ------------------------
|
||||
MSG1="hostname=${HOSTNAME} \
|
||||
uuid=${UUID} part=1 \
|
||||
scrver=${SCRIPTVERSION} \
|
||||
ath0_ch_nmbr=${ATH0_CH_NMBR} \
|
||||
ath0_ch_width=${ATH0_CH_WIDTH} \
|
||||
ath0_ch_cntr=${ATH0_CH_CNTR} \
|
||||
ath0_obss_util=${ATH0_OBSS_UTIL} \
|
||||
ath0_chutil=${ATH0_CH_UTIL} \
|
||||
ath0_txdp=${ATH0_TXDP} \
|
||||
ath0_rxdp=${ATH0_RXDP} \
|
||||
ath0_txudp=${ATH0_TXUDP} \
|
||||
ath0_txmbdp=${ATH0_TXMBDP} \
|
||||
ath0_txmdp=${ATH0_TXMDP} \
|
||||
ath0_txbdp=${ATH0_TXBDP} \
|
||||
ath0_txflr=${ATH0_TXFLR} \
|
||||
ath0_txrate=${ATH0_TXRATE} \
|
||||
ath0_rxrate=${ATH0_RXRATE} \
|
||||
ath0_pckerr=${ATH0_PCKERR} \
|
||||
ath0_retr=${ATH0_RETR} \
|
||||
ath0_bcnsuc=${ATH0_BCNSUC} \
|
||||
ath0_bcnflr=${ATH0_BCNFLR} \
|
||||
ath0_usercount=${ATH0_USERCOUNT} \
|
||||
ath0_usgld=${ATH0_USGLD} \
|
||||
ath0_usslv=${ATH0_USSLV} \
|
||||
ath0_usbrn=${ATH0_USBRN} \
|
||||
ath0_ustrs=${ATH0_USTRS} \
|
||||
ath0_fcsok=${WIFISTATS_ATH0_FCSOK} \
|
||||
ath0_fcserr=${WIFISTATS_ATH0_FCSERR} \
|
||||
fw_ver=${FWVER} ipaddress=${IPADDRESS} ipmask=${IPMASK} defgw=${DEFGW} macaddress=${MACADDRESS} neigh_switch=${NEIGH_SW} \
|
||||
location.lat=${LOCATION_LAT} location.lon=${LOCATION_LON}"
|
||||
|
||||
# ------------------------
|
||||
# Part 2: ath1 only
|
||||
# ------------------------
|
||||
MSG2="hostname=${HOSTNAME} \
|
||||
uuid=${UUID} part=2 \
|
||||
scrver=${SCRIPTVERSION} \
|
||||
ath1_ch_nmbr=${ATH1_CH_NMBR} \
|
||||
ath1_ch_width=${ATH1_CH_WIDTH} \
|
||||
ath1_ch_cntr=${ATH1_CH_CNTR} \
|
||||
ath1_obss_util=${ATH1_OBSS_UTIL} \
|
||||
ath1_chutil=${ATH1_CH_UTIL} \
|
||||
ath1_txdp=${ATH1_TXDP} \
|
||||
ath1_rxdp=${ATH1_RXDP} \
|
||||
ath1_txudp=${ATH1_TXUDP} \
|
||||
ath1_txmbdp=${ATH1_TXMBDP} \
|
||||
ath1_txmdp=${ATH1_TXMDP} \
|
||||
ath1_txbdp=${ATH1_TXBDP} \
|
||||
ath1_txflr=${ATH1_TXFLR} \
|
||||
ath1_txrate=${ATH1_TXRATE} \
|
||||
ath1_rxrate=${ATH1_RXRATE} \
|
||||
ath1_pckerr=${ATH1_PCKERR} \
|
||||
ath1_retr=${ATH1_RETR} \
|
||||
ath1_bcnsuc=${ATH1_BCNSUC} \
|
||||
ath1_bcnflr=${ATH1_BCNFLR} \
|
||||
ath1_usercount=${ATH1_USERCOUNT} \
|
||||
ath1_usgld=${ATH1_USGLD} \
|
||||
ath1_usslv=${ATH1_USSLV} \
|
||||
ath1_usbrn=${ATH1_USBRN} \
|
||||
ath1_ustrs=${ATH1_USTRS} \
|
||||
ath1_fcsok=${WIFISTATS_ATH1_FCSOK} \
|
||||
ath1_fcserr=${WIFISTATS_ATH1_FCSERR} \
|
||||
location.lat=${LOCATION_LAT} location.lon=${LOCATION_LON}"
|
||||
|
||||
# Send messages via syslog (two separate lines, same tag)
|
||||
logger -t "debug|${HOSTNAME}" "$MSG1"
|
||||
logger -t "debug|${HOSTNAME}" "$MSG2"
|
||||
64
files/files/wirelessduediligence.sh
Normal file
64
files/files/wirelessduediligence.sh
Normal file
@@ -0,0 +1,64 @@
|
||||
#!/bin/sh
|
||||
# Usage: ./duediligence.sh [/path/to/config.json]
|
||||
set -eu
|
||||
|
||||
CFG="${1:-/tmp/config.json}"
|
||||
|
||||
if ! command -v jq >/dev/null 2>&1; then
|
||||
echo '{"error":"jq not found in PATH"}'
|
||||
exit 2
|
||||
fi
|
||||
|
||||
if [ ! -f "$CFG" ]; then
|
||||
# Still emit JSON so Ansible can parse the error
|
||||
printf '{"error":"config not found: %s"}\n' "$CFG"
|
||||
exit 2
|
||||
fi
|
||||
|
||||
jq -c '
|
||||
def classify(n):
|
||||
if n==0 then "NO_VAPS"
|
||||
elif n==1 then "ONE_VAP"
|
||||
elif n==2 then "TWO_VAPS"
|
||||
else "MORE_THAN_TWO_VAPS" end;
|
||||
|
||||
def radio_summary($r):
|
||||
( .wireless.radios[$r] // {} ) as $rad
|
||||
| ( $rad.vaps // [] ) as $v
|
||||
| {
|
||||
radio_enabled: ($rad.enabled // false),
|
||||
radio_mode: ($rad.mode // "unknown"),
|
||||
vaps_total: ($v | length),
|
||||
indices: ( $v | to_entries | map(.key) ),
|
||||
enabled_ap_indices:
|
||||
( $v
|
||||
| to_entries
|
||||
| map(select(.value.mode=="ap" and (.value.enabled==true)) | .key)
|
||||
),
|
||||
classification: classify($v | length),
|
||||
vaps:
|
||||
( $v
|
||||
| to_entries
|
||||
| map({
|
||||
index: .key,
|
||||
mode: (.value.mode // "null"),
|
||||
enabled: (.value.enabled // false),
|
||||
lbd: (.value.lbd // null),
|
||||
zone: (.value.network.zone // null),
|
||||
ssid: (.value.ssid // "")
|
||||
})
|
||||
)
|
||||
};
|
||||
|
||||
{
|
||||
file: input_filename,
|
||||
radios: {
|
||||
wifi0: radio_summary("wifi0"),
|
||||
wifi1: radio_summary("wifi1"),
|
||||
wlan0: radio_summary("wlan0")
|
||||
},
|
||||
global: {
|
||||
preferred5G: (.wireless.lbd.preferred5G // null)
|
||||
}
|
||||
}
|
||||
' "$CFG"
|
||||
Reference in New Issue
Block a user