configurable logging level, winsize, adcthresh, request rate
This commit is contained in:
parent
81d68e1429
commit
5d217e6c5a
1 changed files with 76 additions and 35 deletions
111
src/main.rs
111
src/main.rs
|
|
@ -1,8 +1,8 @@
|
|||
use anyhow::{Context, Result};
|
||||
use clap::Parser;
|
||||
use clap::{arg, Parser};
|
||||
use crc::{Crc, CRC_16_IBM_3740};
|
||||
use hound::{SampleFormat, WavSpec, WavWriter};
|
||||
use log::{debug, error, info, LevelFilter};
|
||||
use log::{debug, error, info, trace, LevelFilter};
|
||||
use serialport::SerialPort;
|
||||
use std::collections::HashMap;
|
||||
use std::io::{BufRead, BufReader, Read, Write};
|
||||
|
|
@ -26,19 +26,38 @@ struct Args {
|
|||
#[arg(short, long, default_value_t = 115_200)]
|
||||
baud_rate: u32,
|
||||
|
||||
/// Turn debugging information on
|
||||
#[arg(long)]
|
||||
adcthresh: Option<u32>,
|
||||
|
||||
#[arg(long)]
|
||||
winsize: Option<u32>,
|
||||
|
||||
#[arg(long, default_value_t = 10, help = "Value in Hz")]
|
||||
requst_rate: u32,
|
||||
|
||||
#[arg(short, long)]
|
||||
first_sample: bool,
|
||||
|
||||
#[arg(short, long, action = clap::ArgAction::Count)]
|
||||
debug: u8,
|
||||
verbose: u8,
|
||||
}
|
||||
|
||||
fn main() {
|
||||
// Initialize logging with debug level
|
||||
let args = Args::parse();
|
||||
let log_level = match args.verbose {
|
||||
0 => LevelFilter::Info,
|
||||
1 => LevelFilter::Debug,
|
||||
_ => LevelFilter::Trace,
|
||||
};
|
||||
env_logger::builder()
|
||||
.filter_level(LevelFilter::Info)
|
||||
.filter_level(log_level)
|
||||
.format_timestamp_millis()
|
||||
.init();
|
||||
|
||||
let args = Args::parse();
|
||||
assert!(
|
||||
args.requst_rate >= 1 && args.requst_rate <= 100,
|
||||
"Request rate must be in 1..100 range!"
|
||||
);
|
||||
|
||||
debug!("Trying to open the serial port: {}", args.port);
|
||||
let mut port = match serialport::new(args.port, args.baud_rate).open() {
|
||||
|
|
@ -62,8 +81,8 @@ fn main() {
|
|||
panic!("Couldn't detect hailsens!")
|
||||
}
|
||||
|
||||
get_threshold(&mut port, args.device_id).expect("Couldn't get threshold");
|
||||
let winsize = get_winsize(&mut port, args.device_id).expect("Couldn't get winsize") as usize;
|
||||
get_set_threshold(&mut port, args.device_id, args.adcthresh).expect("Couldn't get threshold");
|
||||
let winsize = get_set_winsize(&mut port, args.device_id, args.winsize).expect("Couldn't get winsize") as usize;
|
||||
debug!("Expected buf size is: {}", exp_buf_size(winsize));
|
||||
|
||||
let spec = WavSpec {
|
||||
|
|
@ -73,7 +92,7 @@ fn main() {
|
|||
sample_format: SampleFormat::Int,
|
||||
};
|
||||
|
||||
info!("Starting main loop...");
|
||||
debug!("Starting main loop...");
|
||||
let running = Arc::new(AtomicBool::new(true));
|
||||
let r = running.clone();
|
||||
// Set up Ctrl-C handler
|
||||
|
|
@ -82,7 +101,7 @@ fn main() {
|
|||
r.store(false, Ordering::SeqCst);
|
||||
})
|
||||
.unwrap();
|
||||
info!("Press Ctrl-C to stop");
|
||||
debug!("Press Ctrl-C to stop");
|
||||
|
||||
let mut last_chunk_id: u32 = 0;
|
||||
let mut err_counter: u32 = 0;
|
||||
|
|
@ -101,27 +120,29 @@ fn main() {
|
|||
}
|
||||
};
|
||||
if cur_chunk_id != last_chunk_id {
|
||||
info!("New data available: {}", cur_chunk_id);
|
||||
info!("Getting new chunk!");
|
||||
debug!("New data available: {}", cur_chunk_id);
|
||||
debug!("Getting new chunk!");
|
||||
match get_chunk(&mut port, args.device_id, args.baud_rate, winsize) {
|
||||
Some(data) => {
|
||||
info!("Received new data with len: {}", data.len());
|
||||
debug!("Received new data with len: {}", data.len());
|
||||
|
||||
let timestamp_ms = current_timestamp_ms();
|
||||
let filename = format!("./out/wave_{}.wav", timestamp_ms);
|
||||
|
||||
// Create a new WAV file
|
||||
let mut writer = WavWriter::create(&filename, spec)
|
||||
.expect("Can't create new WAV file!");
|
||||
let mut writer =
|
||||
WavWriter::create(&filename, spec).expect("Can't create new WAV file!");
|
||||
let mut i16_writer = writer.get_i16_writer(data.len() as u32);
|
||||
for sample in data {
|
||||
unsafe {
|
||||
i16_writer.write_sample_unchecked(sample);
|
||||
}
|
||||
}
|
||||
i16_writer.flush().expect("Something went wrong while writing WAV file");
|
||||
i16_writer
|
||||
.flush()
|
||||
.expect("Something went wrong while writing WAV file");
|
||||
info!("WAV file {} has been written.", filename);
|
||||
|
||||
|
||||
err_counter = err_counter.saturating_sub(1);
|
||||
last_chunk_id = cur_chunk_id;
|
||||
}
|
||||
|
|
@ -131,7 +152,7 @@ fn main() {
|
|||
}
|
||||
}
|
||||
}
|
||||
std::thread::sleep(Duration::from_millis(20));
|
||||
std::thread::sleep(Duration::from_millis((1000 / args.requst_rate) as u64));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -151,13 +172,19 @@ fn get_stats(port: &mut Box<dyn SerialPort>, id: u32) -> Result<u32> {
|
|||
let num_since_startup: u32 = split.next().context("Missing value")?.parse()?;
|
||||
let _num_since_last_read: u32 = split.next().context("Missing value")?.parse()?;
|
||||
let _num_in_10min: u32 = split.next().context("Missing value")?.parse()?;
|
||||
debug!("Got num_since_startup: {}", num_since_startup);
|
||||
trace!("Got num_since_startup: {}", num_since_startup);
|
||||
Ok(num_since_startup)
|
||||
}
|
||||
|
||||
fn get_winsize(port: &mut Box<dyn SerialPort>, id: u32) -> Option<u32> {
|
||||
fn get_set_winsize(port: &mut Box<dyn SerialPort>, id: u32, new_winsize: Option<u32>) -> Option<u32> {
|
||||
let command;
|
||||
if let Some(i) = new_winsize {
|
||||
debug!("Setting new winsize: {i}");
|
||||
command = format!("@{id} winsize {i}\n");
|
||||
} else {
|
||||
command = format!("@{} winsize\n", id);
|
||||
}
|
||||
debug!("Getting window size...");
|
||||
let command = format!("@{} winsize\n", id);
|
||||
let response = process_command(port, command).unwrap_or_default();
|
||||
let winsize_str = response.split_whitespace().nth(3);
|
||||
match winsize_str {
|
||||
|
|
@ -173,8 +200,18 @@ fn get_winsize(port: &mut Box<dyn SerialPort>, id: u32) -> Option<u32> {
|
|||
}
|
||||
}
|
||||
|
||||
fn get_threshold(port: &mut Box<dyn SerialPort>, id: u32) -> Option<u32> {
|
||||
let command = format!("@{} adcthresh\n", id);
|
||||
fn get_set_threshold(
|
||||
port: &mut Box<dyn SerialPort>,
|
||||
id: u32,
|
||||
new_threshold: Option<u32>,
|
||||
) -> Option<u32> {
|
||||
let command;
|
||||
if let Some(i) = new_threshold {
|
||||
debug!("Setting new threshold: {i}");
|
||||
command = format!("@{id} adcthresh {i}\n");
|
||||
} else {
|
||||
command = format!("@{} adcthresh\n", id);
|
||||
}
|
||||
let response = process_command(port, command).unwrap_or_default();
|
||||
let number_str = response.split_whitespace().nth(3);
|
||||
match number_str {
|
||||
|
|
@ -259,16 +296,16 @@ fn get_sample_rate(port: &mut Box<dyn SerialPort>, id: u32) -> u32 {
|
|||
}
|
||||
|
||||
fn process_command(port: &mut Box<dyn SerialPort>, command: String) -> Option<String> {
|
||||
debug!("Writing command to the serial port: {}", command);
|
||||
trace!("Writing command to the serial port: {}", command);
|
||||
port.write_all(command.as_bytes())
|
||||
.expect("Failed to write to serial port!");
|
||||
port.flush().expect("Failed to flush serial port!");
|
||||
debug!("Waiting for response from the serial port...");
|
||||
trace!("Waiting for response from the serial port...");
|
||||
let mut reader = BufReader::new(port);
|
||||
let mut response = String::new();
|
||||
match reader.read_line(&mut response) {
|
||||
Ok(_) => {
|
||||
debug!("Received response from the serial port");
|
||||
trace!("Received response from the serial port");
|
||||
Some(response)
|
||||
}
|
||||
Err(ref e) if e.kind() == std::io::ErrorKind::TimedOut => {
|
||||
|
|
@ -304,16 +341,16 @@ fn get_chunk(
|
|||
win_size: usize,
|
||||
) -> Option<Vec<i16>> {
|
||||
let command = format!("@{} convbuf\n", id);
|
||||
debug!("Writing convbuf to the serial port");
|
||||
trace!("Writing convbuf to the serial port");
|
||||
port.write_all(command.as_bytes())
|
||||
.expect("Failed to write to serial port!");
|
||||
port.flush().expect("Failed to flush serial port!");
|
||||
debug!("Waiting for response from the serial port...");
|
||||
trace!("Waiting for response from the serial port...");
|
||||
let mut adc_buffer: Vec<u8> = vec![0; MAX_DATA_LEN];
|
||||
std::thread::sleep(calculate_timeout(baud_rate, exp_buf_size(win_size)));
|
||||
match port.read(adc_buffer.as_mut_slice()) {
|
||||
Ok(len) => {
|
||||
debug!("Buffer is received with len: {}", len);
|
||||
trace!("Buffer is received with len: {}", len);
|
||||
}
|
||||
Err(ref e) if e.kind() == std::io::ErrorKind::TimedOut => {
|
||||
debug!("Read timed out");
|
||||
|
|
@ -323,11 +360,11 @@ fn get_chunk(
|
|||
panic!("Failed to read from serial port: {}", e);
|
||||
}
|
||||
}
|
||||
debug!("Checking header...");
|
||||
trace!("Checking header...");
|
||||
if header_is_ok(&adc_buffer) {
|
||||
debug!("Header is ok!");
|
||||
trace!("Header is ok!");
|
||||
} else {
|
||||
error!("Header is corrupted!");
|
||||
trace!("Header is corrupted!");
|
||||
return None;
|
||||
}
|
||||
let data_slice = adc_buffer.get(4..4 + win_size * 2);
|
||||
|
|
@ -350,7 +387,7 @@ fn get_chunk(
|
|||
);
|
||||
None
|
||||
} else {
|
||||
debug!("CRC is correct!");
|
||||
trace!("CRC is correct!");
|
||||
// converting raw bytes to correct format
|
||||
|
||||
Some(convert_to_i16(data_buf))
|
||||
|
|
@ -364,7 +401,11 @@ fn get_chunk(
|
|||
}
|
||||
|
||||
fn convert_to_i16(buffer: &[u8]) -> Vec<i16> {
|
||||
assert_eq!(buffer.len() % 2, 0, "Buffer length must be a multiple of 2.");
|
||||
assert_eq!(
|
||||
buffer.len() % 2,
|
||||
0,
|
||||
"Buffer length must be a multiple of 2."
|
||||
);
|
||||
let len = buffer.len() / 2; // Number of i16 elements
|
||||
let ptr = buffer.as_ptr() as *const i16;
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue