fix: Save and close taking time when Flex or Icom is not connected

This commit is contained in:
2026-07-07 11:07:16 +02:00
parent 1184a675c2
commit 5b37397a64
3 changed files with 76 additions and 9 deletions
+32 -4
View File
@@ -3,6 +3,7 @@
package cat
import (
"context"
"fmt"
"net"
"strconv"
@@ -27,9 +28,10 @@ type TCI struct {
digitalDefault string // surfaced when the rig reports a digital mode (FT8/…)
spotsEnabled bool // mirror cluster spots onto the TCI panorama
mu sync.Mutex // guards conn + writes + state
conn *websocket.Conn
ready bool
mu sync.Mutex // guards conn + writes + state
conn *websocket.Conn
dialCancel context.CancelFunc // cancels an in-flight Connect dial (Interrupt/Stop)
ready bool
// Cached state pushed by the radio.
device string
@@ -70,8 +72,18 @@ func (t *TCI) Connect() error {
return fmt.Errorf("tci: no host configured")
}
url := fmt.Sprintf("ws://%s", net.JoinHostPort(host, strconv.Itoa(port)))
// Cancellable dial so Interrupt() (Stop / Settings "Save & Close") aborts it at
// once instead of waiting out a dead server's 5 s handshake timeout.
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
t.mu.Lock()
t.dialCancel = cancel
t.mu.Unlock()
dialer := websocket.Dialer{HandshakeTimeout: 5 * time.Second}
conn, _, err := dialer.Dial(url, nil)
conn, _, err := dialer.DialContext(ctx, url, nil)
cancel()
t.mu.Lock()
t.dialCancel = nil
t.mu.Unlock()
if err != nil {
return fmt.Errorf("tci: connect %s: %w", url, err)
}
@@ -122,6 +134,22 @@ func (t *TCI) Disconnect() {
}
}
// Interrupt aborts an in-flight Connect dial so Stop()/Start() don't block on a
// dead server's handshake timeout. Satisfies the Manager's interruptible
// interface. Safe from another goroutine; a no-op when not dialing.
func (t *TCI) Interrupt() {
t.mu.Lock()
cancel := t.dialCancel
c := t.conn
t.mu.Unlock()
if cancel != nil {
cancel()
}
if c != nil {
_ = c.Close()
}
}
// ReadState returns the cached state pushed by the radio.
func (t *TCI) ReadState() (RigState, error) {
t.mu.Lock()