← Back to home

VHF Logger

User guide and setup β€” VHF/UHF contest logger with aircraft scatter

Logger: index.html  Β·  This help file: zlog-help.html

VHF Logger started as a small experiment: building a simple online QSO logger with the help of Claude Code. It began basic and has been growing steadily ever since β€” and still is. Today it covers a full contest log, ON4KST chat, a live aircraft display with a prediction of when aircraft scatter becomes usable, and a watchlist you can build yourself or generate automatically from the stations currently logged in on ON4KST. Each of these windows/features can be individually enabled or disabled in Settings.

Beta: the program is still in active development and has not been thoroughly tested yet. Expect rough edges, and please back up your log regularly (EDI export, or the auto-backup setting).

1. First-time setup

When you open the logger for the first time, Settings opens automatically. Fill in these fields:

Station identification

FieldExampleEDI fieldDescription
CallsignOZ7ZPCallYour own callsign (upper case)
LocatorJO44VWPWWLoYour Maidenhead locator, 4 or 6 characters
Band144 MHzPBandActive contest band
Category3LPSectSection code β€” updates automatically when you change band (3L/3H = SO Low/High, 4L/4H = MO Low/High on 144 MHz). IARU Region 1 VHF+ contest sections (SO, MO, SO-LP, MO-LP, 6H, SO-MGM, MO-MGM, 6H-MGM) are listed alongside the NAC codes, labelled "IARU-R1 …" β€” pick whichever matches the contest you're entering.
WWL bonus500CWWLs/CWWLBPoints awarded per unique WWL square (4-char locator). NAC uses 500 (the default). IARU Region 1 contests have no locator bonus β€” set this to 0 when entering one. See chapter 3 for how this affects the score.
Operator NameJens HansenRNameYour name
Emailjens@example.dkREmailYour email address
ClubOZ7ZPClubClub callsign or name
Station ASL (m)50PASLoStation height above sea level in metres

Address (used in EDI submission)

FieldExampleEDI fieldDescription
AddressElmevej 4RAdr1Street address
Post code8000RPoCoPostal code
CityAarhus CRCityCity
Phone+45 12345678RPhonePhone number

Station equipment (used in EDI submission)

FieldExampleEDI fieldDescription
TX EquipmentIC-9700STXEqTransmitter description
RX EquipmentIC-9700SRXEqReceiver description β€” often the same as TX
Antenna17el YagiSAntAntenna description
Antenna height (m)12SAntHeiAntenna height above ground in metres
Antenna ASL (m)62SAntAslAntenna height above sea level in metres (station ASL + antenna height)
Antenna gain (dBd)14.5SGainAntenna gain in dBd
TX Power (W)100STXPowTransmit power in watts
Remarksβ€”RemarksFree-text remarks included in the EDI file
All settings are saved automatically in the browser β€” you only need to fill them in once.
Don't know your Maidenhead locator? Look it up at levinecentral.com/ham/grid_square.php or search for your address in any QTH locator tool.

2. Logging a QSO

Form mode β€” step-by-step example

The following example logs a QSO between OZ7Z (your station, JO44VW) and G3YDY (JO01FQ) at 17:15 UTC on 144 MHz:

  1. Dato β€” leave empty for today, or type 260101 for a specific date. Press Enter.
  2. Tid β€” leave empty for current UTC, or type 1715. Press Enter.
  3. Call β€” type G3YDY and press Enter. If G3YDY is in your locator database, the Loc field fills automatically on blur.
  4. RST S β€” your report to G3YDY. Type 59 (or leave 59 as default) and press Enter.
  5. RST R β€” G3YDY's report to you. Type 57 and press Enter.
  6. Nr S / Nr R β€” serial numbers, if enabled in Settings. Nr S is pre-filled from the running counter (editable). Nr R is required when serials are enabled β€” the QSO cannot be saved without it.
  7. Loc β€” type JO01FQ and press Enter. The distance (720 km) is calculated and the QSO is saved.
Duplicates (same callsign logged twice) are marked DUPE and do not count towards the score.

Editing a logged QSO

Each QSO row has two buttons on the right:

ButtonAction
✎Opens the edit dialog β€” change date, time, callsign, mode, RST or locator. Distance is recalculated automatically. Changing an RST between 2 and 3 digits auto-switches Mode between SSB and CW (unless Mode is set to FM or Digital, which are left alone). Press Gem to save or Annuller to cancel.
Γ—Opens the delete dialog β€” see below.

QSO actions (Γ— button)

The Γ— button opens an action menu with three choices:

One-liner mode

Enable under Entry mode β†’ One-liner in Settings. Type everything on one line and press Enter. Tokens are order-independent β€” the logger recognises each by its format.

Important convention: the RST you send (your report to the other station) is marked with a sent marker after it β€” ' (apostrophe) by default. The RST you receive is written without the marker. The marker itself is configurable in Settings β†’ Advanced β†’ Sent marker (up to 2 characters) if you prefer something other than '.

ExampleMeaning
G3YDY JO01FQBoth RST = 59 (default) β€” minimal entry
G3YDY 59' 57 JO01FQSent 59, received 57, locator JO01FQ
G3YDY 57 JO01FQSent 59 (default), received 57
17:32 G3YDY 57 JO01FQLog with a specific time (17:32 UTC) instead of the current time
1732 G3YDY 57 JO01FQSame β€” time without colon is also recognised (HHMM format)
G3YDY 599' 579 JO01FQCW QSO β€” 3-digit RST auto-sets mode to CW; hint shows CW

Full format: CALL [HH:MM or HHMM] [SND-RST'] [RCV-RST] [NR] LOCATOR
Locator and callsign are the only required fields β€” everything else is optional.

CW auto-detection: if either the sent or received RST is 3 digits (e.g. 599), the QSO is automatically saved as CW (mode 2). The hint line shows CW to confirm.
Propagation reports: the RST's third character can also be a letter instead of a tone digit, for traditional propagation-mode signal reports β€” A for aurora, S for rain scatter (regnscatter). E.g. 55A, 55S', or glued with a serial number as 55S555.

Serial numbers in one-liner mode

When Serial numbers is enabled in Settings, you can glue a serial number directly onto the RST β€” no separate token needed. Whether it's a sent or received serial depends on the same marker convention used for RST:

ExampleMeaning
G3YDY 55009' 56010 JO01FQSent RST 55 with sent serial 009; received RST 56 with received serial 010
G3YDY 55' 56010 JO01FQSent RST 55, serial auto-filled from the running counter; received RST 56 with received serial 010

The hint line shows Snt#: / Rcv#: as you type to confirm what was recognised.

When serial numbers are enabled, a received serial number is mandatory β€” the QSO is rejected with "Enter received serial number" if none was typed or recognised, in both one-liner and form mode.
Auto-increment reference: if you type an explicit sent serial (e.g. 009 in 55009'), that value becomes the new reference β€” the next QSO's auto-filled sent serial continues from 010, not from wherever the old counter was. This lets you correct the running count on the fly if it ever drifts from what you actually sent over the air.
Ambiguous glued numbers: a glued received RST+serial like 55123 is genuinely ambiguous β€” it could mean RST 55 + serial 123, or RST 551 + serial 23, and the parser has to guess (it prefers the longer RST). This only happens when every digit after the RST is 1–9 (no zero); numbers like 56010 are unambiguous and parse correctly either way. When in doubt, type the RST and serial as two separate space-separated tokens instead β€” e.g. 55 123 β€” which is always read correctly.

Entering a custom time and date (one-liner)

To log a QSO with a time other than the current UTC time, type it in HH:MM or HHMM format (with or without colon) anywhere in the one-liner line, before the callsign β€” e.g. 17:32 G3YDY 57 JO01FQ or 1732 G3YDY 57 JO01FQ. The hint line confirms it is recognised: Tid: 17:32.

To log a QSO with a different date, fill in the small Dato YYMMDD field that appears below the input box (e.g. 260101 for 1 January 2026). Leave it empty to use today's date. The date field is not cleared between QSOs so you can log several QSOs with the same back-dated date without re-typing it. Press F3 to clear the date field together with the input.

Entering a custom time and date (form mode)

Form mode has a Dato YYMMDD field and a Tid UTC field at the start of the form. Both default to the current date and time if left blank. They are cleared automatically after each QSO is saved.

Locator autocomplete in one-liner

When you press Space or Enter after a callsign (or a partial callsign, 3+ characters), the logger looks it up in the locator database automatically. Nothing is inserted into the line yet β€” a picker with the matching candidates opens above the input field instead.

The picker (and Ctrl-X cycling) closes automatically as soon as you type anything further β€” so once you move on to the RST, Enter reliably saves the QSO instead of re-confirming a stale suggestion.
Whenever a locator is known β€” typed directly, resolved, or just suggested from the DB β€” the hint line also shows QTF (bearing from your home station), e.g. Loc: JO65EU QTF: 56Β°. Requires a home locator to be set in Settings.
If the line ends up with two locator-shaped tokens (e.g. you typed one yourself and a second got inserted by mistake), Enter refuses to log the QSO and shows an error instead. Press Ctrl+X to choose which one to keep β€” it removes both and re-inserts just the selected one β€” then press Enter again to log.
Shorthand locator without field letters: typing just the square+subsquare, e.g. 44XX instead of JO44XX, is recognized too β€” common practice over the air for a nearby contact. It's resolved to the full locator closest to your home station (checking your home field and its neighbors), so it almost always just means "my own field" unless the target square happens to sit right across a field boundary. Requires a home locator to be set in Settings.

Duplicate warning

As soon as the typed callsign matches an already-logged QSO, the one-liner input turns red and a short beep sounds β€” in addition to the DUPLET text shown in the hint line below. Both cues clear automatically once you move past the callsign or clear the line.

Portable/mobile suffixes don't create a new station for duplicate purposes: OZ1DSK, OZ1DSK/P and OZ1DSK-P are all treated as the same call. Prefix-style calls like OZ/DL4MM are recognised as valid callsigns too.

New ODX: logging a QSO that becomes the new longest-distance contact in the log plays a distinct two-tone rising chime β€” different from the duplicate warning beep β€” right after it's saved.

Wildcard callsign lookup

Use ? as a wildcard for a single unknown character in a callsign. Press Space after the partial callsign to search the locator database:

ExampleMatches
G?YDYG3YDY, G4YDY, …
OZ?ZOZ1Z, OZ7Z, …
OZ??ROZ1HR, OZ5YR, …

A picker appears with all matches from the database. Select the correct station β€” the wildcard token in the input is replaced with the actual callsign and the locator is inserted automatically.

Prefix search also works without wildcards: type OZ7 and press Space to see all database entries beginning with OZ7.

Live search β€” replaces the log list

As soon as the last thing you're typing is 2 or more characters containing a letter, the QSO log table is temporarily replaced with every locator-database entry where that text appears β€” anywhere in the callsign or the locator, not just at the start. This is separate from the Space/Enter picker above: it updates on every keystroke, doesn't require a complete callsign first, and searches locator text too.

TypedMatches (because it appears...)
jo44any locator starting JO44...
wea locator ending in WE, e.g. JO44WE
4wanywhere in the middle, e.g. the 4W in JO44WE
oz7any callsign containing OZ7
o?7z? as a wildcard for one unknown character β€” matches OZ7Z, OK7Z, …
jo??wewildcards work in locators too, not just callsigns β€” matches JO44WE, JO33WE, …

Matches you've already worked (logged in this session) are separated into their own narrow column on the left, so you can see at a glance who's still needed. Everything else fills the remaining 3 columns to use the panel's width. Both lists are sorted alphabetically by callsign, filling each column top-to-bottom before wrapping to the next. Each entry shows distance and QTF (bearing) after the locator, e.g. JO44WE Β· 182km 177Β° β€” same figures as the map/log, requires a home locator to be set in Settings. Click any entry to fill that call and locator into the input, same as picking from the Space/Enter picker.

Press Esc, clear the input, or move on to the next field (a space) to bring the log table back. If you were on a different tab (Watchlist/KST/Online), it switches you to Log list automatically so you can see the results.

Queuing the next QSO β€” /n

While logging a QSO you can note one or more upcoming stations using /n CALL anywhere in the line:

ExampleEffect
G3YDY 57 JO01FQ /n G4SWXLogs G3YDY, then pre-fills G4SWX (+ locator if in DB)
G3YDY 57 JO01FQ /n G4SWX /n SM5EPOQueue: G4SWX first, then SM5EPO

The hint line shows the queue as β†’ G4SWX β†’ SM5EPO while you type. After logging:

  1. The first queued callsign is pre-filled (with locator from DB if available).
  2. The remaining /n entries stay in the input so they are passed on when that QSO is logged.
  3. When the last queued QSO is logged the input clears normally.
Press F3 to clear the input and the entire queue at any time.

3. Score

The score is shown continuously in the bar below the top menu:

Worked example

You are OZ7Z (JO44VW) on 144 MHz and have logged three QSOs:

#StationLocatorDistanceWWL square
1G3YDYJO01FQ720 kmJO01
2G4SWXJO02RF630 kmJO02
3SM5EPOJO89WK700 kmJO89

Score calculation:

KM pts  = 720 + 630 + 700 = 2050
WWL     = 3 unique squares Γ— 500 = 1500
Total   = (2050 + 1500) Γ— 1 = 3550

The band multiplier is Γ—1 for 144 MHz. Microwave bands get a higher multiplier:

BandMultiplier
50–1296 MHzΓ—1
2.3 GHzΓ—2
3.4 GHzΓ—3
5.7 GHzΓ—4
10 GHzΓ—5
24 GHz+Γ—6–×10

4. EDI export / import

Click ↓ EDI to download your contest log in REG1TEST format (Tucnak-compatible). The file can be uploaded directly to vushf.dk.

Click ↑ EDI to load a previously saved EDI file back into the logger. If the log already contains QSOs, you're asked whether to Replace them or Merge the imported QSOs in β€” merge skips any QSO that's already logged (matched on callsign + date + time), so it's safe to re-import the same file without creating duplicates. Distances are recalculated from the locators using the current home locator setting; any QSO with a blank locator field in the file is looked up in the locator database instead.

Importing also updates your Contest start date / Contest end date (Settings) to match the date range of the imported QSOs, and your callsign to the file's PCall= field β€” so the sync date window (see Β§11) lines up automatically instead of pointing at whatever date was set before.

Filename: OZ7Z_144MHz_260506.edi

Each QSO line: date ; time ; call ; mode ; RST-sent ; nr-sent ; RST-rcvd ; nr-rcvd ; locator ; distance-km

Settings β†’ Advanced β†’ Local backup every N QSO automatically triggers this same download after every Nth QSO you log (0 = off), so you always have a recent backup on disk without clicking ↓ EDI yourself. Each auto-backup gets a _bkNNN suffix (current QSO count) so successive files don't overwrite each other.

Distance formula: distances are calculated using the spherical haversine formula with Earth radius 6373.6 km (Hamlib/Tucnak standard) and always rounded up. This matches the vushf.dk contest robot.

5. Locator database

Import a text file with known stations for callsign autocomplete. One station per line:

G3YDY;JO01FQ
G4SWX;JO02RF
SM5EPO;JO89WK
OZ7Z;JO44VW;Allan

Supported formats:

A callsign may appear more than once with different locators (e.g. a portable station at different QTH). If there are two or more locators for the same call, a picker appears when you press Space in the one-liner or leave the Callsign field in form mode.

Click 📂 Load locator file in Settings. The database is stored in the browser and merged with any new file you load.

If you load or update the locator database after QSOs are already logged, click ↻ Recalc in the top bar to look up any missing locators for already-logged QSOs from the database, recalculate distances, and re-run the duplicate check for the whole log in one go.

6. Aircraft scatter

Aircraft scatter allows VHF/UHF QSOs over long distances via reflection from aircraft. Flight data is fetched via vushf.dk as a proxy β€” it tries airscatter.dk first and automatically falls back to OpenSky Network if airscatter.dk is unavailable. The active source is shown in the info bar below the map: 42 aircraft Β· airscatter.dk or 42 aircraft Β· OpenSky.

Adding stations to the Watchlist

Open ⚙ Settings and switch to the ✈ Watchlist sub-tab (next to General, top of the Settings panel). It has an add-row at the top and a list of your stations below β€” there is no fixed row count or upper limit.

  1. Type a callsign and locator into the two fields, then click + TilfΓΈj (or press Enter) to add the station to the list.
  2. Each row in the list can be edited directly β€” click into the Kald or Lokator field and type; changes save automatically.
  3. The checkbox on the left of each row controls whether that station is actively watched for scatter β€” the same checkbox state is shared with the live Watchlist tab (see below).
  4. Click the βœ• button on a row to remove just that station.

To import a station list from a file, click ↳ Import file at the top of the Watchlist sub-tab. To clear all stations at once, click the red βœ• Ryd liste button β€” you will be asked to confirm.

A quick way to fill the Watchlist: use the Online tab's + TilfΓΈj til watchlist range button (see chapter 7) to bulk-add every currently online KST station within a chosen distance β€” no manual typing needed.

Getting started with scatter

  1. Click ✈ Planes in the top bar β€” aircraft within the search radius are now fetched every 10 seconds.
  2. Open the ✈ Watchlist tab in the left panel (this is the live scatter view, separate from the Settings β†’ Watchlist setup above).
  3. Tick the checkboxes next to the stations you want to check scatter against. Use the header checkbox to select all at once.
  4. The logger automatically shows which aircraft are in scatter position and when the next one arrives.
The Watchlist tab shows your stations even when ✈ Planes is off β€” the scatter column just stays empty (β€”) until you turn it on. You can also remove a station directly from this tab with the βœ• button on its row, without going through Settings β†’ Watchlist setup.

What does the watchlist show?

DisplayMeaning
G3YDY ✈ (12)Aircraft in scatter position now β€” approx. 12 minutes remaining
G4SWX (5)No current scatter, but next aircraft arrives in approximately 5 minutes
SM5EPONo scatter or incoming aircraft detected
(faded / strikethrough)Station already logged as a QSO

Scatter parameters

The scatter corridor angle and minimum aircraft distance are set automatically based on the selected band. You can adjust them manually in Settings:

ParameterDescription
Scatter angle (Β°)Width of the scatter corridor. Narrower at higher frequencies (e.g. 2Β° on 10 GHz, 5Β° on 144 MHz).
Plane range (km)Maximum search radius for aircraft β€” default 400 km
Min plane dist (km)Aircraft closer than this are ignored (within line-of-sight) β€” default 130 km

Map overlays

7. ON4KST chat

The logger has a built-in client for the ON4KST VHF chat network. Use it to arrange skeds with other operators during a contest.

Connecting

  1. Click the KST tab in the top-left panel.
  2. Enter your callsign, password and the channel you want to join (e.g. 144 for the 144 MHz room).
  3. Click Connect β€” incoming messages appear in the chat window.
  4. Type a message in the input box at the bottom and press Enter to send.
  5. Click Disconnect to log out.
You need an ON4KST account to use the chat. Register at on4kst.org.

The chat window is split in two: the top pane shows the full channel traffic, while a smaller pane below it β€” "Mine beskeder & svar til mig" β€” mirrors only the messages you sent and any lines mentioning your own callsign, so you can follow your own conversations without scrolling through a busy channel.

The browser asks for notification permission the first time you click Connect. If granted, a desktop pop-up appears whenever your own callsign is mentioned and the tab isn't currently visible β€” so you won't miss a sked request while looking at another window, without the pop-up stealing focus from wherever you're working.

Reloading the page (F5) does not disconnect you from KST β€” the connection runs on the server independently of the browser tab. On reload, the logger checks whether it's still connected and resumes the chat automatically, replaying any messages that arrived in the meantime, instead of forcing a fresh reconnect.

Split view β€” KST above the QSO entry

For single-op use, enable Settings β†’ Advanced β†’ Split view: KST above QSO entry to dock a compact chat panel β€” with its own message box β€” directly above the QSO entry, so you can watch and reply to KST without switching tabs.

Right-click β€” scatter sked from Watchlist

When a station in the Watchlist tab is also online on KST it shows a Β·KST badge next to its callsign. Right-click the callsign to open a context menu with a pre-filled scatter sked message. Example:

G3YDY pls sked on 144.300 AP in 8 min

The frequency is taken from your active band and the time is the current scatter ETA. Edit the message if needed and press Enter to send it.

Online tab β€” all logged-in users

The Online tab (tab 4) shows all stations currently logged into the KST channel. Click Fetch active users to refresh the list. The list is filtered by distance β€” only stations within the configured maximum (default 1000 km) are shown.

BadgeMeaning
Β·WLStation is in your Watchlist
Β·MEYour own callsign

Left-click any callsign β€” in the chat log, the "Mine" pane, the split-view panel, or the Online list β€” to instantly fill the message box with /cq G3YDY, ready to send. Right-click instead opens an editable popup pre-filled the same way, if you want to change the message before sending.

Sorting: click the Call, Lokator or km column header to sort the list by that field. Click the same header again to reverse the direction (ascending ↔ descending, shown by a β–²/β–Ό marker). Stations with an unknown distance always sort to the bottom.

Bulk-add to Watchlist by range

Below the header row of the Online tab is a + TilfΓΈj til watchlist button with two range fields, "fra" (from) and "til" (to), in km. This adds every currently online station whose distance falls within that range to your Watchlist in one click β€” skipping stations already in the list or without a valid locator. Newly added stations are automatically checked as actively watched. Your home locator must be set in Settings for this to work.

8. Layout

9. Keyboard shortcuts

KeyAction
EnterMove to next field / save QSO / one-liner: look up locator (same as Space when only a callsign has been typed)
SpaceOne-liner: look up locator from database after callsign (or wildcard) β€” opens the picker, nothing inserted until Ctrl-X
Ctrl+XOne-liner: cycle to the next locator suggestion when several matches were found
↑ / ↓Navigate callsign/locator picker
EnterSelect highlighted entry in picker
EscClose picker / cancel autocomplete
F2Jump to the full KST tab and focus its message box
F3Clear QSO entry and date field (works in both modes)
F4Jump back from the KST tab to QSO entry; or, when Split view is enabled (Β§7), toggle focus between the split-view message box and QSO entry
F3 works regardless of which field has focus β€” useful for abandoning a QSO in progress without touching the mouse.
Need to type / often for portable calls (e.g. OZ1DSK/P) or the /n next-call shortcut, but your keyboard needs Shift for it? Set an Alt '/' key in Settings β†’ Advanced β€” that key then inserts / instead, in both the one-liner and the form callsign field.

10. Data and backup

The log is saved automatically in the browser's localStorage after every QSO β€” it survives browser restarts. Data is not deleted when the page is refreshed.

If the log already has QSOs in it when the page starts, a popup reports your callsign, the QSO dates, the count, and whether a net-copy exists on the server and is up to date (see Β§11) β€” click OK, or Sync now if it's out of sync.

The log is stored per band β€” each band you select in Settings has its own separate storage key (e.g. zlog_log_144MHz). Switching bands loads that band's log instead of continuing the previous one, so QSOs from different bands never get mixed together, even across multiple browser tabs on the same computer.

Important: Clear log permanently deletes all QSOs for the currently selected band. Download the EDI file before clearing.

To move your log to another computer: use the browser DevTools (F12 β†’ Application β†’ Local Storage) and copy the key for your band (e.g. zlog_log_144MHz) and zlog_settings.

11. Multi-machine sync

The logger can synchronise the QSO log in real time between two or more computers on the same operator setup β€” for example a desktop running the map and a laptop at the radio.

  1. Click the 🔗 Net button in the top bar. When active it turns green.
  2. Both machines see each other's QSOs within approximately 3 seconds.
  3. New QSOs logged on either machine appear on the other automatically.
  4. Clearing the log on one machine also clears it on the other.
Sync requires sync_log.php to be present on the server. Each callsign + band + date window combination uses its own sync file, so different operators β€” and different contest sessions on the same callsign/band β€” do not interfere with each other.

The date window is set in Settings via Contest start date and Contest end date (YYMMDD). Both reset to today automatically whenever you click Clear log, so a fresh contest day naturally gets its own sync file β€” and both are set automatically from the QSO dates when you import an EDI file (Β§4). For a contest spanning more than one calendar day, widen Contest end date manually before you start.

Both machines must be using the same callsign, band and sync date window in Settings for sync to work β€” check the Net button's tooltip, which shows the active window, e.g. OZ7Z 144 MHz [260819–260819].