Panadapter spots are now worth reading. The comment carries the spotter, the
entity and the status in DXHunter's own shape — "CQ up 2 [F4BPO] [Franz Josef
Land] [New Slot]" — which needed two things nothing documents: SmartSDR splits
its command line on SPACES, so the words ran together until every space became
non-breaking; and it truncates past ~60 characters, so the cluster's own words
are trimmed first and the three brackets always survive. RBN column padding is
collapsed on the way in, or a preserved run of spaces opened a gap wide enough
to push the rest off screen.
"Already worked" means the CALLSIGN is in the log, not the entity: saying it of
a station never contacted was simply wrong. Each status can also be kept off the
panadapter entirely, and the WSJT-X decode spots obey the same switches — the
palette governs the panadapter, not one of the two things that feed it.
And the radio is no longer hammered: a spot whose frequency, colour and comment
are unchanged is not removed and redrawn. A busy skimmer feed re-spots the same
station every few seconds; one two-minute session sent 2128 adds, 88 of them for
a single callsign, and the display did not move a pixel for any of them.
CI-V, from an IC-7850 that kept killing JTDX: a reply the rig sent to another
controller on the same bus is no longer taken for ours, and a set_ptt, set_freq
or set_mode whose acknowledgement goes missing is verified by reading the rig
back instead of being reported as a failure. WSJT-X and JTDX answer a failed
command with a Rig Control Error and drop the link mid-over — 98 keyings, 6 lost
acknowledgements, 2 dropped connections in one session. The check waits 700 ms,
not the poll's 150: the rig has just failed to answer twice because it was
retuning, and a short probe would fail for the same reason.
Auto-call is withdrawn — it duplicated DXHunter, which already answers decodes,
and two programs deciding that from one shack key over each other. The library
is kept whole and dormant; a guard in App.tsx makes sure a stored preference
cannot key a transmitter whose switch no longer exists.
Also:
- the log rotates while running, not only at startup: the CI-V trace left on
wrote 416 MB and nothing would have stopped it before the disk did. Closing
it now releases the crash file too — the runtime keeps its own duplicate.
- the interface zoom announces itself, with a badge, a click back to 100% and
a View menu; Ctrl+wheel and Ctrl+0 always worked and nothing said so.
- no more elastic bounce, and no swipe-to-navigate out of the app.
- Edit QSO: your own TX power and the contacted station's extended locator
were saved and written back with no box to set them.
- FT decodes: continents are a multiple choice; a compound MSHV message that
answers two stations in one line is recognised as addressed to you.
50 lines
1.3 KiB
Go
50 lines
1.3 KiB
Go
package applog
|
|
|
|
import (
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
"testing"
|
|
)
|
|
|
|
// The log has to be bounded WHILE RUNNING, not only at startup. The CI-V wire
|
|
// trace left on for a day wrote 416 MB, and nothing would have stopped it
|
|
// before the disk did.
|
|
func TestRotatesMidSession(t *testing.T) {
|
|
orig := maxLogBytes
|
|
maxLogBytes = 8 * 1024 // small, so the test costs milliseconds
|
|
defer func() { maxLogBytes = orig }()
|
|
|
|
dir := t.TempDir()
|
|
p, err := Init(dir)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
defer Close()
|
|
|
|
line := strings.Repeat("x", 256)
|
|
for i := 0; i < 100; i++ { // ~25 KB: several times the limit
|
|
Printf("%s", line)
|
|
}
|
|
|
|
if _, err := os.Stat(p + ".1"); err != nil {
|
|
t.Fatalf("no previous generation kept: %v", err)
|
|
}
|
|
fi, err := os.Stat(p)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if fi.Size() > maxLogBytes {
|
|
t.Fatalf("current log is %d bytes, over the %d limit — it did not roll over", fi.Size(), maxLogBytes)
|
|
}
|
|
// The new file says where the rest went: a log that starts mid-sentence with
|
|
// no explanation is how an operator concludes the app lost its history.
|
|
b, err := os.ReadFile(p)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if !strings.Contains(string(b), "continued from "+filepath.Base(p)+".1") {
|
|
t.Error("the new file does not point at the one it continues")
|
|
}
|
|
}
|