chore: release v0.19.4

This commit is contained in:
2026-07-10 17:16:32 +02:00
parent 0c3089344b
commit 6c39204301
11 changed files with 275 additions and 22 deletions
+41 -1
View File
@@ -89,6 +89,8 @@ const (
keyCATFlexHost = "cat.flex.host" // FlexRadio IP (native backend)
keyCATFlexPort = "cat.flex.port" // FlexRadio TCP port (default 4992)
keyCATFlexSpots = "cat.flex.spots" // push cluster spots to the panadapter
keyCATFlexDecodeSpots = "cat.flex.decode_spots" // push WSJT-X decodes (heard stations) to the panadapter
keyCATFlexDecodeSecs = "cat.flex.decode_secs" // decode spot display duration (seconds) before auto-removal
keyCATPollMs = "cat.poll_ms"
keyCATDelayMs = "cat.delay_ms" // pause between commands
keyCATDigitalDefault = "cat.digital_default" // mode to use when CAT reports DATA
@@ -277,6 +279,8 @@ type CATSettings struct {
FlexHost string `json:"flex_host"` // FlexRadio IP (native backend)
FlexPort int `json:"flex_port"` // FlexRadio TCP port (default 4992)
FlexSpots bool `json:"flex_spots"` // push cluster spots to the panadapter
FlexDecodeSpots bool `json:"flex_decode_spots"` // push WSJT-X decodes (heard stations) to the panadapter
FlexDecodeSecs int `json:"flex_decode_secs"` // decode spot display duration (s) before removal (default 120)
IcomPort string `json:"icom_port"` // Icom USB CI-V serial port (e.g. COM5)
IcomBaud int `json:"icom_baud"` // Icom CI-V baud (default 115200)
IcomAddr int `json:"icom_addr"` // Icom CI-V address, decimal (IC-7610 = 152)
@@ -453,6 +457,8 @@ type App struct {
dbBackend string // "sqlite" | "mysql" — the logbook backend actually opened at startup
dbBackendErr string // non-empty when a configured MySQL backend failed and we fell back to SQLite
catFlexSpots bool // push cluster spots to the FlexRadio panadapter
catFlexDecodeSpots bool // push WSJT-X decodes (heard stations) to the panadapter
catFlexDecodeSecs int // decode spot display duration (seconds)
liveActMu sync.Mutex // guards the entry-strip activity reported for live status
liveFreqHz int64 // last freq/band/mode the UI reported (fallback when CAT is off)
liveBand string
@@ -4460,7 +4466,7 @@ func (a *App) GetCATSettings() (CATSettings, error) {
if a.settings == nil {
return CATSettings{Backend: "omnirig", OmniRigNum: 1, PollMs: 250}, fmt.Errorf("db not initialized")
}
m, err := a.settings.GetMany(a.ctx, keyCATEnabled, keyCATBackend, keyCATOmniRigNum, keyCATFlexHost, keyCATFlexPort, keyCATFlexSpots, keyCATIcomPort, keyCATIcomBaud, keyCATIcomAddr, keyCATIcomNetHost, keyCATIcomNetUser, keyCATIcomNetPass, keyCATIcomNetAudio, keyCATTCIHost, keyCATTCIPort, keyCATTCISpots, keyCATPollMs, keyCATDelayMs, keyCATDigitalDefault)
m, err := a.settings.GetMany(a.ctx, keyCATEnabled, keyCATBackend, keyCATOmniRigNum, keyCATFlexHost, keyCATFlexPort, keyCATFlexSpots, keyCATFlexDecodeSpots, keyCATFlexDecodeSecs, keyCATIcomPort, keyCATIcomBaud, keyCATIcomAddr, keyCATIcomNetHost, keyCATIcomNetUser, keyCATIcomNetPass, keyCATIcomNetAudio, keyCATTCIHost, keyCATTCIPort, keyCATTCISpots, keyCATPollMs, keyCATDelayMs, keyCATDigitalDefault)
if err != nil {
return CATSettings{}, err
}
@@ -4471,6 +4477,8 @@ func (a *App) GetCATSettings() (CATSettings, error) {
FlexHost: m[keyCATFlexHost],
FlexPort: 4992,
FlexSpots: m[keyCATFlexSpots] == "1",
FlexDecodeSpots: m[keyCATFlexDecodeSpots] == "1",
FlexDecodeSecs: 120,
IcomPort: m[keyCATIcomPort],
IcomBaud: 115200,
IcomAddr: 0x98, // IC-7610 default
@@ -4488,6 +4496,9 @@ func (a *App) GetCATSettings() (CATSettings, error) {
if n, _ := strconv.Atoi(m[keyCATFlexPort]); n > 0 && n <= 65535 {
out.FlexPort = n
}
if n, _ := strconv.Atoi(m[keyCATFlexDecodeSecs]); n >= 10 && n <= 3600 {
out.FlexDecodeSecs = n
}
if n, _ := strconv.Atoi(m[keyCATTCIPort]); n > 0 && n <= 65535 {
out.TCIPort = n
}
@@ -4549,6 +4560,13 @@ func (a *App) SaveCATSettings(s CATSettings) error {
if s.FlexSpots {
flexSpots = "1"
}
flexDecodeSpots := "0"
if s.FlexDecodeSpots {
flexDecodeSpots = "1"
}
if s.FlexDecodeSecs < 10 || s.FlexDecodeSecs > 3600 {
s.FlexDecodeSecs = 120
}
tciSpots := "0"
if s.TCISpots {
tciSpots = "1"
@@ -4567,6 +4585,8 @@ func (a *App) SaveCATSettings(s CATSettings) error {
keyCATFlexHost: strings.TrimSpace(s.FlexHost),
keyCATFlexPort: strconv.Itoa(s.FlexPort),
keyCATFlexSpots: flexSpots,
keyCATFlexDecodeSpots: flexDecodeSpots,
keyCATFlexDecodeSecs: strconv.Itoa(s.FlexDecodeSecs),
keyCATIcomPort: strings.TrimSpace(s.IcomPort),
keyCATIcomBaud: strconv.Itoa(s.IcomBaud),
keyCATIcomAddr: strconv.Itoa(s.IcomAddr),
@@ -7855,6 +7875,24 @@ func (a *App) consumeUDPEvents() {
continue
}
switch {
case ev.DecodeCall != "":
// A WSJT-X decode (heard station). Render it on the FlexRadio
// panadapter when the option is on; green + SNR comment, auto-expiring
// after the configured duration. De-duped per call in the Flex backend.
if a.catFlexDecodeSpots && a.cat != nil {
secs := a.catFlexDecodeSecs
if secs <= 0 {
secs = 120
}
a.cat.SendSpot(cat.SpotInfo{
FreqHz: ev.DecodeFreqHz,
Callsign: ev.DecodeCall,
Mode: ev.Mode,
Color: "#FF34C759", // green — distinct from cluster orange
Comment: fmt.Sprintf("%s %+ddB", ev.Mode, ev.DecodeSNR),
LifetimeSec: secs,
})
}
case ev.LoggedADIF != "":
applog.Printf("udp: emit udp:logged_qso (%d bytes ADIF)\n", len(ev.LoggedADIF))
wruntime.EventsEmit(a.ctx, "udp:logged_qso", map[string]any{
@@ -8966,6 +9004,8 @@ func (a *App) reloadCAT() {
a.cat.SetPollInterval(time.Duration(s.PollMs) * time.Millisecond)
a.cat.SetCommandDelay(time.Duration(s.DelayMs) * time.Millisecond)
a.catFlexSpots = s.Enabled && ((s.Backend == "flex" && s.FlexSpots) || (s.Backend == "tci" && s.TCISpots))
a.catFlexDecodeSpots = s.Enabled && s.Backend == "flex" && s.FlexDecodeSpots
a.catFlexDecodeSecs = s.FlexDecodeSecs
if !s.Enabled {
a.cat.Stop()
return