From e6b8a17772e26a2278ada53dd391e6aa3be11f5f Mon Sep 17 00:00:00 2001 From: rouggy Date: Thu, 30 Jul 2026 20:50:05 +0200 Subject: [PATCH] fix: a rig reporting LSB/USB left the mode selector empty MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit From a Kenwood trace: IF answered mode digit 1 on 7.160 MHz, the backend read LSB correctly, and the entry form showed no mode at all while the frequency tracked perfectly. Nothing was wrong in the backend. Radios report the SIDEBAND, and the station's mode list holds SSB — so the value pushed into the selector was not in its own list of options and nothing could match. Yaesu and Icom report the same way, so this was never Kenwood-specific; it only surfaced there. Normalising at the point where a rig-reported mode enters the form fixes every backend at once, rather than editing three mode tables and the next backend someone writes. It is also the ADIF-correct direction, which matters more than the selector: LSB and USB are SUBMODEs in ADIF, not modes. MODE=LSB is not a valid value and is what would have gone to LoTW and eQSL. An operator who has deliberately put LSB or USB in their own mode list keeps them — the list is their statement of what they log, not ours. --- changelog.json | 6 ++++-- frontend/src/App.tsx | 31 +++++++++++++++++++++++++++---- 2 files changed, 31 insertions(+), 6 deletions(-) diff --git a/changelog.json b/changelog.json index 5595d23..41e27b8 100644 --- a/changelog.json +++ b/changelog.json @@ -8,7 +8,8 @@ "The CAT protocol trace covers the Kenwood backend as well, not just CI-V. Settings → CAT.", "Updating selected QSOs from the callsign databases now shows a progress bar with the callsign being queried, in a corner rather than a dialog so the rest of OpsLog stays usable — a contest log is thousands of contacts and one network round trip each. The menu entry is renamed \"Update from the callsign databases\": it has always queried every configured provider, QRZ.com then HamQTH.", "The world map can show the grey line: the day/night terminator with its twilight band, redrawn every minute. Button at the top right of the map, off by default, and the choice is remembered.", - "The protocol trace checkboxes (CAT and WinKeyer) now show whether the trace is really running. They came back unticked on a trace that was still on, so ticking the box to enable it actually switched it off and the log sent afterwards contained no trace." + "The protocol trace checkboxes (CAT and WinKeyer) now show whether the trace is really running. They came back unticked on a trace that was still on, so ticking the box to enable it actually switched it off and the log sent afterwards contained no trace.", + "A radio reporting LSB or USB now selects SSB in the entry form. Radios report the sideband, the mode list holds SSB, so nothing matched and the mode stayed empty while the frequency tracked correctly. It also keeps the logged mode ADIF-valid: LSB and USB are submodes there, not modes." ], "fr": [ "Le backend Kenwood est désormais éprouvé face à une radio qui répond : OpsLog dialogue avec l'émulateur TS-2000 qu'il embarque déjà pour les amplis ACOM, ce qui vérifie fréquence, mode, VFO, split et PTT de bout en bout. Un essai sur un vrai Kenwood reste nécessaire, mais le dialogue n'est plus non testé.", @@ -16,7 +17,8 @@ "La trace du protocole CAT couvre aussi le backend Kenwood, plus seulement le CI-V. Réglages → CAT.", "La mise à jour des QSO sélectionnés depuis les annuaires affiche désormais une barre de progression avec l'indicatif en cours d'interrogation, dans un coin plutôt qu'en fenêtre : le reste d'OpsLog reste utilisable — un log de concours, c'est des milliers de contacts et un aller-retour réseau pour chacun. L'entrée de menu devient « Mettre à jour depuis les annuaires » : elle a toujours interrogé tous les annuaires configurés, QRZ.com puis HamQTH.", "La carte du monde peut afficher la ligne grise : le terminateur jour/nuit et sa bande de crépuscule, redessinés chaque minute. Bouton en haut à droite de la carte, désactivé par défaut, et le choix est mémorisé.", - "Les cases de trace du protocole (CAT et WinKeyer) reflètent désormais l'état réel de la trace. Elles réapparaissaient décochées alors que la trace tournait : cocher la case pour l'activer la désactivait en fait, et le journal envoyé ensuite ne contenait aucune trace." + "Les cases de trace du protocole (CAT et WinKeyer) reflètent désormais l'état réel de la trace. Elles réapparaissaient décochées alors que la trace tournait : cocher la case pour l'activer la désactivait en fait, et le journal envoyé ensuite ne contenait aucune trace.", + "Une radio qui annonce LSB ou USB sélectionne désormais SSB dans la saisie. Les radios annoncent la bande latérale, la liste des modes contient SSB : rien ne correspondait et le mode restait vide alors que la fréquence suivait. Cela garde aussi le mode journalisé conforme à l'ADIF, où LSB et USB sont des sous-modes et non des modes." ] }, { diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index 10ae289..9b421aa 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -392,6 +392,8 @@ export default function App() { // === Lists from settings (fallback for first paint) === const [bands, setBands] = useState(DEFAULT_BANDS); const [modes, setModes] = useState(DEFAULT_MODES); + const modesRef = useRef(modes); + useEffect(() => { modesRef.current = modes; }, [modes]); const [modePresets, setModePresets] = useState([]); // === Entry === @@ -2044,9 +2046,29 @@ export default function App() { // a 599 left from a CW QSO would stick when jumping to an SSB spot. function applyModeFromSpot(m: string) { if (!m) return; - setMode(m); + const logged = catModeToLoggedMode(m); + setMode(logged); rstUserEditedRef.current = false; - applyModePreset(m); + applyModePreset(logged); + } + // catModeToLoggedMode maps what a radio reports onto a mode this station + // actually logs. + // + // Radios report the SIDEBAND — a Kenwood or Yaesu on 40 m answers LSB, not + // SSB. The mode list is SSB, so nothing matched and the selector sat empty + // while the frequency tracked perfectly: "the mode is not recognised". + // + // It is also the ADIF-correct direction. LSB and USB are SUBMODEs there, not + // modes; MODE=LSB is not a valid ADIF value and is what would be sent to LoTW + // and eQSL. So this protects the upload as much as the selector. + // + // A station that has deliberately put LSB or USB in its own mode list keeps + // them: the list is the operator's statement of what they log. + function catModeToLoggedMode(m: string): string { + const list = modesRef.current; + if (!m || list.includes(m)) return m; + if ((m === 'LSB' || m === 'USB') && list.includes('SSB')) return 'SSB'; + return m; } function applyModePreset(m: string) { if (rstUserEditedRef.current) return; @@ -2213,8 +2235,9 @@ export default function App() { else if (s.mode) nextMode = s.mode; } if (nextMode) { - setMode(nextMode); - applyModePreset(nextMode); // flip 599↔59 on mode change (respects edits) + const logged = catModeToLoggedMode(nextMode); + setMode(logged); + applyModePreset(logged); // flip 599↔59 on mode change (respects edits) } } }