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:
+21
-15
@@ -2147,39 +2147,45 @@ export default function App() {
|
|||||||
// Split the macro on <LOGQSO> so the log happens AT the token's position, not
|
// 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".
|
// 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>.
|
// 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';
|
const isRig = cwSourceRef.current === 'icom' || cwSourceRef.current === 'flex';
|
||||||
for (let p = 0; p < parts.length; p++) {
|
for (let p = 0; p < parts.length; p++) {
|
||||||
if (aborted()) return; // ESC / Stop before this segment → stop sending, don't log
|
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) {
|
if (resolved) {
|
||||||
// Trailing word space so back-to-back sends don't run together in the keyer
|
// 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
|
// buffer ("CQ"+"TEST" → "CQTEST"); the keyer keys it as a word gap at the
|
||||||
// current WPM, so it scales automatically.
|
// current WPM, so it scales automatically.
|
||||||
const keyed = resolved + ' ';
|
const keyed = resolved + ' ';
|
||||||
setWkSent(resolved);
|
setWkSent(resolved);
|
||||||
|
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) {
|
if (isRig) {
|
||||||
// The rig keyer (Icom 0x17 / Flex CWX) gives no busy echo we track, so
|
await waitMs(Math.round(estimateCwMs(resolved, wkWpm)) + 600);
|
||||||
// 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 {
|
} else {
|
||||||
await WinkeyerSend(keyed).catch((e) => setError(String(e?.message ?? e)));
|
// WinKeyer: watch the busy echo, capped by the estimate (+slack) since
|
||||||
// Wait for the keyer to actually finish this segment before we log /
|
// over a remote/serial-over-IP link that echo can lag tens of seconds.
|
||||||
// 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;
|
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
|
for (let i = 0; i < 20 && !wkBusyRef.current && !aborted(); i++) await sleep(50); // ≤1s to start
|
||||||
const deadline = Date.now() + capMs;
|
const deadline = Date.now() + capMs;
|
||||||
while (wkBusyRef.current && !aborted() && Date.now() < deadline) await sleep(50);
|
while (wkBusyRef.current && !aborted() && Date.now() < deadline) await sleep(50);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if (aborted()) return; // aborted while this segment was sending → don't log
|
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 (logAfter) void save(); // log NOW — the buffered CW keeps sending
|
||||||
if (p < parts.length - 1) void save();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// stopAutoCall cancels any running auto-call loop.
|
// stopAutoCall cancels any running auto-call loop.
|
||||||
|
|||||||
Reference in New Issue
Block a user