diff --git a/changelog.json b/changelog.json index c076631..691a9ba 100644 --- a/changelog.json +++ b/changelog.json @@ -27,7 +27,8 @@ "CAT settings: a “Play it through the speakers” checkbox sits under the Icom RX-audio option — the same remembered switch as the console’s speaker button, applied immediately.", "Icom network audio: “Talk to radio” now works over the LAN too — live microphone straight to the rig, PTT included. With RX audio and a headset, OpsLog is a complete remote station: hear, talk, key CW and log over one network link.", "Icom console: the SUB display shows the sub receiver’s frequency at all times (it was blank until split), and engaging split copies the mode to the TX VFO so it matches the main.", - "Icom network audio: the stream now opens regardless of the speaker choice — speakers-off (or a failed output device) was silently disabling the whole stream: no audio session, no recordings, no voice keyer, despite the RX-audio option being ticked." + "Icom network audio: the stream now opens regardless of the speaker choice — speakers-off (or a failed output device) was silently disabling the whole stream: no audio session, no recordings, no voice keyer, despite the RX-audio option being ticked.", + "Icom network: a radio in standby keeps its session and the console’s ON button — the quiet-CI-V recovery was tearing the session down every 15 s, so a radio that was off when OpsLog started could never be powered on." ], "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).", @@ -54,7 +55,8 @@ "Réglages CAT : une case « Écouter dans les enceintes » sous l’option RX audio Icom — le même interrupteur mémorisé que le bouton haut-parleur de la console, appliqué immédiatement.", "Audio réseau Icom : « Talk to radio » fonctionne aussi par le LAN — micro en direct vers la radio, PTT compris. Avec le RX audio et un casque, OpsLog devient une station remote complète : écouter, parler, manipuler la CW et loguer sur un seul lien réseau.", "Console Icom : l’affichage SUB montre la fréquence du sub receiver en permanence (il restait vide hors split), et activer le split copie le mode sur le VFO TX pour qu’il suive le main.", - "Audio réseau Icom : le flux s’ouvre désormais indépendamment du choix d’écoute — enceintes coupées (ou périphérique de sortie en échec) désactivait silencieusement tout le flux : pas de session audio, ni enregistrements, ni voice keyer, malgré la case RX audio cochée." + "Audio réseau Icom : le flux s’ouvre désormais indépendamment du choix d’écoute — enceintes coupées (ou périphérique de sortie en échec) désactivait silencieusement tout le flux : pas de session audio, ni enregistrements, ni voice keyer, malgré la case RX audio cochée.", + "Réseau Icom : une radio en veille garde sa session et le bouton ON de la console — la récupération du CI-V muet détruisait la session toutes les 15 s, donc une radio éteinte au lancement d’OpsLog ne pouvait jamais être allumée." ] }, { diff --git a/internal/cat/icomnet.go b/internal/cat/icomnet.go index 2627ee2..5f79529 100644 --- a/internal/cat/icomnet.go +++ b/internal/cat/icomnet.go @@ -403,6 +403,12 @@ func (n *icomNet) civPump() { var lastErr error quietSaid := false gaveUp := false + // sawData: this session has heard at least one CI-V payload. A radio in + // STANDBY is silent on CI-V by design — only the transport chats — and the + // quiet-recovery below must not treat that as a fault: it was tearing the + // session down every 15 s, and with it the console and its ON button, so a + // radio that was off when OpsLog started could never be turned on at all. + sawData := false for { select { case <-n.done: @@ -434,6 +440,7 @@ func (n *icomNet) civPump() { debugLog.Printf("icom net: CI-V replies are back after %s", time.Since(lastData).Round(time.Second)) quietSaid, gaveUp = false, false } + sawData = true lastData = time.Now() n.txAtData.Store(n.txCiv.Load()) n.trackRxSeq(icnLE.Uint16(buf[6:])) // note gaps for retransmit @@ -468,7 +475,7 @@ func (n *icomNet) civPump() { } } } - if !quietSaid && time.Since(lastData) > 10*time.Second { + if !quietSaid && sawData && time.Since(lastData) > 10*time.Second { quietSaid = true scopeAge := "never" if !lastScope.IsZero() {