Code refactoring

This commit is contained in:
Данила Горнушко 2024-06-10 14:12:20 +03:00
parent 488431d253
commit daa938e580

View file

@ -164,7 +164,7 @@ fn init_logger(
} else { } else {
message message
} }
)) ));
}) })
.level(log_level) .level(log_level)
.chain(fern::log_file(path).expect("Failed to setup app_dispatch!")) .chain(fern::log_file(path).expect("Failed to setup app_dispatch!"))
@ -179,7 +179,7 @@ fn init_logger(
"{} {}", "{} {}",
now.format(time_format_string), now.format(time_format_string),
message message
)) ));
}) })
.filter(|metadata| { .filter(|metadata| {
metadata.level() == Level::Info && metadata.target().contains("stats10min") metadata.level() == Level::Info && metadata.target().contains("stats10min")
@ -210,7 +210,7 @@ fn init_logger(
} else { } else {
message message
} }
)) ));
}) })
.level(log_level) .level(log_level)
.chain(std::io::stdout()), .chain(std::io::stdout()),
@ -238,6 +238,7 @@ fn init_logger(
Ok(()) Ok(())
} }
#[allow(clippy::too_many_lines)]
fn main() { fn main() {
// enable colorful logs if running on Windows 10 // enable colorful logs if running on Windows 10
let _ = enable_ansi_support::enable_ansi_support(); let _ = enable_ansi_support::enable_ansi_support();
@ -271,7 +272,7 @@ fn main() {
port.set_timeout(Duration::from_millis(100)) port.set_timeout(Duration::from_millis(100))
.expect("Couldn't set serial port timeout!"); .expect("Couldn't set serial port timeout!");
let command = format!("@{} name\n", args.device_id); let command = format!("@{} name\n", args.device_id);
match process_command(&mut port, command) { match process_command(&mut port, &command) {
Some(response) => { Some(response) => {
if response.contains("'HAILSENS'") { if response.contains("'HAILSENS'") {
info!("Detected hailsens."); info!("Detected hailsens.");
@ -315,7 +316,7 @@ fn main() {
if args.reset_counters { if args.reset_counters {
info!("Resetting counters..."); info!("Resetting counters...");
process_command(&mut port, format!("@{} rstcnt\n", args.device_id)); process_command(&mut port, format!("@{} rstcnt\n", args.device_id).as_str());
} }
let spec = WavSpec { let spec = WavSpec {
@ -365,27 +366,26 @@ fn main() {
StatsOptions::DetectedNew(cur_stats) => { StatsOptions::DetectedNew(cur_stats) => {
success_cnt = success_cnt.saturating_add(1); success_cnt = success_cnt.saturating_add(1);
if prev_stats.map_or(true, |v| v != cur_stats) { if prev_stats.map_or(true, |v| v != cur_stats) {
match prev_stats { if let Some(prev_stats) = prev_stats {
Some(prev_stats) => { match (
match ( cur_stats.hail_since_startup > prev_stats.hail_since_startup,
cur_stats.hail_since_startup > prev_stats.hail_since_startup, cur_stats.noise_since_startup > prev_stats.noise_since_startup,
cur_stats.noise_since_startup > prev_stats.noise_since_startup, ) {
) { (true, true) => {
(true, true) => { info!(target: "detected", "Hail and noise detected, {cur_stats}");
info!(target: "detected", "Hail and noise detected, {cur_stats}")
}
(true, false) => {
info!(target: "detected", "Hail detected, {cur_stats}")
}
(false, true) => {
if args.noise_logging {
info!(target: "detected", "Noise detected, {cur_stats}")
}
}
(false, false) => (),
} }
(true, false) => {
info!(target: "detected", "Hail detected, {cur_stats}");
}
(false, true) => {
if args.noise_logging {
info!(target: "detected", "Noise detected, {cur_stats}");
}
}
(false, false) => (),
} }
None => info!("Initial {cur_stats}"), } else {
info!("Initial {cur_stats}");
} }
if samples_needed if samples_needed
&& prev_stats.map_or(args.first_sample, |v| { && prev_stats.map_or(args.first_sample, |v| {
@ -398,46 +398,44 @@ fn main() {
debug!("New data available: {}", cur_stats.hail_since_startup); debug!("New data available: {}", cur_stats.hail_since_startup);
debug!("Getting new chunk!"); debug!("Getting new chunk!");
} }
match get_chunk(&mut port, args.device_id, args.baud_rate, winsize) { if let Some(data) =
Some(data) => { get_chunk(&mut port, args.device_id, args.baud_rate, winsize)
debug!("Received new data with len: {}", data.len()); {
debug!("Received new data with len: {}", data.len());
if let Some(wav_path) = args.wavs_path.as_deref() { if let Some(wav_path) = args.wavs_path.as_deref() {
let path = Path::new(wav_path); let path = Path::new(wav_path);
let filename = let filename =
format!("{}_{}.wav", args.name, current_timestamp_ms()); format!("{}_{}.wav", args.name, current_timestamp_ms());
let path = path.join(filename); let path = path.join(filename);
// Create a new WAV file // Create a new WAV file
if let Ok(mut writer) = WavWriter::create(&path, spec) { if let Ok(mut writer) = WavWriter::create(&path, spec) {
let mut i16_writer = let mut i16_writer = writer.get_i16_writer(data.len() as u32);
writer.get_i16_writer(data.len() as u32); for sample in data {
for sample in data { unsafe {
unsafe { i16_writer.write_sample_unchecked(sample);
i16_writer.write_sample_unchecked(sample);
}
} }
if let Err(e) = i16_writer.flush() {
error!("Failed to write WAV file: {}", e);
}
info!(
"Sample: {}. WAV file {} has been written.",
cur_stats.hail_since_startup,
path.display()
);
} else {
error!("Can't create new WAV file!");
} }
if let Err(e) = i16_writer.flush() {
error!("Failed to write WAV file: {}", e);
}
info!(
"Sample: {}. WAV file {} has been written.",
cur_stats.hail_since_startup,
path.display()
);
} else {
error!("Can't create new WAV file!");
} }
}
success_cnt = success_cnt.saturating_add(1); success_cnt = success_cnt.saturating_add(1);
needed_retry = false; needed_retry = false;
} } else {
_ => { error!("Couldn't receive new data!");
error!("Couldn't receive new data!"); handle_error_with_timeout(&mut err_cnt, args.request_rate);
handle_error_with_timeout(&mut err_cnt, args.request_rate); needed_retry = true;
needed_retry = true;
}
} }
} }
} }
@ -479,10 +477,9 @@ fn handle_error_with_timeout(err_counter: &mut u32, request_rate: u32) {
} }
fn get_stats(port: &mut Box<dyn SerialPort>, id: u32) -> StatsOptions { fn get_stats(port: &mut Box<dyn SerialPort>, id: u32) -> StatsOptions {
let command = format!("@{} adcstats\n", id); let command = format!("@{id} adcstats\n");
let response = match process_command(port, command) { let Some(response) = process_command(port, &command) else {
Some(resp) => resp, return StatsOptions::None;
None => return StatsOptions::None,
}; };
let split: Vec<&str> = response let split: Vec<&str> = response
@ -493,12 +490,11 @@ fn get_stats(port: &mut Box<dyn SerialPort>, id: u32) -> StatsOptions {
for i in split { for i in split {
let num: Result<u32, _> = i.parse(); let num: Result<u32, _> = i.parse();
match num { if let Ok(num) = num {
Ok(num) => nums.push(num), nums.push(num);
Err(_) => { } else {
debug!("Can't parse '{i}' as u32"); debug!("Can't parse '{i}' as u32");
return StatsOptions::None; return StatsOptions::None;
}
} }
} }
@ -527,11 +523,11 @@ fn get_set_param(
let mut request_str = format!("@{id} {cmd}"); let mut request_str = format!("@{id} {cmd}");
if let Some(i) = new_param { if let Some(i) = new_param {
debug!("Setting new {debug_name}: {i}"); debug!("Setting new {debug_name}: {i}");
request_str.push_str(&format!(" {i}")) request_str.push_str(&format!(" {i}"));
} }
request_str.push('\n'); request_str.push('\n');
debug!("Getting {debug_name}..."); debug!("Getting {debug_name}...");
let response = process_command(port, request_str).unwrap_or_default(); let response = process_command(port, &request_str).unwrap_or_default();
let result_str = response.split_whitespace().nth(3); let result_str = response.split_whitespace().nth(3);
match result_str { match result_str {
Some(num_str) => { Some(num_str) => {
@ -556,9 +552,9 @@ fn get_sample_rate(port: &mut Box<dyn SerialPort>, id: u32) -> u32 {
fallback_freq fallback_freq
} }
let command = format!("@{} srate\n", id); let command = format!("@{id} srate\n");
let response: String; let response: String;
if let Some(res) = process_command(port, command) { if let Some(res) = process_command(port, &command) {
response = res; response = res;
} else { } else {
return fallback(); return fallback();
@ -579,7 +575,7 @@ fn get_sample_rate(port: &mut Box<dyn SerialPort>, id: u32) -> u32 {
} else { } else {
return fallback(); return fallback();
} }
let sample_times: HashMap<i32, Option<f64>> = [ let sample_times = HashMap::from([
(-1, None), (-1, None),
(0, Some(1.5)), (0, Some(1.5)),
(1, Some(3.5)), (1, Some(3.5)),
@ -589,20 +585,14 @@ fn get_sample_rate(port: &mut Box<dyn SerialPort>, id: u32) -> u32 {
(5, Some(39.5)), (5, Some(39.5)),
(6, Some(79.5)), (6, Some(79.5)),
(7, Some(160.5)), (7, Some(160.5)),
] ]);
.iter() let adc_div_dict = HashMap::from([
.cloned() (0x0, 1u32),
.collect();
let adc_div_dict: HashMap<u32, u32> = [
(0x0, 1),
(0x2000, 2), (0x2000, 2),
(0x2800, 4), (0x2800, 4),
(0x3000, 8), (0x3000, 8),
(0x3800, 16), (0x3800, 16),
] ]);
.iter()
.cloned()
.collect();
if !sample_times.contains_key(&adc_sample_time) { if !sample_times.contains_key(&adc_sample_time) {
error!("Received invalid ADC sample time!"); error!("Received invalid ADC sample time!");
return fallback(); return fallback();
@ -623,7 +613,7 @@ fn get_sample_rate(port: &mut Box<dyn SerialPort>, id: u32) -> u32 {
res res
} }
fn process_command(port: &mut Box<dyn SerialPort>, command: String) -> Option<String> { fn process_command(port: &mut Box<dyn SerialPort>, command: &str) -> Option<String> {
trace!("Writing command to the serial port: {}", command); trace!("Writing command to the serial port: {}", command);
if let Err(e) = port.write_all(command.as_bytes()) { if let Err(e) = port.write_all(command.as_bytes()) {
error!("Failed to write to serial port!: {}", e); error!("Failed to write to serial port!: {}", e);
@ -653,7 +643,7 @@ fn process_command(port: &mut Box<dyn SerialPort>, command: String) -> Option<St
fn nice_freq_string(freq_hz: u32) -> String { fn nice_freq_string(freq_hz: u32) -> String {
if freq_hz < 1000 { if freq_hz < 1000 {
format!("{:.2} Hz", freq_hz) format!("{freq_hz:.2} Hz")
} else if freq_hz < 1_000_000 { } else if freq_hz < 1_000_000 {
format!("{:.2} kHz", freq_hz / 1000) format!("{:.2} kHz", freq_hz / 1000)
} else { } else {
@ -673,7 +663,7 @@ fn get_chunk(
baud_rate: u32, baud_rate: u32,
win_size: usize, win_size: usize,
) -> Option<Vec<i16>> { ) -> Option<Vec<i16>> {
let command = format!("@{} convbuf\n", id); let command = format!("@{id} convbuf\n");
trace!("Writing convbuf to the serial port"); trace!("Writing convbuf to the serial port");
if let Err(e) = port.write_all(command.as_bytes()) { if let Err(e) = port.write_all(command.as_bytes()) {
error!("Failed to write to serial port!: {}", e); error!("Failed to write to serial port!: {}", e);
@ -687,10 +677,10 @@ fn get_chunk(
std::thread::sleep(calculate_timeout(baud_rate, exp_buf_size(win_size))); std::thread::sleep(calculate_timeout(baud_rate, exp_buf_size(win_size)));
match port.read(adc_buffer.as_mut_slice()) { match port.read(adc_buffer.as_mut_slice()) {
Ok(len) => { Ok(len) => {
if len != exp_buf_size(win_size) { if len == exp_buf_size(win_size) {
warn!("Received buffer with unexpected data length: {len}");
} else {
trace!("Buffer is received with length: {}", len); trace!("Buffer is received with length: {}", len);
} else {
warn!("Received buffer with unexpected data length: {len}");
} }
} }
Err(ref e) if e.kind() == std::io::ErrorKind::TimedOut => { Err(ref e) if e.kind() == std::io::ErrorKind::TimedOut => {
@ -717,28 +707,23 @@ fn get_chunk(
None None
} }
}); });
match (data_slice, crc_slice) { if let (Some(data_buf), Some(crc_buf)) = (data_slice, crc_slice) {
(Some(data_buf), Some(crc_buf)) => { let crc16_obj = Crc::<u16>::new(&CRC_16_IBM_3740);
let crc16_obj = Crc::<u16>::new(&CRC_16_IBM_3740); let crc_calculated = crc16_obj.checksum(data_buf);
let crc_calculated = crc16_obj.checksum(data_buf); let received_crc = u16::from_le_bytes(crc_buf);
let received_crc = u16::from_le_bytes(crc_buf); if received_crc == crc_calculated {
if received_crc != crc_calculated { trace!("CRC is correct!");
error!( Some(convert_to_i16(data_buf))
"CRC mismatch! Received CRC: {:04X}, Calculated CRC: {:04X}", } else {
received_crc, crc_calculated error!(
); "CRC mismatch! Received CRC: {:04X}, Calculated CRC: {:04X}",
None received_crc, crc_calculated
} else { );
trace!("CRC is correct!");
// converting raw bytes to correct format
Some(convert_to_i16(data_buf))
}
}
_ => {
error!("Couldn't slice received data!");
None None
} }
} else {
error!("Couldn't slice received data!");
None
} }
} }
@ -763,7 +748,7 @@ fn header_is_ok(vec: &[u8]) -> bool {
vec.get(0..4) vec.get(0..4)
.map(|bytes| u32::from_be_bytes(bytes.try_into().unwrap_or_default())) .map(|bytes| u32::from_be_bytes(bytes.try_into().unwrap_or_default()))
.unwrap_or_default() .unwrap_or_default()
== 0x55AA55AA == 0x55AA_55AA
} }
fn exp_buf_size(win_size: usize) -> usize { fn exp_buf_size(win_size: usize) -> usize {
@ -781,15 +766,15 @@ fn current_timestamp_ms() -> u128 {
fn sync_datetime(port: &mut Box<dyn SerialPort>, id: u32) { fn sync_datetime(port: &mut Box<dyn SerialPort>, id: u32) {
info!("Setting correct date/time on hailsens..."); info!("Setting correct date/time on hailsens...");
let formatted_date_time = Local::now().format("%Y-%m-%dT%H:%M:%S").to_string(); let formatted_date_time = Local::now().format("%Y-%m-%dT%H:%M:%S").to_string();
let request_str = format!("@{} date {}\n", id, formatted_date_time); let request_str = format!("@{id} date {formatted_date_time}\n");
match process_command(port, request_str) { if let Some(response) = process_command(port, &request_str) {
Some(response) => { let response = response.trim();
let response = response.trim(); if let Some(parsed) = response.split_whitespace().nth(1) {
match response.split_whitespace().nth(1) { info!("Hailsens date/time: {parsed}");
Some(parsed) => info!("Hailsens date/time: {parsed}"), } else {
None => warn!("Received date/time with incorrect format: {response}"), warn!("Received date/time with incorrect format: {response}");
}
} }
None => error!("Couldn't set date/time!"), } else {
error!("Couldn't set date/time!");
} }
} }