sync: auto-sync from GURU-5070 at 2026-06-15 18:03:38
Author: Mike Swanson Machine: GURU-5070 Timestamp: 2026-06-15 18:03:38
This commit is contained in:
@@ -15,6 +15,9 @@ controller knows and making prioritized, validated changes. Built for any site;
|
||||
to read it (the two planes: Mongo config/interference now, live Network API later).
|
||||
- **[references/methodology.md](references/methodology.md)** — the prioritized tuning playbook
|
||||
(synthesized from a multi-model pass + live recon). Read before recommending any change.
|
||||
- **[references/interference-model.md](references/interference-model.md)** — design for the
|
||||
AP-interference / airtime-reduction model (which radios to disable / power down), incl. the data
|
||||
feasibility (needs Plane 2 + a collector — the signals aren't in Mongo).
|
||||
|
||||
## What it does (current = Plane 1, read-only)
|
||||
1. **Audit a site** — config + interference, no live plane needed:
|
||||
|
||||
61
.claude/skills/unifi-wifi/references/interference-model.md
Normal file
61
.claude/skills/unifi-wifi/references/interference-model.md
Normal file
@@ -0,0 +1,61 @@
|
||||
# AP interference / airtime-reduction model — design + data feasibility
|
||||
|
||||
Goal (per Mike): a fleet/site-level model that decides **which AP radios to disable, and where to
|
||||
reduce power**, to cut total airtime contention while preserving client coverage. Per AP **per
|
||||
radio, all bands** (not 2.4-only, not per-client). Inputs: each AP's view of neighboring APs (RF)
|
||||
+ historical client connections.
|
||||
|
||||
## Data feasibility (probed on Cascades 2026-06-15)
|
||||
| Signal the model wants | In Mongo `ace`? | Source to use |
|
||||
|---|---|---|
|
||||
| **Our AP ↔ our AP RF visibility** (A hears B at RSSI r) | **NO** — `rogue` is FOREIGN APs only; our managed APs are filtered out (0 rows match our SSIDs) | **Live Network API** `stat/device` neighbor table / triggered RF scan (Plane 2) |
|
||||
| **Historical client→AP connections / roam overlap** | **NO** — `user` keeps only `last_uplink_mac` (last AP); no sessions, `alarm` empty, `stat` collections empty | **Accumulated `stat/sta` polling** over time (Plane 2 + a collector) |
|
||||
| **Physical AP coordinates** | **NO** — 0 APs placed on the 1 floorplan | derive coarse topology from **AP names** (room#/floor encoded) |
|
||||
| Radio config (channel/band/width/power/min_rssi) | **YES** | Mongo `device.radio_table` (Plane 1) |
|
||||
| Foreign interference per channel | **YES** | Mongo `rogue` aggregate (Plane 1) |
|
||||
|
||||
**Conclusion:** the interference graph the model needs (our-AP mutual RSSI + client overlap)
|
||||
**cannot** be built from Mongo. It requires **Plane 2 (the live Network API)** plus a **collector**
|
||||
that accumulates snapshots over time. Mongo gives config + foreign-interference + (via names) a
|
||||
coarse topology prior to seed the model before enough live data is collected.
|
||||
|
||||
## Model design
|
||||
Per band `b` (ng/na/6e), build a weighted graph over AP radios:
|
||||
|
||||
- **Nodes:** each AP's radio on band `b`.
|
||||
- **RF edges** `w_rf(A,B)`: from the live neighbor table — how strongly A hears B (and vice-versa),
|
||||
scaled up when same/overlapping channel. Strong mutual RSSI on the same channel = high
|
||||
co-channel interference.
|
||||
- **Overlap edges** `w_ov(A,B)`: fraction of clients that have associated with BOTH A and B over
|
||||
the collection window (built by snapshotting `stat/sta` every N minutes). High overlap = they
|
||||
cover the same space → one is redundant.
|
||||
- **Per-radio metrics:** `load` (num_sta, live `cu_total`), `unique_coverage` (clients only this
|
||||
radio serves at good RSSI), `interference_contribution` (Σ strong RF edges on same channel).
|
||||
|
||||
**Recommendation logic (greedy, coverage-safe):**
|
||||
1. **Disable a radio** when: high `interference_contribution` AND high `coverage_redundancy`
|
||||
(its clients keep good signal from neighbors) AND `unique_coverage ≈ 0`. Disable the worst
|
||||
offender, recompute the graph, repeat until a redundancy floor is hit (don't open holes).
|
||||
2. **Reduce power** when interference is high but `unique_coverage > 0` (can't disable without a
|
||||
hole) — shrink the cell to cut contention while keeping coverage.
|
||||
3. **Leave** radios that carry unique coverage and contribute little interference.
|
||||
Band weighting: 2.4 prunes most aggressively (most redundant + least capacity value); 5/6 lighter;
|
||||
6GHz usually keep (clean band, steer up). Output = ranked per-AP-per-radio actions with the metric
|
||||
that justified each, applied **per zone** with live before/after validation.
|
||||
|
||||
## Prerequisites to build it (the real next step)
|
||||
1. **Wire Plane 2** — provision a dedicated **read-only UniFi admin or Network integration API key**
|
||||
on `.29` (doable with our root SSH), vault as `infrastructure/uos-server-network-api`. Gives
|
||||
`stat/device` (live neighbor RSSI, `cu_total`, `num_sta`, satisfaction) + `stat/sta` (client→AP).
|
||||
2. **Stand up a collector** — a periodic job (cron on `.30`/a fleet host) snapshotting
|
||||
`stat/device` + `stat/sta` into a small store (sqlite/postgres). The **overlap + RF matrix
|
||||
accrue over the collection window** (a week+ gives a usable model; longer = better). This is the
|
||||
"historical look at devices connected" Mike asked for — the controller doesn't retain it, so we
|
||||
accumulate it ourselves.
|
||||
3. **Build the model** on the accumulated data; seed early recommendations from the Mongo config +
|
||||
AP-name topology prior until enough live data exists.
|
||||
|
||||
## Status
|
||||
Phase 1 (config + foreign-interference audit) is built (`scripts/audit-site.sh`). The interference
|
||||
model is **blocked on Plane 2 + the collector** — needs a go to provision the UniFi API account and
|
||||
stand up the collector.
|
||||
Reference in New Issue
Block a user