Add TP-Link AP support with wireless client sub-locations

- Add NodeType enum (switch, ap, wireless_client, wired_client)
- Poll SNMPv2c and SNMPv3 in parallel to win race with ping
- Render APs with bordered sub-locations containing wireless clients
- Fall back to parent interface stats when child lacks them
- Log when unreachable nodes become reachable via merge

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Ian Gulliver
2026-02-02 20:33:42 -08:00
parent bd829eb888
commit 92ab5d8a6e
11 changed files with 261 additions and 23 deletions

View File

@@ -388,6 +388,9 @@ func (n *Nodes) mergeNodes(keep, merge *Node) {
return
}
keepWasUnreachable := keep.Unreachable
mergeWasUnreachable := merge.Unreachable
for name := range merge.Names {
if keep.Names == nil {
keep.Names = NameSet{}
@@ -429,6 +432,26 @@ func (n *Nodes) mergeNodes(keep, merge *Node) {
merge.cancelFunc()
}
hasIPs := false
for _, iface := range keep.Interfaces {
if len(iface.IPs) > 0 {
hasIPs = true
break
}
}
if hasIPs && (keepWasUnreachable || mergeWasUnreachable) {
keep.Unreachable = false
if n.t != nil && n.t.errors != nil {
n.t.errors.RemoveUnreachable(keep)
}
if keepWasUnreachable {
log.Printf("[merge] %s is now reachable (merged with node that has IPs)", keep.DisplayName())
}
if mergeWasUnreachable {
log.Printf("[merge] %s is now reachable (merged into %s)", merge.DisplayName(), keep.DisplayName())
}
}
n.removeNode(merge)
}