- Rust 99.4%
- Shell 0.3%
- Just 0.3%
| crates | ||
| docs | ||
| scripts | ||
| vendor | ||
| .gitignore | ||
| .gitmodules | ||
| Cargo.lock | ||
| Cargo.toml | ||
| Justfile | ||
| LICENSE | ||
| README.md | ||
ham-rs
Pure Rust tools for amateur-radio control.
Workspace
| Crate | Purpose |
|---|---|
ham-audio |
Linux PipeWire device discovery and gated voice-audio bridge |
ham-radio |
Vendor-neutral radio types, state, capabilities, and async control trait |
icom-civ |
Icom CI-V frames, streaming decoder, BCD frequencies, and mode encoding |
ic7100 |
IC-7100 command construction and exclusive async serial controller |
mfj-226 |
MFJ-226 PC Mode serial client and documented wire-format types |
mfj-226-cli |
MFJ-226 interactive TUI and one-shot text/JSON automation CLI |
ham-cli |
ham command-line utility and interactive terminal UI |
ham-api |
Reusable Axum router and the hamd HTTP server |
nwr-same |
NOAA Weather Radio channels, stations, and SAME/EAS alert parsing |
The dependency direction is intentionally one-way: applications depend on the radio abstractions and protocol codec, while neither library depends on a UI or network server.
IC-7100 voice console and hamd
The MVP targets Linux with PipeWire and an Icom IC-7100 connected over USB. On Debian-family systems, install the native build dependency first:
sudo apt install libpipewire-0.3-dev
hamd is the sole owner of the IC-7100 serial port. Start it before using the
TUI or command-line radio controls:
just api
In another terminal, start the TUI:
just run
just run has no Hamlib serial preflight or postflight; it is an HTTP client
of hamd. just validate likewise only reads hamd's health and current
radio snapshot. Neither command is evidence that a live radio or audio path
has been verified.
First-run TUI setup selects only PipeWire audio endpoints and stores stable
audio IDs in ~/.config/ham-rs/config.toml. It does not discover, select, or
open a serial port. Older config files may retain a [radio] table; it is
ignored for compatibility. Run ham tui --setup to repeat audio selection.
Inside the console, W applies and reads back the WX4EMA VHF FM preset
(147.015 MHz, +600 kHz, 88.5 Hz), A arms transmit, Space toggles PTT, and X
forces receive. PTT remains opt-in on the hamd host and requires a live
WebSocket control session; hamd enforces a 60-second continuous key-down
ceiling. See the ham-api README for the API and
PTT requirements.
Press Tab to open the receive-only NWR / SAME tab. Use Up/Down and Enter to
tune and save one of the seven NOAA Weather Radio channels, or press S to scan
all seven and save the channel with the strongest reading from hamd's
GET /v1/radio/s-meter endpoint. The saved channel is restored when the tab is
opened on a later run. The
tab records the IC-7100 receive audio in durable 12-second WAV chunks and shows
a slightly delayed, local Whisper transcription. It also demodulates the SAME
AFSK data directly: watch alerts turn the NWR outline yellow, warnings turn it
red, and the SAME end-of-message clears the alert outline.
NWR sessions are stored under $XDG_STATE_HOME/ham-rs/recordings (or
~/.local/state/ham-rs/recordings) with chunk-NNN.wav, transcript.md, and
alerts.jsonl files. The first chunk triggers a one-time download of the
checksum-verified base.en Whisper model. Set HAM_RS_WHISPER_MODEL to use a
local model; MEETRS_MODEL and a verified model in ~/.meetrs/models are also
reused automatically.
The receive-only Digital / FT8 tab starts the local FT8/FT4 decoder on the
saved IC-7100 PipeWire input, shows 15-second-cycle diagnostics and recent
decodes, and releases the capture stream when the tab is left. C clears the
decode history. Automated tests use fakes and local test servers; they do not
verify a live radio, audio path, decode, or transmission.
ham scan and ham tune
Alongside the interactive console, ham exposes commands for sweeping and
tuning through the running hamd hardware owner. There is no direct-serial
fallback and no --direct option.
ham scan <BAND>
Asks hamd to sweep one of ten HF band presets (160m, 80m, 60m, 40m,
30m, 20m, 17m, 15m, 12m, 10m) in --step-hz increments (default
5000, range 1–1000000). Progress and terminal results arrive through the
scan SSE stream:
cargo run -p ham-cli -- scan 20m
cargo run -p ham-cli -- scan 20m --step-hz 2000 --json
S-meter readings are the radio's raw 0-255 scale, not the S1-S9+ scale
printed on the front panel. --threshold (default 15) flags readings above
the sweep's mean. Ctrl-C asks hamd to cancel the scan; because hamd owns
the transaction, it performs scan cleanup and restoration server-side.
ham scan <BAND> --listen [--listen-above N]
--listen asks hamd to stop at the first reading above --listen-above
(default 60) and tune there.
cargo run -p ham-cli -- scan 20m --listen
cargo run -p ham-cli -- scan 20m --listen --listen-above 80
--listen-above is an absolute raw S-meter floor (0-255), unlike
--threshold, which is relative to the sweep's mean. hamd classifies hits
and reports whether it snapped onto a digital dial frequency. A successful
listen hit is deliberately left tuned; other terminal scan outcomes are
handled by the daemon's cleanup path.
ham tune <FREQ_HZ> [--mode MODE]
Asks hamd to tune to a frequency, in hertz, and leaves the radio there:
cargo run -p ham-cli -- tune 14074000 --mode usb-data
cargo run -p ham-cli -- tune 1840000
The client defaults to http://127.0.0.1:8080. Override it with
HAM_API_ADDR (an address or full base URL) and set HAM_API_TOKEN when
hamd requires bearer authentication. The same values can be stored in the
config file:
[api]
address = "radio-host:8080"
token = "replace-with-the-shared-token"
Environment variables take priority over the config file. ham scan, ham tune, and the TUI all use this API client; none opens the configured serial
port.
--mode accepts lsb, usb, am, cw, rtty, fm, wfm, cw-r,
rtty-r, dv, usb-data, and lsb-data. With no mode, mode selection and
any digital-dial snapping are server-side decisions. ham tune deliberately
leaves the radio tuned where requested.
Development
cargo fmt --all --check
cargo clippy --workspace --all-targets
cargo test --workspace
Try the command-line tools:
cargo run -p ham-cli -- info
cargo run -p ham-cli -- tui --help
Run the API server on its default loopback address, 127.0.0.1:8080:
cargo run -p ham-api --bin hamd
curl http://127.0.0.1:8080/health
curl http://127.0.0.1:8080/v1/radio
Override the listener with HAM_API_ADDR.