From 7c02b20cf7368cbe1d7ea6a90aa677b65fd11060 Mon Sep 17 00:00:00 2001 From: Luca Cireddu Date: Fri, 26 Dec 2025 18:08:15 +0100 Subject: [PATCH 1/5] fix(program): Align code with new library --- Cargo.toml | 22 +++++++++---------- src/config.rs | 10 +++++++++ src/main.rs | 59 ++++++++++++++++++++++++++++++++------------------- 3 files changed, 58 insertions(+), 33 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 109857b..fde5216 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,15 +9,15 @@ keywords = ["wavelog", "hamlib", "adif", "tokio", "reqwest"] edition = "2021" [dependencies] -chrono = { version = "0.4.38", features = ["serde"] } -clap = { version = "4.5.17", features = ["cargo", "color", "derive", "env", "unicode"] } -hamlib-client = "1.0.0" +chrono = { version = "0.4.42", features = ["serde"] } +clap = { version = "4.5.53", features = ["cargo", "color", "derive", "env", "unicode"] } +hamlib-client = "1.1.0" lazy_static = "1.5.0" -log = "0.4.22" -log4rs = "1.3.0" -regex = "1.10.6" -reqwest = { version = "0.12.7", features = ["json"] } -serde = { version = "1.0.210", features = ["derive"] } -serde_json = { version = "1.0.128", features = ["std"] } -thiserror = "1.0.63" -tokio = { version = "1.40.0", features = ["full"] } +log = "0.4.29" +log4rs = "1.4.0" +regex = "1.12.2" +reqwest = { version = "0.12.28", features = ["json"] } +serde = { version = "1.0.228", features = ["derive"] } +serde_json = { version = "1.0.147", features = ["std"] } +thiserror = "1.0.69" +tokio = { version = "1.48.0", features = ["full"] } diff --git a/src/config.rs b/src/config.rs index 2f31e43..0ba9d7a 100644 --- a/src/config.rs +++ b/src/config.rs @@ -110,4 +110,14 @@ pub struct Config { long_help = "Set the name of Satellite (empty values disable Sat Mode)" )] pub sat: String, + + #[arg( + short = 'm', + long, + action = ArgAction::Set, + default_value = "", + help = "Froce mode", + long_help = "Force the mode reported (empty values is the same of not setting this option)" + )] + pub force_mode: String, } diff --git a/src/main.rs b/src/main.rs index f727c30..091e010 100644 --- a/src/main.rs +++ b/src/main.rs @@ -14,8 +14,8 @@ * */ -mod errors; mod config; +mod errors; mod logging; mod wavelog; @@ -44,10 +44,19 @@ async fn main() { } async fn program(configuration: &Config) -> Result<(), WavelogHamlibError> { - log::trace!("Creating Wavelog client for {} with radio name \"{}\"", &configuration.wavelog_url, configuration.wavelog_radio); - let wavelog_client = wavelog::Client::new(&configuration.wavelog_url, &configuration.wavelog_key); - - log::trace!("Creating client for {}:{}", &configuration.rigctl_host, configuration.rigctl_port); + log::trace!( + "Creating Wavelog client for {} with radio name \"{}\"", + &configuration.wavelog_url, + configuration.wavelog_radio + ); + let wavelog_client = + wavelog::Client::new(&configuration.wavelog_url, &configuration.wavelog_key); + + log::trace!( + "Creating client for {}:{}", + &configuration.rigctl_host, + configuration.rigctl_port + ); let mut rigctl = RigCtlClient::new(&configuration.rigctl_host, configuration.rigctl_port, None); rigctl.set_communication_timeout(configuration.rigctl_timeout); @@ -67,27 +76,33 @@ async fn program(configuration: &Config) -> Result<(), WavelogHamlibError> { let tx_vfo = split_vfo.tx_vfo; log::debug!("TX vfo: {}", &tx_vfo); - let rx_mode = rigctl.get_mode(rx_vfo).await?; - log::trace!("{}: {}", &rx_vfo, &rx_mode); + let force_mode = Mode::from(&configuration.force_mode.as_str()); + log::debug!("Force mode: {}", &force_mode); + + let (rx_mode, tx_mode) = if force_mode == Mode::None { + let rx_mode = rigctl.get_mode(rx_vfo).await?; + let tx_mode = rigctl.get_mode(rx_vfo).await?; + (Mode::from(rx_mode.mode), Mode::from(tx_mode.mode)) + } else { + (force_mode, force_mode) + }; + log::trace!("{} Mode: {}", &rx_vfo, &rx_mode); + log::trace!("{} Mode: {}", &tx_vfo, &tx_mode); + let rx_freq = rigctl.get_freq(rx_vfo).await?; log::trace!("{}: {}", &rx_vfo, &rx_freq); - - let tx_mode = rigctl.get_split_mode(rx_vfo).await?; - log::trace!("{}: {}", &tx_vfo, &tx_mode); - let tx_freq = rigctl.get_split_freq(rx_vfo).await?; + let tx_freq = rigctl.get_freq(tx_vfo).await?; log::trace!("{}: {}", &tx_vfo, &tx_freq); - let update_prop_mode = - if !&configuration.sat.is_empty() { - log::debug!("Enabling SAT propagation mode"); - Some(PropagationMode::SAT) - } else { - None - }; + let update_prop_mode = if !&configuration.sat.is_empty() { + log::debug!("Enabling SAT propagation mode"); + Some(PropagationMode::SAT) + } else { + None + }; let update_tx_freq = - if &configuration.sat == "QO-100" - && tx_freq.frequency == rx_freq.frequency { + if &configuration.sat == "QO-100" && tx_freq.frequency == rx_freq.frequency { log::debug!("Manually setting TX Frequency for QO-100 satellite activity"); tx_freq.frequency - 8089500000 } else { @@ -98,9 +113,9 @@ async fn program(configuration: &Config) -> Result<(), WavelogHamlibError> { let update = Update { radio: String::from(&configuration.wavelog_radio), frequency: update_tx_freq, - mode: Mode::from(tx_mode.mode), + mode: tx_mode, frequency_rx: Some(rx_freq.frequency), - mode_rx: Some(Mode::from(rx_mode.mode)), + mode_rx: Some(rx_mode), prop_mode: update_prop_mode, power: None, sat_name: Some(String::from(&configuration.sat)).filter(String::is_empty), From 288ab5ef1df5f0563d47b6a9b1c9894f71a293a0 Mon Sep 17 00:00:00 2001 From: Luca Cireddu Date: Fri, 26 Dec 2025 18:14:54 +0100 Subject: [PATCH 2/5] feat(logging): migrate to tracing --- Cargo.toml | 8 ++++---- src/config.rs | 2 +- src/errors.rs | 6 +++--- src/log.rs | 42 +++++++++++++++++++++++++++++++++++++++++ src/logging.rs | 44 ------------------------------------------- src/main.rs | 51 +++++++++++++++++++++++++------------------------- src/wavelog.rs | 38 ++++++++++++++++++++++++++----------- 7 files changed, 103 insertions(+), 88 deletions(-) create mode 100644 src/log.rs delete mode 100644 src/logging.rs diff --git a/Cargo.toml b/Cargo.toml index fde5216..8d20054 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "wavelog-hamlib" -version = "1.2.0" +version = "1.3.0" authors = ["Luca Cireddu "] description = "Simple tool to connect Hamlib rigctld instance with Wavelog" repository = "https://github.com/sardylan/wavelog-hamlib.git" @@ -13,11 +13,11 @@ chrono = { version = "0.4.42", features = ["serde"] } clap = { version = "4.5.53", features = ["cargo", "color", "derive", "env", "unicode"] } hamlib-client = "1.1.0" lazy_static = "1.5.0" -log = "0.4.29" -log4rs = "1.4.0" regex = "1.12.2" reqwest = { version = "0.12.28", features = ["json"] } serde = { version = "1.0.228", features = ["derive"] } serde_json = { version = "1.0.147", features = ["std"] } -thiserror = "1.0.69" tokio = { version = "1.48.0", features = ["full"] } +tracing = "0.1.44" +tracing-log = "0.2.0" +tracing-subscriber = { version = "0.3.22", features = ["ansi", "serde", "chrono", "env-filter"] } diff --git a/src/config.rs b/src/config.rs index 0ba9d7a..3dac07b 100644 --- a/src/config.rs +++ b/src/config.rs @@ -17,7 +17,7 @@ use clap::crate_name; use clap::value_parser; use clap::{ArgAction, Parser}; -use log::Level; +use tracing::Level; #[derive(Parser, Debug)] #[command(version, author, about, long_about = None)] diff --git a/src/errors.rs b/src/errors.rs index b558787..3fd87bd 100644 --- a/src/errors.rs +++ b/src/errors.rs @@ -15,7 +15,7 @@ */ use hamlib_client::error::RigCtlError; -use std::fmt; +use std::fmt::{Display, Formatter}; #[derive(Debug)] pub enum WavelogHamlibError { @@ -35,8 +35,8 @@ impl From for WavelogHamlibError { } } -impl fmt::Display for WavelogHamlibError { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { +impl Display for WavelogHamlibError { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { match &self { WavelogHamlibError::Hamlib(e) => write!(f, "Hamlib error: {}", &e), WavelogHamlibError::Wavelog(e) => write!(f, "Wavelog error: {}", &e), diff --git a/src/log.rs b/src/log.rs new file mode 100644 index 0000000..a2c78fc --- /dev/null +++ b/src/log.rs @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2024 Luca Cireddu + * + * This program is free software: you can redistribute it and/or modify it under + * the terms of the GNU General Public License as published by the Free Software + * Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see . + * + */ + +use tracing::Level; +use tracing_subscriber::{prelude::*, EnvFilter}; + +pub fn configure(level: &Level) { + tracing_log::LogTracer::init().expect("Failed to set logger"); + + let crate_name = clap::crate_name!().replace('-', "_"); + + let filter = EnvFilter::try_new(format!("{}={},warn", crate_name, level)) + .unwrap_or_else(|_| EnvFilter::new(format!("{}={},warn", crate_name, Level::INFO))); + + let fmt_layer = tracing_subscriber::fmt::layer() + .with_writer(std::io::stderr) + .with_ansi(true) + .with_level(true) + .with_file(true) + .with_line_number(true) + .with_thread_ids(true) + .with_target(true); + + tracing_subscriber::registry() + .with(filter) + .with(fmt_layer) + .try_init() + .ok(); +} diff --git a/src/logging.rs b/src/logging.rs deleted file mode 100644 index bd15618..0000000 --- a/src/logging.rs +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright (C) 2024 Luca Cireddu - * - * This program is free software: you can redistribute it and/or modify it under - * the terms of the GNU General Public License as published by the Free Software - * Foundation, version 3. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along with - * this program. If not, see . - * - */ - -use log::{Level, LevelFilter}; -use log4rs::append::console::{ConsoleAppender, Target}; -use log4rs::config::{Appender, Root}; -use log4rs::encode::pattern::PatternEncoder; -use log4rs::Config; - -pub fn configure(level: &Level) { - let console_encoder = PatternEncoder::new("{date(%Y-%m-%dT%H:%M:%S%.6f%:z)(utc)} {module} {highlight({level})} {message}{n}"); - - let console_appender = ConsoleAppender::builder() - .target(Target::Stderr) - .encoder(Box::new(console_encoder)) - .build(); - - let level_filter = match level { - Level::Error => { LevelFilter::Error } - Level::Warn => { LevelFilter::Warn } - Level::Info => { LevelFilter::Info } - Level::Debug => { LevelFilter::Debug } - Level::Trace => { LevelFilter::Trace } - }; - - log4rs::init_config(Config::builder() - .appender(Appender::builder().build("stderr", Box::new(console_appender))) - .build(Root::builder().appender("stderr").build(level_filter)) - .unwrap() - ).unwrap(); -} \ No newline at end of file diff --git a/src/main.rs b/src/main.rs index 091e010..aa8cb88 100644 --- a/src/main.rs +++ b/src/main.rs @@ -16,7 +16,7 @@ mod config; mod errors; -mod logging; +mod log; mod wavelog; use crate::config::Config; @@ -28,23 +28,24 @@ use hamlib_client::RigCtlClient; use std::string::String; use std::time::Duration; use tokio::time::sleep; +use tracing::{debug, error, info, trace, warn}; #[tokio::main] async fn main() { let configuration = Config::parse(); - logging::configure(&configuration.log_level); + log::configure(&configuration.log_level); match program(&configuration).await { Ok(_) => {} Err(e) => { - log::error!("{}", e) + error!("{}", e) } } } async fn program(configuration: &Config) -> Result<(), WavelogHamlibError> { - log::trace!( + trace!( "Creating Wavelog client for {} with radio name \"{}\"", &configuration.wavelog_url, configuration.wavelog_radio @@ -52,7 +53,7 @@ async fn program(configuration: &Config) -> Result<(), WavelogHamlibError> { let wavelog_client = wavelog::Client::new(&configuration.wavelog_url, &configuration.wavelog_key); - log::trace!( + trace!( "Creating client for {}:{}", &configuration.rigctl_host, configuration.rigctl_port @@ -61,23 +62,23 @@ async fn program(configuration: &Config) -> Result<(), WavelogHamlibError> { rigctl.set_communication_timeout(configuration.rigctl_timeout); rigctl.connect().await?; - log::info!("Connected"); + info!("Connected"); loop { - log::debug!("Getting info from Hamlib"); + debug!("Getting info from Hamlib"); let vfo = rigctl.get_vfo().await?; - log::trace!("Rig vfo: {}", &vfo); + trace!("Rig vfo: {}", &vfo); let rx_vfo = vfo.vfo; - log::debug!("RX vfo: {}", &rx_vfo); + debug!("RX vfo: {}", &rx_vfo); let split_vfo = rigctl.get_split_vfo().await?; - log::trace!("Rig split_vfo: {}", &split_vfo); + trace!("Rig split_vfo: {}", &split_vfo); let tx_vfo = split_vfo.tx_vfo; - log::debug!("TX vfo: {}", &tx_vfo); + debug!("TX vfo: {}", &tx_vfo); let force_mode = Mode::from(&configuration.force_mode.as_str()); - log::debug!("Force mode: {}", &force_mode); + debug!("Force mode: {}", &force_mode); let (rx_mode, tx_mode) = if force_mode == Mode::None { let rx_mode = rigctl.get_mode(rx_vfo).await?; @@ -86,16 +87,16 @@ async fn program(configuration: &Config) -> Result<(), WavelogHamlibError> { } else { (force_mode, force_mode) }; - log::trace!("{} Mode: {}", &rx_vfo, &rx_mode); - log::trace!("{} Mode: {}", &tx_vfo, &tx_mode); + trace!("{} Mode: {}", &rx_vfo, &rx_mode); + trace!("{} Mode: {}", &tx_vfo, &tx_mode); let rx_freq = rigctl.get_freq(rx_vfo).await?; - log::trace!("{}: {}", &rx_vfo, &rx_freq); + trace!("{}: {}", &rx_vfo, &rx_freq); let tx_freq = rigctl.get_freq(tx_vfo).await?; - log::trace!("{}: {}", &tx_vfo, &tx_freq); + trace!("{}: {}", &tx_vfo, &tx_freq); let update_prop_mode = if !&configuration.sat.is_empty() { - log::debug!("Enabling SAT propagation mode"); + debug!("Enabling SAT propagation mode"); Some(PropagationMode::SAT) } else { None @@ -103,13 +104,13 @@ async fn program(configuration: &Config) -> Result<(), WavelogHamlibError> { let update_tx_freq = if &configuration.sat == "QO-100" && tx_freq.frequency == rx_freq.frequency { - log::debug!("Manually setting TX Frequency for QO-100 satellite activity"); + debug!("Manually setting TX Frequency for QO-100 satellite activity"); tx_freq.frequency - 8089500000 } else { tx_freq.frequency }; - log::debug!("Preparing update"); + debug!("Preparing update"); let update = Update { radio: String::from(&configuration.wavelog_radio), frequency: update_tx_freq, @@ -120,23 +121,23 @@ async fn program(configuration: &Config) -> Result<(), WavelogHamlibError> { power: None, sat_name: Some(String::from(&configuration.sat)).filter(String::is_empty), }; - log::trace!("Update: {}", &update); + trace!("Update: {}", &update); - log::debug!("Sending update to Wavelog"); + debug!("Sending update to Wavelog"); let result = wavelog_client.send_update(update).await; - log::trace!("Result: {:?}", &result); + trace!("Result: {:?}", &result); match result { Ok(response) => { if !response { - log::warn!("Error sending update to Wavelog"); + warn!("Error sending update to Wavelog"); } } Err(e) => { - log::error!("{}", e); + error!("{}", e); } } - log::debug!("Sleeping"); + debug!("Sleeping"); sleep(Duration::from_millis(configuration.interval)).await; } } diff --git a/src/wavelog.rs b/src/wavelog.rs index 111392c..56cbd01 100644 --- a/src/wavelog.rs +++ b/src/wavelog.rs @@ -20,6 +20,7 @@ use reqwest::{Method, Url}; use serde::{Deserialize, Serialize, Serializer}; use std::fmt::{Display, Formatter}; use std::str::FromStr; +use tracing::{debug, trace}; pub struct Update { pub radio: String, @@ -55,10 +56,20 @@ struct Request { impl Display for Request { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { - write!(f, "{} - {} - {}: {} {} {} {} {} {} {}", - self.key, self.timestamp, self.radio, self.frequency, - self.mode, self.frequency_rx, self.mode_rx, self.prop_mode, - self.power, self.sat_name) + write!( + f, + "{} - {} - {}: {} {} {} {} {} {} {}", + self.key, + self.timestamp, + self.radio, + self.frequency, + self.mode, + self.frequency_rx, + self.mode_rx, + self.prop_mode, + self.power, + self.sat_name + ) } } @@ -72,7 +83,10 @@ impl Request { mode: update.mode.to_string(), frequency_rx: update.frequency_rx.unwrap_or(0), mode_rx: update.mode_rx.unwrap_or(Mode::None).to_string(), - prop_mode: update.prop_mode.unwrap_or(PropagationMode::None).to_string(), + prop_mode: update + .prop_mode + .unwrap_or(PropagationMode::None) + .to_string(), power: update.power.unwrap_or(0), sat_name: update.sat_name.unwrap_or("".to_string()), } @@ -104,20 +118,22 @@ impl Client { } pub async fn send_update(&self, update: Update) -> Result { - log::debug!("Sending data to Wavelog"); + debug!("Sending data to Wavelog"); let request_body = Request::generate(&self.key, update); - log::trace!("Request: {}", &request_body); + trace!("Request: {}", &request_body); let url = self.url.join("/api/radio").unwrap(); - log::trace!("URL: {}", &url); + trace!("URL: {}", &url); let response_body: Response = reqwest::Client::new() .request(Method::POST, url.as_str()) .json(&request_body) - .send().await? - .json().await?; - log::trace!("Response: {}", &response_body); + .send() + .await? + .json() + .await?; + trace!("Response: {}", &response_body); Ok(response_body.status == "success") } } From 1ad877a48a74795f6265333b786db99801e3aa8c Mon Sep 17 00:00:00 2001 From: Luca Cireddu Date: Fri, 26 Dec 2025 18:24:20 +0100 Subject: [PATCH 3/5] Update src/config.rs Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- src/config.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/config.rs b/src/config.rs index 3dac07b..2b163ea 100644 --- a/src/config.rs +++ b/src/config.rs @@ -116,7 +116,7 @@ pub struct Config { long, action = ArgAction::Set, default_value = "", - help = "Froce mode", + help = "Force mode", long_help = "Force the mode reported (empty values is the same of not setting this option)" )] pub force_mode: String, From 1e19e0a136cbcc00c3ed1cc854a186e2acb3ad83 Mon Sep 17 00:00:00 2001 From: Luca Cireddu Date: Fri, 26 Dec 2025 18:24:40 +0100 Subject: [PATCH 4/5] Update src/main.rs Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- src/main.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main.rs b/src/main.rs index aa8cb88..e395371 100644 --- a/src/main.rs +++ b/src/main.rs @@ -82,7 +82,7 @@ async fn program(configuration: &Config) -> Result<(), WavelogHamlibError> { let (rx_mode, tx_mode) = if force_mode == Mode::None { let rx_mode = rigctl.get_mode(rx_vfo).await?; - let tx_mode = rigctl.get_mode(rx_vfo).await?; + let tx_mode = rigctl.get_mode(tx_vfo).await?; (Mode::from(rx_mode.mode), Mode::from(tx_mode.mode)) } else { (force_mode, force_mode) From 45f16662055113a579c244696608188a61d0b14a Mon Sep 17 00:00:00 2001 From: Luca Cireddu Date: Fri, 26 Dec 2025 18:29:39 +0100 Subject: [PATCH 5/5] Update src/config.rs Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- src/config.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/config.rs b/src/config.rs index 2b163ea..9040c82 100644 --- a/src/config.rs +++ b/src/config.rs @@ -117,7 +117,7 @@ pub struct Config { action = ArgAction::Set, default_value = "", help = "Force mode", - long_help = "Force the mode reported (empty values is the same of not setting this option)" + long_help = "Forces the mode reported (empty values is the same of not setting this option)" )] pub force_mode: String, }