Files
JE-Skin/src-tauri/src/serial_core/record.rs

90 lines
2.2 KiB
Rust

use eskin_finger_sdk::types::FingerSample;
#[derive(Clone)]
pub struct FrameTiming {
pub pts_ms: Option<u64>,
pub dts_ms: u64,
}
#[derive(Clone)]
pub struct RecordedFrame<F> {
pub timing: FrameTiming,
pub frame: F,
}
#[derive(Clone, Default)]
pub struct Recording<F> {
pub frames: Vec<RecordedFrame<F>>,
}
impl<F> Recording<F> {
pub fn new() -> Recording<F> {
Self {
frames: Vec::new(),
}
}
pub fn push(&mut self, item: RecordedFrame<F>) {
self.frames.push(item);
}
}
pub type FingerRecording = Recording<FingerSample>;
pub fn export_recording_csv<W>(
recording: &Recording<FingerSample>,
mut writer: W,
) -> anyhow::Result<()>
where
W: std::io::Write,
{
// Infer channel count from the first sample's combined_forces (just fz)
// We write: timestamp_us, sequence, module, fx, fy, fz
let mut wrt = csv::Writer::from_writer(&mut writer);
wrt.write_record(["timestamp_us", "sequence", "module", "fx", "fy", "fz"])?;
for frame in &recording.frames {
let s = &frame.frame;
wrt.write_record(&[
s.timestamp_us.to_string(),
s.sequence.to_string(),
format!("{:?}", s.combined_forces.module),
s.combined_forces.force.fx.to_string(),
s.combined_forces.force.fy.to_string(),
s.combined_forces.force.fz.to_string(),
])?;
}
wrt.flush()?;
Ok(())
}
pub struct FingerSampleCsvPacket {
pub timestamp_us: u64,
pub sequence: u32,
pub fz: u32,
}
pub fn import_csv<R: std::io::Read>(
reader: R,
) -> anyhow::Result<Vec<FingerSampleCsvPacket>> {
let mut rdr = csv::Reader::from_reader(reader);
let mut packets = Vec::new();
for result in rdr.records() {
let record = result?;
if record.len() < 6 {
continue;
}
let timestamp_us = record.get(0).unwrap_or("0").parse::<u64>().unwrap_or(0);
let sequence = record.get(1).unwrap_or("0").parse::<u32>().unwrap_or(0);
let fz = record.get(5).unwrap_or("0").parse::<u32>().unwrap_or(0);
packets.push(FingerSampleCsvPacket {
timestamp_us,
sequence,
fz,
});
}
Ok(packets)
}