feat: env check auto-disables dummy_radio0 STA (2.4GHz recon root cause)

The stock STA client interface (wlan0) holds phy0's channel, pinning wlan0mon
so 2.4GHz recon captures nothing (verified: iw set channel -> Resource busy
until wlan0 is down). env_check now disables it (uci wireless.dummy_radio0
disabled=1 + wifi reload) at startup and /api/recon/status exposes wlan0_sta
so the recon page can warn if it regresses.
This commit is contained in:
2026-08-19 10:42:26 -05:00
parent 5eb81b90f1
commit 5a72566381
3 changed files with 55 additions and 2 deletions
@@ -1462,7 +1462,7 @@ views.recon = (root) => {
compare: [], history: {}, mapBand: null,
archive: null, archives: [], scanRemaining: null,
hopperOnline: null, historyReset: false, scanErr: null,
wlan0Pinned: false, wlan0Hopping: null };
wlan0Pinned: false, wlan0Sta: false, wlan0Hopping: null };
const cols = reconLoadCols();
// ---- title cards (stat cards with optional mini charts) ----
@@ -1661,10 +1661,11 @@ views.recon = (root) => {
if (state.hopperOnline === false) bits.push('Hopper radio offline — fewer networks seen');
if (state.historyReset) bits.push('History reset — previous scans archived (see Previous Scans)');
if (state.wlan0Pinned) bits.push('2.4GHz under-sampled — OpenAP/Evil WPA holds wlan0mon');
if (state.wlan0Sta) bits.push('2.4GHz starved — client STA (wlan0) pins phy0');
if (state.wlan0Hopping === false) bits.push('2.4GHz starved — wlan0mon hopping is off');
if (state.scanErr) bits.push(state.scanErr);
scanStatus.textContent = bits.join(' · ');
scanStatus.classList.toggle('warn', state.hopperOnline === false || state.historyReset || state.wlan0Pinned || state.wlan0Hopping === false || !!state.scanErr);
scanStatus.classList.toggle('warn', state.hopperOnline === false || state.historyReset || state.wlan0Pinned || state.wlan0Sta || state.wlan0Hopping === false || !!state.scanErr);
}
scanToggle.addEventListener('change', () => {
if (pendingScan) { scanToggle.checked = !scanToggle.checked; return; }
@@ -2527,6 +2528,7 @@ views.recon = (root) => {
state.hopperOnline = r.data.hopper_online;
state.historyReset = !!r.data.history_reset;
state.wlan0Pinned = !!r.data.wlan0_pinned;
state.wlan0Sta = !!r.data.wlan0_sta;
state.wlan0Hopping = r.data.wlan0_hopping;
if (!pendingScan) scanToggle.checked = scanning;
renderScanBar();