Sfoglia il codice sorgente

test: cover newest-wins telemetry and show source indicator

main
Jan 1 mese fa
parent
commit
310101755c
2 ha cambiato i file con 21 aggiunte e 1 eliminazioni
  1. +18
    -0
      internal/control/control_test.go
  2. +3
    -1
      internal/control/ui.html

+ 18
- 0
internal/control/control_test.go Vedi File

@@ -1128,3 +1128,21 @@ func TestTelemetryUnsubscribeDuringPublishDoesNotPanic(t *testing.T) {
t.Fatal("subscriber done not closed")
}
}

func TestTelemetryHubKeepsNewestMeasurement(t *testing.T) {
hub := NewTelemetryHub()
sub, unsubscribe := hub.Subscribe()
defer unsubscribe()
for i := 0; i < 8; i++ {
hub.PublishMeasurement(&offpkg.MeasurementSnapshot{Timestamp: time.Now(), Sequence: uint64(i + 1)})
}
var got TelemetryMessage
select {
case got = <-sub.ch:
case <-time.After(2 * time.Second):
t.Fatal("expected telemetry message")
}
if got.Seq != 8 {
t.Fatalf("expected newest seq 8, got %d", got.Seq)
}
}

+ 3
- 1
internal/control/ui.html Vedi File

@@ -319,6 +319,7 @@ input.input-error{border-color:var(--red);box-shadow:0 0 0 3px rgba(176,48,48,.1
<button class="danger-btn" id="header-danger-reset-fault" type="button">Reset Fault</button>
<div class="led" id="led-conn"></div>
<div class="status-text" id="conn-label">connecting</div>
<div class="status-text" id="telemetry-label">telemetry: --</div>
</div>
</div>
<div class="flow-banner" id="flow-banner">
@@ -1012,7 +1013,7 @@ function setIngField(path,val){if(!S.ingestDraft)S.ingestDraft=clone(ingFromSrv(

// ── API ────────────────────────────────────────────────────────────────────
async function api(path,opts){const r=await fetch(path,opts);const t=await r.text();if(!r.ok)throw new Error(t.trim()||`HTTP ${r.status}`);if(!t)return{};try{return JSON.parse(t);}catch{return{ok:true};}}
function setConn(ok,label){const led=$('led-conn'),lbl=$('conn-label');led.className='led '+(ok?S.pending>0?'on-amber':'on-green':'on-red');lbl.textContent=ok?S.pending>0?'busy':label||'connected':label||'offline';}
function setConn(ok,label){const led=$('led-conn'),lbl=$('conn-label');led.className='led '+(ok?S.pending>0?'on-amber':'on-green':'on-red');lbl.textContent=ok?S.pending>0?'busy':label||'connected':label||'offline';const tl=$('telemetry-label');if(tl){const src=S.telemetry?.source||'snapshot';const why=S.telemetry?.fallbackReason;tl.textContent=src==='ws'?'telemetry: ws':`telemetry: snapshot${why?` (${why})`:''}`;}}
async function loadConfig({silent=false}={}){try{const cfg=await api('/config');S.server.config=cfg;S.server.configOk=true;S.server.lastConfigAt=Date.now();syncIngDraft();syncCfgFromServer();syncFreqPresetIdx(cfg.fm?.frequencyMHz);setConn(true);render();if(!silent)log('Config synchronized','info');return cfg;}catch(e){S.server.configOk=false;if(!S.server.runtimeOk)setConn(false);render();if(!silent)log('Config load failed: '+e.message,'err');throw e;}}
async function loadRuntime({silent=true}={}){try{const rt=await api('/runtime');S.server.runtime=rt;S.server.runtimeOk=true;S.server.lastRuntimeAt=Date.now();const synced=syncTransitions(rt.engine);notifyTransition(rt.engine,!synced);pushHistory(rt);setConn(true);render();return rt;}catch(e){S.server.runtimeOk=false;if(!S.server.configOk)setConn(false);render();if(!silent)log('Runtime load failed: '+e.message,'err');throw e;}}
async function loadMeasurements({silent=true}={}){if(!S.telemetry.snapshotPollingActive)return S.server.measurements;try{const ms=await api('/measurements');S.server.measurements=ms;S.server.lastMeasurementsAt=Date.now();S.telemetry.source='snapshot';render();return ms;}catch(e){if(!silent)log('Measurements load failed: '+e.message,'err');throw e;}}
@@ -1208,6 +1209,7 @@ function _render(){
setText('badge-backend',cfg.backend?.kind||cfg.backend||'--');
setText('badge-mode',eng.state&&eng.state!=='idle'?'TX Active':'Control Plane');
setText('badge-live',S.server.runtimeOk?'Connected':'Waiting');
setConn(S.server.configOk||S.server.runtimeOk);

// ── Overview: freq display
const applied=isFinite(Number(eng.appliedFrequencyMHz))?Number(eng.appliedFrequencyMHz):(isFinite(Number(S.server.measurements?.appliedFrequencyMHz))?Number(S.server.measurements.appliedFrequencyMHz):NaN),desired=Number(cfg.fm?.frequencyMHz);


Loading…
Annulla
Salva