#!/bin/sh
# Do units whose busiest AP is on a DFS channel have more devices away from
# it -- especially on a neighbour's non-DFS 5 GHz radio -- than units whose
# busiest AP is not? That is what devices which avoid or only passively scan
# DFS channels would look like.
#
# Reads the two TSVs sdan-fleet-check.rb writes. Needs no client-to-unit
# mapping: 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-dfs-split.sh https://pre-alpha.henryhaller.com/sdan-dfs-split.sh
#   sh /tmp/sdan-dfs-split.sh                  # newest run in /tmp
#   sh /tmp/sdan-dfs-split.sh <stations.tsv>   # a specific run

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; }
ap="${sta%-stations.tsv}.tsv"
[ -f "$ap" ] || { echo "per-AP TSV $ap not found"; exit 1; }
echo "run: $ap"
echo

awk -v apf="$ap" -v staf="$sta" '
BEGIN { FS = "\t" }
FNR == 1 { for (i = 1; i <= NF; i++) col[FILENAME, $i] = i; next }
FILENAME == apf { ch[$(col[apf, "name"])] = $(col[apf, "channel_5g_by_freq"]) + 0; next }
{
  b = $(col[staf, "vlan_busiest_ap"])
  if (b == "") next
  rel  = $(col[staf, "vlan_relation"])
  band = $(col[staf, "band"]) + 0
  c = ch[b]
  g = (c == 0) ? "unknown" : ((c >= 52 && c <= 144) ? "DFS" : "non-DFS")
  n[g]++
  vl[g, $(col[staf, "vlan"])] = 1
  if (rel == "busiest") { h[g]++; if (band == 2) h24[g]++ }
  else if (rel == "same_unit") { o[g]++ }
  else {
    a[g]++
    s = ch[$(col[staf, "ap_name"])]
    if (band == 5 && s > 0 && (s < 52 || s > 144)) an[g]++
    if (band == 2) a24[g]++
  }
}
function pc(x, t) { return t ? sprintf("%d (%.0f%%)", x, 100 * x / t) : "-" }
END {
  for (k in vl) { split(k, p, SUBSEP); nv[p[1]]++ }
  printf "%-44s %16s %16s\n", "busiest AP of the unit VLAN is on", "DFS", "non-DFS"
  printf "%-44s %16d %16d\n", "unit VLANs (2+ devices)", nv["DFS"], nv["non-DFS"]
  printf "%-44s %16d %16d\n", "devices", n["DFS"], n["non-DFS"]
  printf "%-44s %16s %16s\n", "on the busiest AP", pc(h["DFS"], n["DFS"]), pc(h["non-DFS"], n["non-DFS"])
  printf "%-44s %16s %16s\n", "  ..of those on 2.4 GHz", pc(h24["DFS"], h["DFS"]), pc(h24["non-DFS"], h["non-DFS"])
  printf "%-44s %16s %16s\n", "on another AP in the same unit", pc(o["DFS"], n["DFS"]), pc(o["non-DFS"], n["non-DFS"])
  printf "%-44s %16s %16s\n", "on another unit or common-area AP", pc(a["DFS"], n["DFS"]), pc(a["non-DFS"], n["non-DFS"])
  printf "%-44s %16s %16s\n", "  ..of those on a non-DFS 5 GHz radio", pc(an["DFS"], a["DFS"]), pc(an["non-DFS"], a["non-DFS"])
  printf "%-44s %16s %16s\n", "  ..of those on 2.4 GHz", pc(a24["DFS"], a["DFS"]), pc(a24["non-DFS"], a["non-DFS"])
  if (n["unknown"]) printf "\n%d device(s) skipped: busiest AP reported no 5 GHz channel\n", n["unknown"]
  print ""
  print "DFS is costing home attachment if the DFS column has a clearly lower share on"
  print "the busiest AP, more of its away devices on non-DFS 5 GHz radios, or more of"
  print "its at-home devices on 2.4 GHz. Similar columns mean DFS is not a factor."
  print "Expect some non-DFS 5 GHz share in the DFS column anyway: about a third of"
  print "5 GHz radios are non-DFS, so neighbours are often on one."
}' "$ap" "$sta"
