fix: recon env-check verifies runtime wlan0mon hopping (2.4GHz starvation)

The band UCI config looked correct but pineapd was not hopping wlan0mon at
runtime, so 2.4GHz recon results were entirely absent. env_check now parses
_pineap INTERFACE LIST and warns when wlan0mon hop is off; /api/recon/status
exposes wlan0_hopping and the recon scan bar surfaces it.
This commit is contained in:
2026-08-19 10:29:50 -05:00
parent 904843307e
commit 5eb81b90f1
3 changed files with 75 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 };
wlan0Pinned: false, wlan0Hopping: null };
const cols = reconLoadCols();
// ---- title cards (stat cards with optional mini charts) ----
@@ -1661,9 +1661,10 @@ 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.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.scanErr);
scanStatus.classList.toggle('warn', state.hopperOnline === false || state.historyReset || state.wlan0Pinned || state.wlan0Hopping === false || !!state.scanErr);
}
scanToggle.addEventListener('change', () => {
if (pendingScan) { scanToggle.checked = !scanToggle.checked; return; }
@@ -2526,6 +2527,7 @@ views.recon = (root) => {
state.hopperOnline = r.data.hopper_online;
state.historyReset = !!r.data.history_reset;
state.wlan0Pinned = !!r.data.wlan0_pinned;
state.wlan0Hopping = r.data.wlan0_hopping;
if (!pendingScan) scanToggle.checked = scanning;
renderScanBar();
if (wasScanning !== scanning) restartPoll();