The frontend caches statuses and only asks about unknown keys, so flipping
the chase mode left half the screen judged under the old rules until a
restart — which read as the mode not working. The backend now broadcasts an
invalidation and the panels re-ask as rows repaint. The entity badges also
say their name with a question mark, dashed, when the need is only a missing
QSL — the 50% opacity was invisible on a filled chip.
The gap between worked and confirmed becomes visible everywhere. A Chase
setting on the DX Cluster page picks the mode; in new-plus-unconfirmed the
verdicts for DXCC/band/mode/slot, prefix, county and state are judged against
CONFIRMED-only ledgers built from the operator's chosen sources (LoTW, card,
eQSL, QRZ.com — HRDLog has no confirmation field in ADIF to offer), and a
need that exists only because a QSL never arrived is flagged Unconf: the
cluster and decode badges render it dimmed, the convention the grid hunt
introduced. The grid's own Chase selector folds into the global one; its
square-matching scope stays where it was, being grid-specific. One snapshot
key change rebuilds the cache when any of it flips.
The WAS gap made visible: a worked-states set joins the cluster status cache
(distinct states over the three US entities), the status entries carry a
NewState flag wherever the state resolves (log county first, ULS licence
second), and the decode panel gains the badge in its status column plus the
filter chip alongside NEW/BAND/MODE/GRID. Colour from the shared marker
palette, so the cluster can adopt it later without a second hue.
The voice keyer grows to F1-F12 — the UI was already data-driven, so the
count constant, the F-key range and the labels are the whole change.
And the preferences stop stuttering on a busy station: every spot batch,
decode batch and CAT snapshot re-rendered the entire App tree behind the
dialog — cluster grid, decodes panel, thousands of nodes — and the pointer
janked over the very panel the operator was trying to use. While Settings is
open the flushes park their batches in the pending refs (bounded) and CAT
repaints at most every two seconds; closing the dialog drains everything.
Configure (message 15), mode field only, every other field sent as
no-change: an FT4 spot clicked while WSJT-X sits in FT8 lands the operator
ready to decode instead of staring at gibberish. Sent to every instance
heard this session — one already in the right mode treats it as a no-op —
and only for modes the decoder actually speaks (FT8/FT4/JT65/JT9/MSK144/
Q65/FST4); CW and SSB are none of its business. Toggle in the Connections
panel, on by default.
WSJT-X restates the same DX Call in every Status packet, and a spot clicked
in OpsLog put that call into the last-UDP memory (deliberately, for another
case) — so the guard let the decoder's next restatement straight through and
the entry snapped back to old news. The decoder's stream now only counts when
its value CHANGES; a clear over there resets the edge so re-selecting the
same station still lands. Explicit picks (N1MM, remote, spot relays) are
untouched.
Message 13 paints callsigns in WSJT-X/JTDX's own Band Activity window with
verdicts from the same cluster status cache that colours the spot grid:
watchlist pink, new DXCC green, new band for its entity orange. Deduplicated
per instance+call+verdict, one datagram each; a verdict that lapses (the
operator worked them) clears that call, and turning the option off clears
everything via the protocol's CLEARALL!. Off by default, switch in the
Connections panel.
Message 7 asks a program heard for the first time this session to replay the
decodes already on its screen, so the FT decodes panel starts full instead of
empty until the next period. Replayed lines arrive marked not-new and are
shown but never auto-answered — the auto-caller now checks, on top of its
30-second freshness gate.
Two lookups race when a second callsign is typed before the first answered,
and the slow one landed last: the grid showed the previous call's QSOs under
the new call's name — LU5AVM's contact filed under LW8ETV, screenshot in
hand. A request token now discards any response that is not the newest.
It keeps 'not repeating' on a network rig and every guess at which guard was
tripping proved wrong. Each round now logs play / playing-flag / end / gap,
and every exit names its reason.
Over the network the rig's mode read fails now and then and the CAT push
blanks the mode for a poll or two; the auto-CQ loop treated that blank as
'not a phone mode' and stopped after the first call. Only a KNOWN non-phone
mode stops the loop now.
The CI-V keyer is the same 0x17 command on the same IcomController whatever
carries the link; only the warnings and enable checks insisted on the USB
backend, telling a network operator their working keyer would fail.
Two halves of the same station confusion. The entry form pre-filled MY_RIG
from the per-band default on every band change, so the log-time priority (the
radio that is keying beats the radio that was planned) never ran — the field
was no longer empty by the time the backend looked. The form now asks the
active radio first, through a new ActiveRadioMyRig binding.
And the manual record button started its capture from the From-radio sound
card unconditionally, where the automatic recorder already knew a network
Icom's audio is pushed from the 50003 stream: a manual take on the IC-7760
was a faithful recording of the Flex's DAX. Same source rule for both, and
the button is offered with no sound card at all when the network stream is
the source.
Two effects, wrong order: the ticking effect ran before the reset effect on a
new take, so its closure captured the PREVIOUS take's elapsed as its starting
point — the counter showed 0 for one second and then jumped back to thirty
minutes. Effects run in declaration order; the reset now comes first.
Double-clicking a cluster spot tuned the slice and zoomed the panadapter in
the same breath. On a cross-band jump SmartSDR moves the panadapter itself to
follow the slice, and that follow lands after — and overrides — a zoom sent in
the same instant, so the width the operator configured never appeared. A spot
clicked ON the panadapter never hit this, because the radio had already tuned
before our zoom arrived; the two paths now behave the same. The Chase new
panel's pick is sequenced identically.
Every other spot click — cluster grid, band map, watchlist, alert list — goes
through handleSpotClick, which applies the operator's per-mode panadapter
width after the tune. The Chase new panel had its own pick handler that tuned
and stopped there; it now makes the same view change, after the tune for the
same reason.
The F1 panel widens 560 → 600 px, the header row drops its outer padding and
wide gaps, and the country badge tightens — so 'Central African Republic' and
the NEW SLOT chip share one line instead of the chip dropping alone underneath.
The watchlist joins the Main-tab pane list (Settings → Main view), rendered in
a card like the other docked panels.
The three filters persist across tab switches — the component unmounts on every
switch, and filters that reset each time are filters nobody trusts.
Needed-only now hides the worked SPOT LINES as well as the all-worked cards,
which is DXHunter's own Not-Worked behaviour and the reported complaint: a
filter that says needed and still lists five green Worked rows answers a
different question than the one asked.
The add-row checkbox is relabelled 'as contest' — it marks the entry being
ADDED, and read as a filter beside the All/DX/Contest buttons it looked
redundant.
The concept, transplanted: a list of callsigns or prefixes being hunted,
matched against the live spot stream, one card per entry with the spots
underneath and the two questions that matter answered on every line — is this
slot still needed, and what is it worth (the cluster's own NEW badges, read
from the same status index).
The file is DXHunter's own watchlist.json, field for field, ClubLog block
included though phase 2 will fill it — a file that round-trips unchanged is the
whole of 'same format', and a test pins it with a real DXHunter entry. Global
(dataDir), not per profile.
CONTEST is per entry, not the global mode DXHunter has: a contest entry is
judged against the current UTC day — the boundary lives in the query's date
bound, so midnight needs no timer and resets nothing. Normal entries read the
same in-memory worked index the alerts use. Prefix matching is why RI0SP
catches RI0SP/MM, pinned by test.
Notify goes through the existing alert:fired event — the frontend already
toasts and sounds it — throttled to one alert per entry per two minutes,
because a DXpedition lights every skimmer on the planet.
Tab wired like NET Control: opt-in from Tools, persisted, closable. Single
click fills the callsign, double click works the spot — the cluster's own
gesture, kept.
An operator who does not chase parks does not want NEW POTA shouting from every
activator spot. Two switches (Settings → DX Cluster, on by default): off, the
marker is withdrawn at the display layer — applySpotDisplay, the same chokepoint
the grid, the band map and the filter read through — so the badge, the colour,
the filter chip and the reference column all go quiet together, and a new-band +
new-POTA spot reads NEW BAND alone. The facts keep being computed; only the
telling stops, so ticking the box back on needs no rescan.
Three from review. Aqua for NEW SLOT sat right next to the POTA green — it is
now the sky cyan the panadapter palette has shipped for new-slot all along.
The NEW COUNTY chip was green while its badge is violet, and NEW SLOT's chip
was still caution yellow: chips now carry the badge's own colour (color-mix for
the muted border/背景), because a filter that does not look like what it selects
has to be learned twice.
And the NEW CALL chip matched only the DISPLAYED status, which is manufactured
by the slot-highlight option — with that option off the chip matched nothing
and read as broken. It now filters on the fact itself (worked_slot false), so
it works either way.
The Send-spot dialog took catState.freq_hz, which is the TX frequency. Working
a DXpedition split, that is where WE transmit: the spot went out five up from
the DX, pointing the whole cluster at the pile-up instead of the station. The
RX frequency is where we listen — where the DX is — and is what a spot names.
The feature needs more rounds than the next release can wait for, so main goes
back to before it: the packages, bindings, migration, UI and i18n all move to
the feature/labels branch, which holds every commit. The 0.26.23 block keeps
only the Station column.
The 0031 migration may already have run on a machine that launched a dev build;
the two label tables it created are inert and the recorded migration row is
harmless — the runner only applies filenames it has, so re-adding the migration
when the branch merges will skip cleanly there and apply everywhere else.
The printing session in three steps. The worklist is the paper queue (ADIF
qsl_sent R/Q), grouped by callsign since several QSOs of one station share a
card. Each recipient is reviewed before anything prints: routing first — via
manager when qsl_via says so, direct when an address is known, bureau otherwise
— then the address itself, editable and fetchable from QRZ (the MANAGER's
address when routing says via). What is printed is the reviewed text verbatim,
not a re-resolution that could differ from what was checked.
One PDF per label kind, never one file for all: a roll printer holds one stock
at a time, and a file mixing 29 mm addresses with 62 mm QSO labels could not be
printed at all. Pages are rasterised by the designer's own renderer at the
stock's dpi and carried into the PDF untouched — internal/pdf is a hand-written
image-page writer (DeviceGray + flate: monochrome, lossless, no cgo) because
that is the entire need.
Bureau stations get no address label (no envelope); return labels are printed
one per envelope. Finishing offers the log update: QSL_SENT=Y, the chosen date,
via B or D per routing — through the same BulkUpdateQSL the paper view uses.
The designer's data model lives in internal/labels: STOCKS are the physical
roll in the printer (geometry in mm, margins, dpi — seeded with the common
Brother DK sizes, the QL family being what prompted the feature), TEMPLATES are
one design each, of two kinds: the QSO label glued on the card, whose repeating
table carries several contacts of the same station, and the address label for
the envelope, whose lines collapse when a variable is empty.
Everything is measured in millimetres — labels are sold in mm, and an operator
lining a design up against a physical sticker thinks in mm; pixels exist only in
the renderer, at the stock's dpi. The canvas renderer is shared between the
editor's preview and the future print path, so there is no second
implementation for the preview to disagree with.
The preview is fed with the log's latest contacts rather than lorem ipsum: real
data shows a too-narrow column immediately.
Printing (PDF, one page per label at exact size) is the next module; nothing
here prints yet.
The grouping keyed on the callsign alone, so every spot of a station outside the
first one's band and mode was dropped from the list. RI1FJL spotted on 17m CW,
20m, 30m, 12m and 15m FT8 showed as a single row: four slots gone from the one
view an operator uses to find them.
A duplicate is the dozen skimmers that all heard the same CQ — same station,
same band, same mode. The same station on another band is the opposite of a
duplicate; it is what the chaser is scanning for.
Every flush commits state the whole window re-renders on, and the window was a
flat 50 ms — twenty full renders a second under an RBN firehose. That is paid
everywhere else in the interface, and it is what a dropdown highlighting its
entries a beat behind the mouse actually is.
The window now follows the rate: 50 ms on a quiet cluster, where a spot should
appear the moment it arrives; 200 ms past five a second; 500 ms past twenty,
where half a second's delay on a line already scrolling past is invisible.
The pane drew its own title bar above the grid's toolbar, so the cluster spent
two lines on headers where Recent QSOs beside it spent one — in a pane often
only a few spots tall. The grid's toolbar now takes what the caller wants on its
left, and the pane passes its title, live count and Filters button there.
Reported by VK4DX.
The sixth CW engine, and the one the TCI backend was left without. A SunSDR
keys from the WebSocket that already carries the CAT: no WinKeyer, no second
serial port, nothing to wire.
CW_MACROS:0,<text>; send
CW_MACROS_SPEED:<wpm>; speed
CW_MACROS_STOP; abort
Confirmed against the TCI command table in ars-ka0s/eesdr-tci — the source that
settled SPOT. CW_MACROS rather than TCI 2.0's CW_MSG: it exists from 1.6, and
OpsLog resolves its own variables, so the before/after callsign fields have
nothing to carry.
Commas and semicolons are stripped before sending. They are the protocol's own
separators: a comma would become another argument, a semicolon would end the
command with the message half keyed and the rest parsed as a command.
Only the MACRO speed is set, not the paddle keyer's — an operator who set their
paddle to 28 wpm did not ask for it to change because a macro went out at 25.
And there is no backspace: TCI can stop a message but cannot un-type one, so the
type-ahead correction the Flex engine offers is absent rather than faked.
Everything is computed in kilometres and converted once at display time, in
lib/units — storing miles anywhere would give the same number two sources of
truth and a rounding error that grows with every hop.
The grids capture the unit inside their column definitions, header and formatter
both, so a change is published to them the way the date format already is;
without that a toggle would only appear after a language change or a restart.
The preference is portable, like the other display ones.
The SOTA feeds put the summit in the spot's own text, so there is nothing to
poll: a regex on the comment gives the reference, and clicking the spot writes
SOTA@<ref> into the award references the way a park already wrote POTA@<ref>.
The regex is narrow on purpose — association/region-NNN, anchored — because
POTA (US-4475), WWFF (DLFF-0001) and portable callsigns (DL/SP9DPM/P) share
that field and none of them is a summit. Pinned by a table test.
Off by default: the reference is only there on the summit feeds, and an empty
column for every operator who does not chase them is worse than a checkbox.
The chip read a.spe ?? a.acom ?? a.pgxl, so a KPA fell through to the
not-connected fallback: red on a working amplifier, and a click that opened the
settings instead of switching to STANDBY. Reported from a KPA500 whose panel
showed band, SWR and temperature at the same time.
The card's offline text also borrowed the Acom's string, so a KPA that dropped
its link announced itself as an Acom.
It showed what the radio calls itself over CAT — 'Kenwood (911)' for a K3,
a bare 'CAT' for a Flex that reports nothing useful. That is the answer to
a question nobody asks once the rig has a name in the list, and it made
the two radios look alike in the one place they have to be told apart.
The name the operator typed comes first now, on the chip and in the menu,
and falls back to the radio's own identity when they typed none. The model
identity is still in the tooltip, where it answers 'what is actually
connected' without taking the place of 'which of my rigs is this'.
It only became a menu from two radios, on the reasoning that a single
radio has nothing to switch to. That hides the feature from precisely the
operator who has not made a second radio yet — the click lands on a
settings dialog they did not ask for, which is what happened on the first
try. With one radio the menu now shows that radio and 'Add a radio…'.
Right-click still goes straight to the CAT settings.
The answer to 'I have two rigs' was 'make two profiles', which is a heavy
instrument for a light question: a profile carries the whole station —
logbook, callsign, awards, cluster, macros — so switching one to change
which radio is connected takes all of that with it, including a change of
logbook when the profiles point at different databases.
Radios are a list now, the way amplifiers already are. The CAT chip in the
status bar opens it, one click connects the chosen rig, and nothing else
about the station moves.
The storage keeps the ACTIVE radio in the same settings keys everything
already reads (cat.backend, cat.icom_port, …), and switching writes the
chosen entry into them and reloads the link. So the consoles, the CAT
sharing, the band-follow and every panel see exactly what they saw before
and needed no change at all — the list is a second store beside the
configuration, not a replacement for it.
Details that matter more than they look:
- An operator who has run one rig for a year opens the list and finds it
there, because a missing list reads as the CURRENT settings rather
than as nothing. It is written on the first save, not on the first
read.
- Editing the CAT panel updates the active entry, or an edit made before
switching away would be lost on the way back.
- A new radio starts as a COPY of the current one: a second rig is
usually the same shape with one port changed, and an empty form is a
form to fill in twice.
- Switching saves the panel first, so edits to the radio being left
behind are kept.
- The chip only becomes a menu with more than one radio; with one it
opens the CAT settings exactly as it always did.
TCI already carries the frequency, the mode, the meters and now the audio.
It also carries everything else about the radio — and OpsLog was logging
most of it once as '(unhandled once)' and throwing it away. The console is
mostly a place to put what was already arriving.
That makes it the cheapest panel here, and it is worth saying why. A K3
console costs a command and a reply for every value it shows, which is why
it reads its settings in a rotation and its meters only while on screen.
TCI PUSHES: the radio announces its drive, its filters, its noise blanker
and the rest on connect, and again whenever any of them changes —
including when the operator changes them in ExpertSDR3's own window, which
this panel therefore follows without asking anything.
What it drives: drive and tune drive, mic gain, TUNE, volume, mute,
squelch and its threshold, NB, NR, ANF, APF, AGC speed, the passband, RIT
and XIT with their offsets, and the VFO lock. The S-meter is a real dBm
reading, so its S units are arithmetic rather than the calibration guess a
K3's meter needs.
Setters never update the cached state. The radio answers with the new
value, and taking its word is what keeps the panel honest when a setting
is refused, clamped, or changed at the radio a second later — the one
exception being a slider mid-drag, held for 900 ms so it is not dragged
back by its own echo.
Capped width and centred, like the other consoles. Also offered as a
docked pane — and the Elecraft console is offered there too now: App has
always had that pane, Settings simply never listed it.
TWO FAULTS, ONE SYMPTOM — 'it refreshes ten times a second and the
buttons cannot be pressed'.
Preferences is a child of the main view, so every cluster spot, CAT push
and decode re-rendered the entire panel. On a busy evening that is
several times a second, and the panel is large enough that the rebuild
outlasts the gap between them: buttons missed their clicks because the
element under the pointer was replaced between the press and the release.
It is memoised now, and the callbacks App hands it hold their identity —
without that the memo compares unequal every time and buys nothing.
The dropdown menu was an absolutely-positioned child, so it was clipped
by whichever scrolling or overflow-hidden box it sat in: the satellite
list showed one entry of eight. It is portalled to the body now,
positioned from the field's rectangle, re-measured while open, and opens
upward when the field is near the bottom of the screen — which is exactly
where these fields tend to be.
SATELLITES: the field read the list once, when the details panel first
mounted — which is at startup. A list saved in Preferences afterwards
therefore did nothing until a restart. It comes from App now, which
already reloads the lists when Preferences close.
RDA COMPARE: a failed comparison wrote its error into the message beside
the FILL DISTRICTS button, a row above — the error appeared under a
button nobody had pressed while the one that had been pressed showed
nothing, which reads as 'the button does nothing'. It has its own message
now, and reports the two results that look like silence: no disagreement
at all, and no Russian contacts to compare. Both buttons say what they
are doing while they do it, and the comparison logs before it starts
reading — on a remote MySQL that read is seconds of quiet.
SAT_NAME is compared character for character by the awards and by LoTW:
AO-91 and AO91 are two different satellites to everything downstream, and
typing it afresh on every pass is how one of them ends up in a log. So
the station keeps its own list (Preferences → Lists → Satellites) and the
field offers it, alphabetically — while still accepting anything typed,
because a bird worked once and never added to the list must not be
impossible to log.
Not seeded with a shipped list of two dozen birds: an empty list means
this station does not work satellites, and filling the dropdown with
names nobody here has heard makes the field harder to use, not easier.
Also fixes the RDA district comparison: its conflict list was capped at
about six visible rows of a list holding up to two hundred, in a panel
that would not scroll to show the rest, and nothing in it could be acted
on. Taller, scrolling, and a callsign opens the contact.
The list is a ring buffer that held a thousand spots, and on a busy
evening a thousand arrive in a couple of minutes. So the buffer decided
how long a spot lived, and the spot LIFETIME setting never got the chance
to expire anything: fifteen minutes meant nothing when the oldest spot
was pushed out after two.
Now settable (Preferences → Cluster, beside the lifetime, since between
them they decide the same thing), 100 to 10 000. The ceiling is a real
limit rather than a round number: every spot is matched against the
worked index and the alert rules, and is a row the cluster grid and every
open band map re-render.
Reading the cluster means running down dozens of lines, and a single
click did the whole job — QSY, mode, callsign — so every line looked at
dragged the radio with it. One stray click while reading took the
operator off the station they were working.
Looking and going are two different intentions, so they are two gestures
now. The band map is unchanged: clicking a spot there is already a
deliberate act, not a way of reading a list.
Reported from a real FTDX101, and each one is a different kind of wrong.
MIC GAIN was read and written through the 0-255 scale the audio gains
use, but the CAT reference gives MG000-100. A rig set to 80 therefore
showed 38, and moving the slider sent 204 — outside the range the radio
accepts, so it refused the command and the slider sprang back. That
snap-back was the symptom; the scale was the cause.
POWER was capped at 100 W by the slider, not by the radio. There is no
CAT command for 'how much power can you make', so the ceiling comes from
the model name, with the rig believed if it ever reports more than the
table expects — it has just proved what it can do.
NAR is the narrow IF filter, and on a rig that does not implement NA the
button showed a state the radio never gave and did nothing when pressed,
which reads as a fault in the radio. Now shown only when the rig answers,
with a tooltip saying what it is.
Also: the frequency readout steps the Hz digits under the wheel, not just
the kHz ones. Zero-beating a CW signal is a few tens of Hz and it was the
one move the display would not make. And the split chaser is CW-only —
its marker comes from a CW skimmer.
An operator reading a cluster page sees 28500 and wants to be there. The
hands are on the callsign field; reaching for the frequency box, or the
mouse, is the part that loses the station. So the call field takes a bare
number on Enter: kHz for a frequency, or a band on its own.
Ambiguity resolves to the band on purpose -- 40 is 40 m, not 40 kHz --
because neither of those kHz values is anywhere a radio tunes, and it
reads the way an operator says it. Anything with a letter in it is a
callsign and behaves exactly as before; a number that is neither a band
nor a plausible frequency does nothing at all.
Bands go through the ordinary band change, so the antennas, the per-band
power table and the outbound integrations hear about it as they would
from the dropdown. Also adds 4 m to the QSY table, so a band that can now
be typed is a band that has a frequency to go to.
The Elecraft backend already existed; what was missing was somewhere to
operate the radio from. This adds the panel, on the Kenwood-dialect
client the K3 already speaks, in a tab of its own beside the Yaesu and
Icom consoles.
Scope is the six controls asked for and nothing else. Every extra command
added without a radio to test it against is a control that may or may not
do what its label says, and a K3 exposes dozens.
No K3 was available while writing this, so the two halves are treated
differently. The setters are the commands the reference documents
unambiguously and whose effect is visible and reversible (PC, AG,
TX/RX). The meters are the opposite: their scaling differs by model and
firmware, so the raw answers are logged next to the power setting, the
panel says the scaling is provisional, and an unmeasured SWR shows as
'—' rather than as a perfect 1.0 — a good match on an antenna nobody
measured is the reading that costs a radio.
ATU tune sends SWT20 (the K3 front-panel tap) and logs exactly what it
sent, so a wrong mapping names itself instead of leaving an operator
guessing which button OpsLog pressed.
Their agent protocol has no download verb, so the return path is a file
exported from their site. Running that file through the ordinary ADIF
import is the wrong tool and does real damage: it matches on callsign +
UTC minute + band + mode, their export is rebuilt from their own
database and rarely agrees to the minute, and 'update duplicates' then
inserts everything that failed to match -- several hundred copies of
contacts already in the log.
This path matches only. It stamps the confirmation on QSOs it finds,
falls back to the mode-CLASS key for the modes their export renames, and
REPORTS what it could not match instead of adding it: an unmatched
confirmation is a question about the log, not a contact to create.
Also logs and reports how many rows a delete actually removed -- silence
there made a delete that did nothing indistinguishable from one that
worked.
Same reasoning as the selected-rows export: ExportADIFFiltered was called
with includeAppFields=false, so a filtered export lost the award
references. A second entry, next to the standard one.
The right-click export always called ExportADIFSelected with
includeAppFields=false, so it wrote strictly standard ADIF. That is the
right default when the file is going to another logger, but it silently
drops every APP_ tag -- and an award reference such as RDA@KR-04 lives in
APP_OPSLOG_AWARDREFS and nowhere else. Backing up a selection, or moving
it to another OpsLog, lost the awards.
Adds a second entry rather than a flag on the first: the two exports
answer different questions, and a checkbox in a context menu would have
to be read before every export.
The upload targets in the QSO context menu gain HAMLOG.online, so a selection
goes there the same way it goes to QRZ or LoTW.
The confirmation toast now names the service from a map rather than a chain of
ternaries that stopped after three: hrdlog, eqsl and hamlog were echoed as their
internal ids, which is not what the operator clicked on.
HAMLOG.online is a seventh external service: one API key, one ADIF record per
QSO, immediate / delayed / on-close like the rest. They publish no API
documentation, so the protocol is read from THEIR OWN client — the HAMLOG Agent
(github.com/hamlogonline/Agent), which is the authoritative source short of
asking them:
POST https://hamlog.online/api/agent/
{"ADIFADD": {"APIKEY": k, "ADIFDATA": record}} → {"STATUS":"OK"}
{"KEYSTATUS": {"APIKEY": k}} → {"STATUS":"OK","CALLSIGN":…}
Success is STATUS == OK, not "no ERROR field": their failure carries ERROR and
no STATUS, and reading an unknown reply — a proxy page, a maintenance notice —
as an acceptance is how a contact goes missing without anyone noticing.
KEYSTATUS buys something no other service here offers: the key can be checked
BEFORE the first QSO, and the answer names the account. A key pasted from
another callsign is caught in the settings panel rather than through a week of
silent refusals.
Their confirmations are also an award source now, ticked like LoTW rather than
expressed through "custom". It reads the ADIF extras, not a column: the standard
names a field for hamlog.EU and none for hamlog.ONLINE, and borrowing the other
site's field would write a falsehood into every exported log. Three plausible
key names from their own export are accepted too, so nobody has to rename a
column by hand after an export.
Yaesu gains antenna selection (AN), remembered per band — the antenna picked on
a band comes back with it, with no table to fill in anywhere. Rigs with one
socket never answer AN and never show the row; the log says which case it is.
And a serial port that is refused now names its likely holder. OmniRig stays
resident once activated and keeps the port of the rig configured in it, so a
native backend never gets it — "Serial port busy" alone accused nobody, and an
FTDX10 spent a morning being blamed for it.
An Icom reached over the LAN streams its receive audio through the Icom
protocol, and Windows sees no sound card for it at all — the audio settings
could only offer the PC's own microphone, so "From radio" had nothing right to
point at and the QSO recorder had nothing to record. The recorder now accepts a
PUSHED source: the decoded stream goes to the speakers and to the recorder
alike, with no virtual cable to set up. Which source it uses follows the CAT
backend, and it is restarted only when that answer changes, so an ordinary
settings save never cuts a recording in half.
OmniRig no longer sends SetSimplexMode to a Yaesu when tuning. It is a silent
no-op on some — an FT-891 logged OK on every spot click while FreqA never
moved — and actively harmful on others. From an FT-2000 log, one QSY:
Vfo="AB"(0x80) Split=0x10000 (off) the operator's state
Vfo="BA"(0x100) Split=0x8000 (ON) after SetSimplexMode
The rig-agnostic "receive and transmit HERE, simplex" call turned split on and
moved reception to VFO B. OpsLog then displayed B — reading the radio correctly,
after having moved it itself. Icom is untouched: there the call is the
authoritative one and the direct write is unreliable.
Also:
- the NEW county badge shows in the entry form itself, inside the field,
where the operator is deciding whether to call.
- the basemap buttons clear the zoom controls; Light sat a few pixels from
the minus button and was being clicked by mistake.
- French cluster status: DÉJÀ CTC reads DÉJÀ QSO.