[docs](trx-rs): propose the logbook and the ham radio layout
Issue #54 asks for a ham radio layout and an ADIF logbook, with no detail behind either. This is what they would be: what the logbook has to hold, how it is stored, where ADIF is read and written, and which of the existing parts each half hangs off. Two things it settles before any code is written. The log is append-only JSON Lines rather than the whole-file dump the bookmarks use, because a station with forty thousand QSOs would rewrite megabytes to log one contact and lose the lot if the power went mid-dump. And a decode is not a QSO: the decoders only ever heard something, so a decoded callsign pre-fills an entry and never writes one. The layout is a fifth entry in the operator layouts that already exist, gated on the rig being able to transmit. 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:
@@ -322,3 +322,150 @@ trx-configurator
|
||||
| `trx-app` | Config types and validation | Yes |
|
||||
| `serialport` | Serial port enumeration | Yes (transitive) |
|
||||
| `soapysdr` | SDR device enumeration (optional) | Yes (feature-gated) |
|
||||
|
||||
---
|
||||
|
||||
## Logbook and Ham Radio Layout
|
||||
|
||||
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 on one screen.
|
||||
|
||||
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
|
||||
frequencies, not contacts. Neither is the operator's own log.
|
||||
|
||||
### Requirements
|
||||
|
||||
| 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-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-003 | The system shall allow a logged QSO to be edited and deleted. |
|
||||
| REQ-LOG-004 | The system shall survive a crash without losing a QSO that was recorded before it. |
|
||||
| REQ-LOG-005 | The system shall list, search and filter the log by callsign, band, mode and date range. |
|
||||
| REQ-ADIF-001 | The system shall export the log as an ADIF 3.1.x `.adi` file. |
|
||||
| REQ-ADIF-002 | The system shall import ADIF `.adi` files produced by other logging software, preserving fields it does not itself use. |
|
||||
| REQ-ADIF-003 | When importing, the system shall identify QSOs already held and shall not duplicate them. |
|
||||
| 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-LOG-007 | The system shall show whether a callsign has been worked before, and on which bands. |
|
||||
| REQ-LAY-001 | The system shall offer a "Ham radio" operator layout presenting the transceiver controls and the logbook together. |
|
||||
| REQ-LAY-002 | Where the selected rig cannot transmit, the system shall not offer the ham layout. |
|
||||
|
||||
### A decode is not a QSO
|
||||
|
||||
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
|
||||
by itself — REQ-LOG-006 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.
|
||||
|
||||
### Architecture
|
||||
|
||||
#### New crate: `trx-logbook`
|
||||
|
||||
```
|
||||
src/trx-client/
|
||||
trx-logbook/
|
||||
src/
|
||||
lib.rs # LogbookHandle: open, add, edit, delete, query, import, export
|
||||
qso.rs # Qso: the record, its ADIF field mapping, band/mode helpers
|
||||
adif.rs # ADI reader and writer (pure Rust, no new dependencies)
|
||||
store.rs # Append-only JSON Lines file, in-memory index, compaction
|
||||
dedupe.rs # Worked-before and import-collision rules
|
||||
```
|
||||
|
||||
A library crate under `src/trx-client/`, beside `trx-frontend`, consumed by
|
||||
`trx-frontend-http`. The log belongs to the station rather than to a rig or a frontend, so it
|
||||
sits where any frontend can reach it.
|
||||
|
||||
#### Storage: append-only, not a rewritten blob
|
||||
|
||||
Bookmarks use `PickleDb` with `AutoDump`, which rewrites the whole file on every write. That
|
||||
is right for a few dozen bookmarks and wrong for a log: a station with 40 000 QSOs would
|
||||
rewrite several megabytes to log one contact, and lose the lot if the power went during the
|
||||
dump.
|
||||
|
||||
The log is instead a JSON Lines file — the shape `trx-decode-log` already uses — at
|
||||
`~/.config/trx-rs/logbook.jsonl`, appended one record per write and read into an in-memory
|
||||
index at startup. An edit or a delete appends a new revision of that record's id; the load
|
||||
keeps the last one, and a compaction pass rewrites the file when superseded records exceed a
|
||||
threshold. Appending is O(1) and atomic per line, so a crash costs at most the line being
|
||||
written.
|
||||
|
||||
#### ADIF in-repo
|
||||
|
||||
ADI is a tagged text format: `<FIELD:length>value`, records ended by `<EOR>`, a header ended
|
||||
by `<EOH>`, everything outside a tag ignored. It is small enough to implement exactly, which
|
||||
this project already prefers for its decoders, and doing so keeps the dependency list where it
|
||||
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
|
||||
carried through import to export unchanged, so a round trip through trx-rs does not quietly
|
||||
strip what another logger wrote. ADX (the XML form) is out of scope.
|
||||
|
||||
#### Integration points
|
||||
|
||||
| Source | What it gives the log | How |
|
||||
|--------|----------------------|-----|
|
||||
| `RigState` | `FREQ`, `BAND`, `MODE`/`SUBMODE`, and the rig id a QSO was made on | watch channel already in the frontend context |
|
||||
| Client config `general.callsign` | `STATION_CALLSIGN`, `OPERATOR` | already surfaced as `owner_callsign` in frontend meta |
|
||||
| Rig latitude/longitude | `MY_GRIDSQUARE` | `latLonToMaidenhead`, already in the frontend |
|
||||
| Decoder panels and map | a pre-filled entry: callsign, grid, and the report to offer | existing decode history; no new plumbing |
|
||||
| `bandForHz` | `BAND` from a frequency | exists in `map-core.ts`; move to a shared module |
|
||||
|
||||
#### HTTP API
|
||||
|
||||
| Method | Path | Purpose |
|
||||
|--------|------|---------|
|
||||
| `GET` | `/logbook` | Query: filters, paging |
|
||||
| `POST` | `/logbook` | Add a QSO |
|
||||
| `PUT` | `/logbook/{id}` | Edit |
|
||||
| `DELETE` | `/logbook/{id}` | Delete |
|
||||
| `GET` | `/logbook/export.adi` | Export, honouring the current filter |
|
||||
| `POST` | `/logbook/import` | Import, answering with counts: added, duplicate, rejected |
|
||||
| `GET` | `/logbook/worked/{call}` | Worked-before: bands and modes |
|
||||
|
||||
Writes require the control role, as the rig endpoints do.
|
||||
|
||||
### Frontend
|
||||
|
||||
A **Logbook tab** joins the tab order: an entry form that opens pre-filled, a table with the
|
||||
filters of REQ-LOG-005, and import/export. Worked-before shows against the callsign as it is
|
||||
typed.
|
||||
|
||||
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:
|
||||
|
||||
```ts
|
||||
ham: {
|
||||
label: "Ham radio",
|
||||
unavailable: "Ham radio needs a rig that can transmit",
|
||||
advanced: true, audio: true, scheduler: false,
|
||||
preferredTab: "logbook", capability: "ham",
|
||||
}
|
||||
```
|
||||
|
||||
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
|
||||
spectrum rather than a tab away.
|
||||
|
||||
### Phases
|
||||
|
||||
| Phase | Lands |
|
||||
|-------|-------|
|
||||
| 1 | `trx-logbook`: `Qso`, the ADI reader and writer, round-trip tests against files from other loggers |
|
||||
| 2 | Store, dedupe, and the HTTP API behind the control role |
|
||||
| 3 | Logbook tab: entry, table, filters, import, export |
|
||||
| 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 |
|
||||
|
||||
### Open questions
|
||||
|
||||
- One station log, or one per rig? The proposal assumes one, with the rig id recorded on each
|
||||
QSO, since a callsign worked on the second rig is still worked.
|
||||
- Multiple operators at one station: `OPERATOR` per QSO, or per session?
|
||||
- Clock: the client's or the server's? The server's is proposed — it is the machine at the
|
||||
radio — with the offset shown if the browser disagrees by more than a second.
|
||||
- Should the log file be configurable, or fixed beside the bookmarks?
|
||||
- Import collisions: the proposed key is callsign, band, mode and time to the minute. Contest
|
||||
operators work the same station twice in a minute on different bands, which that key allows;
|
||||
a same-band dupe inside a minute is treated as the same QSO.
|
||||
|
||||
Reference in New Issue
Block a user