소스 검색

feat: poll refinement snapshot into health tiles

master
Jan Svabenik 7 시간 전
부모
커밋
971bcff767
1개의 변경된 파일27개의 추가작업 그리고 0개의 파일을 삭제
  1. +27
    -0
      web/app.js

+ 27
- 0
web/app.js 파일 보기

@@ -79,6 +79,8 @@ const healthResets = qs('healthResets');
const healthAge = qs('healthAge');
const healthGpu = qs('healthGpu');
const healthFps = qs('healthFps');
const healthRefinePlan = qs('healthRefinePlan');
const healthRefineWindows = qs('healthRefineWindows');

const drawerEl = qs('eventDrawer');
const drawerCloseBtn = qs('drawerClose');
@@ -739,6 +741,14 @@ async function loadGPU() {
} catch {}
}

async function loadRefinement() {
try {
const res = await fetch('/api/refinement');
if (!res.ok) return;
refinementInfo = await res.json();
} catch {}
}

function queueConfigUpdate(partial) {
if (isSyncingConfig) return;
pendingConfigUpdate = { ...(pendingConfigUpdate || {}), ...partial };
@@ -827,6 +837,21 @@ function updateHeroMetrics() {
healthAge.textContent = stats.last_sample_ago_ms >= 0 ? `${stats.last_sample_ago_ms} ms` : 'n/a';
healthGpu.textContent = gpuInfo.error ? `${gpuInfo.active ? 'ON' : 'OFF'} · ${gpuInfo.error}` : (gpuInfo.active ? 'ON' : (gpuInfo.available ? 'Ready' : 'N/A'));
healthFps.textContent = `${renderFps.toFixed(0)} fps`;
if (healthRefinePlan) {
const plan = refinementInfo.plan || {};
healthRefinePlan.textContent = `${plan.selected?.length || 0}/${plan.budget || 0} · drop ${plan.dropped_by_snr || 0}/${plan.dropped_by_budget || 0}`;
}
if (healthRefineWindows) {
const windows = refinementInfo.windows || [];
if (!Array.isArray(windows) || windows.length === 0) {
healthRefineWindows.textContent = 'n/a';
} else {
const spans = windows.map(w => w.span_hz || 0).filter(v => v > 0);
const minSpan = spans.length ? Math.min(...spans) : 0;
const maxSpan = spans.length ? Math.max(...spans) : 0;
healthRefineWindows.textContent = spans.length ? `${fmtHz(minSpan)}–${fmtHz(maxSpan)}` : 'n/a';
}
}
}

function renderBandNavigator() {
@@ -2174,6 +2199,7 @@ window.addEventListener('keydown', (ev) => {
loadConfig();
loadStats();
loadGPU();
loadRefinement();
fetchEvents(true);
fetchRecordings();
loadDecoders();
@@ -2181,6 +2207,7 @@ connect();
requestAnimationFrame(renderLoop);
setInterval(loadStats, 1000);
setInterval(loadGPU, 1000);
setInterval(loadRefinement, 1500);
setInterval(() => fetchEvents(false), 2000);
setInterval(fetchRecordings, 5000);
setInterval(loadSignals, 1500);


불러오는 중...
취소
저장