diff --git a/app.go b/app.go index d66fdd5..31f258b 100644 --- a/app.go +++ b/app.go @@ -20721,6 +20721,64 @@ func (a *App) WinkeyerSetSpeed(wpm int) error { } // GetWinkeyerStatus returns the current link status (used on mount). +// KeyerStatus is the keyer's state plus WHICH keyer it is. +// +// Five of the six engines key over the CAT link the rig is already on: there +// is no serial port to open and no Connect to offer. The Station Control card +// knew none of that — it read the WinKeyer manager alone, so a station keying +// through TCI saw a red light, "no port", and a Connect button that could only +// fail. Reported as the TCI keyer being unusable, when in fact only this card +// was wrong: the F-keys and the macros have been dispatching by engine all +// along. +// +// Decided HERE and not in each panel, because "is the keyer up" has one +// answer and two places were entitled to disagree about it. +type KeyerStatus struct { + winkeyer.Status + Engine string `json:"engine"` + // OverCAT: the keying rides the CAT link. No port, no Connect, and + // Connected means the CAT backend that does the keying is up. + OverCAT bool `json:"over_cat"` +} + +// keyerCATBackends maps a CAT-keying engine to the backend that has to be +// running for it. Icom has two — the USB port and the rig's own LAN server — +// and both key the same way. +var keyerCATBackends = map[string][]string{ + "icom": {"icom", "icom-net"}, + "flex": {"flex"}, + "yaesu": {"yaesu"}, + "kenwood": {"kenwood", "elecraft"}, + "tci": {"tci"}, +} + +func (a *App) GetKeyerStatus() KeyerStatus { + engine := strings.TrimSpace(a.settingOr(keyWKEngine, "winkeyer")) + out := KeyerStatus{Status: a.GetWinkeyerStatus(), Engine: engine} + want, overCAT := keyerCATBackends[engine] + if !overCAT { + return out // winkeyer or serial: the manager's own status is the truth + } + out.OverCAT = true + // The manager is not connected and never will be on this engine, so its + // fields would all read "off". The rig's link is what matters. + out.Port, out.Error = "", "" + out.Connected = false + if a.cat != nil { + st := a.cat.State() + for _, b := range want { + if st.Connected && st.Backend == b { + out.Connected = true + break + } + } + if !out.Connected { + out.Error = fmt.Sprintf("the %s keyer needs its CAT backend connected", engine) + } + } + return out +} + func (a *App) GetWinkeyerStatus() winkeyer.Status { if a.winkeyer == nil { return winkeyer.Status{} diff --git a/changelog.json b/changelog.json index be098cb..352befb 100644 --- a/changelog.json +++ b/changelog.json @@ -3,11 +3,13 @@ "version": "0.27.25", "en": [ "The relaunch after an update goes back to the helper that waited for OpsLog to close before starting the new version. Two rewrites tried to do without it and both left some operators with no window. Windows Defender may flag it — allow OpsLog in Defender if it does.", - "WSJT-X can now transmit through an Icom reached over Ethernet. Set its output to a virtual audio cable and choose that cable under Settings ▸ Audio — OpsLog streams it to the radio while WSJT-X holds PTT through the shared CAT." + "WSJT-X can now transmit through an Icom reached over Ethernet. Set its output to a virtual audio cable and choose that cable under Settings ▸ Audio — OpsLog streams it to the radio while WSJT-X holds PTT through the shared CAT.", + "The TCI keyer is no longer labelled \"coming soon\" — it works, and has since it landed. What was broken was the Station Control card: it looked only at the WinKeyer serial link, so an engine that keys over CAT showed a red light, \"no port\" and a Connect button that could only fail, and the card was hidden altogether when no port was set. It now says which link carries the keying." ], "fr": [ "La relance après une mise à jour revient à l’assistant qui attendait la fermeture d’OpsLog avant de démarrer la nouvelle version. Deux réécritures ont essayé de s’en passer et laissaient certains opérateurs sans fenêtre. Windows Defender peut le signaler — dans ce cas, autorisez OpsLog dans Defender.", - "WSJT-X peut désormais émettre à travers un Icom joint en Ethernet. Réglez sa sortie sur un câble audio virtuel et choisissez ce câble dans Réglages ▸ Audio — OpsLog le diffuse vers la radio pendant que WSJT-X tient le PTT via le CAT partagé." + "WSJT-X peut désormais émettre à travers un Icom joint en Ethernet. Réglez sa sortie sur un câble audio virtuel et choisissez ce câble dans Réglages ▸ Audio — OpsLog le diffuse vers la radio pendant que WSJT-X tient le PTT via le CAT partagé.", + "Le keyer TCI ne porte plus la mention « bientôt » — il fonctionne, et depuis son arrivée. Ce qui était cassé, c’est la carte de Station Control : elle ne regardait que la liaison série WinKeyer, si bien qu’un moteur qui manipule par CAT affichait un voyant rouge, « aucun port » et un bouton Connecter qui ne pouvait qu’échouer — et la carte était même masquée faute de port. Elle indique désormais par quelle liaison passe la manipulation." ] }, { diff --git a/frontend/src/components/StationControlPanel.tsx b/frontend/src/components/StationControlPanel.tsx index 3902f64..8527d94 100644 --- a/frontend/src/components/StationControlPanel.tsx +++ b/frontend/src/components/StationControlPanel.tsx @@ -26,7 +26,7 @@ import { GetTunerGeniusStatus, GetTunerGeniusSettings, GetPSUStatus, GetPSUSettings, SetPSUOutput, GetCATState, - GetWinkeyerStatus, WinkeyerSetSpeed, WinkeyerStop, WinkeyerConnect, + GetKeyerStatus, WinkeyerSetSpeed, WinkeyerStop, WinkeyerConnect, GetDVKStatus, GetDVKMessages, DVKPlay, DVKStop, } from '../../wailsjs/go/main/App'; @@ -155,7 +155,7 @@ function KeyerCard({ t }: { t: (k: string, v?: any) => string }) { const [st, setSt] = useState(null); useEffect(() => { let alive = true; - const tick = () => GetWinkeyerStatus().then((s: any) => { if (alive) setSt(s); }).catch(() => {}); + const tick = () => GetKeyerStatus().then((s: any) => { if (alive) setSt(s); }).catch(() => {}); tick(); const h = window.setInterval(tick, 1000); return () => { alive = false; window.clearInterval(h); }; @@ -193,11 +193,18 @@ function KeyerCard({ t }: { t: (k: string, v?: any) => string }) { {t('station.stop')} + {/* Five of the six engines key over the CAT link the rig is already + on. There is no port to name and no Connect to offer, and + offering one anyway is what made the TCI keyer look unusable: + a red light, "no port", and a button that could only fail. */}
- {st?.port || t('station.noPort')} + + {st?.over_cat ? t('station.keyerViaCat', { engine: (st.engine || '').toUpperCase() }) + : (st?.port || t('station.noPort'))} + {!!st?.version && v{st.version}}
- {!on && ( + {!on && !st?.over_cat && (