Commit Graph
13 Commits
Author SHA1 Message Date
rouggy 55879809f2 fix(udp): ignore N0CALL, and stop returning a grid as a callsign
N0CALL is what WSJT-X transmits under when its owner never set a callsign. It
has a letter, a digit and an ordinary shape, so nothing rejected it: it was
spotted, coloured, counted as a new WPX prefix, and now that CQ grids are read
it would have put a grid into the worked index under a callsign nobody holds.

The obvious fix - adding it to looksLikeCall's reject list - was wrong, and the
test caught it before it shipped. That function answers "could this token be a
callsign at all", and the CQ grammar uses it to decide whether the word after CQ
is a modifier (DX, NA, a zone) or the call itself. Teaching it that N0CALL is
not a callsign made "CQ N0CALL JN36" skip a slot and return JN36. Shape and
policy are different questions and now live in different functions.

Chasing that turned up the real defect behind it: ANY unrecognised word after CQ
made the parser skip a slot, and a four-character grid passes every shape test a
callsign does. "CQ FOO JN36" returned JN36 as the sender - logged, spotted and
coloured as a station. A grid in the callsign slot is now refused outright.
2026-08-10 21:51:49 +02:00
rouggy 9b2115be8f feat(cluster): grids from the UDP decodes, plus spotter continent and LoTW
Backend groundwork; the columns and filters that consume it come next.

GRIDS. A CQ is the one WSJT-X message that carries a locator, and wsjtSender was
throwing that token away. It is now returned, validated as a real field+square,
and remembered per callsign. This is the ONLY grid source available: a DX-cluster
line carries the spotter's grid at best and never the DX's, and a per-callsign
QRZ lookup under an RBN firehose is not a trade worth making. So grids are known
for the stations this receiver decoded - which is exactly the FT8/FT4 watering
hole an operator is looking at while grid chasing.

RR73 is why the grid is validated rather than pattern-matched. R is inside A-R
and 73 inside 00-99, so a sign-off satisfies the Maidenhead shape exactly and
would have planted a grid that does not exist into the index, silently.

NEW GRID keys on "GRID|MODE" with the mode put through the same normMode as
everything else, so the "group digital modes" option decides whether a grid
worked on FT8 is still new on FT4 - one rule, no branch. Grids are truncated to
four characters: a log holds a mix of JN36 and JN36QU, and without that the same
square is new forever, once per subsquare.

On cost, which was the condition: one more DISTINCT scan when the status
snapshot is rebuilt, then map lookups per spot. The same shape as the county and
POTA sets it sits beside, and the snapshot exists precisely so a spot batch never
touches the logbook.

Spotter continent and the LoTW flag come from tables already in memory - the
DXCC prefix table and ARRL's user list - so they cost a lookup each. The spotter
continent answers a different question from the DX's: whether anyone near you is
hearing this at all.
2026-08-10 16:52:36 +02:00
rouggy 4352b9aec5 fix(udp): read WSJT-X packets that arrive through a relay
A forwarder (W&P, seen in the field in front of MSHV) prepends the origin as
plain text before re-broadcasting:

    "127.0.0.1:2237|" + <the original, untouched WSJT-X packet>

That puts the magic 15 bytes in, so every datagram failed on "bad magic
0x3132372e" — those four bytes being ASCII "127." — and an operator running
MSHV behind the relay saw no decodes, no callsigns and no auto-logged QSOs.

No new service type: what follows the header IS a WSJT-X packet, so the parser
and everything downstream apply unchanged, and a separate type would duplicate
decode, status and logged-ADIF handling to strip 15 bytes. ParseWSJT skips the
header instead, which also covers any other relay that wraps traffic this way.

The match is deliberately narrow — the magic must fall within the first 64
bytes AND every byte before it must be printable ASCII. A corrupt or truncated
packet that merely contains those four bytes somewhere is not resurrected into
a QSO; it fails exactly as it did before.

Test data is the real captured datagram, header included.
2026-08-09 08:06:21 +02:00
rouggy a0f7f2abf0 feat(udp): show the packet behind a parse error, and stop repeating it
"WSJT parse error: bad magic 0x3132372e" named neither the sender nor the
payload, so there was nothing to act on — even though those four bytes are
ASCII "127.", i.e. some program broadcasting an address on a port expecting
WSJT-X binary.

The line now carries the remote address, the size, a printable preview and a
hex dump of the first 96 bytes. Text senders are readable at a glance; a
genuinely binary payload still shows its bytes.

And it stops after five. The reported case wrote that line about 150 times a
second: a permanently misconfigured port would fill the 10 MB rotating log with
one repeated sentence and bury every other piece of evidence — the log's whole
purpose. The fifth line names the two things worth checking, the sender and the
service type.

N1MM's parse error goes through the same path; it had no packet detail either.
2026-08-09 07:59:51 +02:00
rouggy 9846354bf9 chore: release v0.23.2 2026-08-02 23:51:46 +02:00
rouggy f6cd6e999a chore: release v0.22.9 2026-08-02 06:40:10 +02:00
rouggy a036120871 feat: remote_call UDP accepts <FREQ>/<MODE> from DXHunter and tunes the active CAT backend 2026-07-29 17:49:29 +02:00
rouggy 28b6f04ea4 feat: When a call is cleared from MSHV/WSJTx/JTDX it also clears the call field of OpsLog 2026-07-16 11:52:42 +02:00
rouggy 6c39204301 chore: release v0.19.4 2026-07-10 17:16:32 +02:00
rouggy 4f32012930 feat: Implemented UDP Outbound Adif message, freq to pstrotator 2026-07-05 18:17:30 +02:00
rouggy 67203cd4a8 up 2026-06-14 00:55:27 +02:00
rouggy 5c004f5e2f feat: upload to external services clublog qrz 2026-05-28 22:52:50 +02:00
rouggy e82e30dd02 up 2026-05-28 21:32:46 +02:00