debug(icom): say what the CI-V stream was doing when it goes quiet

A real IC-7760 keeps going silent on the CI-V stream two-three minutes into a
session while the control link stays alive. At 10 s of silence the pump now
logs the last real socket error and the retransmit backlog, and notes when the
stream resumes — the 30 s watchdog that follows cannot tell a dead socket from
a rig that stopped talking, and the next occurrence should.
This commit is contained in:
2026-08-29 16:07:42 +02:00
parent b2eb6a4b1e
commit 7f328d4eb5
+24 -1
View File
@@ -359,6 +359,14 @@ func (n *icomNet) civPump() {
buf := make([]byte, 8192)
lastIdle := time.Now()
lastReq := time.Now()
// Diagnosis for the recurring 2-3-minute silence a real IC-7760 shows on
// this stream while the control link stays alive: when the stream has been
// quiet for 10 s, say so ONCE, with the last read error — a socket error
// and a rig that stopped talking are different repairs, and the 30 s
// watchdog that follows cannot tell them apart from where it sits.
lastPkt := time.Now()
var lastErr error
quietSaid := false
for {
select {
case <-n.done:
@@ -366,7 +374,18 @@ func (n *icomNet) civPump() {
default:
}
_ = n.civ.SetReadDeadline(time.Now().Add(100 * time.Millisecond))
if k, err := n.civ.Read(buf); err == nil && k >= 16 {
k, err := n.civ.Read(buf)
if err != nil {
if e, ok := err.(net.Error); !ok || !e.Timeout() {
lastErr = err // a REAL socket error, not the read deadline
}
}
if err == nil && k >= 16 {
if quietSaid {
debugLog.Printf("icom net: CI-V stream is talking again after %s of silence", time.Since(lastPkt).Round(time.Second))
quietSaid = false
}
lastPkt = time.Now()
n.markRx()
switch typ := icnLE.Uint16(buf[4:]); {
case typ == 0x07: // ping
@@ -410,6 +429,10 @@ func (n *icomNet) civPump() {
}
}
}
if !quietSaid && time.Since(lastPkt) > 10*time.Second {
quietSaid = true
debugLog.Printf("icom net: CI-V stream quiet for 10 s (control link still alive; last socket error: %v; missing-seq backlog: %d) — idles and retransmit requests are still being sent", lastErr, len(n.rxMissing))
}
if time.Since(lastIdle) > 150*time.Millisecond {
_, _ = n.civ.Write(icnCtrl(0x00, 0, n.vID, n.vRemote))
lastIdle = time.Now()