From a Paper Grid to a Live Scoreboard: Building the N1MM Field Day Tracker

Open source · Windows & Linux · Offline · No account
N1MM Field Day Tracker
Live matrix of which participating stations you have worked, on which bands, fed straight from N1MM Logger+. No spreadsheet. No shouting across the tent.

Why a newcomer started writing code before his first field day

I joined the WLD club recently. September will be my first field day with them, and like most new members I spent the first few meetings mostly listening. But one thing came up again and again in those conversations, always with the same half-amused sigh: the list.

Every field day, someone sits at a table with a printed or half-digital Excel sheet. Down the left: the participating stations. Across the top: 160 m, 80 m, 40 m. Every time an operator works one of the other participating clubs, someone has to be told, and someone has to put a mark in the right box. It works, it has worked for years, but it is slow, it is error prone, and at three in the morning when you actually need it most, it is exactly the thing nobody wants to maintain.

Meanwhile, right next to that sheet, a computer is already logging every single QSO perfectly.

That gap bothered me. So instead of showing up in September with nothing but enthusiasm and a thermos flask, I decided to contribute something a newcomer can actually contribute: software. This post describes what came out of it, version 1 of the N1MM Field Day Tracker.


The core idea

The tracker is not a logger. That distinction matters, and it was the first design decision.

N1MM Logger+ remains the official log. It is mature, it is trusted, it handles the contest rules, and nobody in their right mind should try to replace it during a live event. The tracker sits beside it and answers one very specific question that N1MM does not answer.

The one question
Which participating stations have we already worked, on which bands, and which combinations are still open?

That is it. One question, answered live, on a big readable screen, without anybody having to update a spreadsheet by hand.

Here is roughly what that looks like on the display in the corner of the tent:

STATION 160m 80m 40m ON4XYZ/PON6ABC/PON7DEF/PON5GHI/PON9JKL/P n/a
worked manual override still open n/a excluded

Automatic coupling with N1MM Logger+

This is the part that makes the whole thing worthwhile.

N1MM Logger+ can broadcast every logged contact over the network as a UDP message. You enable it under:

N1MM Logger+ setup
Config › Config Ports, Mode Control, Audio, Other… › Broadcast Data
Tick Contacts
Destination: 127.0.0.1:12060 (same machine) or 192.168.1.50:12060 (separate tracker laptop)
Contest: FDREG1

From that moment every QSO you log lands in the tracker within milliseconds. The matrix cell turns green. Nobody had to say anything, write anything, or remember anything.

N1MM+ logging PCs UDP :12060 TRACKER parse · match · store plain JSON files LOCAL VIEW 127.0.0.1 GITHUB PAGES public snapshot

Four things that bit me along the way

Real field days are messier than the documentation suggests, and the interesting engineering was almost entirely in the edge cases.

Trap 01
The LookupInfo trap
This one cost me an evening. LookupInfo packets have a field structure identical to real contacts, arrive on the same recommended port, and are broadcast the moment an operator merely looks up a callsign, before anything is logged. A naive parser happily counts QSOs that never happened. The tracker filters strictly on the XML root tag and counts everything else as an ignored packet type in the sync log.
Trap 02
Frequency, never the band label
N1MM's <band> text field is locale dependent: it may say 3.5 or 3,5 depending on the Windows regional settings of the logging PC. So the tracker never reads it. Band is always derived from rxfreq (which, delightfully, is expressed in units of 10 Hz) against an IARU Region 1 band plan.
Trap 03
Callsign suffixes
All 38 stations on our participant list carry /P, while N1MM may log them with or without. Normalisation is applied on both sides, so ON4BAF, ON4BAF/P, on4baf/p and F/ON4BAF/P all resolve to the same station. Strict matching is available for those who want it, but it is off by default.
Trap 04
Multiple logging PCs
Either each PC broadcasts to the tracker directly, or, if you run N1MM in networked mode, one station enables All Computers and forwards the whole network's contacts. The tracker handles both without any configuration difference. Warning straight from the N1MM docs, worth repeating: enable All Computers on one station only, or you create a circular packet storm.

N1MM also broadcasts contactreplace and contactdelete, and the tracker follows both. Fix a busted callsign in the log and it un-marks the old cell and marks the new one. Delete a QSO and the cell opens back up.


ADIF import: the safety net

Realtime is wonderful right up until it isn’t. A laptop is off. The tracker was started an hour late. A station joins in the evening. Someone’s network cable was, in the finest field day tradition, doubling as a tent guy-line.

So the tracker imports ADIF files as a catch-up mechanism. Feed it a log at any point and it will merge everything in, deduplicate against what it already has, and produce an honest import report: records read, new, duplicate, outside the field day window, unknown station, unparseable. No silent magic. You always see exactly what happened.


Manual overrides: because paper still exists

Software that assumes the digital record is complete is software written by someone who has never been on a field. A QSO gets written on a scrap of paper. A station is worked on a rig that isn’t hooked to a computer at all. Something is logged that shouldn’t count.

Any cell in the matrix can therefore be set by hand:

Status Meaning
Not worked Still open
Worked (N1MM) Automatic, from the live feed
Manually worked Set by an operator, with a reason
Manually not worked Correcting a false positive
Excluded This combination doesn’t apply

Manual always wins over automatic. That is a hard rule in the codebase, tested on every build. And manual cells are never distinguished by colour alone, there is a marker too, because colour blindness exists and so does bright sunlight on a tablet screen in an open field.


Everyone follows along, live

Here is the part that got the club genuinely excited.

The view is built exactly once, as static HTML that reads a snapshot.json file. Locally, the app serves that view on 127.0.0.1. And with one button, or automatically every few minutes, the identical snapshot is pushed to GitHub Pages.

Same code, same colours, same filters. The published page refreshes itself every 30 seconds. So members at home, family, other clubs, anyone with the link can watch the grid fill up in real time. No login, no app, just a URL.

Because that page is genuinely public, the tracker warns you about it in the interface and lets you strip remarks and operator notes out of the published snapshot before it goes live.

Beyond the main matrix there are views for still to work (the one you actually want at 03:00), per band, per station, and per source PC, which doubles as your feed diagnostics, plus a statistics view. Everything is filterable by callsign, status, band, category and section, with CSV and PDF export for the archive.


Windows and Linux, yes really

N1MM Logger+ is Windows software. The tracker is not.

Because the coupling happens over UDP across the network, the logging PCs can sit in the operating tent running Windows while the tracker runs on whatever machine you happen to have, including a Linux laptop, or a small box in the corner serving the display. All data lives in plain JSON files with atomic writes and corruption recovery. No database to install, no server, no cloud service, no account. It runs entirely offline. Only the optional GitHub publishing needs internet.

The interface starts in English and switches to Dutch, French or Spanish.


📦 Open source · download & build
Free and open source. Use it, fork it, break it, improve it.

Windows users get an installer, Linux users get an x86_64 tarball. Source, documentation and issue tracker all live in the repository. Contributions, bug reports and band plan corrections for other IARU regions are very welcome.


What version 1 is, and what it isn’t

V1 deliberately does not do cloud sync, multi-user editing of the tracker itself, authentication, online score reporting, or automatic creation of unknown stations. The participant list decides who counts. A callsign that isn’t on it is ignored, never silently added.

That restraint is the point. A field day tool has exactly one chance to work, in a tent, possibly in the rain, with tired operators and a generator. Fewer moving parts means fewer things that can fail at 02:00.

See you in September

I still have a great deal to learn from the people in this club, about antennas, about propagation, about how a field day actually runs when the mast goes up. But a spreadsheet that nobody enjoys maintaining seemed like a solvable problem, and solving it was something I could do before my first event rather than after it.

If it works as intended, the most visible result will be that nobody thinks about the list at all. That would be the best possible outcome.

73 and see you on the bands.

← Back to blog