Code refactoring
This commit is contained in:
parent
488431d253
commit
daa938e580
1 changed files with 104 additions and 119 deletions
223
src/main.rs
223
src/main.rs
|
|
@ -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!");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue