docs: update overview and sample config

This commit is contained in:
2026-01-18 09:24:16 +01:00
parent bceb049e0e
commit ee25271275
3 changed files with 441 additions and 1 deletions
+334
View File
@@ -0,0 +1,334 @@
# trx-rs Project Overview
## What is trx-rs?
**trx-rs** is a modular transceiver (radio) control stack written in Rust. It provides a backend service for controlling amateur radio transceivers via CAT (Computer-Aided Transceiver) protocols, with multiple frontend interfaces for access and monitoring.
### Current Capabilities
| Feature | Status |
|---------|--------|
| Yaesu FT-817 CAT control | Implemented |
| HTTP/Web UI with SSE | Implemented |
| rigctl-compatible TCP | Implemented |
| VFO A/B switching | Implemented |
| PTT control | Implemented |
| Signal/TX power metering | Implemented |
| Front panel lock | Implemented |
| Multiple rig backends | Extensible (only FT-817) |
| Backend/frontend registry | Implemented |
| TCP CAT transport | Partial (config wiring only) |
| JSON TCP control (line-delimited) | Implemented (configurable frontend) |
| Plugin registry loading | Implemented (shared libraries) |
| Qt/QML GUI frontend | In progress (Linux only, optional) |
| Configuration file (TOML) | Implemented |
| Rig state machine | Implemented |
| Command handlers | Implemented |
| Event notifications | Implemented (rig task emits events) |
| Retry/polling policies | Implemented |
| Controller-based rig task | Implemented |
---
## Current Architecture
```
┌──────────────────────────────────────────────────────────────────────────┐
│ trx-bin │
│ ┌────────────────────────────────────────────────────────────────────┐ │
│ │ Application │ │
│ │ ┌──────────────┐ ┌──────────────┐ ┌──────────────────────────┐ │ │
│ │ │ Config │ │ CLI │ │ Rig Task │ │ │
│ │ │ (TOML file) │ │ (clap) │ │ (main loop) │ │ │
│ │ └──────────────┘ └──────────────┘ └──────────────────────────┘ │ │
│ └────────────────────────────────────────────────────────────────────┘ │
│ │ │
│ ┌───────────────────┴───────────────────┐ │
│ ▼ ▼ │
│ ┌─────────────────────┐ ┌─────────────────────┐ │
│ │ trx-core │ │ Frontend Layer │ │
│ │ ┌───────────────┐ │ │ ┌───────────────┐ │ │
│ │ │ controller/ │ │ │ │ HTTP │ │ │
│ │ │ - machine │ │ │ │ (REST+SSE) │ │ │
│ │ │ - handlers │ │ │ └───────────────┘ │ │
│ │ │ - events │ │ │ ┌───────────────┐ │ │
│ │ │ - policies │ │ │ │ HTTP JSON │ │ │
│ │ └───────────────┘ │ │ │ (TCP/JSON) │ │ │
│ └─────────────────────┘ │ └───────────────┘ │ │
│ │ │ ┌───────────────┐ │ │
│ │ │ │ rigctl │ │ │
│ │ │ │ (TCP/hamlib) │ │ │
│ │ │ └───────────────┘ │ │
│ │ └─────────────────────┘ │
│ ▼ │
│ ┌─────────────────────┐ │
│ │ trx-backend │ │
│ │ ┌───────────────┐ │ │
│ │ │ FT-817 Driver │ │ │
│ │ └───────────────┘ │ │
│ └─────────────────────┘ │
└──────────────────────────────────────────────────────────────────────────┘
```
### Key Components
| Component | Purpose |
|-----------|---------|
| `trx-core` | Core types, traits (`Rig`, `RigCat`), state definitions, controller components |
| `trx-core/rig/controller` | State machine, command handlers, event system, policies |
| `trx-backend` | Backend factory and abstraction layer |
| `trx-backend-ft817` | FT-817 CAT protocol implementation |
| `trx-frontend` | Frontend trait (`FrontendSpawner`) |
| `trx-frontend-http` | Web UI with REST API and SSE |
| `trx-frontend-http-json` | JSON-over-TCP control frontend |
| `trx-frontend-qt` | Qt/QML GUI frontend (Linux only, optional) |
| `trx-frontend-rigctl` | Hamlib rigctl-compatible TCP interface |
| `trx-bin` | Main executable with config file support |
---
## Configuration
trx-rs supports TOML configuration files with the following search order:
1. `--config <path>` (explicit CLI argument)
2. `./trx-rs.toml` (current directory)
3. `~/.config/trx-rs/config.toml` (XDG user config)
4. `/etc/trx-rs/config.toml` (system-wide)
CLI arguments override config file values.
Plugin discovery:
- Uses shared libraries with a `trx_register` entrypoint.
- Searches `./plugins`, `~/.config/trx-rs/plugins`, and any paths in `TRX_PLUGIN_DIRS`.
Qt remote client:
- Uses JSON TCP (`frontends.http_json`) with optional bearer tokens.
- Configure the client with `frontends.qt.remote.enabled/url/auth.token`.
### Example Configuration
```toml
[general]
callsign = "N0CALL"
[rig]
model = "ft817"
initial_freq_hz = 144300000
initial_mode = "USB"
[rig.access]
type = "serial"
port = "/dev/ttyUSB0"
baud = 9600
[frontends.http]
enabled = true
listen = "127.0.0.1"
port = 8080
[frontends.rigctl]
enabled = true
listen = "127.0.0.1"
port = 4532
[frontends.http_json]
enabled = true
listen = "127.0.0.1"
port = 9000
auth.tokens = ["demo-token"]
[frontends.qt]
enabled = false
remote.enabled = true
remote.url = "127.0.0.1:9000"
remote.auth.token = "demo-token"
[behavior]
poll_interval_ms = 500
poll_interval_tx_ms = 100
max_retries = 3
retry_base_delay_ms = 100
```
Use `trx-bin --print-config` to generate an example configuration.
---
## Rig Controller Components
Located in `trx-core/src/rig/controller/`:
### State Machine (`machine.rs`)
Explicit state machine for rig lifecycle management:
```rust
pub enum RigMachineState {
Disconnected,
Connecting { started_at: Option<u64> },
Initializing { rig_info: Option<RigInfo> },
PoweredOff { rig_info: RigInfo },
Ready(ReadyStateData),
Transmitting(TransmittingStateData),
Error { error: RigStateError, previous_state: Box<RigMachineState> },
}
```
Events trigger state transitions:
- `RigEvent::Connected`, `Initialized`, `PoweredOn`, `PoweredOff`
- `RigEvent::PttOn`, `PttOff`
- `RigEvent::Error(RigStateError)`, `Recovered`, `Disconnected`
### Command Handlers (`handlers.rs`)
Trait-based command system with validation:
```rust
pub trait RigCommandHandler: Debug + Send + Sync {
fn name(&self) -> &'static str;
fn can_execute(&self, ctx: &dyn CommandContext) -> ValidationResult;
fn execute<'a>(&'a self, executor: &'a mut dyn CommandExecutor)
-> Pin<Box<dyn Future<Output = DynResult<CommandResult>> + Send + 'a>>;
}
```
Implemented commands:
- `SetFreqCommand`, `SetModeCommand`, `SetPttCommand`
- `PowerOnCommand`, `PowerOffCommand`
- `ToggleVfoCommand`, `LockCommand`, `UnlockCommand`
- `GetTxLimitCommand`, `SetTxLimitCommand`, `GetSnapshotCommand`
The rig task (`trx-bin/src/rig_task.rs`) now syncs the state machine to the live `RigState`
and emits events whenever rig status changes.
### Event Notifications (`events.rs`)
Typed event system for rig state changes:
```rust
pub trait RigListener: Send + Sync {
fn on_frequency_change(&self, old: Option<Freq>, new: Freq);
fn on_mode_change(&self, old: Option<&RigMode>, new: &RigMode);
fn on_ptt_change(&self, transmitting: bool);
fn on_state_change(&self, old: &RigMachineState, new: &RigMachineState);
fn on_meter_update(&self, rx: Option<&RigRxStatus>, tx: Option<&RigTxStatus>);
fn on_lock_change(&self, locked: bool);
fn on_power_change(&self, powered: bool);
}
pub struct RigEventEmitter {
// Manages listeners and dispatches events
}
```
### Policies (`policies.rs`)
Configurable retry and polling behavior:
```rust
pub trait RetryPolicy: Send + Sync {
fn should_retry(&self, attempt: u32, error: &RigError) -> bool;
fn delay(&self, attempt: u32) -> Duration;
fn max_attempts(&self) -> u32;
}
pub trait PollingPolicy: Send + Sync {
fn interval(&self, transmitting: bool) -> Duration;
fn should_poll(&self, transmitting: bool) -> bool;
}
```
Implementations:
- `ExponentialBackoff` - Exponential delay with max cap
- `FixedDelay` - Constant delay between retries
- `NoRetry` - Fail immediately
- `AdaptivePolling` - Faster polling during TX
- `FixedPolling` - Constant interval
- `NoPolling` - Disable automatic polling
### Error Types
`RigError` now includes error classification:
```rust
pub struct RigError {
pub message: String,
pub kind: RigErrorKind, // Transient or Permanent
}
impl RigError {
pub fn timeout() -> Self; // Transient
pub fn communication(msg) -> Self; // Transient
pub fn invalid_state(msg) -> Self; // Permanent
pub fn not_supported(op) -> Self; // Permanent
pub fn is_transient(&self) -> bool;
}
```
---
## Remaining Improvement Opportunities
### Integration Work
1. **Plugin UX improvements** - Add structured plugin metadata (name, version, capabilities) and surface it in CLI help.
### Testing
- Add integration tests with mock backends
- Add more backend/frontend unit tests
### Features
- Add more rig backends (IC-7300, TS-590, etc.)
- Add TX limit support for FT-817 (or document per-backend constraints in UI)
- Add WebSocket support for bidirectional communication
- Add metrics/telemetry export (Prometheus)
- Add authentication for HTTP frontend
### Code Quality
- Add CI/CD pipeline
- Add pre-commit hooks
---
## Implementation Status
| Component | Status | Tests |
|-----------|--------|-------|
| State Machine | Implemented | 5 tests |
| Command Handlers | Implemented | 3 tests |
| Event Notifications | Implemented | 2 tests |
| Retry/Polling Policies | Implemented | 5 tests |
| Config File Support | Implemented | 4 tests |
| rigctl Frontend | Implemented | - |
| HTTP Frontend | Implemented | - |
| FT-817 Backend | Implemented | - |
**Total: 19 unit tests passing**
---
## Building and Running
```bash
# Build
cargo build --release
# Run with CLI args
./target/release/trx-bin -r ft817 "/dev/ttyUSB0 9600"
# Run with config file
./target/release/trx-bin --config /path/to/config.toml
# Print example config
./target/release/trx-bin --print-config > trx-rs.toml
# Run tests
cargo test
# Run clippy
cargo clippy
```
+28 -1
View File
@@ -4,13 +4,40 @@
# trx-rs (work in progress)
This is an early, untested snapshot of a transceiver control stack (core + backend + HTTP frontend). Things may change quickly and APIs are not stable yet. Expect rough edges and bugs; use at your own risk and please report issues you hit. Features, tests and docs are still being written (or not).
This is an early, untested snapshot of a transceiver control stack (core + backend + frontends). Things may change quickly and APIs are not stable yet. Expect rough edges and bugs; use at your own risk and please report issues you hit. Features, tests and docs are still being written (or not).
The rig task is now driven by the controller components (state machine, handlers, and policies). Polling and retry behavior are configurable via the `[behavior]` section in the config file.
## Supported backends
- Yaesu FT-817 (feature-gated crate `trx-backend-ft817`)
- Planned: other rigs I own; contributions and reports are welcome.
## Frontends
- HTTP status/control frontend (`trx-frontend-http`)
- JSON TCP control frontend (`trx-frontend-http-json`)
- Qt/QML GUI frontend (`trx-frontend-qt`, Linux only, optional via `qt-frontend` feature)
- rigctl-compatible TCP frontend (`trx-frontend-rigctl`, listens on 127.0.0.1:4532)
## Plugin discovery
`trx-bin` can load shared-library plugins that register backends/frontends via a
`trx_register` entrypoint. Search paths:
- `./plugins`
- `~/.config/trx-rs/plugins`
- `TRX_PLUGIN_DIRS` (path-separated)
Example plugin: `examples/trx-plugin-example`
## Qt remote client
The Qt frontend can run as a remote client over the JSON TCP interface.
Configure the server with `frontends.http_json.auth.tokens` and the client with
`frontends.qt.remote.enabled`, `frontends.qt.remote.url`, and
`frontends.qt.remote.auth.token`.
## License
This project is licensed under the BSD-2-Clause license. See `LICENSES/` for bundled third-party license files.
+79
View File
@@ -0,0 +1,79 @@
# trx-rs Configuration File
#
# Copy this file to one of:
# ./trx-rs.toml (current directory)
# ~/.config/trx-rs/config.toml (user config)
# /etc/trx-rs/config.toml (system-wide)
#
# Or specify a custom path with: trx-bin --config /path/to/config.toml
#
# CLI arguments override config file values.
[general]
# Callsign or station identifier displayed in frontends
callsign = "N0CALL"
# Log level: trace, debug, info, warn, error
# log_level = "info"
[rig]
# Rig model: ft817 (more models coming)
model = "ft817"
# Initial frequency (Hz) before first CAT read
initial_freq_hz = 144300000
# Initial mode before first CAT read (LSB, USB, CW, CWR, AM, WFM, FM, DIG, PKT)
initial_mode = "USB"
[rig.access]
# Access type: "serial" or "tcp"
type = "serial"
# Serial port settings (when type = "serial")
port = "/dev/ttyUSB0"
baud = 9600
# TCP settings (when type = "tcp")
# host = "192.168.1.100"
# tcp_port = 4532
[frontends.http]
# Enable HTTP/REST frontend with SSE for real-time updates
enabled = true
listen = "127.0.0.1"
port = 8080
[frontends.rigctl]
# Enable rigctl-compatible TCP interface (hamlib compatible)
enabled = false
listen = "127.0.0.1"
port = 4532
[frontends.http_json]
# Enable JSON-over-TCP control interface
enabled = true
listen = "127.0.0.1"
# Set to 0 to bind an ephemeral port
port = 0
# List of accepted bearer tokens (empty = no auth)
# auth.tokens = ["example-token"]
[frontends.qt]
# Enable Qt/QML GUI frontend (Linux only, requires system Qt6)
enabled = false
# Use remote JSON TCP server instead of local rig task
# remote.enabled = true
# remote.url = "127.0.0.1:9000"
# remote.auth.token = "example-token"
[behavior]
# Polling interval when idle (milliseconds)
poll_interval_ms = 500
# Polling interval when transmitting (milliseconds)
poll_interval_tx_ms = 100
# Maximum retry attempts for transient errors
max_retries = 3
# Base delay for exponential backoff (milliseconds)
retry_base_delay_ms = 100