fix: <LOGQSO> logs immediately at its position instead of waiting the full CW-duration estimate first (buffered keyers keep sending; logging never interrupts them) — was delaying the log up to ~10s; only the final segment still waits, for auto-call timing

This commit is contained in:
2026-07-21 16:01:15 +02:00
parent 54dd109288
commit 1f54656256
+27 -21
View File
@@ -2147,39 +2147,45 @@ export default function App() {
// Split the macro on <LOGQSO> so the log happens AT the token's position, not
// only at the very end: "TU <LOGQSO> QRZ" sends "TU", logs, then sends "QRZ".
// Each split boundary (every part except the last) is one <LOGQSO>.
const parts = rawText.split(/<LOGQSO>/i);
// RESOLVE every segment up front — while the form still holds the callsign — so a
// segment AFTER the <LOGQSO> (which logs and clears the form) still expands its
// variables correctly.
const parts = rawText.split(/<LOGQSO>/i).map((pt) => resolveCW(pt));
const isRig = cwSourceRef.current === 'icom' || cwSourceRef.current === 'flex';
for (let p = 0; p < parts.length; p++) {
if (aborted()) return; // ESC / Stop before this segment → stop sending, don't log
const resolved = resolveCW(parts[p]);
const resolved = parts[p];
const isLast = p === parts.length - 1;
const logAfter = !isLast; // a <LOGQSO> follows this segment
if (resolved) {
// Trailing word space so back-to-back sends don't run together in the keyer
// buffer ("CQ"+"TEST" → "CQTEST"); the keyer keys it as a word gap at the
// current WPM, so it scales automatically.
const keyed = resolved + ' ';
setWkSent(resolved);
if (isRig) {
// The rig keyer (Icom 0x17 / Flex CWX) gives no busy echo we track, so
// wait the ESTIMATED send duration before moving on / logging.
const sendFn = cwSourceRef.current === 'flex' ? FlexSendCW : IcomSendCW;
await sendFn(keyed).catch((e) => setError(String(e?.message ?? e)));
await waitMs(Math.round(estimateCwMs(resolved, wkWpm)) + (p < parts.length - 1 ? 200 : 600));
} else {
await WinkeyerSend(keyed).catch((e) => setError(String(e?.message ?? e)));
// Wait for the keyer to actually finish this segment before we log /
// continue. We'd like to watch busy rise then fall, but over a
// remote/serial-over-IP link that echo can lag tens of seconds, so cap
// the wait at the ESTIMATED send duration + slack: proceed when busy
// clears OR the estimate elapses, whichever comes first.
const capMs = Math.round(estimateCwMs(resolved, wkWpm) * 1.4) + 2500;
for (let i = 0; i < 20 && !wkBusyRef.current && !aborted(); i++) await sleep(50); // ≤1s to start
const deadline = Date.now() + capMs;
while (wkBusyRef.current && !aborted() && Date.now() < deadline) await sleep(50);
const sendFn = cwSourceRef.current === 'flex' ? FlexSendCW : cwSourceRef.current === 'icom' ? IcomSendCW : null;
if (sendFn) await sendFn(keyed).catch((e) => setError(String(e?.message ?? e)));
else await WinkeyerSend(keyed).catch((e) => setError(String(e?.message ?? e)));
// Only WAIT for the CW to finish on the FINAL segment — auto-call needs the
// send done before its gap+resend. A segment a <LOGQSO> follows is NOT waited
// on: the keyer has already buffered the CW, so logging happens AT ONCE and
// never interrupts what's being sent. (Gating the log on a CW-length ESTIMATE
// made <LOGQSO> log up to ~10s late when the estimate ran long.)
if (isLast) {
if (isRig) {
await waitMs(Math.round(estimateCwMs(resolved, wkWpm)) + 600);
} else {
// WinKeyer: watch the busy echo, capped by the estimate (+slack) since
// over a remote/serial-over-IP link that echo can lag tens of seconds.
const capMs = Math.round(estimateCwMs(resolved, wkWpm) * 1.4) + 2500;
for (let i = 0; i < 20 && !wkBusyRef.current && !aborted(); i++) await sleep(50); // ≤1s to start
const deadline = Date.now() + capMs;
while (wkBusyRef.current && !aborted() && Date.now() < deadline) await sleep(50);
}
}
}
if (aborted()) return; // aborted while this segment was sending → don't log
// A <LOGQSO> token follows every part except the last → log the contact here.
if (p < parts.length - 1) void save();
if (logAfter) void save(); // log NOW — the buffered CW keeps sending
}
}
// stopAutoCall cancels any running auto-call loop.