chore(flex): log the spots other programs post to the radio
Chasing a split pileup with a CW skimmer means acting on the report the DX just sent: SDC posts what it decodes as panadapter spots, so the 5NN is already on the radio and OpsLog already subscribes to 'spot all'. What is not known is the shape of those spots -- which field carries the report, whether it is the callsign or the comment, what source the skimmer names itself. Guessing produces a feature that never fires, so this logs the first 60 foreign spots of a session verbatim and does nothing else. Bounded because a skimmer posts hundreds an hour.
This commit is contained in:
@@ -60,6 +60,9 @@ type Flex struct {
|
||||
txRawLogged bool // log the first raw transmit status once (field-name audit)
|
||||
|
||||
spotsEnabled bool // push cluster spots + manage the panadapter overlay
|
||||
// foreignSpotSeen counts what probeForeignSpot has already reported, so a
|
||||
// skimmer posting all evening cannot turn the log into its own transcript.
|
||||
foreignSpotSeen int
|
||||
spotIdx map[int]bool // panadapter spot indices currently known to the radio
|
||||
pendingSpot map[int]string // seq → callsign, awaiting the spot index in the R response
|
||||
pendingSpotMode map[int]string // seq → ADIF mode, paired with pendingSpot
|
||||
@@ -883,6 +886,9 @@ func (f *Flex) handleStatus(payload string) {
|
||||
f.spotIdx[idx] = true
|
||||
}
|
||||
f.mu.Unlock()
|
||||
if !removed {
|
||||
f.probeForeignSpot(payload)
|
||||
}
|
||||
}
|
||||
debugLog.Printf("Flex: status %s", payload)
|
||||
}
|
||||
@@ -1377,6 +1383,40 @@ func (f *Flex) ZoomPan(bandwidthMHz, freqMHz float64, centre bool) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// foreignSpotProbeMax bounds the probe below. Enough lines to see what another
|
||||
// program writes into a spot, few enough that a running skimmer — which posts
|
||||
// hundreds an hour — cannot fill the log file with them.
|
||||
const foreignSpotProbeMax = 60
|
||||
|
||||
// probeForeignSpot records, verbatim, the spots this radio receives from
|
||||
// programs OTHER than OpsLog.
|
||||
//
|
||||
// A CW skimmer (SDC, for one) posts what it decodes as panadapter spots, the
|
||||
// exchange included: chasing a split pileup means finding the "5NN" the DX just
|
||||
// sent and moving the transmit slice there. Acting on that requires knowing
|
||||
// exactly what the spot looks like — which field carries the text, whether the
|
||||
// report is the callsign or the comment, what source names the skimmer — and no
|
||||
// amount of reasoning substitutes for reading real lines off a real radio.
|
||||
//
|
||||
// So this logs and does nothing else. It is deliberately not a feature.
|
||||
func (f *Flex) probeForeignSpot(payload string) {
|
||||
if strings.Contains(payload, "source=OpsLog") {
|
||||
return
|
||||
}
|
||||
f.mu.Lock()
|
||||
if f.foreignSpotSeen >= foreignSpotProbeMax {
|
||||
f.mu.Unlock()
|
||||
return
|
||||
}
|
||||
f.foreignSpotSeen++
|
||||
n := f.foreignSpotSeen
|
||||
f.mu.Unlock()
|
||||
debugLog.Printf("flex: foreign spot %d/%d: %s", n, foreignSpotProbeMax, payload)
|
||||
if n == foreignSpotProbeMax {
|
||||
debugLog.Printf("flex: that is enough foreign spots to go on — no more will be logged this session")
|
||||
}
|
||||
}
|
||||
|
||||
// SendSpot renders a cluster spot on the panadapter via "spot add". Spots carry
|
||||
// a lifetime so the radio expires them on its own (the API has no "spot clear").
|
||||
// Per the SmartSDR API, spaces inside a field value are encoded as 0x7F.
|
||||
|
||||
Reference in New Issue
Block a user