fix: Flex with multiple slices opened was always showing slice A s-meter.

This commit is contained in:
2026-07-10 23:13:06 +02:00
parent 6c39204301
commit 73f3ec51f7
10 changed files with 192 additions and 15 deletions
+1
View File
@@ -330,6 +330,7 @@ type FlexMeter struct {
Src string `json:"src,omitempty"` // SLC / TX- / RAD / AMP…
Name string `json:"name,omitempty"` // FWDPWR, SWR, LEVEL, PATEMP…
Unit string `json:"unit,omitempty"`
Slice int `json:"slice"` // for SLC meters, the slice index it belongs to; -1 otherwise
Value float64 `json:"value"`
Lo float64 `json:"lo"`
Hi float64 `json:"hi"`
+24 -6
View File
@@ -140,6 +140,7 @@ type meterInfo struct {
src string // SLC (slice), TX-, COD, RAD, AMP…
name string // FWDPWR, SWR, LEVEL, PATEMP, +13.8B…
unit string // dbm, dbfs, swr, volts, degc, watts…
slc int // for src=SLC meters, the slice index (the ".num" field); -1 otherwise
lo float64
hi float64
}
@@ -641,7 +642,7 @@ func (f *Flex) handleStatus(payload string) {
// One meter per token; its fields are '#'-separated:
// "<n>.src=…#<n>.num=…#<n>.nam=…#<n>.low=…#<n>.hi=…#<n>.unit=…".
num := -1
var mi meterInfo
mi := meterInfo{slc: -1}
for _, sub := range strings.Split(tok, "#") {
key, val, ok := splitKV(sub)
if !ok {
@@ -661,6 +662,12 @@ func (f *Flex) handleStatus(payload string) {
mi.src = val
case "nam":
mi.name = val
case "num":
// For a slice (SLC) meter this field is the slice index —
// how we tell slice A's S-meter from slice B's.
if v, e := strconv.Atoi(strings.TrimSpace(val)); e == nil {
mi.slc = v
}
case "unit", "units":
mi.unit = val
case "low", "lo":
@@ -675,6 +682,7 @@ func (f *Flex) handleStatus(payload string) {
old, seen := f.meterMeta[num]
if !seen {
newIDs = append(newIDs, num)
old.slc = -1
}
if mi.src != "" {
old.src = mi.src
@@ -685,6 +693,9 @@ func (f *Flex) handleStatus(payload string) {
if mi.unit != "" {
old.unit = mi.unit
}
if mi.slc >= 0 {
old.slc = mi.slc
}
if mi.lo != 0 {
old.lo = mi.lo
}
@@ -1079,15 +1090,22 @@ func (f *Flex) SendSpot(s SpotInfo) error {
}
// De-dupe by callsign: WSJT decodes re-fire every cycle, so a station already
// spotted gets its previous spot removed first — one live spot per call,
// refreshed, instead of a pile that all expire independently.
// refreshed, instead of a pile that all expire independently. NB: capture the
// old index under the lock but send OUTSIDE it — f.send() takes f.mu itself,
// and Go mutexes aren't reentrant (calling send while locked deadlocks the
// whole Flex goroutine → the radio drops OFFLINE).
upperCall := strings.ToUpper(s.Callsign)
f.mu.Lock()
if old, ok := f.spotByCall[strings.ToUpper(s.Callsign)]; ok {
delete(f.spotByCall, strings.ToUpper(s.Callsign))
old, hadOld := f.spotByCall[upperCall]
if hadOld {
delete(f.spotByCall, upperCall)
delete(f.spotCall, old)
delete(f.spotIdx, old)
f.send(fmt.Sprintf("spot remove %d", old))
}
f.mu.Unlock()
if hadOld {
f.send(fmt.Sprintf("spot remove %d", old))
}
cmd := fmt.Sprintf("spot add rx_freq=%.6f callsign=%s color=%s source=OpsLog lifetime_seconds=%d trigger_action=Tune timestamp=%d",
float64(s.FreqHz)/1e6, call, color, life, time.Now().Unix())
if m := flexEncode(s.Mode); m != "" {
@@ -1321,7 +1339,7 @@ func (f *Flex) FlexState() FlexTXState {
sort.Ints(ids) // stable order so the UI doesn't reshuffle each poll
for _, id := range ids {
mi := f.meterMeta[id]
st.Meters = append(st.Meters, FlexMeter{ID: id, Src: mi.src, Name: mi.name, Unit: mi.unit, Value: f.meterVal[id], Lo: mi.lo, Hi: mi.hi})
st.Meters = append(st.Meters, FlexMeter{ID: id, Src: mi.src, Name: mi.name, Unit: mi.unit, Slice: mi.slc, Value: f.meterVal[id], Lo: mi.lo, Hi: mi.hi})
}
}
return st