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.
'No QSOs processed' (exit 8) covers already-uploaded, out-of-certificate-
date-range, and a station callsign that does not match the location being
signed with -- TQSL's message does not say which. An operator whose QSO
was refused and then accepted after a round trip through another logger
is reporting a difference in the record itself, and the temp ADIF is
deleted the moment TQSL returns, so that difference could not be seen.
Logged on any non-zero exit: the record verbatim, the exit code and the
station location. It is QSO data; the key password is not logged.
Withdrawing auto-call added a runtime guard and removed every control.
The stored preference was left alone, so 'enabled: true' still sits in
localStorage on the machines that had it on -- and any build without the
guard reads it and keys the transmitter for a feature that no longer has
a switch anywhere in the interface.
loadAutoCall now switches it off and writes it back the first time it
reads it, so the disarming survives a downgrade or a reinstall. Also
drops the dead auto-call state left behind in the settings modal.
A withdrawn feature that keys a radio has to be disarmed where it is
remembered, not only where it runs.
Club Log wrote to this station about 167 requests in four minutes and a
coming IP block. That was one deletion of a couple of hundred rows going
through delete.php, which is a REAL-TIME endpoint: it exists for an
operator removing a contact they just logged wrongly, at human pace.
Today's earlier fix stops the requests that were pointless -- QSOs Club
Log never had. This one handles the rest, which are legitimate but still
a batch: one delete every 1.2 s, and a stop at 25 with a line saying to
finish on clublog.org. There is no bulk-delete API to move to, so going
slower and refusing to push a large deletion through a real-time endpoint
is the whole of the answer.
Costs the operator nothing: the withdrawals already run in the
background.
Five entries were written after v0.26.9 was tagged (b952e07), so they
were never in the release the operators actually got -- their What's New
stops at the Club Log delete fix.
Send-on-type keys each character as it is typed, which only the WinKeyer
and Flex CWX can do -- so the checkbox is shown for those two alone. The
stored preference, however, survives a change of engine: an operator who
had used it on a WinKeyer and moved to CI-V carried an invisible switch
that was still on.
The consequences fit the report exactly. Nothing keyed while typing,
because wkSendRaw falls through to the WinKeyer that is not there; and
Enter sent nothing either, because sendText believes the text has already
gone out. Macros take another path and kept working.
The panel now derives the flag from the engine rather than trusting the
stored value.
The transmit row already carries SPLIT, TUNE, MOX, the chaser, its offset
and the TX readout. The marker field was the one control on it that is
set once -- to agree with SDC -- and then never touched again, so it is
summoned by right-clicking the button instead of parked there. Enter
commits, Escape restores. The button's tooltip says so: an unannounced
right-click is not a feature.
Nobody has seen 0.26.9 yet: a fix to a feature released in the same block,
and the panel field it should have had from the start, are not news --
they are how the feature works. Folded into the one entry.
The marker text is chosen in the skimmer, and the two have to agree or
nothing fires -- so it belongs next to the switch, not in a settings page
the operator would have to remember exists. Kept as raw text until blur:
it is a comma-separated list and normalising each keystroke would eat the
comma as it is typed.
GetFlexRSTChase read settings.Get with profileScope() prepended, but the
store already prefixes the active profile: it wrote p3.flex.rst_chase and
read p3.p3.flex.rst_chase. The switch went on in the UI, was saved, and
came back off on the next spot -- so the feature did nothing, silently.
Every refusal after a marker is recognised is now logged with its reason.
The operator has just seen a report marked on the panadapter; if the
slice does not move, the log has to say what stopped it.
Working a DXpedition split means guessing where it listens. The useful
information is not the callsign the DX answered but the FREQUENCY that
station was calling on, and a CW skimmer already marks it: SDC posts each
decoded report to the panadapter as a spot.
Those spots reach OpsLog through the radio's spot feed. On a marker, the
TRANSMIT slice moves there plus a signed offset; the receive slice never
moves, because losing the DX is worse than missing a call. The marker
text is a setting -- it is chosen in SDC by the operator, so any constant
here would be wrong for whoever chose otherwise -- and the switch is a
button beside SPLIT, since it is turned on when a DXpedition appears and
off when it is worked.
Moves are throttled and ignore a marker landing where the slice already
is: a busy pile-up produces several reports a second and the slice would
otherwise never be anywhere long enough to call.
The spot feed is now subscribed to unconditionally. It was tied to
OpsLog's own spot overlay, so an operator running SDC with the overlay
off received nothing -- the reason no foreign spot was ever logged. The
connect-time 'spot clear' stays behind the overlay flag: it wipes every
spot on the radio, a skimmer's included.
The award field list offered us_county, which returns STATE,County --
correct for the United States, where Jefferson County exists in several
states, and wrong for every award whose district is already unique. An
RDA reference (RO-19) never matched, and there was no other field to
point an award at.
Adds county, the raw CNTY value, alongside it.
The import printed four numbers and left nothing behind. 1106 matched
and 395 unmatched out of 1501 is not a report: the operator cannot see
which contacts were confirmed, nor work through the discrepancies.
Two additions. The Results view is now filled with the confirmed
contacts, flagged new entity/band/mode/slot against what LoTW and paper
QSL already confirm -- the only sense in which a HAMLOG confirmation
changes anything. And the unmatched ones can be written out as ADIF,
because a few hundred of them are a list to open and compare, not
something to read in a log window.
Deleting a selection with 'delete from the remote services' on took
minutes. Club Log was called for EVERY deleted QSO, uploaded or not, and
for the ones it never had it answers 403 -- a full network round trip per
contact, in series, on the goroutine the UI was waiting on. QRZ already
skipped records with no stored logid; Club Log had no equivalent guard.
Three changes, each fixing one part of the delay:
- only contacts whose clublog upload status is Y or M are withdrawn;
- the withdrawals run in the background, after a snapshot -- the local
log is the operator's own copy and must not wait on two websites;
- the hooks read the rows in one query instead of one per id, which on
a remote MySQL logbook was 2 round trips per QSO before the DELETE.
Consecutive refusals now abort the run: Club Log blocks an account that
keeps sending requests it refuses, so working through the rest of the
selection only earns a longer block.
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.
After an import that inserted instead of updating, there was no way to
ask which records it created: an import of old contacts carries old QSO
dates, so it hides among them. created_at is the only column that knows,
and it was not filterable.
Listed as a date column so a bare YYYY-MM-DD compares on the date part,
like qso_date.
The QSL Info tab knew every upload service except the newest one, so a
contact uploaded to HAMLOG.online could be edited everywhere but there.
It is stored in the ADIF extras rather than QSO columns -- like the
OpsLog card -- hence a channel of its own instead of a CONFIRMATIONS
entry, but it gets the ordinary sent/received/date editor because it
behaves like QRZ.com or Club Log, not like a printed card.
Its four columns move from the QSL group to Uploads for the same reason:
QSL is for cards, an upload service belongs with the upload services.
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.
A log imported from HAMLOG.online carries the Russian district in CNTY, and the
offline RDA database has its own answer for the same contact. Which wins is a
real question — but only if the two are independent. If HAMLOG's value is itself
a lookup in the same kind of database, there is nothing to arbitrate and a
precedence rule would be ceremony around a redundancy.
So this measures instead of deciding: Settings → RDA gains a read-only compare
that reports agreements, disagreements, and the contacts where only one side
knows, then lists the disagreements — callsign, date, both districts, whether
the database answer was a DATED record (the award administrators' own fact) or
the callsign's current district (an assumption), and whether the QSO is
confirmed on HAMLOG (their value has then been through a match of two logs).
It changes nothing in the log. What to do about a conflict is the next decision,
and it should be taken with the operator's own numbers in hand.
Also: the four HAMLOG fields become filterable, so 'never sent there' is a
filter rather than a guess. A field that can be written and not read back is
half a feature — pinned by a test against the bulk-editable list.
A real record from their export settles it:
<CALL:4>RL6M … <CNTY:5>RO-19 <APP_HAMLOG_R150COUNTRY:6>Russia
<APP_HAMLOG_QSO_CFM:1>Y
The confirmation lives in APP_HAMLOG_QSO_CFM. The four names guessed before a
file was available — APP_HAMLOG_QSL and friends — were all wrong, which is the
argument for reading one rather than reasoning about it.
So that becomes the canonical key everywhere: the award source, the row colours,
the grid column and the bulk editor. Importing a log downloaded from HAMLOG now
carries its confirmations into OpsLog with nothing to rename. The older names,
including the APP_OPSLOG_HAMLOG_QSL that OpsLog itself wrote in the meantime,
are still honoured on read so nothing already stamped stops counting.
Preferences → Confirmations gains a HAMLOG.online row, sent and received, with
the same defaults every other service has: a new QSO can start at N so the
backlog is meaningful from the first contact. The defaults reach it through a
new setExtraDefault — fill() writes through a pointer to a string field and
these two live in the extras map, which no pointer reaches.
The QSO grid gains four HAMLOG columns (status and date, both directions),
hidden by default: a column per service shown to everyone is how a grid becomes
unreadable.
And the paragraph explaining what "Sent" means is gone from that page.
Bulk edit offered two HAMLOG fields, both dates, and the first question they
drew was the right one: which of these is the status? Collapsing the flag into
the date was neat in the storage and a riddle in the dialog, where the eight
fields above it are four status/date pairs.
So four keys now — APP_OPSLOG_HAMLOG_SENT / _SENT_DATE and _QSL / _QSL_DATE —
and four fields, in the shape an operator already reads for eQSL, QRZ, Club Log
and HRDLog. The stamp written after a successful upload follows: Y in the
status, the day in the date.
Nothing else changes: the QSL Manager's backlog still asks whether the sent key
is present, and the award engine still treats any non-N value in the QSL key as
a confirmation.
A log sent to hamlog.online by hand — an ADIF exported from OpsLog and dropped
on their site — had no way of being marked as sent afterwards. The QSL Manager
then listed every one of those contacts as backlog and offered to upload them a
second time.
Both HAMLOG keys join the bulk-editable extras, so a selection (or the whole
log) can be stamped in one pass. They are DATES rather than Y/N flags because
that is the shape the sent stamp already uses: the QSL Manager's backlog asks
whether the key is present, and a date also says when it went.
The test pins that they are reachable through the extras path and NOT offered as
columns — a mapping claiming both would write to a table that has neither.
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.
An upload now leaves a trace on the QSO: APP_OPSLOG_HAMLOG_SENT holds the day
it went. The date rather than a Y, so a log says WHEN — and so one shape serves
three readers: eligibility (a stamped QSO is not sent twice), the QSL Manager's
backlog, and the appearance rules' sent channel.
HAMLOG joins the QSL Manager's service list. It has no status column to select
on, so its backlog is the ABSENCE of that extras key — a LIKE over the extras
JSON, which is a full scan and is the right trade here: it answers a button an
operator presses, and the alternative is a promoted column for a field no other
program would ever read. The match is on the quoted key, so a QSO whose comment
merely mentions the text is not taken for one already sent — which is what the
test pins.
HAMLOG.online is now reachable: Settings → External services → HAMLOG.ONLINE
takes the API key, the auto-upload switch and the timing, exactly like the six
services beside it, and a link opens the page where the key is issued.
The button next to it checks the KEY, not the connection. HAMLOG answers
KEYSTATUS with the callsign the key belongs to — something no other service
here offers — so the result reads "Key is valid — account F4BPO" rather than a
green tick. A key pasted from a club account or a second station is visible at
once, which is precisely the mistake a tick would have hidden.
No on-close timing, for the same reason as Cloudlog: there is no per-QSO upload
column to select a backlog from at shutdown, so the option would have done
nothing. Immediate or delayed, and a stored on_close falls back to immediate
rather than silently uploading nothing.
The appearance rules gain a HAMLOG.online channel too, so a row can be coloured
"confirmed" on that alone. It reads the ADIF extras — the standard names a field
for hamlog.EU and none for hamlog.ONLINE — using the same keys the award engine
reads, so the two can never disagree about what a confirmation is. "To send"
skips it: a QSO is either uploaded or not, there is no card to be owed.
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.
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.
Ultrabeam on a serial port never worked, and three faults were stacked so
each hid the next:
- Stop() did not wait for the poll loop, so a stopped client kept the COM
port. Every later client then failed with "Serial port busy" — the
program holding it being OpsLog itself.
- startUltrabeam tore the old client down CONCURRENTLY with starting the
new one, and "Test connection" built a second client on a port already
ours. Harmless over TCP, fatal on a port with one owner.
- A silent serial port returns (0, nil) and bufio retries that a hundred
times: a 4 s timeout became ~7 minutes of a frozen poll loop logging
nothing.
The controller then answered at once. Confirmed on hardware: the USB cable
presents TWO COM ports, only the second reaches the controller, and only at
19200 baud — so the speed is pinned in code (an FTDI cable opens at any
speed, and a wrong one is indistinguishable from a dead controller) and the
port field says which one to pick. The first exchange after each connect is
hex-dumped, which separates silence from a wrong baud from a misread frame.
Databases now carry only the tables their role needs. Every target used to
get the whole migration set, so a shared MySQL logbook grew settings and
station_profiles tables nothing ever wrote to — an operator inspecting the
server could not tell which copy was authoritative. Statements are filtered
by role, unknown tables are kept in both (fail-safe), and existing databases
are cleaned once, dropping only EMPTY tables. Settings → Database gains a
Compact button, since SQLite frees pages inside the file and never shrinks it.
Also:
- Awards: the callsigns behind a cell open the QSL Manager on Paper QSL,
searched, ready for the card dates.
- The record button no longer goes missing after an update: whether manual
recording is possible is a per-profile question that was asked once, at
startup, before the profile was known.
- Alert rules and filter presets confirm that they were saved.
- Spot clicks on the radio panadapter carry the POTA park into F3.
- The build gate is re-checked wherever the active callsign can change; it
ran at startup alone, and a fresh install has no callsign then.
The COM port was a bare text field — the only serial device in the app without
a port list, and typing one by hand gave no clue when it failed.
A Combobox rather than the Select the other devices use, deliberately: the port
of a USB adapter that is not plugged in does not appear in any list, and
refusing a typed value would mean the antenna cannot be configured until the
adapter is in. Detected ports are offered, anything else is still accepted, and
the value is trimmed and upper-cased on the way in.
The failure itself was already logged by the SteppIR client ("cannot open COM7
@ 4800 baud"); what was missing was the line above it not claiming the antenna
had connected. That is fixed separately.
Carries the 0.26.2 changelog entries for this and the three preceding commits —
one file, and splitting it four ways would have said less than this does.
Three faults an operator's log finally made visible, plus the interface
work that came out of the same session.
Reliability:
- UDP events were dropped on backpressure without a word. A period hands
over twenty-odd decodes at once, and one slow write to the radio was
enough to fill the queue — so a decode simply never appeared, and the
only detector was the operator comparing the panel with JTDX. The drop
is now counted and logged, panadapter spots went to their own goroutine
so the radio can no longer hold the decode stream up, and the queue is
deep enough for a full period.
- The CAT manager waited for its poll loop with a bare <-done. A loop
wedged in a serial read then blocked every later restart inside Start,
before it could even try to connect: the rig stayed dead, no line was
written anywhere, and only killing the process recovered it. The wait
is bounded at ten seconds and says what it abandoned and why the next
connect may fail.
- Shutdown had no logging at all, so a hang left nothing to go on and a
process the operator had to kill — which then blocked the restart after
an update. Every step is logged, and a watchdog forces the exit if one
of them never returns.
Auto-call:
- A QSO in progress is now held by OpsLog itself rather than inferred
from the sender's Status. The moment WSJT-X/JTDX dropped the DX call or
the Enable-Tx flag between overs, the exchange looked finished and the
next CQ was answered, interleaving two and then three QSOs on one
slice. Released on log, on halt, on taking over, and by a watchdog.
Cluster console:
- Replies to a command were buried under the spot flood; a Replies
toggle hides the DX spots, which the list above already shows.
- Twelve named command buttons beside the input, configured in
Settings -> Cluster; a button with no command is not drawn.
- Following the tail is now an explicit switch, and sending a command
re-arms it. It used to measure "am I at the bottom" AFTER committing
the new lines, so a ten-line reply looked like the operator had
scrolled up and was never followed — the one case it exists for.
Awards:
- An award can name NO field. The matching controls disappear with it
and only hand-assigned references count, which is the only thing that
can feed a reference like WWBOTA. A test pins that nothing else is
scanned.
- WWBOTA added to the catalogue with its 31 342 references.
Elsewhere: the rotor widget's Stop button acknowledges the press like
the direction presets already did, and the docked band map can be
switched to fit-to-band from its own header.
STATION_CALLSIGN was the one field the option deliberately skipped, on the
grounds that stamping the active call could re-route a mixed-call log.
That protected nothing. The same option already writes this profile's grid,
rig, antenna, city and postal address onto every record it finds blank — it
has assumed "this log is mine" long before it reaches the callsign. And the
thing that actually keeps a multi-op log intact is that a record CARRYING a
station callsign is never touched, which has always been true and still is.
Withholding it only meant the option quietly failed on the one field an
operator goes and checks afterwards, leaving imported QSOs with no station
call at all — invisible in the ADIF they export, and unroutable for LoTW
and Club Log.
Counted and logged: "did it fill the callsign?" is the first question after
an import, and the log is where it gets answered.
The embedded key was registered to XV9Q, not to OpsLog. Not a cosmetic
detail: Club Log identifies the client software by that key, so every
OpsLog upload in the world was attributed to that callsign. Its owner
received the abuse warning OpsLog earned when the on-close sweep was still
posting hundreds of QSOs through the realtime endpoint - and a revocation
aimed at them would have cut Club Log uploads for every user of this
program at once.
G7VJR issued a key for "OpsLog" on request. Same mechanism, same UX: the
key identifies the software, the operator still supplies their own e-mail
and password, so it authorises nothing on its own.
Club Log asks that it not be published in source code. The source is on a
private remote and only the built exe is released, but it remains
recoverable from that binary by anyone who looks - as it is for every
logger that embeds one. It is an identifier that can be attributed, not a
secret.
Extends to frequency and mode what PTT already had. A missing FB is not a
missing command: the rig acts on the frame as it decodes it, and what
expires is our wait for the answer, on a bus shared with the rig's own
transceive updates. JTDX in "Split: Fake It" moves the dial and the mode
immediately before every key-down, so those acks queue behind each other.
Losing one is fatal to the client rather than merely untidy: rigctld answers
RPRT -9, JTDX reads that as losing rig control and tears the connection down
mid-over. An operator's log shows three set_freq failures and one set_mode,
each followed within 300 ms by a fresh rigctld client -- and shows the PTT
resend rescuing an over that would otherwise have ended there.
Opt-in per caller rather than folded into exec: only a command that says
"be in this state" can be repeated safely, and a relative one must never
come through here.
The acknowledgement loss itself is still unexplained. Every failure in that
log is preceded by a state read reporting SSB on a rig in DATA, which points
at CI-V frame desync rather than a slow rig, and needs a trace to pin down.
HTTPS to a relay board could not work. Nearly every board that offers it signs
its own certificate — there is no authority anywhere that could have signed it —
so the request failed verification before it left.
A checkbox, per board, off by default. Not a blanket switch, because the other
HTTPS case is real and opposite: a board reached from outside through a proxy
with a genuine certificate, where verification is the only thing standing
between an antenna switch and the internet. Same setting, two boards, different
answers.
Off by default is only safe if the failure explains itself, so a certificate
error now names the box to tick. Go's own "x509: certificate signed by unknown
authority" is accurate and tells an operator nothing about what to do next.
Shown only once an https:// URL is actually in the board's configuration. A
board on plain HTTP has no certificate to argue about, and an option that cannot
matter yet is one more thing to wonder about.
The flag joins the driver cache key: ticking it has to rebuild the driver, or
the cached one would go on refusing the certificate with the verifying client it
already holds.
The boards that take a bare host — WebSwitch, KMTronic — keep verification. An
https:// typed there is the proxy case by construction, since they default to
plain HTTP on the LAN.
Three tests against a real self-signed TLS server: accepted with the box,
refused with a message naming it without the box, and one board's setting not
leaking into another's.
Two faults in the combiner coupling, both reported from the operating position.
THE POWER LEVEL WAS NEVER COUPLED. ON, OFF and OPERATE fanned out to the group;
L/M/H did not — it was simply the command nobody had linked. Two combined
amplifiers left at different power levels feed the combiner unevenly, which is
the thing the coupling exists to prevent.
THE COMMANDS DID NOT LEAVE TOGETHER. The second amplifier was commanded only
once the first had answered, and an SPE answers over its own link in its own
time. The combiner heard power appear on one input before the other and beeped
about it, on every OFF and every ON.
Each target now gets a goroutine, all parked on one channel until every one is
ready; closing it releases them together. That is the difference between "start
one, then start the other" and "both leave at once" — they have separate clients
and separate connections, so nothing downstream re-serialises them.
It matters most on the power level, which is not one command at all: an SPE has
no "set level", so the driver taps the POWER key and waits for the amp to report
the new one before tapping again — up to three taps, up to two seconds each. One
after the other, the pair would sit at different levels for six seconds.
A single amplifier still runs inline: no goroutine, no barrier, nothing new to
go wrong for the operators who have one amp. The one that was clicked stays
first, because its failure is the one worth reporting.