diff --git a/scripts/discover-unifi.sh b/scripts/discover-unifi.sh index 19f3c1f..3ae616b 100755 --- a/scripts/discover-unifi.sh +++ b/scripts/discover-unifi.sh @@ -20,15 +20,19 @@ # UNIFI_API_KEY=... # and source it before calling. # -# Output: TSV on stdout. Column layout depends on the endpoint: +# Output: TSV on stdout. IP is column 1 for hosts/devices so these can +# be piped into discover-gaps.sh directly: # -# hosts: host_id host_name host_ip model_name controller_version -# sites: site_id site_name host_id description -# devices: mac ip name model site_id host_id +# hosts: IP MAC NAME MODEL FW_VERSION SOURCE +# (IP is LAN — picked from reportedState.ipAddrs first +# private-range entry; falls back to WAN if none found) +# devices: IP MAC NAME MODEL HOST_NAME SOURCE +# (APs, switches — the actual network equipment) +# sites: SITE_ID SITE_NAME HOST_ID SOURCE +# (metadata only — no IP column, not useful for gap analysis) # -# Each row ends with a SOURCE column so outputs can be concatenated and -# still distinguished: -# unifi: +# SOURCE column is "unifi:" so concatenated outputs stay +# distinguishable. # # Requires: curl + jq (apt install jq). @@ -107,12 +111,27 @@ ui_get() { # ---------------------------------------------------------------------- emit_hosts() { + # LAN IP is the first RFC1918 entry in reportedState.ipAddrs that is + # NOT also present as a WAN ipv4 (reportedState.wans[]) — UDMs with + # RFC1918-addressed WAN2 interfaces would otherwise get mis-picked as + # their LAN IP. Falls back through the usual chain if nothing matches. ui_get /ea/hosts | jq -r ' + . as $h | + (($h.reportedState.wans // []) | map(.ipv4 // empty)) as $wans | [ - (.id // "-"), - (.hardware.name // .userData.name // .reportedState.name // "-"), - (.ipAddress // .reportedState.ip // "-"), - (.hardware.shortname // .type // "-"), + ( + ([(.reportedState.ipAddrs // [])[] | select( + (test("^10\\.") or + test("^192\\.168\\.") or + test("^172\\.(1[6-9]|2[0-9]|3[0-1])\\.") + ) and + (. as $ip | ($wans | index($ip)) == null) + )] | .[0]) + // .reportedState.ip // .ipAddress // "-" + ), + (.reportedState.mac // "-"), + (.reportedState.hostname // .reportedState.name // "-"), + (.reportedState.hardware.shortname // .reportedState.hardware.name // .type // "-"), (.reportedState.version // "-"), "unifi:hosts" ] | @tsv @@ -120,26 +139,29 @@ emit_hosts() { } emit_sites() { + # Sites have no IP — no point running these through discover-gaps.sh. + # Kept here for inventory purposes only. ui_get /ea/sites | jq -r ' [ (.siteId // .id // "-"), (.meta.name // .name // "-"), (.hostId // "-"), - (.meta.desc // "-"), "unifi:sites" ] | @tsv ' } emit_devices() { + # /ea/devices returns per-host wrappers; flatten into one row per AP/switch. ui_get /ea/devices | jq -r ' + . as $h | + (.devices // [])[] | [ - (.mac // "-"), (.ip // "-"), - (.name // .hardware.name // "-"), - (.model // .hardware.shortname // "-"), - (.siteId // "-"), - (.hostId // "-"), + (.mac // .id // "-"), + (.name // "-"), + (.model // .shortname // "-"), + ($h.hostName // $h.hostId // "-"), "unifi:devices" ] | @tsv '