diff --git a/internal/runtime/runtime.go b/internal/runtime/runtime.go
index d397bb5..30f31f1 100644
--- a/internal/runtime/runtime.go
+++ b/internal/runtime/runtime.go
@@ -34,6 +34,7 @@ type DetectorUpdate struct {
CFARRank *int `json:"cfar_rank"`
CFARScaleDb *float64 `json:"cfar_scale_db"`
CFARWrapAround *bool `json:"cfar_wrap_around"`
+ EdgeMarginDb *float64 `json:"edge_margin_db"`
}
type SettingsUpdate struct {
@@ -195,6 +196,13 @@ func (m *Manager) ApplyConfig(update ConfigUpdate) (config.Config, error) {
if update.Detector.CFARScaleDb != nil {
next.Detector.CFARScaleDb = *update.Detector.CFARScaleDb
}
+ if update.Detector.EdgeMarginDb != nil {
+ v := *update.Detector.EdgeMarginDb
+ if math.IsNaN(v) || math.IsInf(v, 0) || v < 0 {
+ return m.cfg, errors.New("edge_margin_db must be >= 0")
+ }
+ next.Detector.EdgeMarginDb = v
+ }
}
if update.Recorder != nil {
if update.Recorder.Enabled != nil {
diff --git a/web/app.js b/web/app.js
index d1ee8e4..2aebd36 100644
--- a/web/app.js
+++ b/web/app.js
@@ -42,6 +42,7 @@ const emaAlphaInput = qs('emaAlphaInput');
const hysteresisInput = qs('hysteresisInput');
const stableFramesInput = qs('stableFramesInput');
const gapToleranceInput = qs('gapToleranceInput');
+const edgeMarginInput = qs('edgeMarginInput');
const agcToggle = qs('agcToggle');
const dcToggle = qs('dcToggle');
const iqToggle = qs('iqToggle');
@@ -418,6 +419,7 @@ function applyConfigToUI(cfg) {
if (hysteresisInput) hysteresisInput.value = cfg.detector.hysteresis_db ?? 3;
if (stableFramesInput) stableFramesInput.value = cfg.detector.min_stable_frames ?? 3;
if (gapToleranceInput) gapToleranceInput.value = cfg.detector.gap_tolerance_ms ?? cfg.detector.hold_ms;
+ if (edgeMarginInput) edgeMarginInput.value = cfg.detector.edge_margin_db ?? 3.0;
agcToggle.checked = !!cfg.agc;
dcToggle.checked = !!cfg.dc_block;
iqToggle.checked = !!cfg.iq_balance;
@@ -1416,6 +1418,10 @@ if (gapToleranceInput) gapToleranceInput.addEventListener('change', () => {
const v = parseInt(gapToleranceInput.value, 10);
if (Number.isFinite(v)) queueConfigUpdate({ detector: { gap_tolerance_ms: v } });
});
+if (edgeMarginInput) edgeMarginInput.addEventListener('change', () => {
+ const v = parseFloat(edgeMarginInput.value);
+ if (Number.isFinite(v)) queueConfigUpdate({ detector: { edge_margin_db: v } });
+});
agcToggle.addEventListener('change', () => queueSettingsUpdate({ agc: agcToggle.checked }));
dcToggle.addEventListener('change', () => queueSettingsUpdate({ dc_block: dcToggle.checked }));
diff --git a/web/index.html b/web/index.html
index 1b932c2..c75478e 100644
--- a/web/index.html
+++ b/web/index.html
@@ -197,6 +197,7 @@
+