diff --git a/src/main.cpp b/src/main.cpp index 60facfa..79f9518 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1349,6 +1349,7 @@ async function poll(){ document.getElementById('connDot').style.background='#f28a86'; document.getElementById('bt').textContent='OFFLINE'; } + setTimeout(poll, 1000); } document.getElementById('jp').addEventListener('input',e=>document.getElementById('pv').textContent=PT[+e.target.value]); @@ -1358,7 +1359,7 @@ document.getElementById('aamp').addEventListener('click',async()=>{try{await fet document.getElementById('asw').addEventListener('click',async()=>{try{await fetch('/api/sweep',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({dwell_ms:+document.getElementById('sd').value,steps1:+document.getElementById('ss1').value,steps2:+document.getElementById('ss2').value,span1_mhz:+document.getElementById('sp1').value,span2_mhz:+document.getElementById('sp2').value})});}catch(e){}}); document.getElementById('dl').addEventListener('click',()=>{const a=document.createElement('a');a.href='/api/log';a.download='jammer-log.txt';a.click();}); -poll();setInterval(poll,1000); +poll(); // ── Capture / Replay ───────────────────────────────────────────────────────── let capPolling=false; @@ -1453,48 +1454,76 @@ static void handleTelemetry() { int8_t effDbm = jamPower + ampGainDb; float effWatts = powf(10.0f, effDbm / 10.0f) / 1000.0f; // dBm -> watts - String json = "{"; - json += "\"uptime_ms\":" + String(millis() - uptimeStart) + ","; - json += "\"free_heap\":" + String(ESP.getFreeHeap()) + ","; - json += "\"temp_c\":" + String(tempC, 1) + ","; - json += "\"jamming_enabled\":" + String(jammingEnabled ? "true" : "false") + ","; - json += "\"jam_power\":" + String(jamPower) + ","; - json += "\"jam_power_idx\":" + String(jamPowerIdx) + ","; - json += "\"amp_gain_db\":" + String(ampGainDb) + ","; - json += "\"eff_power_dbm\":" + String(effDbm) + ","; - json += "\"eff_power_w\":" + String(effWatts, 3) + ","; + String err1 = jsonEscape(radio1Error); + String err2 = jsonEscape(radio2Error); - // Sweep state - json += "\"sweep_freq1\":" + String(sweepFreq1, 4) + ","; - json += "\"sweep_center1\":" + String(SWEEP_1_CENTER_MHZ, 2) + ","; - json += "\"sweep_span1\":" + String(sweep1SpanMhz, 2) + ","; - json += "\"sweep_steps1\":" + String(sweep1Steps) + ","; - json += "\"sweep_freq2\":" + String(sweepFreq2, 4) + ","; - json += "\"sweep_center2\":" + String(SWEEP_2_CENTER_MHZ, 2) + ","; - json += "\"sweep_span2\":" + String(sweep2SpanMhz, 2) + ","; - json += "\"sweep_steps2\":" + String(sweep2Steps) + ","; - json += "\"sweep_dwell_ms\":" + String(sweepDwellMs) + ","; + static char jsonBuf[1024]; // Generously sized to avoid fragmentation + snprintf(jsonBuf, sizeof(jsonBuf), + "{" + "\"uptime_ms\":%lu," + "\"free_heap\":%lu," + "\"temp_c\":%.1f," + "\"jamming_enabled\":%s," + "\"jam_power\":%d," + "\"jam_power_idx\":%d," + "\"amp_gain_db\":%d," + "\"eff_power_dbm\":%d," + "\"eff_power_w\":%.3f," + "\"sweep_freq1\":%.4f," + "\"sweep_center1\":%.2f," + "\"sweep_span1\":%.2f," + "\"sweep_steps1\":%u," + "\"sweep_freq2\":%.4f," + "\"sweep_center2\":%.2f," + "\"sweep_span2\":%.2f," + "\"sweep_steps2\":%u," + "\"sweep_dwell_ms\":%lu," + "\"radio1_status\":%d," + "\"radio1_error\":\"%s\"," + "\"radio1_freq\":%.4f," + "\"radio1_active\":%s," + "\"radio2_status\":%d," + "\"radio2_error\":\"%s\"," + "\"radio2_freq\":%.4f," + "\"radio2_active\":%s," + "\"hop_count1\":%lu," + "\"hop_count2\":%lu," + "\"min_heap\":%lu," + "\"ap_clients\":%d" + "}", + (unsigned long)(millis() - uptimeStart), + (unsigned long)ESP.getFreeHeap(), + (double)tempC, + jammingEnabled ? "true" : "false", + (int)jamPower, + (int)jamPowerIdx, + (int)ampGainDb, + (int)effDbm, + (double)effWatts, + (double)sweepFreq1, + (double)SWEEP_1_CENTER_MHZ, + (double)sweep1SpanMhz, + (unsigned)sweep1Steps, + (double)sweepFreq2, + (double)SWEEP_2_CENTER_MHZ, + (double)sweep2SpanMhz, + (unsigned)sweep2Steps, + (unsigned long)sweepDwellMs, + (int)radio1Status, + err1.c_str(), + (double)sweepFreq1, + radio1Status == 2 ? "true" : "false", + (int)radio2Status, + err2.c_str(), + (double)sweepFreq2, + radio2Status == 2 ? "true" : "false", + (unsigned long)hopCount1, + (unsigned long)hopCount2, + (unsigned long)(minFreeHeap == 0xFFFFFFFF ? ESP.getFreeHeap() : minFreeHeap), + (int)WiFi.softAPgetStationNum() + ); - // Radio 1 - json += "\"radio1_status\":" + String(radio1Status) + ","; - json += "\"radio1_error\":\"" + jsonEscape(radio1Error) + "\","; - json += "\"radio1_freq\":" + String(sweepFreq1, 4) + ","; - json += "\"radio1_active\":" + String(radio1Status == 2 ? "true" : "false") + ","; - - // Radio 2 - json += "\"radio2_status\":" + String(radio2Status) + ","; - json += "\"radio2_error\":\"" + jsonEscape(radio2Error) + "\","; - json += "\"radio2_freq\":" + String(sweepFreq2, 4) + ","; - json += "\"radio2_active\":" + String(radio2Status == 2 ? "true" : "false") + ","; - - // 24-hour health metrics - json += "\"hop_count1\":" + String(hopCount1) + ","; - json += "\"hop_count2\":" + String(hopCount2) + ","; - json += "\"min_heap\":" + String(minFreeHeap == 0xFFFFFFFF ? ESP.getFreeHeap() : minFreeHeap) + ","; - json += "\"ap_clients\":" + String(WiFi.softAPgetStationNum()); - - json += "}"; - server.send(200, "application/json; charset=utf-8", json); + server.send(200, "application/json; charset=utf-8", jsonBuf); } static void handleToggle() {