feat(antgenius): the selected antenna can fill MY_ANTENNA
A station with a switch knows something the log does not: which antenna is actually connected. The working conditions hold what was PLANNED for the band, and stay right until the operator throws the switch — after which every QSO keeps claiming the other antenna. Optional, and off by default: a station that names its antennas differently in the two places would otherwise find its log quietly rewritten. The name written is the one configured on the device, since that is the name the operator gave it and the one they will look for. WHICH PORT is the real problem, and the reason this is not a one-liner. The switch has two, the radio has two jacks, and the QSO went out through one of them; naming the wrong port's antenna is worse than naming the band default, because it looks authoritative. The radio's own TX antenna selection decides, and the jack-to-port wiring is a setting — it is the station's cabling and neither device can report it. When the port cannot be told — a transverter jack, a rig that reports nothing, both switch ports live — nothing is written and the band default stands. Silence beats a confident guess in a field nobody re-checks.
This commit is contained in:
@@ -0,0 +1,129 @@
|
||||
package main
|
||||
|
||||
// MY_ANTENNA from the Antenna Genius.
|
||||
//
|
||||
// A station with a switch has a truth the log does not: which antenna is
|
||||
// actually connected right now. The working conditions hold what was PLANNED
|
||||
// for the band — the default antenna ticked for 20 m — and that is right until
|
||||
// the operator throws the switch, at which point the log quietly keeps claiming
|
||||
// the other antenna for the rest of the session.
|
||||
//
|
||||
// So, as an option: when the Antenna Genius knows which antenna is selected,
|
||||
// its name wins. The name is the one configured on the device, because that is
|
||||
// the name the operator gave it and the one they will look for in the log.
|
||||
//
|
||||
// WHICH PORT is the whole difficulty. An Antenna Genius has two, A and B, and a
|
||||
// FlexRadio has two transmit antenna jacks, ANT1 and ANT2. The QSO was made on
|
||||
// exactly one of them, and stamping the wrong port's antenna would be worse
|
||||
// than stamping the band default — a wrong answer that looks authoritative. The
|
||||
// radio's own TX antenna selection is what decides.
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"hamlog/internal/antgenius"
|
||||
"hamlog/internal/applog"
|
||||
)
|
||||
|
||||
const (
|
||||
keyAntGeniusMyAnt = "antgenius.my_antenna" // use the selected antenna as MY_ANTENNA
|
||||
keyAntGeniusPortForA1 = "antgenius.port_for_ant1" // which AG port ANT1 is wired to (1=A, 2=B)
|
||||
)
|
||||
|
||||
// antGeniusPortFor maps the radio's transmit antenna jack to an Antenna Genius
|
||||
// port.
|
||||
//
|
||||
// The wiring is the station's, not something that can be read from either
|
||||
// device: ANT1 usually goes to port A and ANT2 to port B, which is what the
|
||||
// setting defaults to, but a station wired the other way round would otherwise
|
||||
// log every QSO with the other antenna's name.
|
||||
func (a *App) antGeniusPortFor(txAnt string) int {
|
||||
ant1Port := 1
|
||||
if a.settingOr(keyAntGeniusPortForA1, "1") == "2" {
|
||||
ant1Port = 2
|
||||
}
|
||||
other := 3 - ant1Port
|
||||
switch strings.ToUpper(strings.TrimSpace(txAnt)) {
|
||||
case "ANT1", "ANT 1", "1", "A":
|
||||
return ant1Port
|
||||
case "ANT2", "ANT 2", "2", "B":
|
||||
return other
|
||||
}
|
||||
return 0 // XVTR, a rig with one jack, or nothing reported: no port to name
|
||||
}
|
||||
|
||||
// antGeniusAntennaName returns the name of the antenna currently selected on
|
||||
// the port the radio is transmitting through, or "" when it cannot be told.
|
||||
//
|
||||
// Deliberately silent rather than approximate. Every "" here means the log
|
||||
// keeps the band default it would have had anyway, which is a defensible
|
||||
// answer; a guessed port is not.
|
||||
func (a *App) antGeniusAntennaName() string {
|
||||
if a.antgenius == nil {
|
||||
return ""
|
||||
}
|
||||
st := a.antgenius.GetStatus()
|
||||
if !st.Connected {
|
||||
return ""
|
||||
}
|
||||
// The jack in use comes from the FlexRadio's own state — TXAnt lives on the
|
||||
// Flex panel state, not on the backend-agnostic RigState, because only a
|
||||
// Flex has named antenna jacks to report.
|
||||
txAnt := ""
|
||||
if a.cat != nil {
|
||||
if fs, ok := a.cat.FlexState(); ok {
|
||||
txAnt = fs.TXAnt
|
||||
}
|
||||
}
|
||||
port := a.antGeniusPortFor(txAnt)
|
||||
if port == 0 {
|
||||
// One switch port in use and no ambiguity about which: a station whose
|
||||
// radio has a single jack still deserves the name. Two ports carrying
|
||||
// different antennas with nothing to choose between them does not.
|
||||
if st.PortA > 0 && st.PortB == 0 {
|
||||
port = 1
|
||||
} else if st.PortB > 0 && st.PortA == 0 {
|
||||
port = 2
|
||||
} else {
|
||||
return ""
|
||||
}
|
||||
}
|
||||
idx := st.PortA
|
||||
if port == 2 {
|
||||
idx = st.PortB
|
||||
}
|
||||
if idx <= 0 {
|
||||
return ""
|
||||
}
|
||||
return antGeniusNameOf(st, idx)
|
||||
}
|
||||
|
||||
// antGeniusNameOf looks an antenna index up in the device's own list.
|
||||
func antGeniusNameOf(st antgenius.Status, idx int) string {
|
||||
for _, ant := range st.Antennas {
|
||||
if ant.Index == idx {
|
||||
return strings.TrimSpace(ant.Name)
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// applyAntGeniusAntenna overrides MY_ANTENNA with the switch's selection, when
|
||||
// the option is on.
|
||||
//
|
||||
// Called at log time rather than while the entry form is open: an operator who
|
||||
// changes antenna mid-QSO is telling us what the contact was actually made on,
|
||||
// and the value that matters is the one at the moment it is logged.
|
||||
func (a *App) applyAntGeniusAntenna(myAntenna *string) {
|
||||
if myAntenna == nil || a.settingOr(keyAntGeniusMyAnt, "") != "1" {
|
||||
return
|
||||
}
|
||||
name := a.antGeniusAntennaName()
|
||||
if name == "" {
|
||||
return
|
||||
}
|
||||
if *myAntenna != name {
|
||||
applog.Printf("antgenius: MY_ANTENNA %q → %q (the antenna selected on the switch)", *myAntenna, name)
|
||||
}
|
||||
*myAntenna = name
|
||||
}
|
||||
Reference in New Issue
Block a user