From a1b5a2593016bd23ae751b559e85cf9b569dd8db Mon Sep 17 00:00:00 2001 From: Marco Radocchia Date: Wed, 3 Aug 2022 16:54:22 +0200 Subject: [PATCH] Added quiet option to mute stdout --- src/args.rs | 11 ++++++++--- src/main.rs | 47 ++++++++++++++++------------------------------- 2 files changed, 24 insertions(+), 34 deletions(-) diff --git a/src/args.rs b/src/args.rs index 83b339f..395deca 100644 --- a/src/args.rs +++ b/src/args.rs @@ -78,12 +78,12 @@ pub struct Args { #[clap(short, long, default_value_t = 120, value_parser = parse_interval)] pub interval: u64, - /// Print output as to stdout (for use in unix pipeline). + /// Print output as `` to stdout (for use in unix pipeline). #[clap(short = 'P', long, action = SetTrue)] pub pipe: bool, /// Output CSV directory. - #[clap(short, long, default_value = "~", value_parser = parse_directory, requires = "csv")] + #[clap(short, long, default_value = "~", value_parser = parse_directory)] pub directory: PathBuf, /// Output CSV filename format (see @@ -91,7 +91,12 @@ pub struct Args { #[clap(short, long, default_value = "%Y%m%d")] pub format: String, - /// Dumps data to CSV file. + /// Dumps data to CSV file (can be swapped at runtime signalling `datalogger` process with + /// SIGUSR1). #[clap(long, action = SetTrue)] pub csv: bool, + + /// Mute standard output. + #[clap(short, long, action = SetTrue)] + pub quiet: bool, } diff --git a/src/main.rs b/src/main.rs index c59a036..a7b5116 100644 --- a/src/main.rs +++ b/src/main.rs @@ -22,7 +22,7 @@ use chrono::{DateTime, Local}; use dht22_pi::{self, Reading, ReadingError}; use error::ErrorKind; use signal_hook::{ - consts::{SIGINT, SIGUSR1}, + consts::SIGUSR1, flag::register, }; use std::{ @@ -76,7 +76,7 @@ impl Display for Measure { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { write!( f, - "{} {} -> Humidity: {}%, Temperature: {}°C", + "Date: {}, Time: {}, Humidity: {}%, Temperature: {}°C", self.datetime.date().format("%Y-%m-%d"), self.datetime.time().format("%H:%M:%S"), self.reading.humidity, @@ -102,7 +102,7 @@ fn run(args: Args) -> Result<(), ErrorKind> { let (tx, rx) = mpsc::channel::(); // Output thread. - let output_thread = thread::spawn(move || -> Result<(), ErrorKind> { + thread::spawn(move || -> Result<(), ErrorKind> { // Register signal hook for SIGUSR1 events: such events swap the current args.csv value // (this is used to enable/disable writing of measures to output file at runtime). let sig = Arc::new(AtomicBool::new(false)); @@ -115,23 +115,18 @@ fn run(args: Args) -> Result<(), ErrorKind> { let mut csv = args.csv; for measure in rx { - // If SIGUSR1 received (so set to true), swap csv and restore sig to false. + // If SIGUSR1 received (hence sig is true), swap csv and restore sig to false. if sig.load(Ordering::Relaxed) { csv = !csv; sig.store(false, Ordering::Relaxed); } if csv { - // If `pipe` options is passed, print with "," format to stdout. - if args.pipe { - println!("{}", measure.to_pipe()); - } - let filename = Local::now().format(&args.format).to_string(); let csv_file = &args.directory.join(filename).with_extension("csv"); match OpenOptions::new().create(true).append(true).open(csv_file) { Ok(mut file) => { - // If file is empty write headers. + // If file is empty, then write headers. if file .metadata() .expect("unable to get output file metadata") @@ -146,27 +141,24 @@ fn run(args: Args) -> Result<(), ErrorKind> { } Err(e) => return Err(ErrorKind::FileError(e.to_string())), } - } else if args.pipe { - println!("{}", measure.to_pipe()); - } else if args.csv == csv && !args.csv { - // Print human readable output to stdout only if args.csv is left unchanged and it - // was set to false at launch (this means the user is intentionally trying to print - // human readable to stdout). - println!("{measure}"); + } + + if !args.quiet { + // If `pipe` options is passed, print with "," format to stdout, else + // print human readable values. + if args.pipe { + println!("{}", measure.to_pipe()); + } else { + println!("{}", measure); + } } } Ok(()) }); - // Register signal hook for SIGINT events: in this case error is unrecoverable, so it's fine to - // panic. - let int = Arc::new(AtomicBool::new(false)); - // Set `int` to true when the program receives a SIGTERM kill signal. - register(SIGINT, Arc::clone(&int)).expect("unable to register SIGTERM event handler"); - // Start main loop: loop guard is 'received SIGINT'. - while !int.load(Ordering::Relaxed) { + loop { let start_measuring = Instant::now(); let mut retries = 0; tx.send(Measure::new( @@ -198,13 +190,6 @@ fn run(args: Args) -> Result<(), ErrorKind> { // Sleep for `args.interval` corrected by the time spent measuring. thread::sleep(Duration::from_secs(args.interval) - start_measuring.elapsed()); } - - drop(tx); - output_thread - .join() - .expect("unable to join 'output_thread'")?; - - Ok(()) } fn main() {