fix(icom): re-open the CI-V flow when the rig goes quiet mid-session
The IC-7760 recurrently stops answering CI-V a few minutes into a network session while the transport keeps chatting — pings answered, session alive, commands unanswered — and the only recovery was the 30 s watchdog's full teardown. At 10 s of CI-V silence the pump now says 'open' again on the existing stream, which is all it should take if the rig quietly closed the data flow; the watchdog remains as the backstop. The send counters gain a mutex since the pump now transmits too.
This commit is contained in:
+4
-2
@@ -18,7 +18,8 @@
|
|||||||
"MY_RIG follows the radio actually connected: the entry form now asks the active radio first, before the per-band default — an IC-7760 on the air no longer logs as the Flex the band plan names.",
|
"MY_RIG follows the radio actually connected: the entry form now asks the active radio first, before the per-band default — an IC-7760 on the air no longer logs as the Flex the band plan names.",
|
||||||
"QSO recorder: a manual take on a network Icom records the network RX stream, not the “From radio” sound card (which captured another radio’s DAX on a mixed station).",
|
"QSO recorder: a manual take on a network Icom records the network RX stream, not the “From radio” sound card (which captured another radio’s DAX on a mixed station).",
|
||||||
"Icom network audio: duplicate and late-retransmitted packets no longer reach the recorder — recordings came out longer than the QSO, slowed and stuttering, while the speakers played fine.",
|
"Icom network audio: duplicate and late-retransmitted packets no longer reach the recorder — recordings came out longer than the QSO, slowed and stuttering, while the speakers played fine.",
|
||||||
"Icom network audio: it now starts with the app — launching OpsLog connected with audio silently off, and the option had to be unticked and re-saved to hear anything."
|
"Icom network audio: it now starts with the app — launching OpsLog connected with audio silently off, and the option had to be unticked and re-saved to hear anything.",
|
||||||
|
"Icom network: when the rig goes quiet on CI-V while the session stays up (seen on the IC-7760), the CI-V flow is re-opened on the spot — recovery in seconds instead of the 35-second full reconnect."
|
||||||
],
|
],
|
||||||
"fr": [
|
"fr": [
|
||||||
"Console Elecraft : le S-mètre est calibré sur un vrai K3 — S9 et les +dB correspondent désormais à l’affichage de la radio (il lisait environ deux points S trop bas).",
|
"Console Elecraft : le S-mètre est calibré sur un vrai K3 — S9 et les +dB correspondent désormais à l’affichage de la radio (il lisait environ deux points S trop bas).",
|
||||||
@@ -36,7 +37,8 @@
|
|||||||
"MY_RIG suit la radio réellement connectée : le formulaire interroge d’abord la radio active, avant le défaut par bande — un IC-7760 à l’antenne ne se logue plus comme le Flex prévu par le plan de bande.",
|
"MY_RIG suit la radio réellement connectée : le formulaire interroge d’abord la radio active, avant le défaut par bande — un IC-7760 à l’antenne ne se logue plus comme le Flex prévu par le plan de bande.",
|
||||||
"Enregistreur de QSO : une prise manuelle sur un Icom réseau enregistre le flux RX réseau, pas la carte son « From Radio » (qui capturait le DAX d’une autre radio sur une station mixte).",
|
"Enregistreur de QSO : une prise manuelle sur un Icom réseau enregistre le flux RX réseau, pas la carte son « From Radio » (qui capturait le DAX d’une autre radio sur une station mixte).",
|
||||||
"Audio réseau Icom : les paquets dupliqués ou retransmis en retard n’atteignent plus l’enregistreur — les enregistrements sortaient plus longs que le QSO, ralentis et hachés, alors que les haut-parleurs jouaient bien.",
|
"Audio réseau Icom : les paquets dupliqués ou retransmis en retard n’atteignent plus l’enregistreur — les enregistrements sortaient plus longs que le QSO, ralentis et hachés, alors que les haut-parleurs jouaient bien.",
|
||||||
"Audio réseau Icom : il démarre maintenant avec l’application — au lancement, la connexion se faisait audio coupé, et il fallait décocher/recocher l’option pour entendre quelque chose."
|
"Audio réseau Icom : il démarre maintenant avec l’application — au lancement, la connexion se faisait audio coupé, et il fallait décocher/recocher l’option pour entendre quelque chose.",
|
||||||
|
"Réseau Icom : quand la radio se tait sur le CI-V alors que la session tient (constaté sur l’IC-7760), le flux CI-V est rouvert immédiatement — récupération en quelques secondes au lieu des 35 secondes de reconnexion complète."
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
+21
-2
@@ -97,6 +97,7 @@ type icomNet struct {
|
|||||||
// CAT goroutine) and during dial — never by the pump — so no lock is needed.
|
// CAT goroutine) and during dial — never by the pump — so no lock is needed.
|
||||||
vTracked uint16
|
vTracked uint16
|
||||||
vCivSeq uint16
|
vCivSeq uint16
|
||||||
|
seqMu sync.Mutex // guards vTracked/vCivSeq: the command loop AND the pump's quiet-recovery both send
|
||||||
|
|
||||||
rx chan []byte // CI-V byte chunks from civPump → Read (control replies)
|
rx chan []byte // CI-V byte chunks from civPump → Read (control replies)
|
||||||
scopeRx chan []byte // scope (0x27) frames, kept off rx so the panadapter
|
scopeRx chan []byte // scope (0x27) frames, kept off rx so the panadapter
|
||||||
@@ -227,10 +228,12 @@ func (n *icomNet) Write(p []byte) (int, error) {
|
|||||||
if icnTrace {
|
if icnTrace {
|
||||||
debugLog.Printf("icom net TX: % X", p)
|
debugLog.Printf("icom net TX: % X", p)
|
||||||
}
|
}
|
||||||
seq := n.vTracked
|
n.seqMu.Lock()
|
||||||
pkt := icnCivData(seq, n.vID, n.vRemote, n.vCivSeq, p)
|
seq, civSeq := n.vTracked, n.vCivSeq
|
||||||
n.vTracked++
|
n.vTracked++
|
||||||
n.vCivSeq++
|
n.vCivSeq++
|
||||||
|
n.seqMu.Unlock()
|
||||||
|
pkt := icnCivData(seq, n.vID, n.vRemote, civSeq, p)
|
||||||
n.sentMu.Lock()
|
n.sentMu.Lock()
|
||||||
n.sentBuf[seq] = pkt
|
n.sentBuf[seq] = pkt
|
||||||
delete(n.sentBuf, seq-1024) // keep the buffer bounded (~last 1024 packets) so
|
delete(n.sentBuf, seq-1024) // keep the buffer bounded (~last 1024 packets) so
|
||||||
@@ -441,6 +444,22 @@ func (n *icomNet) civPump() {
|
|||||||
}
|
}
|
||||||
debugLog.Printf("icom net: no CI-V DATA for 10 s (transport last heard %s ago; last scope frame %s ago; last socket error: %v; missing-seq backlog: %d)",
|
debugLog.Printf("icom net: no CI-V DATA for 10 s (transport last heard %s ago; last scope frame %s ago; last socket error: %v; missing-seq backlog: %d)",
|
||||||
time.Since(lastPkt).Round(time.Second), scopeAge, lastErr, len(n.rxMissing))
|
time.Since(lastPkt).Round(time.Second), scopeAge, lastErr, len(n.rxMissing))
|
||||||
|
// And try the gentle repair before the 30 s watchdog tears the whole
|
||||||
|
// session down: if the rig quietly closed the CI-V data flow (the
|
||||||
|
// transport is still chatting, so the session itself stands), saying
|
||||||
|
// "open" again on the same stream is all it should take. Harmless
|
||||||
|
// when the cause is elsewhere — the watchdog still fires at 30 s.
|
||||||
|
n.seqMu.Lock()
|
||||||
|
seq, civSeq := n.vTracked, n.vCivSeq
|
||||||
|
n.vTracked++
|
||||||
|
n.vCivSeq++
|
||||||
|
n.seqMu.Unlock()
|
||||||
|
ocPkt := icnOpenClose(seq, n.vID, n.vRemote, civSeq, 0x04)
|
||||||
|
n.sentMu.Lock()
|
||||||
|
n.sentBuf[seq] = ocPkt
|
||||||
|
n.sentMu.Unlock()
|
||||||
|
_, _ = n.civ.Write(ocPkt)
|
||||||
|
debugLog.Printf("icom net: re-sent the CI-V open on the existing stream")
|
||||||
}
|
}
|
||||||
if time.Since(lastIdle) > 150*time.Millisecond {
|
if time.Since(lastIdle) > 150*time.Millisecond {
|
||||||
_, _ = n.civ.Write(icnCtrl(0x00, 0, n.vID, n.vRemote))
|
_, _ = n.civ.Write(icnCtrl(0x00, 0, n.vID, n.vRemote))
|
||||||
|
|||||||
Reference in New Issue
Block a user