Skip to content

Commit

Permalink
Merge pull request #6 from sunsided/feature/disk-dump
Browse files Browse the repository at this point in the history
Add support for dumping data to disk
  • Loading branch information
sunsided authored Jul 6, 2024
2 parents 773191d + c9b06ba commit 8b30713
Show file tree
Hide file tree
Showing 29 changed files with 591 additions and 29 deletions.
2 changes: 2 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
*.csv filter=lfs diff=lfs merge=lfs -text
*.bin filter=lfs diff=lfs merge=lfs -text
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,4 @@
/target
*.log
*.raw
*.gz
33 changes: 33 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ serde_json = "1.0.120"
json5 = "0.4.1"
ttl-queue = "0.2.0"
num-traits = "0.2.19"
async-compression = { version = "0.4.11", features = ["gzip", "tokio"] }

[patch.crates-io]
# serial-sensors-proto = { git = "https://github.com/sunsided/serial-sensors-proto", features = ["std", "alloc", "unsafe", "quaternion", "micromath"] }
Expand Down
13 changes: 13 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,16 @@ I'm currently using it for these projects:
At the moment it doesn't do much: it simply dumps out the information as it comes.

![A screenshot of the application in action](readme/picture.jpg)

## Logging data streams to disk

By using the `dump` subcommand and the `--dir /path/to/log` arguments, data streams can be logged
as CSV. The command creates one file per sensor and information type. The CSV will contain
both the device-side and host-side timestamps to allow for better inference of sensor data rates
later on.

By using the optional `--raw /path/to/file.bin` argument, the raw data stream can be logged.

```shell
cargo run -- dump --port /dev/ttyACM0 --raw stream.raw --dir dump/
```
59 changes: 53 additions & 6 deletions src/cli.rs
Original file line number Diff line number Diff line change
@@ -1,25 +1,72 @@
use clap::Parser;
use std::path::PathBuf;

use clap::{Parser, Subcommand};

use crate::utils::version;

#[derive(Parser, Debug)]
#[command(author, version = version(), about)]
#[command(propagate_version = true)]
pub struct Cli {
#[arg(
global = true,
short,
long,
value_name = "FLOAT",
help = "Tick rate, i.e. number of ticks per second",
default_value_t = 1.0
value_name = "PORT",
help = "The port name",
default_value = "/dev/ttyACM0"
)]
pub port: String,

#[arg(
global = true,
short,
long,
value_name = "BAUD_RATE",
help = "The baud rate",
default_value_t = 1_000_000
)]
pub tick_rate: f64,
pub baud: u32,

#[command(subcommand)]
pub command: Commands,
}

#[derive(Subcommand, Debug)]
pub enum Commands {
Ui(UiCommand),
Dump(Dump),
}

/// Runs a UI to visualize the incoming data stream.
#[derive(Parser, Debug)]
pub struct UiCommand {
#[arg(
short,
long,
value_name = "FLOAT",
help = "Frame rate, i.e. number of frames per second",
default_value_t = 60.0
default_value_t = 30.0
)]
pub frame_rate: f64,
}

/// Dumps received data to disk.
#[derive(Parser, Debug)]
pub struct Dump {
#[arg(
short,
long,
value_name = "RAW_FILE",
help = "The file in which to store raw data"
)]
pub raw: Option<PathBuf>,

#[arg(
short,
long,
value_name = "DIRECTORY",
help = "The directory in which to store data"
)]
pub dir: PathBuf,
}
25 changes: 16 additions & 9 deletions src/components/utils.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
use std::fmt::Display;
use std::ops::Neg;

use num_traits::ConstZero;
use ratatui::prelude::*;
use serial_sensors_proto::versions::Version1DataFrame;
use serial_sensors_proto::{IdentifierCode, ScalarData, SensorData, SensorId, Vector3Data};
Expand Down Expand Up @@ -34,14 +32,23 @@ where
Span::styled(format!("{:+4.6}", value), highlight.to_style_dim())
}

pub fn highlight_axis_3<T>(x: T, y: T, z: T) -> (Max, Max, Max)
where
T: PartialOrd + ConstZero + Neg<Output = T>,
{
pub fn highlight_axis_3(x: i16, y: i16, z: i16) -> (Max, Max, Max) {
// Fake abs.
let (x, x_pos) = if x > T::ZERO { (x, true) } else { (-x, false) };
let (y, y_pos) = if y > T::ZERO { (y, true) } else { (-y, false) };
let (z, z_pos) = if z > T::ZERO { (z, true) } else { (-z, false) };
let (x, x_pos) = if x > 0 {
(x, true)
} else {
(x.saturating_neg(), false)
};
let (y, y_pos) = if y > 0 {
(y, true)
} else {
(y.saturating_neg(), false)
};
let (z, z_pos) = if z > 0 {
(z, true)
} else {
(z.saturating_neg(), false)
};

if x > y && x > z {
(Max::Positive.flip_if(!x_pos), Max::None, Max::None)
Expand Down
4 changes: 3 additions & 1 deletion src/data_buffer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ use serial_sensors_proto::{DataFrame, IdentifierCode, SensorData, SensorId};

use crate::fps_counter::FpsCounter;

const BUFFER_CAP: usize = 100;

#[derive(Debug)]
pub struct SensorDataBuffer {
inner: RwLock<InnerSensorDataBuffer>,
Expand Down Expand Up @@ -145,7 +147,7 @@ impl SensorDataBuffer {

impl Default for InnerSensorDataBuffer {
fn default() -> Self {
let capacity = 100;
let capacity = BUFFER_CAP;
Self {
sensor_specific: true,
maker: String::new(),
Expand Down
Loading

0 comments on commit 8b30713

Please sign in to comment.