#!/bin/sh
# Are devices away from their unit's AP because of where they landed when
# they last associated (e.g. everyone reconnecting at once after a reload),
# or because that is where they choose to be? Splits devices by how long
# their current association has lasted: if long sessions -- the ones that
# began at the reload -- are away much more often than recent ones, devices
# are stuck where the reload put them and it fades as they reconnect.
#
# Reads the stations TSV sdan-fleet-check.rb writes. A unit VLAN's busiest
# AP stands in for home, as in the report's "unit VLAN spread" section.
# Columns are found by header name.
#
# Usage, as root on the rXg after a fleet check run:
#   curl -o /tmp/sdan-away-age.sh https://pre-alpha.henryhaller.com/sdan-away-age.sh
#   sh /tmp/sdan-away-age.sh                  # newest run in /tmp
#   sh /tmp/sdan-away-age.sh <stations.tsv>   # a specific run
#
# WEAK=-75 sets the signal under which an away device is counted as one an
# Association Request RSSI threshold at that level would have refused.

sta=${1:-$(ls -t /tmp/sdan-fleet-check-*-stations.tsv 2>/dev/null | head -1)}
[ -f "$sta" ] || { echo "no stations TSV found -- run sdan-fleet-check.rb first"; exit 1; }
weak=${WEAK:--75}
echo "run: $sta"
echo

awk -v weak="$weak" '
BEGIN {
  FS = "\t"
  nb = split("600 1800 3600 7200 21600 86400", lim, " ")
  split("under 10 min|10-30 min|30-60 min|1-2 h|2-6 h|6-24 h|over 24 h", lab, "|")
}
FNR == 1 { for (i = 1; i <= NF; i++) col[$i] = i; next }
{
  if ($(col["vlan_busiest_ap"]) == "") next
  s = $(col["connected_s"])
  if (s == "") next
  s += 0
  k = nb + 1
  for (i = 1; i <= nb; i++) if (s < lim[i]) { k = i; break }
  rel = $(col["vlan_relation"])
  n[k]++; N++
  if (rel == "busiest") h[k]++
  else if (rel == "same_unit") o[k]++
  else {
    a[k]++; if ($(col["band"]) + 0 == 2) a24[k]++
    sig = $(col["signal"]) + 0; sg[k] += sig; if (sig < weak) aw[k]++
  }
}
function pc(x, t) { return t ? sprintf("%d (%.0f%%)", x, 100 * x / t) : "-" }
END {
  printf "%-14s %8s %16s %16s %16s %10s %16s\n", "SESSION AGE", "DEVICES", "IN THEIR UNIT", "AWAY", "AWAY ON 2.4", "AWAY SIG", "AWAY < " weak
  for (k = 1; k <= nb + 1; k++) {
    nk = n[k] + 0; ak = a[k] + 0
    if (!nk) continue
    printf "%-14s %8d %16s %16s %16s %10s %16s\n", lab[k], nk, pc(h[k] + o[k], nk), pc(ak, nk),
      pc(a24[k] + 0, ak), ak ? sprintf("%.0f", sg[k] / ak) : "-", pc(aw[k] + 0, ak)
    tw += aw[k]; ta += ak
  }
  printf "%-14s %8d %16s %16s %16s %10s %16s\n", "all", N, "", pc(ta, N), "", "", pc(tw, ta)
  print ""
  print "IN THEIR UNIT = on the VLAN busiest AP or another AP in its unit. AWAY SIG is"
  print "the mean signal the serving AP hears from away devices. AWAY < " weak " are away"
  print "devices an Association Request RSSI of " weak " would have refused on that AP."
  print "Stuck after a reload: sessions as old as the reload are away clearly more often"
  print "than recent ones. Similar rows mean devices choose those APs whenever they join."
  print "At night, long sessions are mostly stationary devices and recent ones are"
  print "devices waking up, so compare the same hour across runs."
}' "$sta"
