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.
40 lines
1.7 KiB
Go
40 lines
1.7 KiB
Go
package cat
|
|
|
|
// "Serial port busy" is a true statement that helps nobody.
|
|
//
|
|
// A COM port has exactly one owner, and when a rig's port is refused the owner
|
|
// is almost always another program on the same desktop — most often OmniRig,
|
|
// which stays resident once any application has activated it and keeps the port
|
|
// of the rig configured in it. An operator switching from OmniRig to a native
|
|
// backend therefore hits this the moment they save: OpsLog is now asking for a
|
|
// port OmniRig never let go of. The message named none of that.
|
|
//
|
|
// It also happens the other way round, and the wording says so rather than
|
|
// accusing: a digital application (WSJT-X, JTDX, MSHV) configured on the rig's
|
|
// port directly, rather than through OpsLog's CAT sharing, holds it just as
|
|
// firmly.
|
|
|
|
import "strings"
|
|
|
|
// busyHint returns a sentence to append to an open error, or "" when the error
|
|
// is not about the port being taken.
|
|
//
|
|
// Deliberately not a wrapped error: this is advice for a human reading a log,
|
|
// and it must not change how any caller compares the error.
|
|
func busyHint(port string, err error) string {
|
|
if err == nil {
|
|
return ""
|
|
}
|
|
msg := strings.ToLower(err.Error())
|
|
busy := strings.Contains(msg, "busy") ||
|
|
strings.Contains(msg, "access is denied") ||
|
|
strings.Contains(msg, "denied") ||
|
|
strings.Contains(msg, "in use")
|
|
if !busy {
|
|
return ""
|
|
}
|
|
return " — another program holds " + port +
|
|
". OmniRig is the usual one (it stays running and keeps the port of the rig configured in it, so a native backend can never have it);" +
|
|
" a digital application pointed straight at the rig instead of at OpsLog's CAT sharing does the same. Close it, then reconnect."
|
|
}
|