diff --git a/DECISIONS.md b/DECISIONS.md index ac8048e..99c677a 100644 --- a/DECISIONS.md +++ b/DECISIONS.md @@ -22,6 +22,23 @@ Format: `YYYY-MM-DD: ` - 2026-06-14: Aesthetic = industrial instrument faceplate (amber VFD via DSEG7 font, LED S-meter, illuminated mode buttons) — matches the radio-gear domain and the Sethian dark/orange brand. Verified by headless screenshot. +- 2026-06-14: RepeaterBook integration — local `repeaters.json` + a proximity-ordered + panel "Repeaters" card; tapping a row tunes the radio (freq + duplex + tone) over + CI-V. Operating convenience without per-request API calls. +- 2026-06-14: CSV-only data path (dropped the token-gated API client + systemd timer). + RepeaterBook's API is now auth-gated (`401 auth_missing`, manual app-token approval); + Seth supplied a CSV proximity export instead, so manual re-ingest is enough (YAGNI). +- 2026-06-14: No lat/long in the CSV → rank by file order (RepeaterBook's own proximity + sort) instead of haversine. The export is already nearest-first; geocoding is overkill. +- 2026-06-14: Mixed FM+DSTAR repeaters labeled FM (operable as analog now); pure DSTAR + labeled DV (freq/offset only — call routing is set on the head). +- 2026-06-14: **Live CI-V verification of repeater commands.** Verified on the rig: + duplex direction `0x0F` (read → 0x10 simplex), repeater tone `0x1B/00`, tone-switch + `0x16/42`. The tone field is 3 bytes on the wire (`00` pad + 2-byte BCD, e.g. + `00 08 85` = 88.5 Hz) — radio.py adds/strips the pad. A full `tune_repeater` to a live + repeater ACKed every step. Offset *amount* cmd `0x0D` is **rejected (NG)** by the + ID-5100 → removed; the radio applies its configured auto-offset when a duplex + direction is selected, so standard (0.6/5 MHz) repeaters work from duplex alone. ## Deferred / Rejected @@ -33,3 +50,10 @@ Format: `YYYY-MM-DD: ` as trusted until confirmed against the manual's CI-V table or the live rig. - **RS-MS1A data-jack protocol (D-STAR DR/callsign/messaging)** — out of scope for this CI-V layer; separate effort if wanted. +- **RepeaterBook API client + daily systemd refresh** — deferred (CSV-only chosen); + revive if hands-off refresh is wanted. The token-request form text is in the design + spec under `docs/superpowers/specs/`. +- **CI-V offset-amount control** — rejected: the ID-5100 NGs cmd `0x0D`. Offset amount + is a radio-side config (auto-offset); only direction (DUP±) is settable over CI-V. +- **Distance/haversine ranking** — rejected for the CSV path: the export has no + lat/long and is already proximity-sorted, so file order is the rank. diff --git a/README.md b/README.md index e9ef7c5..86758c1 100644 --- a/README.md +++ b/README.md @@ -42,6 +42,28 @@ is up** (one process owns `/dev/ttyUSB0`). The page polls `/api/status` ~1/s for live frequency, mode, S-meter, squelch, and levels; controls POST to `/api/{freq,mode,vol,sql}`. +## Repeaters (RepeaterBook CSV) + +The panel's **Repeaters** card lists nearby repeaters from a local `repeaters.json`, +in RepeaterBook's proximity order, and tunes the radio (freq + duplex + tone) on tap. + +```bash +# refresh the data: drop a new CSV into repeaterbook/, then re-ingest +python3 repeaters.py ingest repeaterbook/RB_2606141409.csv repeaters.json +``` + +- **Data source:** a RepeaterBook CSV proximity export (download from your account for + your area). It has no lat/long, but it's sorted nearest-first, so row order is the rank. +- **Filter:** keeps FM + D-STAR on 2m/70cm (drops DMR/P25/NXDN-only). ~1073 of 1258 rows. +- **API:** `GET /api/repeaters?q=&limit=` (search + nearest-first list); + `POST /api/tune-repeater` (body = one record) → per-step result + `{ok, steps:{freq,duplex,tone_freq,tone_on}, errors}`. +- **Offset:** the offset *amount* is **not** set over CI-V (the ID-5100 rejects it); + only the duplex *direction* (DUP±) is sent, and the radio applies its own configured + offset (standard 0.6/5 MHz). Non-standard offsets are set on the radio head. +- **D-STAR:** DV rows tune freq/direction only — call routing (URCALL/RPT1/RPT2) is the + separate RS-MS1A protocol, set on the head. + ## Library ```python @@ -67,6 +89,10 @@ python3 -m unittest test_civ -v - **Frequency BCD is little-endian; level/meter BCD is big-endian** (`128 -> 01 28`). - **Mode FM = 0x05** confirmed empirically. `DV = 0x17` is from the generic ICOM table and **not yet verified on this radio** — confirm before relying on it. +- **Repeater commands (verified live 2026-06-14):** duplex direction `0x0F` + (0x10 simplex / 0x11 DUP− / 0x12 DUP+), repeater tone `0x1B/0x00`, tone on/off + `0x16/0x42`. The tone wire field is **3 bytes** (`00` pad + 2-byte BCD; `00 08 85` + = 88.5 Hz). **Offset-amount `0x0D` is rejected (NG)** by the ID-5100 — not supported. - Scope is CI-V (operate the radio). D-STAR DR routing / callsign entry live in the separate RS-MS1A data-jack protocol, not here. ``` diff --git a/docs/screenshots/repeaters-panel.png b/docs/screenshots/repeaters-panel.png new file mode 100644 index 0000000..017d41f Binary files /dev/null and b/docs/screenshots/repeaters-panel.png differ