fix: autocall in remote not working properly
This commit is contained in:
+48
-11
@@ -206,6 +206,16 @@ function rstCategory(mode: string): keyof RSTLists {
|
||||
if (['CW', 'RTTY', 'PSK31', 'PSK63', 'PSK', 'PSK125'].includes(m)) return 'cw';
|
||||
return 'phone';
|
||||
}
|
||||
// estimateCwMs roughly estimates how long the resolved text takes to send in CW
|
||||
// at wpm: ~10 dot-units per character + ~4 extra per word gap, 1 unit = 1200/wpm
|
||||
// ms (PARIS standard). Used to cap waits on the keyer's "busy" status, which can
|
||||
// lag by tens of seconds over a remote/serial-over-IP link.
|
||||
function estimateCwMs(resolved: string, wpm: number): number {
|
||||
const w = Math.max(5, wpm || 25);
|
||||
const chars = resolved.replace(/\s/g, '').length;
|
||||
const spaces = (resolved.match(/\s/g) || []).length;
|
||||
return ((chars * 10 + spaces * 4) * 1200) / w;
|
||||
}
|
||||
// rstOptions returns the valid report choices for a mode from the user's
|
||||
// editable lists (Settings → Modes), with a tiny fallback before they load.
|
||||
function rstOptions(mode: string, lists: RSTLists): string[] {
|
||||
@@ -1059,6 +1069,12 @@ export default function App() {
|
||||
return () => { offUploaded(); offDone(); offEqsl(); if (t) window.clearTimeout(t); };
|
||||
}, [refresh]);
|
||||
|
||||
// Backend-emitted toast messages (e.g. recording auto-send result/skip).
|
||||
useEffect(() => {
|
||||
const off = EventsOn('toast', (msg: any) => { if (msg) showToast(String(msg)); });
|
||||
return () => { off(); };
|
||||
}, [showToast]);
|
||||
|
||||
// Poll PstRotator for the live antenna heading (status bar). Cheap when the
|
||||
// rotator is disabled (the backend just reads settings and returns).
|
||||
useEffect(() => {
|
||||
@@ -1246,12 +1262,20 @@ export default function App() {
|
||||
// source behaves identically.
|
||||
function handleSpotClick(s: any) {
|
||||
const m = inferSpotMode(s.comment ?? '', s.freq_hz);
|
||||
if (catState.connected) {
|
||||
tuneRigCAT(s.freq_hz, m);
|
||||
} else {
|
||||
setFreqMhz((s.freq_hz / 1_000_000).toFixed(5));
|
||||
if (s.band) setBand(s.band);
|
||||
// Reflect the spot's freq/band in the entry strip IMMEDIATELY (optimistic),
|
||||
// then tune the rig if CAT is connected. We must not wait for the CAT status
|
||||
// echo to update the display: on a remote Flex link that echo lags by seconds,
|
||||
// so the frequency used to only catch up once you nudged the VFO. noteManualEdit()
|
||||
// freezes the CAT-driven overwrite for 1.5s so a stale in-flight status can't
|
||||
// revert the optimistic value before the new freq is reported back.
|
||||
if (s.freq_hz && s.freq_hz > 0) {
|
||||
const mhz = (s.freq_hz / 1_000_000).toFixed(5);
|
||||
setFreqMhz(mhz);
|
||||
setRxFreqMhz(mhz);
|
||||
noteManualEdit();
|
||||
}
|
||||
if (s.band) setBand(s.band);
|
||||
if (catState.connected) tuneRigCAT(s.freq_hz, m);
|
||||
if (m) applyModeFromSpot(m);
|
||||
onCallsignInput(s.dx_call, { force: true });
|
||||
applySpotPOTA((s as any).pota_ref);
|
||||
@@ -1576,15 +1600,22 @@ export default function App() {
|
||||
}
|
||||
async function wkSend(rawText: string) {
|
||||
setWkSent('');
|
||||
const resolved = resolveCW(rawText);
|
||||
const doLog = /<LOGQSO>/i.test(rawText); // resolveCW strips the token (unknown var → "")
|
||||
await WinkeyerSend(resolveCW(rawText)).catch((e) => setError(String(e?.message ?? e)));
|
||||
await WinkeyerSend(resolved).catch((e) => setError(String(e?.message ?? e)));
|
||||
// <LOGQSO> (e.g. "BK 73 TU <LOGQSO>") logs the contact AFTER the keyer has
|
||||
// finished sending — wait for the busy flag to rise then fall, so the QSO
|
||||
// isn't logged (and the form cleared) while the CW is still going out.
|
||||
// finished sending — so the QSO isn't logged (and the form cleared) while CW
|
||||
// is still going out. We'd like to wait for the busy flag to rise then fall,
|
||||
// but over a remote/serial-over-IP link that status echo can lag by tens of
|
||||
// seconds, which used to delay logging ~50s. So cap the wait at the ESTIMATED
|
||||
// send duration (text length × WPM) plus slack: log when busy clears OR the
|
||||
// estimate elapses, whichever comes first.
|
||||
if (!doLog) return;
|
||||
const sleep = (ms: number) => new Promise((r) => window.setTimeout(r, ms));
|
||||
const capMs = Math.round(estimateCwMs(resolved, wkWpm) * 1.4) + 2500; // slack for keyer buffering/lag
|
||||
for (let i = 0; i < 20 && !wkBusyRef.current; i++) await sleep(50); // ≤1s for sending to start
|
||||
for (let i = 0; i < 1200 && wkBusyRef.current; i++) await sleep(50); // ≤60s for it to finish
|
||||
const deadline = Date.now() + capMs;
|
||||
while (wkBusyRef.current && Date.now() < deadline) await sleep(50);
|
||||
void save();
|
||||
}
|
||||
// stopAutoCall cancels any running auto-call loop.
|
||||
@@ -1599,8 +1630,14 @@ export default function App() {
|
||||
const m = wkMacros[i];
|
||||
if (!m) break;
|
||||
await wkSend(m.text);
|
||||
for (let k = 0; k < 20 && !wkBusyRef.current && gen === autoCallGenRef.current; k++) await sleep(50); // ≤1s to start
|
||||
for (let k = 0; k < 2400 && wkBusyRef.current && gen === autoCallGenRef.current; k++) await sleep(50); // ≤120s to finish
|
||||
// Wait for the message to finish before the gap+resend. Cap the wait at the
|
||||
// ESTIMATED send time (not the busy flag alone): over a remote/serial-over-IP
|
||||
// link the keyer's "busy" status lags badly and stays stuck true for tens of
|
||||
// seconds, which made the next CQ fire ~120s late — i.e. auto-call looked dead.
|
||||
const capMs = Math.round(estimateCwMs(resolveCW(m.text), wkWpm) * 1.4) + 2500;
|
||||
for (let k = 0; k < 20 && !wkBusyRef.current && gen === autoCallGenRef.current; k++) await sleep(50); // ≤1s to start
|
||||
const deadline = Date.now() + capMs;
|
||||
while (wkBusyRef.current && gen === autoCallGenRef.current && Date.now() < deadline) await sleep(50);
|
||||
if (gen !== autoCallGenRef.current) break;
|
||||
await sleep(Math.max(0, wkAutoCallSecsRef.current) * 1000); // the gap before the next call
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user