fix(trx-server): remove unused RigSdr import in rig_task.rs

Also run cargo fmt to fix formatting issues across trx-server,
trx-frontend-http, and trx-configurator.

https://claude.ai/code/session_01RsHUyVz2wjQjsEsxJo5owt
Signed-off-by: Claude <noreply@anthropic.com>
This commit is contained in:
Claude
2026-03-26 12:59:16 +00:00
committed by Stan Grams
parent c8f33b8939
commit a63f27971d
10 changed files with 413 additions and 130 deletions
+61 -17
View File
@@ -217,7 +217,12 @@ fn check_server_sections(
errors: &mut Vec<String>,
) {
if let Some(general) = table.get("general").and_then(|v| v.as_table()) {
check_unknown_keys(general, SERVER_GENERAL_KEYS, &format!("{}[general].", prefix), warnings);
check_unknown_keys(
general,
SERVER_GENERAL_KEYS,
&format!("{}[general].", prefix),
warnings,
);
validate_log_level(general, &format!("{}[general]", prefix), errors);
validate_coordinates(general, &format!("{}[general]", prefix), errors);
}
@@ -225,13 +230,23 @@ fn check_server_sections(
if let Some(rig) = table.get("rig").and_then(|v| v.as_table()) {
check_unknown_keys(rig, RIG_KEYS, &format!("{}[rig].", prefix), warnings);
if let Some(access) = rig.get("access").and_then(|v| v.as_table()) {
check_unknown_keys(access, ACCESS_KEYS, &format!("{}[rig.access].", prefix), warnings);
check_unknown_keys(
access,
ACCESS_KEYS,
&format!("{}[rig.access].", prefix),
warnings,
);
validate_access(access, &format!("{}[rig.access]", prefix), errors);
}
}
if let Some(listen) = table.get("listen").and_then(|v| v.as_table()) {
check_unknown_keys(listen, LISTEN_KEYS, &format!("{}[listen].", prefix), warnings);
check_unknown_keys(
listen,
LISTEN_KEYS,
&format!("{}[listen].", prefix),
warnings,
);
validate_port(listen, "port", &format!("{}[listen]", prefix), errors);
}
@@ -241,7 +256,12 @@ fn check_server_sections(
}
if let Some(behavior) = table.get("behavior").and_then(|v| v.as_table()) {
check_unknown_keys(behavior, BEHAVIOR_KEYS, &format!("{}[behavior].", prefix), warnings);
check_unknown_keys(
behavior,
BEHAVIOR_KEYS,
&format!("{}[behavior].", prefix),
warnings,
);
}
}
@@ -252,21 +272,41 @@ fn check_client_sections(
errors: &mut Vec<String>,
) {
if let Some(general) = table.get("general").and_then(|v| v.as_table()) {
check_unknown_keys(general, CLIENT_GENERAL_KEYS, &format!("{}[general].", prefix), warnings);
check_unknown_keys(
general,
CLIENT_GENERAL_KEYS,
&format!("{}[general].", prefix),
warnings,
);
validate_log_level(general, &format!("{}[general]", prefix), errors);
}
if let Some(remote) = table.get("remote").and_then(|v| v.as_table()) {
check_unknown_keys(remote, REMOTE_KEYS, &format!("{}[remote].", prefix), warnings);
check_unknown_keys(
remote,
REMOTE_KEYS,
&format!("{}[remote].", prefix),
warnings,
);
}
if let Some(frontends) = table.get("frontends").and_then(|v| v.as_table()) {
check_unknown_keys(frontends, FRONTENDS_KEYS, &format!("{}[frontends].", prefix), warnings);
check_unknown_keys(
frontends,
FRONTENDS_KEYS,
&format!("{}[frontends].", prefix),
warnings,
);
if let Some(http) = frontends.get("http").and_then(|v| v.as_table()) {
validate_port(http, "port", &format!("{}[frontends.http]", prefix), errors);
}
if let Some(rigctl) = frontends.get("rigctl").and_then(|v| v.as_table()) {
validate_port(rigctl, "port", &format!("{}[frontends.rigctl]", prefix), errors);
validate_port(
rigctl,
"port",
&format!("{}[frontends.rigctl]", prefix),
errors,
);
}
}
}
@@ -285,12 +325,21 @@ fn validate_log_level(table: &toml_edit::Table, context: &str, errors: &mut Vec<
}
fn validate_coordinates(table: &toml_edit::Table, context: &str, errors: &mut Vec<String>) {
if let Some(lat) = table.get("latitude").and_then(|v| v.as_float().or_else(|| v.as_integer().map(|i| i as f64))) {
if let Some(lat) = table
.get("latitude")
.and_then(|v| v.as_float().or_else(|| v.as_integer().map(|i| i as f64)))
{
if !(-90.0..=90.0).contains(&lat) {
errors.push(format!("{}.latitude {} is out of range (-90..90)", context, lat));
errors.push(format!(
"{}.latitude {} is out of range (-90..90)",
context, lat
));
}
}
if let Some(lon) = table.get("longitude").and_then(|v| v.as_float().or_else(|| v.as_integer().map(|i| i as f64))) {
if let Some(lon) = table
.get("longitude")
.and_then(|v| v.as_float().or_else(|| v.as_integer().map(|i| i as f64)))
{
if !(-180.0..=180.0).contains(&lon) {
errors.push(format!(
"{}.longitude {} is out of range (-180..180)",
@@ -309,12 +358,7 @@ fn validate_coordinates(table: &toml_edit::Table, context: &str, errors: &mut Ve
}
}
fn validate_port(
table: &toml_edit::Table,
key: &str,
context: &str,
errors: &mut Vec<String>,
) {
fn validate_port(table: &toml_edit::Table, key: &str, context: &str, errors: &mut Vec<String>) {
if let Some(port) = table.get(key).and_then(|v| v.as_integer()) {
if let Some(enabled) = table.get("enabled").and_then(|v| v.as_bool()) {
if enabled && port <= 0 {
+8 -2
View File
@@ -12,7 +12,10 @@ use std::path::PathBuf;
use clap::Parser;
#[derive(Parser)]
#[command(name = "trx-configurator", about = "Interactive configuration generator for trx-rs")]
#[command(
name = "trx-configurator",
about = "Interactive configuration generator for trx-rs"
)]
struct Cli {
/// Generate a default config without interactive prompts
#[arg(long)]
@@ -70,7 +73,10 @@ fn main() {
"client" => ConfigType::Client,
"combined" => ConfigType::Combined,
other => {
eprintln!("Unknown config type '{}'. Use: server, client, combined", other);
eprintln!(
"Unknown config type '{}'. Use: server, client, combined",
other
);
std::process::exit(1);
}
}
+5 -1
View File
@@ -51,7 +51,11 @@ pub struct FrontendsSetup {
// ── Prompt functions ────────────────────────────────────────────────────
pub fn prompt_config_type() -> ConfigType {
let items = &["Server (trx-server.toml)", "Client (trx-client.toml)", "Combined (trx-rs.toml)"];
let items = &[
"Server (trx-server.toml)",
"Client (trx-client.toml)",
"Combined (trx-rs.toml)",
];
let sel = Select::new()
.with_prompt("What configuration would you like to generate?")
.items(items)
+182 -45
View File
@@ -16,8 +16,7 @@ use crate::ConfigType;
fn commented(table: &mut Table, key: &str, val: Item, comment: &str) {
table.insert(key, val);
if let Some(mut kv) = table.key_mut(key) {
kv.leaf_decor_mut()
.set_prefix(format!("# {}\n", comment));
kv.leaf_decor_mut().set_prefix(format!("# {}\n", comment));
}
}
@@ -27,24 +26,40 @@ fn header_comment(table: &mut Table, comment: &str) {
// ── Server document builder ─────────────────────────────────────────────
fn build_server_tables(
general: ServerGeneral,
rig: RigSetup,
listen: ListenSetup,
) -> Table {
fn build_server_tables(general: ServerGeneral, rig: RigSetup, listen: ListenSetup) -> Table {
let mut root = Table::new();
// [general]
{
let mut t = Table::new();
header_comment(&mut t, "General settings");
commented(&mut t, "callsign", value(&general.callsign), "Station callsign");
commented(&mut t, "log_level", value(&general.log_level), "Log level (trace, debug, info, warn, error)");
commented(
&mut t,
"callsign",
value(&general.callsign),
"Station callsign",
);
commented(
&mut t,
"log_level",
value(&general.log_level),
"Log level (trace, debug, info, warn, error)",
);
if let Some(lat) = general.latitude {
commented(&mut t, "latitude", value(lat), "Station latitude (decimal degrees, WGS84)");
commented(
&mut t,
"latitude",
value(lat),
"Station latitude (decimal degrees, WGS84)",
);
}
if let Some(lon) = general.longitude {
commented(&mut t, "longitude", value(lon), "Station longitude (decimal degrees, WGS84)");
commented(
&mut t,
"longitude",
value(lon),
"Station longitude (decimal degrees, WGS84)",
);
}
root.insert("general", Item::Table(t));
}
@@ -53,18 +68,38 @@ fn build_server_tables(
{
let mut t = Table::new();
header_comment(&mut t, "Rig backend configuration");
commented(&mut t, "model", value(&rig.model), "Rig model (ft817, ft450d, soapysdr)");
commented(&mut t, "initial_freq_hz", value(144_300_000i64), "Initial frequency in Hz");
commented(
&mut t,
"model",
value(&rig.model),
"Rig model (ft817, ft450d, soapysdr)",
);
commented(
&mut t,
"initial_freq_hz",
value(144_300_000i64),
"Initial frequency in Hz",
);
commented(&mut t, "initial_mode", value("USB"), "Initial mode");
// [rig.access]
let mut access = Table::new();
header_comment(&mut access, "Rig access method");
commented(&mut access, "type", value(&rig.access_type), "Access type: serial, tcp, or sdr");
commented(
&mut access,
"type",
value(&rig.access_type),
"Access type: serial, tcp, or sdr",
);
match rig.access_type.as_str() {
"serial" => {
if let Some(port) = &rig.serial_port {
commented(&mut access, "port", value(port.as_str()), "Serial port path");
commented(
&mut access,
"port",
value(port.as_str()),
"Serial port path",
);
}
if let Some(baud) = rig.serial_baud {
commented(&mut access, "baud", value(baud as i64), "Baud rate");
@@ -80,7 +115,12 @@ fn build_server_tables(
}
"sdr" => {
if let Some(args) = &rig.sdr_args {
commented(&mut access, "args", value(args.as_str()), "SoapySDR device args string");
commented(
&mut access,
"args",
value(args.as_str()),
"SoapySDR device args string",
);
}
}
_ => {}
@@ -93,10 +133,25 @@ fn build_server_tables(
{
let mut t = Table::new();
header_comment(&mut t, "Polling and retry behavior");
commented(&mut t, "poll_interval_ms", value(500i64), "Rig polling interval (ms)");
commented(&mut t, "poll_interval_tx_ms", value(100i64), "Polling interval during TX (ms)");
commented(
&mut t,
"poll_interval_ms",
value(500i64),
"Rig polling interval (ms)",
);
commented(
&mut t,
"poll_interval_tx_ms",
value(100i64),
"Polling interval during TX (ms)",
);
commented(&mut t, "max_retries", value(3i64), "Maximum retry attempts");
commented(&mut t, "retry_base_delay_ms", value(100i64), "Base retry delay (ms)");
commented(
&mut t,
"retry_base_delay_ms",
value(100i64),
"Base retry delay (ms)",
);
root.insert("behavior", Item::Table(t));
}
@@ -105,8 +160,18 @@ fn build_server_tables(
let mut t = Table::new();
header_comment(&mut t, "JSON TCP listener for client connections");
commented(&mut t, "enabled", value(true), "Enable the TCP listener");
commented(&mut t, "listen", value(&listen.listen), "IP address to listen on");
commented(&mut t, "port", value(listen.port as i64), "TCP port for client connections");
commented(
&mut t,
"listen",
value(&listen.listen),
"IP address to listen on",
);
commented(
&mut t,
"port",
value(listen.port as i64),
"TCP port for client connections",
);
root.insert("listen", Item::Table(t));
}
@@ -118,22 +183,34 @@ fn build_server_tables(
commented(&mut t, "listen", value("127.0.0.1"), "Audio listen address");
commented(&mut t, "port", value(4531i64), "Audio TCP port");
commented(&mut t, "sample_rate", value(48000i64), "Sample rate in Hz");
commented(&mut t, "channels", value(2i64), "Channel count (1 = mono, 2 = stereo)");
commented(&mut t, "frame_duration_ms", value(20i64), "Opus frame duration (ms)");
commented(&mut t, "bitrate_bps", value(256000i64), "Opus bitrate (bps)");
commented(
&mut t,
"channels",
value(2i64),
"Channel count (1 = mono, 2 = stereo)",
);
commented(
&mut t,
"frame_duration_ms",
value(20i64),
"Opus frame duration (ms)",
);
commented(
&mut t,
"bitrate_bps",
value(256000i64),
"Opus bitrate (bps)",
);
root.insert("audio", Item::Table(t));
}
root
}
pub fn build_server(
general: ServerGeneral,
rig: RigSetup,
listen: ListenSetup,
) -> DocumentMut {
pub fn build_server(general: ServerGeneral, rig: RigSetup, listen: ListenSetup) -> DocumentMut {
let mut doc = DocumentMut::new();
doc.decor_mut().set_prefix("# trx-server configuration\n# Generated by trx-configurator\n");
doc.decor_mut()
.set_prefix("# trx-server configuration\n# Generated by trx-configurator\n");
let tables = build_server_tables(general, rig, listen);
for (key, item) in tables.iter() {
doc.insert(key, item.clone());
@@ -154,8 +231,18 @@ fn build_client_tables(
{
let mut t = Table::new();
header_comment(&mut t, "General settings");
commented(&mut t, "callsign", value(&general.callsign), "Station callsign");
commented(&mut t, "log_level", value(&general.log_level), "Log level (trace, debug, info, warn, error)");
commented(
&mut t,
"callsign",
value(&general.callsign),
"Station callsign",
);
commented(
&mut t,
"log_level",
value(&general.log_level),
"Log level (trace, debug, info, warn, error)",
);
root.insert("general", Item::Table(t));
}
@@ -163,8 +250,18 @@ fn build_client_tables(
{
let mut t = Table::new();
header_comment(&mut t, "Remote server connection");
commented(&mut t, "url", value(&remote.url), "Server address (host:port)");
commented(&mut t, "poll_interval_ms", value(750i64), "State poll interval (ms)");
commented(
&mut t,
"url",
value(&remote.url),
"Server address (host:port)",
);
commented(
&mut t,
"poll_interval_ms",
value(750i64),
"State poll interval (ms)",
);
let mut auth = Table::new();
if let Some(token) = &remote.token {
@@ -182,26 +279,61 @@ fn build_client_tables(
header_comment(&mut frontends_table, "Frontend configuration");
let mut http = Table::new();
commented(&mut http, "enabled", value(frontends.http_enabled), "Enable HTTP web frontend");
commented(
&mut http,
"enabled",
value(frontends.http_enabled),
"Enable HTTP web frontend",
);
commented(&mut http, "listen", value("127.0.0.1"), "Listen address");
commented(&mut http, "port", value(frontends.http_port as i64), "HTTP port");
commented(
&mut http,
"port",
value(frontends.http_port as i64),
"HTTP port",
);
frontends_table.insert("http", Item::Table(http));
let mut rigctl = Table::new();
commented(&mut rigctl, "enabled", value(frontends.rigctl_enabled), "Enable Hamlib rigctl frontend");
commented(
&mut rigctl,
"enabled",
value(frontends.rigctl_enabled),
"Enable Hamlib rigctl frontend",
);
commented(&mut rigctl, "listen", value("127.0.0.1"), "Listen address");
commented(&mut rigctl, "port", value(frontends.rigctl_port as i64), "rigctl port");
commented(
&mut rigctl,
"port",
value(frontends.rigctl_port as i64),
"rigctl port",
);
frontends_table.insert("rigctl", Item::Table(rigctl));
let mut http_json = Table::new();
commented(&mut http_json, "enabled", value(true), "Enable JSON-over-TCP frontend");
commented(&mut http_json, "listen", value("127.0.0.1"), "Listen address");
commented(
&mut http_json,
"enabled",
value(true),
"Enable JSON-over-TCP frontend",
);
commented(
&mut http_json,
"listen",
value("127.0.0.1"),
"Listen address",
);
commented(&mut http_json, "port", value(0i64), "Port (0 = ephemeral)");
frontends_table.insert("http_json", Item::Table(http_json));
let mut audio = Table::new();
commented(&mut audio, "enabled", value(true), "Enable audio client");
commented(&mut audio, "server_port", value(4531i64), "Server audio port");
commented(
&mut audio,
"server_port",
value(4531i64),
"Server audio port",
);
frontends_table.insert("audio", Item::Table(audio));
root.insert("frontends", Item::Table(frontends_table));
@@ -216,7 +348,8 @@ pub fn build_client(
frontends: FrontendsSetup,
) -> DocumentMut {
let mut doc = DocumentMut::new();
doc.decor_mut().set_prefix("# trx-client configuration\n# Generated by trx-configurator\n");
doc.decor_mut()
.set_prefix("# trx-client configuration\n# Generated by trx-configurator\n");
let tables = build_client_tables(general, remote, frontends);
for (key, item) in tables.iter() {
doc.insert(key, item.clone());
@@ -235,7 +368,8 @@ pub fn build_combined(
frontends: FrontendsSetup,
) -> DocumentMut {
let mut doc = DocumentMut::new();
doc.decor_mut().set_prefix("# trx-rs combined configuration\n# Generated by trx-configurator\n");
doc.decor_mut()
.set_prefix("# trx-rs combined configuration\n# Generated by trx-configurator\n");
let server = build_server_tables(s_general, rig, listen);
let mut server_item = Item::Table(server);
@@ -294,7 +428,9 @@ pub fn build_default(config_type: ConfigType) -> DocumentMut {
match config_type {
ConfigType::Server => build_server(s_general, rig, listen),
ConfigType::Client => build_client(c_general, remote, frontends),
ConfigType::Combined => build_combined(s_general, rig, listen, c_general, remote, frontends),
ConfigType::Combined => {
build_combined(s_general, rig, listen, c_general, remote, frontends)
}
}
}
@@ -312,7 +448,8 @@ pub fn write_file(doc: &DocumentMut, path: &Path) -> Result<(), String> {
}
}
std::fs::write(path, doc.to_string()).map_err(|e| format!("Failed to write {}: {}", path.display(), e))?;
std::fs::write(path, doc.to_string())
.map_err(|e| format!("Failed to write {}: {}", path.display(), e))?;
println!("Wrote {}", path.display());
Ok(())
}