fix(motor-antenna): honor the configured tunable range for the Ultrabeam

The follow logic skips out-of-range frequencies only when it knows BOTH edges
of the antenna's range. The Ultrabeam path took those edges from the
controller's status frame, but an RCU-01 behind an RS232-to-Ethernet bridge
answers with the short frame that omits FreqMax → the guard saw FreqMax==0 and
disabled itself → OpsLog forwarded every rig frequency, so 80 m (un-tunable)
reached the controller, which clamped the elements down to its lowest band
(~30 m).

ubAdapter now carries the operator-configured FreqMin/FreqMax from Settings →
Antenna (like steppirAdapter already did) and uses them as a hard floor/ceiling,
falling back to the controller-reported bound only when one is left unset. This
guarantees both bounds are present so the guard actually engages. The Tunable
range editor in the Antenna panel, previously SteppIR-only, is now shown for the
Ultrabeam too, with a generic bilingual hint.
This commit is contained in:
2026-08-06 11:02:14 +02:00
parent 82ce3353c4
commit df56391eb8
4 changed files with 33 additions and 10 deletions
+24 -3
View File
@@ -14184,7 +14184,17 @@ type motorAntenna interface {
// ubAdapter / steppirAdapter wrap each concrete client to the shared interface,
// translating only the status shape (both already use the same 0/1/2 direction
// convention, so commands pass straight through).
type ubAdapter struct{ c *ultrabeam.Client }
type ubAdapter struct {
c *ultrabeam.Client
// Configured tunable range (MHz) from Settings → Antenna. The follow logic
// uses this as a hard floor/ceiling: some controllers (e.g. an RCU-01 behind
// an RS232-to-Ethernet bridge) answer with the short status frame that omits
// FreqMax, which would disable the out-of-range guard and let OpsLog forward
// an un-tunable frequency (80 m → the controller clamps the elements to its
// lowest band, ~30 m). Trusting the operator's configured range instead keeps
// the antenna put on bands it can't reach.
freqMin, freqMax int
}
func (a ubAdapter) Start() error { return a.c.Start() }
func (a ubAdapter) Stop() { a.c.Stop() }
@@ -14205,7 +14215,18 @@ func (a ubAdapter) Status() motorStatus {
if err != nil || st == nil {
return motorStatus{}
}
return motorStatus{Connected: st.Connected, Direction: st.Direction, Frequency: st.Frequency, Band: st.Band, Moving: st.MotorsMoving != 0, FreqMin: st.FreqMin, FreqMax: st.FreqMax}
// Prefer the operator's configured range; fall back to whatever the controller
// self-reported only when a bound is left unset. This guarantees BOTH bounds
// are present so the follow guard actually engages — a controller that reports
// FreqMin but not FreqMax (short status frame) would otherwise disable it.
fmin, fmax := a.freqMin, a.freqMax
if fmin <= 0 {
fmin = st.FreqMin
}
if fmax <= 0 {
fmax = st.FreqMax
}
return motorStatus{Connected: st.Connected, Direction: st.Direction, Frequency: st.Frequency, Band: st.Band, Moving: st.MotorsMoving != 0, FreqMin: fmin, FreqMax: fmax}
}
type steppirAdapter struct {
@@ -14376,7 +14397,7 @@ func newMotorClient(s UltrabeamSettings) motorAntenna {
if strings.TrimSpace(s.Host) == "" {
return nil
}
return ubAdapter{ultrabeam.New(s.Host, s.Port)}
return ubAdapter{c: ultrabeam.New(s.Host, s.Port), freqMin: s.FreqMinMHz, freqMax: s.FreqMaxMHz}
}
// startUltrabeam stops any existing client and starts a fresh one if the