[docs](trx-rs): settle the logbook's panel, its prefill, and its formats

Three answers from the issue, folded into the proposal.

The logbook is a panel of its own rather than a strip on the radio page, and
it stands in every layout: a log can be kept without adopting the ham layout,
and read while another is selected.  The ham layout is then the arrangement
that starts from it, with the radio controls around it.

Prefill is exactly six fields — frequency, mode, rig name, time, callsign and
locator — and nothing else.  A signal report in particular stays empty: an
FT8 SNR is not what was sent, and prefilling one would put a number in the
log that nobody exchanged.  The station's own callsign and locator are not
per-entry fields at all; they are station identity, shown once at the top of
the panel and written into the QSO from configuration.

The file format was left to me.  ADIF stays, because it is not one option
among several: LoTW, eQSL, Club Log, QRZ and every other logger read it and
nothing else, so a log that cannot write it cannot be uploaded, confirmed or
moved.  Nothing on disk is ADI regardless — the store is JSON Lines.  The
second format is Cabrillo 3.0, which ADIF cannot replace: contest logs are
submitted in it and rejected in anything else.  It lands with the contest
exchange fields, since without a serial or a zone it has nothing to write.

Refs #54

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SyX26FCpMQxiBoC7r5K1A7
Signed-off-by: Stan Grams <sjg@haxx.space>
This commit is contained in:
sjg
2026-08-07 21:30:10 +02:00
co-authored by Claude Opus 5
parent 76e33a91bb
commit a9e1e86fdc
+82 -29
View File
@@ -328,8 +328,8 @@ trx-configurator
## Logbook and Ham Radio Layout ## Logbook and Ham Radio Layout
Two halves of one feature ([#54](https://git.haxx.space/sjg/trx-rs/issues/54)): a station Two halves of one feature ([#54](https://git.haxx.space/sjg/trx-rs/issues/54)): a station
logbook that speaks ADIF, and an operator layout that puts a transceiver's controls and that logbook in a panel of its own, and an operator layout that puts a transceiver's controls
logbook on one screen. around it.
Nothing in the application records a QSO today. The map's "QSO summary" cards describe Nothing in the application records a QSO today. The map's "QSO summary" cards describe
contacts *between other stations*, reconstructed from decoded traffic; bookmarks are contacts *between other stations*, reconstructed from decoded traffic; bookmarks are
@@ -340,25 +340,49 @@ frequencies, not contacts. Neither is the operator's own log.
| ID | Description | | ID | Description |
|----|-------------| |----|-------------|
| REQ-LOG-001 | The system shall record QSOs the operator makes, each holding at minimum callsign, date, time, band, frequency, mode and both signal reports. | | REQ-LOG-001 | The system shall record QSOs the operator makes, each holding at minimum callsign, date, time, band, frequency, mode and both signal reports. |
| REQ-LOG-002 | When logging a QSO, the system shall pre-fill frequency, band, mode and time from the selected rig, and the station's own callsign and locator from configuration. | | REQ-LOG-002 | When starting a log entry, the system shall pre-fill exactly six fields: frequency, mode, rig name, time, callsign and locator. |
| REQ-LOG-003 | The system shall allow a logged QSO to be edited and deleted. | | REQ-LOG-003 | The system shall leave every other field of a log entry empty for the operator to fill. |
| REQ-LOG-004 | The system shall survive a crash without losing a QSO that was recorded before it. | | REQ-LOG-004 | The system shall allow a logged QSO to be edited and deleted. |
| REQ-LOG-005 | The system shall list, search and filter the log by callsign, band, mode and date range. | | REQ-LOG-005 | The system shall survive a crash without losing a QSO that was recorded before it. |
| REQ-ADIF-001 | The system shall export the log as an ADIF 3.1.x `.adi` file. | | REQ-LOG-006 | The system shall list, search and filter the log by callsign, band, mode and date range. |
| REQ-ADIF-002 | The system shall import ADIF `.adi` files produced by other logging software, preserving fields it does not itself use. | | REQ-LOG-007 | Where a decoded station is on screen, the system shall offer to start a log entry from it, pre-filled, without logging it unattended. |
| REQ-ADIF-003 | When importing, the system shall identify QSOs already held and shall not duplicate them. | | REQ-LOG-008 | The system shall show whether a callsign has been worked before, and on which bands. |
| REQ-LOG-006 | Where a decoded station is on screen, the system shall offer to start a log entry from it, pre-filled, without logging it unattended. | | REQ-FMT-001 | The system shall export the log as an ADIF 3.1.x `.adi` file. |
| REQ-LOG-007 | The system shall show whether a callsign has been worked before, and on which bands. | | REQ-FMT-002 | The system shall import ADIF `.adi` files produced by other logging software, preserving fields it does not itself use. |
| REQ-LAY-001 | The system shall offer a "Ham radio" operator layout presenting the transceiver controls and the logbook together. | | REQ-FMT-003 | When importing, the system shall identify QSOs already held and shall not duplicate them. |
| REQ-LAY-002 | Where the selected rig cannot transmit, the system shall not offer the ham layout. | | REQ-FMT-004 | The system shall export a filtered selection of the log as a Cabrillo 3.0 file for contest submission. |
| REQ-LAY-001 | The system shall present the logbook in a panel of its own, reachable whatever layout is selected. |
| REQ-LAY-002 | The system shall offer a "Ham radio" operator layout presenting the transceiver controls and that panel together. |
| REQ-LAY-003 | Where the selected rig cannot transmit, the system shall not offer the ham layout. |
### A decode is not a QSO ### A decode is not a QSO
The decoders are receive-only: FT8, CW, APRS and the rest report what was *heard*. A heard The decoders are receive-only: FT8, CW, APRS and the rest report what was *heard*. A heard
callsign is the beginning of a log entry, not a contact, and the logbook must never write one callsign is the beginning of a log entry, not a contact, and the logbook must never write one
by itself — REQ-LOG-006 says offer and pre-fill, never auto-log. Digital QSOs made in by itself — REQ-LOG-007 says offer and pre-fill, never auto-log. Digital QSOs made in
WSJT-X or similar arrive the way every other logger takes them: through ADIF import. WSJT-X or similar arrive the way every other logger takes them: through ADIF import.
### What is pre-filled, and what is not
Six fields, and no more (REQ-LOG-002, REQ-LOG-003):
| Field | From | ADIF |
|-------|------|------|
| Frequency | the selected rig's dial | `FREQ`, with `BAND` derived from it |
| Mode | the selected rig | `MODE`, and `SUBMODE` where the mode implies one |
| Rig name | the rig's display name | `MY_RIG` |
| Time | the clock, at the moment the entry opens | `QSO_DATE`, `TIME_ON` |
| Callsign | the decode row or map station the entry was started from, else empty | `CALL` |
| Locator | that station's grid, where the decode carried one, else empty | `GRIDSQUARE` |
Signal reports, power, name, QTH and the rest stay empty. A report in particular is the
operator's to give: an FT8 SNR is not what was sent, and pre-filling one would put a number in
the log that nobody exchanged.
The station's own callsign and locator are not pre-filled per entry either — they are station
identity, taken from configuration when the QSO is written (`STATION_CALLSIGN`, `OPERATOR`,
`MY_GRIDSQUARE`), and shown once at the top of the panel rather than typed into every row.
### Architecture ### Architecture
#### New crate: `trx-logbook` #### New crate: `trx-logbook`
@@ -392,15 +416,35 @@ keeps the last one, and a compaction pass rewrites the file when superseded reco
threshold. Appending is O(1) and atomic per line, so a crash costs at most the line being threshold. Appending is O(1) and atomic per line, so a crash costs at most the line being
written. written.
#### ADIF in-repo #### Two formats, for the two things a log is asked for
ADI is a tagged text format: `<FIELD:length>value`, records ended by `<EOR>`, a header ended The file formats were left open ("pick a well-known ham format"), so: **ADIF for interchange,
by `<EOH>`, everything outside a tag ignored. It is small enough to implement exactly, which Cabrillo for contest submission.** Both are implemented in-repo, in the way this project
this project already prefers for its decoders, and doing so keeps the dependency list where it already implements its decoders, and neither adds a dependency.
is. The reader must be lenient in the ways real files are irregular — lowercase tags, CRLF,
missing header, unknown fields, type indicators — and the writer strict. Unknown fields are **ADIF has to stay.** It is not one option among several — it is the only thing the ecosystem
carried through import to export unchanged, so a round trip through trx-rs does not quietly reads. LoTW, eQSL, Club Log, QRZ.com and every other logger take ADIF and nothing else, so a
strip what another logger wrote. ADX (the XML form) is out of scope. log that cannot write `.adi` cannot be uploaded, confirmed, or moved to another program. That
is a one-way door, and the interoperability is most of the point of keeping a log at all.
Nothing on disk is ADI regardless: the store is JSON Lines, and ADIF is what comes out of an
export.
ADI is a tagged text format — `<FIELD:length>value`, records ended by `<EOR>`, a header ended
by `<EOH>`, everything outside a tag ignored — small enough to implement exactly. The reader
must be lenient in the ways real files are irregular (lowercase tags, CRLF, missing header,
unknown fields, type indicators) and the writer strict. Unknown fields are carried through
import to export unchanged, so a round trip through trx-rs does not quietly strip what another
logger wrote. ADX, the XML serialisation of the same data model, is out of scope: it is part
of the standard but almost nothing reads it.
**Cabrillo is the second format, because ADIF cannot do its job.** Contest logs are submitted
to sponsors in Cabrillo 3.0 and are rejected in anything else — a header of `CALLSIGN:`,
`CONTEST:`, `CATEGORY-*` and `CLAIMED-SCORE:` lines, then one fixed-column `QSO:` line per
contact carrying frequency in kHz, a mode code (`CW`, `PH`, `FM`, `RY`, `DG`), the UTC date and
time, and both stations' calls, reports and exchanges. It is export-only and drops everything
outside the contest's exchange, which is why it complements ADIF rather than replacing it.
It arrives with the contest exchange fields in phase 5, since without a serial or a zone to
put in the exchange there is nothing for it to write.
#### Integration points #### Integration points
@@ -420,7 +464,8 @@ strip what another logger wrote. ADX (the XML form) is out of scope.
| `POST` | `/logbook` | Add a QSO | | `POST` | `/logbook` | Add a QSO |
| `PUT` | `/logbook/{id}` | Edit | | `PUT` | `/logbook/{id}` | Edit |
| `DELETE` | `/logbook/{id}` | Delete | | `DELETE` | `/logbook/{id}` | Delete |
| `GET` | `/logbook/export.adi` | Export, honouring the current filter | | `GET` | `/logbook/export.adi` | ADIF export, honouring the current filter |
| `GET` | `/logbook/export.cbr` | Cabrillo export of a contest selection |
| `POST` | `/logbook/import` | Import, answering with counts: added, duplicate, rejected | | `POST` | `/logbook/import` | Import, answering with counts: added, duplicate, rejected |
| `GET` | `/logbook/worked/{call}` | Worked-before: bands and modes | | `GET` | `/logbook/worked/{call}` | Worked-before: bands and modes |
@@ -428,9 +473,15 @@ Writes require the control role, as the rig endpoints do.
### Frontend ### Frontend
A **Logbook tab** joins the tab order: an entry form that opens pre-filled, a table with the The logbook is **its own panel**, not a strip bolted to the radio page: a `logbook` entry in
filters of REQ-LOG-005, and import/export. Worked-before shows against the callsign as it is the tab order beside Bookmarks, holding the entry form, the table with the filters of
typed. REQ-LOG-006, and import and export. It stands on its own in every layout, so a log can be kept
without adopting the ham layout, and read while another layout is selected (REQ-LAY-001).
The panel is three parts: the station line at the top (own callsign, locator, the rig a QSO
would be logged against), the entry form beneath it opening with the six pre-filled fields,
and the log itself under that, filtered as REQ-LOG-006 asks. Worked-before shows against
the callsign as it is typed.
The **ham layout** is a fifth entry in the operator layouts (`compact`, `broadcast`, `digital`, The **ham layout** is a fifth entry in the operator layouts (`compact`, `broadcast`, `digital`,
`full`), which already gate on capability, seed the disclosure sections and persist per rig: `full`), which already gate on capability, seed the disclosure sections and persist per rig:
@@ -445,8 +496,10 @@ ham: {
``` ```
with the `ham` capability set from `RigCapabilities.tx`. It keeps frequency, VFO, mode, filter, with the `ham` capability set from `RigCapabilities.tx`. It keeps frequency, VFO, mode, filter,
PTT, power and the meters; it hides the broadcast furniture; and it puts the log beside the PTT, power and the meters, and hides the broadcast furniture. What it adds over `full` is where
spectrum rather than a tab away. it starts: the logbook panel, with the radio controls a keystroke away rather than the other
way round — the layout an operator working the bands wants, where logging the contact is the
task and the rig is the instrument.
### Phases ### Phases
@@ -456,7 +509,7 @@ spectrum rather than a tab away.
| 2 | Store, dedupe, and the HTTP API behind the control role | | 2 | Store, dedupe, and the HTTP API behind the control role |
| 3 | Logbook tab: entry, table, filters, import, export | | 3 | Logbook tab: entry, table, filters, import, export |
| 4 | Ham layout, pre-filled entry from a decode row or the map, worked-before | | 4 | Ham layout, pre-filled entry from a decode row or the map, worked-before |
| 5 | Optional: QSL and LoTW/eQSL fields, contest exchange fields, per-band worked/confirmed statistics | | 5 | Contest exchange fields and Cabrillo export; QSL and LoTW/eQSL fields; per-band worked/confirmed statistics |
### Open questions ### Open questions