[feat](trx-frontend-http): add clickable Sig Strength field between Wavelength and Frequency
Add a new "Sig Strength" display field in the freq row that shows the measured signal strength. Clicking the field cycles through three units: dBFS (default), dBf, and dBm. The selected unit is persisted in localStorage. https://claude.ai/code/session_01EvRV8UgsVtbrcH4t2hmFBF Signed-off-by: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -307,6 +307,7 @@ function applyCapabilities(caps) {
|
|||||||
const freqEl = document.getElementById("freq");
|
const freqEl = document.getElementById("freq");
|
||||||
const centerFreqEl = document.getElementById("center-freq");
|
const centerFreqEl = document.getElementById("center-freq");
|
||||||
const wavelengthEl = document.getElementById("wavelength");
|
const wavelengthEl = document.getElementById("wavelength");
|
||||||
|
const sigStrengthEl = document.getElementById("sig-strength");
|
||||||
const modeEl = document.getElementById("mode");
|
const modeEl = document.getElementById("mode");
|
||||||
const bandLabel = document.getElementById("band-label");
|
const bandLabel = document.getElementById("band-label");
|
||||||
const powerBtn = document.getElementById("power-btn");
|
const powerBtn = document.getElementById("power-btn");
|
||||||
@@ -573,6 +574,38 @@ let lastRendered = null;
|
|||||||
let hintTimer = null;
|
let hintTimer = null;
|
||||||
let sigMeasuring = false;
|
let sigMeasuring = false;
|
||||||
let sigLastSUnits = null;
|
let sigLastSUnits = null;
|
||||||
|
let sigLastDbm = null;
|
||||||
|
const SIG_STRENGTH_UNITS = ["dBFS", "dBf", "dBm"];
|
||||||
|
let sigStrengthUnitIdx = loadSetting("sigStrengthUnit", 0);
|
||||||
|
|
||||||
|
function formatSigStrength(dbm) {
|
||||||
|
if (!Number.isFinite(dbm)) return "--";
|
||||||
|
const unit = SIG_STRENGTH_UNITS[sigStrengthUnitIdx] || "dBFS";
|
||||||
|
if (unit === "dBm") return `${dbm} dBm`;
|
||||||
|
if (unit === "dBf") {
|
||||||
|
// dBf = dBm + 107 (referenced to 1 femtowatt across 50 Ω)
|
||||||
|
const dbf = dbm + 107;
|
||||||
|
return `${dbf.toFixed(0)} dBf`;
|
||||||
|
}
|
||||||
|
// dBFS: map receiver range to a full-scale reference
|
||||||
|
// Typical receiver: -140 dBm (noise floor) to 0 dBm (full scale)
|
||||||
|
const dbfs = Math.max(-140, Math.min(0, dbm));
|
||||||
|
return `${dbfs} dBFS`;
|
||||||
|
}
|
||||||
|
|
||||||
|
function refreshSigStrengthDisplay() {
|
||||||
|
if (!sigStrengthEl) return;
|
||||||
|
sigStrengthEl.textContent = formatSigStrength(sigLastDbm);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sigStrengthEl) {
|
||||||
|
sigStrengthEl.addEventListener("click", () => {
|
||||||
|
sigStrengthUnitIdx = (sigStrengthUnitIdx + 1) % SIG_STRENGTH_UNITS.length;
|
||||||
|
saveSetting("sigStrengthUnit", sigStrengthUnitIdx);
|
||||||
|
refreshSigStrengthDisplay();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
let sigMeasureTimer = null;
|
let sigMeasureTimer = null;
|
||||||
let sigMeasureLastTickMs = 0;
|
let sigMeasureLastTickMs = 0;
|
||||||
let sigMeasureAccumMs = 0;
|
let sigMeasureAccumMs = 0;
|
||||||
@@ -3217,13 +3250,17 @@ function render(update) {
|
|||||||
if (update.status && update.status.rx && typeof update.status.rx.sig === "number") {
|
if (update.status && update.status.rx && typeof update.status.rx.sig === "number") {
|
||||||
const sUnits = dbmToSUnits(update.status.rx.sig);
|
const sUnits = dbmToSUnits(update.status.rx.sig);
|
||||||
sigLastSUnits = sUnits;
|
sigLastSUnits = sUnits;
|
||||||
|
sigLastDbm = update.status.rx.sig;
|
||||||
const pct = sUnits <= 9 ? Math.max(0, Math.min(100, (sUnits / 9) * 100)) : 100;
|
const pct = sUnits <= 9 ? Math.max(0, Math.min(100, (sUnits / 9) * 100)) : 100;
|
||||||
signalBar.style.width = `${pct}%`;
|
signalBar.style.width = `${pct}%`;
|
||||||
signalValue.textContent = formatSignal(sUnits);
|
signalValue.textContent = formatSignal(sUnits);
|
||||||
|
refreshSigStrengthDisplay();
|
||||||
} else {
|
} else {
|
||||||
sigLastSUnits = null;
|
sigLastSUnits = null;
|
||||||
|
sigLastDbm = null;
|
||||||
signalBar.style.width = "0%";
|
signalBar.style.width = "0%";
|
||||||
signalValue.textContent = "--";
|
signalValue.textContent = "--";
|
||||||
|
refreshSigStrengthDisplay();
|
||||||
}
|
}
|
||||||
if (bandLabel) {
|
if (bandLabel) {
|
||||||
bandLabel.textContent = typeof update.band === "string" ? update.band : "--";
|
bandLabel.textContent = typeof update.band === "string" ? update.band : "--";
|
||||||
|
|||||||
@@ -176,6 +176,10 @@
|
|||||||
<div class="wavelength-display" id="wavelength" title="Wavelength">--</div>
|
<div class="wavelength-display" id="wavelength" title="Wavelength">--</div>
|
||||||
<div class="label"><span>Wavelength</span></div>
|
<div class="label"><span>Wavelength</span></div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="freq-field sig-strength-col">
|
||||||
|
<div class="sig-strength-display" id="sig-strength" title="Click to change unit">--</div>
|
||||||
|
<div class="label"><span>Sig Strength</span></div>
|
||||||
|
</div>
|
||||||
<div class="freq-field frequency-col">
|
<div class="freq-field frequency-col">
|
||||||
<input class="status-input" id="freq" type="text" value="--" />
|
<input class="status-input" id="freq" type="text" value="--" />
|
||||||
<div class="label"><span>Frequency</span></div>
|
<div class="label"><span>Frequency</span></div>
|
||||||
|
|||||||
@@ -550,6 +550,9 @@ button:disabled { opacity: 0.6; cursor: not-allowed; }
|
|||||||
.wavelength-col {
|
.wavelength-col {
|
||||||
flex: 0 0 auto;
|
flex: 0 0 auto;
|
||||||
}
|
}
|
||||||
|
.sig-strength-col {
|
||||||
|
flex: 0 0 auto;
|
||||||
|
}
|
||||||
.unit-col {
|
.unit-col {
|
||||||
flex: 0 0 auto;
|
flex: 0 0 auto;
|
||||||
}
|
}
|
||||||
@@ -625,6 +628,26 @@ button:disabled { opacity: 0.6; cursor: not-allowed; }
|
|||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
}
|
}
|
||||||
|
.sig-strength-display {
|
||||||
|
min-width: 5.2rem;
|
||||||
|
height: 3.35rem;
|
||||||
|
padding: 0 0.7rem;
|
||||||
|
border: 1px solid var(--border-light);
|
||||||
|
border-radius: 6px;
|
||||||
|
background: var(--input-bg);
|
||||||
|
color: var(--wavelength-fg);
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
font-family: 'DSEG14 Classic', monospace;
|
||||||
|
font-weight: 600;
|
||||||
|
font-size: 1.25rem;
|
||||||
|
letter-spacing: 0.03em;
|
||||||
|
white-space: nowrap;
|
||||||
|
flex-shrink: 0;
|
||||||
|
cursor: pointer;
|
||||||
|
user-select: none;
|
||||||
|
}
|
||||||
small { color: var(--text-muted); }
|
small { color: var(--text-muted); }
|
||||||
.header {
|
.header {
|
||||||
margin-bottom: 0;
|
margin-bottom: 0;
|
||||||
@@ -2747,11 +2770,13 @@ button:focus-visible, input:focus-visible, select:focus-visible {
|
|||||||
min-width: 0;
|
min-width: 0;
|
||||||
}
|
}
|
||||||
.wavelength-col,
|
.wavelength-col,
|
||||||
|
.sig-strength-col,
|
||||||
.unit-col,
|
.unit-col,
|
||||||
.mult-col {
|
.mult-col {
|
||||||
min-width: 0;
|
min-width: 0;
|
||||||
}
|
}
|
||||||
.wavelength-display,
|
.wavelength-display,
|
||||||
|
.sig-strength-display,
|
||||||
.jog-step,
|
.jog-step,
|
||||||
.jog-mult {
|
.jog-mult {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
|||||||
Reference in New Issue
Block a user