Skip to content

Commit dc427a7

Browse files
committed
include option to save raw traffic
1 parent 9209c52 commit dc427a7

File tree

4 files changed

+53
-27
lines changed

4 files changed

+53
-27
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,8 @@ Features:
2525
- [X] Allow to put in labels for the different data columns (instead of column 1, 2, ...)
2626
- [X] Allow to choose Data-bits, Flow-Control, Parity and Stop-Bits for Serial Connection
2727
- [X] Saves the configuration for the serial port after closing and reloads them automatically upon selection
28+
- [X] Option to save raw data to file
2829
- [ ] Allow to select (and copy) more than just the displayed raw traffic (also implement ctrl + A)
29-
- [ ] Save raw data to file (at least as an option)
3030
- [ ] Smarter data parser
3131
- [ ] make serial print selectable and show corresponding datapoint in plot
3232
- [ ] COM-Port names on Windows (display manufacturer, name, pid or vid of device?)

src/gui.rs

Lines changed: 10 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ use serialport::{DataBits, FlowControl, Parity, StopBits};
1919
use crate::data::{DataContainer, SerialDirection};
2020
use crate::serial::{save_serial_settings, Device, SerialDevices};
2121
use crate::toggle::toggle;
22-
use crate::CsvOptions;
22+
use crate::FileOptions;
2323
use crate::{vec2, APP_INFO, PREFS_KEY};
2424

2525
const MAX_FPS: f64 = 60.0;
@@ -185,7 +185,7 @@ pub struct MyApp {
185185
connected_lock: Arc<RwLock<bool>>,
186186
data_lock: Arc<RwLock<DataContainer>>,
187187
names_tx: Sender<Vec<String>>,
188-
save_tx: Sender<CsvOptions>,
188+
save_tx: Sender<FileOptions>,
189189
send_tx: Sender<String>,
190190
clear_tx: Sender<bool>,
191191
history: Vec<String>,
@@ -210,7 +210,7 @@ impl MyApp {
210210
connected_lock: Arc<RwLock<bool>>,
211211
gui_conf: GuiSettingsContainer,
212212
names_tx: Sender<Vec<String>>,
213-
save_tx: Sender<CsvOptions>,
213+
save_tx: Sender<FileOptions>,
214214
send_tx: Sender<String>,
215215
clear_tx: Sender<bool>,
216216
) -> Self {
@@ -653,9 +653,10 @@ impl MyApp {
653653
if let Some(path) = rfd::FileDialog::new().save_file() {
654654
self.picked_path = path;
655655
self.picked_path.set_extension("csv");
656-
if let Err(e) = self.save_tx.send(CsvOptions {
656+
if let Err(e) = self.save_tx.send(FileOptions {
657657
file_path: self.picked_path.clone(),
658658
save_absolute_time: self.gui_conf.save_absolute_time,
659+
save_raw_traffic: self.save_raw,
659660
}) {
660661
print_to_console(
661662
&self.print_lock,
@@ -699,15 +700,11 @@ impl MyApp {
699700
}
700701
ui.end_row();
701702
ui.label("Save Raw Traffic");
702-
ui.horizontal(|ui| {
703-
ui.set_enabled(false);
704-
if ui.add(toggle(&mut self.save_raw))
705-
.on_hover_text("Save raw traffic to CSV. - not implemented yet!")
706-
.changed() {
707-
// gui_states.push(GuiState::Run(self.show_timestamps));
708-
}
709-
ui.label("Not implemented yet.");
710-
});
703+
if ui.add(toggle(&mut self.save_raw))
704+
.on_hover_text("Save second CSV containing raw traffic.")
705+
.changed() {
706+
// gui_states.push(GuiState::Run(self.show_timestamps));
707+
}
711708
ui.end_row();
712709
ui.label("");
713710
ui.end_row();

src/io.rs

Lines changed: 39 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,21 @@
11
use std::error::Error;
2+
use std::fs::File;
3+
use std::io::Write;
4+
use std::path::PathBuf;
25

36
use csv::WriterBuilder;
47

5-
use crate::{CsvOptions, DataContainer};
8+
use crate::DataContainer;
69

7-
pub fn save_to_csv(data: &DataContainer, csv_options: &CsvOptions) -> Result<(), Box<dyn Error>> {
10+
/// A set of options for saving data to a CSV file.
11+
#[derive(Debug)]
12+
pub struct FileOptions {
13+
pub file_path: PathBuf,
14+
pub save_absolute_time: bool,
15+
pub save_raw_traffic: bool,
16+
}
17+
18+
pub fn save_to_csv(data: &DataContainer, csv_options: &FileOptions) -> Result<(), Box<dyn Error>> {
819
let mut wtr = WriterBuilder::new()
920
.has_headers(false)
1021
.from_path(&csv_options.file_path)?;
@@ -25,5 +36,31 @@ pub fn save_to_csv(data: &DataContainer, csv_options: &CsvOptions) -> Result<(),
2536
wtr.write_record(&data_to_write)?;
2637
}
2738
wtr.flush()?;
39+
if csv_options.save_raw_traffic {
40+
let mut path = csv_options.file_path.clone();
41+
let mut file_name = path.file_name().unwrap().to_str().unwrap().to_string();
42+
file_name.replace(".csv", "");
43+
file_name += "raw.csv";
44+
path.set_file_name(file_name);
45+
save_raw(data, &path)?
46+
}
47+
Ok(())
48+
}
49+
50+
pub fn save_raw(data: &DataContainer, path: &PathBuf) -> Result<(), Box<dyn Error>> {
51+
let mut wtr = WriterBuilder::new().has_headers(false).from_path(path)?;
52+
let header = vec![
53+
"Time [ms]".to_string(),
54+
"Abs Time [ms]".to_string(),
55+
"Raw Traffic".to_string(),
56+
];
57+
wtr.write_record(header)?;
58+
59+
for j in 0..data.dataset[0].len() {
60+
let mut data_to_write = vec![data.time[j].to_string(), data.absolute_time[j].to_string()];
61+
data_to_write.push(data.raw_traffic[j].payload.clone());
62+
wtr.write_record(&data_to_write)?;
63+
}
64+
wtr.flush()?;
2865
Ok(())
2966
}

src/main.rs

Lines changed: 3 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ extern crate preferences;
66
extern crate serde;
77

88
use std::cmp::max;
9-
use std::path::PathBuf;
109
use std::sync::mpsc::{Receiver, Sender};
1110
use std::sync::{mpsc, Arc, RwLock};
1211
use std::thread;
@@ -17,7 +16,7 @@ use preferences::AppInfo;
1716

1817
use crate::data::{DataContainer, Packet};
1918
use crate::gui::{load_gui_settings, print_to_console, MyApp, Print, RIGHT_PANEL_WIDTH};
20-
use crate::io::save_to_csv;
19+
use crate::io::{save_to_csv, FileOptions};
2120
use crate::serial::{load_serial_settings, serial_thread, Device};
2221

2322
mod data;
@@ -33,13 +32,6 @@ const APP_INFO: AppInfo = AppInfo {
3332
const PREFS_KEY: &str = "config/gui";
3433
const PREFS_KEY_SERIAL: &str = "config/serial_devices";
3534

36-
/// A set of options for saving data to a CSV file.
37-
#[derive(Debug)]
38-
pub struct CsvOptions {
39-
file_path: PathBuf,
40-
save_absolute_time: bool,
41-
}
42-
4335
fn split(payload: &str) -> Vec<f32> {
4436
let mut split_data: Vec<&str> = vec![];
4537
for s in payload.split(':') {
@@ -57,7 +49,7 @@ fn main_thread(
5749
print_lock: Arc<RwLock<Vec<Print>>>,
5850
raw_data_rx: Receiver<Packet>,
5951
names_rx: Receiver<Vec<String>>,
60-
save_rx: Receiver<CsvOptions>,
52+
save_rx: Receiver<FileOptions>,
6153
clear_rx: Receiver<bool>,
6254
) {
6355
// reads data from mutex, samples and saves if needed
@@ -152,7 +144,7 @@ fn main() {
152144
let print_lock = Arc::new(RwLock::new(vec![Print::Empty]));
153145
let connected_lock = Arc::new(RwLock::new(false));
154146

155-
let (save_tx, save_rx): (Sender<CsvOptions>, Receiver<CsvOptions>) = mpsc::channel();
147+
let (save_tx, save_rx): (Sender<FileOptions>, Receiver<FileOptions>) = mpsc::channel();
156148
let (send_tx, send_rx): (Sender<String>, Receiver<String>) = mpsc::channel();
157149
let (clear_tx, clear_rx): (Sender<bool>, Receiver<bool>) = mpsc::channel();
158150
let (names_tx, names_rx): (Sender<Vec<String>>, Receiver<Vec<String>>) = mpsc::channel();

0 commit comments

Comments
 (0)