feat: Added Ultrabeam/Steppir to Station Control with function to retract elements.

This commit is contained in:
2026-07-16 22:10:36 +02:00
parent f853dd479e
commit 09848adddc
6 changed files with 132 additions and 14 deletions
+39 -7
View File
@@ -10747,6 +10747,11 @@ type motorAntenna interface {
Retract() error
LastSetKHz() int
Status() motorStatus
// Elements returns the per-element lengths (mm) when the antenna exposes them
// (Ultrabeam), or nil when it doesn't (SteppIR tunes its elements from the
// frequency and has no individual-element command).
Elements() []int
SetElement(num, lengthMm int) error
}
// ubAdapter / steppirAdapter wrap each concrete client to the shared interface,
@@ -10760,6 +10765,13 @@ func (a ubAdapter) SetFrequency(k, d int) error { return a.c.SetFrequency(k, d)
func (a ubAdapter) SetDirection(d int) error { return a.c.SetDirection(d) }
func (a ubAdapter) Retract() error { return a.c.Retract() }
func (a ubAdapter) LastSetKHz() int { return a.c.LastSetKHz() }
func (a ubAdapter) SetElement(n, mm int) error { return a.c.ModifyElement(n, mm) }
func (a ubAdapter) Elements() []int {
if st, err := a.c.GetStatus(); err == nil && st != nil {
return st.ElementLengths
}
return nil
}
func (a ubAdapter) Status() motorStatus {
st, err := a.c.GetStatus()
if err != nil || st == nil {
@@ -10776,6 +10788,10 @@ func (a steppirAdapter) SetFrequency(k, d int) error { return a.c.SetFrequency(k
func (a steppirAdapter) SetDirection(d int) error { return a.c.SetDirection(d) }
func (a steppirAdapter) Retract() error { return a.c.Retract() }
func (a steppirAdapter) LastSetKHz() int { return a.c.LastSetKHz() }
func (a steppirAdapter) Elements() []int { return nil } // SteppIR: no per-element control
func (a steppirAdapter) SetElement(_, _ int) error {
return fmt.Errorf("individual element control is not available on the SteppIR")
}
func (a steppirAdapter) Status() motorStatus {
st, err := a.c.GetStatus()
if err != nil || st == nil {
@@ -11062,19 +11078,22 @@ func (a *App) ultrabeamFollowLoop(c motorAntenna, stepKHz int, stop <-chan struc
// direction control). Enabled mirrors the setting; the rest comes from the
// device's most recent status poll.
type UltrabeamStatusInfo struct {
Enabled bool `json:"enabled"`
Connected bool `json:"connected"`
Direction int `json:"direction"` // 0=normal, 1=180°, 2=bidirectional
Frequency int `json:"frequency"` // KHz
Band int `json:"band"`
Moving bool `json:"moving"`
Enabled bool `json:"enabled"`
Type string `json:"type"` // "ultrabeam" | "steppir"
Connected bool `json:"connected"`
Direction int `json:"direction"` // 0=normal, 1=180°, 2=bidirectional
Frequency int `json:"frequency"` // KHz
Band int `json:"band"`
Moving bool `json:"moving"`
Elements []int `json:"elements"` // per-element lengths (mm); empty when unsupported
}
// GetUltrabeamStatus returns the antenna's current state for the UI poll.
func (a *App) GetUltrabeamStatus() UltrabeamStatusInfo {
out := UltrabeamStatusInfo{}
out := UltrabeamStatusInfo{Elements: []int{}}
s, _ := a.GetUltrabeamSettings()
out.Enabled = s.Enabled
out.Type = s.Type
if a.motorAnt == nil {
return out
}
@@ -11084,9 +11103,22 @@ func (a *App) GetUltrabeamStatus() UltrabeamStatusInfo {
out.Frequency = st.Frequency
out.Band = st.Band
out.Moving = st.Moving
if el := a.motorAnt.Elements(); el != nil {
out.Elements = el
}
return out
}
// MotorSetElement sets one element's length (mm) on an Ultrabeam. Returns an
// error on the SteppIR, which has no per-element command.
func (a *App) MotorSetElement(num, lengthMm int) error {
if a.motorAnt == nil {
return fmt.Errorf("antenna not connected — enable it in Settings → Antenna")
}
a.noteMotorMoveCommanded()
return a.motorAnt.SetElement(num, lengthMm)
}
// SetUltrabeamDirection switches the antenna pattern: 0=normal, 1=180°,
// 2=bidirectional (re-issues the current frequency with the new direction).
func (a *App) SetUltrabeamDirection(direction int) error {