add tactile_a codec
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
use crate::serial_core::{frame::TestFrame, record::Recording};
|
||||
|
||||
pub mod test;
|
||||
pub mod tactile_a;
|
||||
pub type TestRecording = Recording<TestFrame>;
|
||||
142
src-tauri/src/serial_core/codecs/tactile_a.rs
Normal file
142
src-tauri/src/serial_core/codecs/tactile_a.rs
Normal file
@@ -0,0 +1,142 @@
|
||||
use std::time::Instant;
|
||||
use crate::serial_core::error::CodecError;
|
||||
use crate::serial_core::frame::{FrameHandler, TactileAFrameMetaData, TactileARepFrame, TestFrame};
|
||||
use crate::serial_core::utils::elapsed_millis;
|
||||
use crate::serial_core::{codec::Codec, codecs::test::TestCodec, frame::{TactileAFrame, TactileAFrameStatusCode}};
|
||||
|
||||
const FRAME_BUFFER_MIN_LENGTH: usize = 15;
|
||||
|
||||
pub struct TactileACodec {
|
||||
buffer: Vec<u8>,
|
||||
frame_nb: u64,
|
||||
}
|
||||
|
||||
pub struct TactileACsvExporter;
|
||||
|
||||
pub struct TactileACsvImporter {
|
||||
|
||||
}
|
||||
|
||||
pub struct TactileAHandler;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct TactileADataPacket {
|
||||
pub data: Vec<i32>,
|
||||
pub dts_ms: u64,
|
||||
}
|
||||
|
||||
impl From<u8> for TactileAFrameStatusCode {
|
||||
fn from(value: u8) -> Self {
|
||||
match value {
|
||||
0 => TactileAFrameStatusCode::Success,
|
||||
_ => TactileAFrameStatusCode::Failure
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl TactileACodec {
|
||||
pub fn new() -> TactileACodec {
|
||||
Self {
|
||||
buffer: Vec::new(),
|
||||
frame_nb: 0
|
||||
}
|
||||
}
|
||||
|
||||
pub fn parse_data_frame(data: &[u8]) -> Result<Vec<i32>> {
|
||||
if data.len() % 2 == 0 {
|
||||
return Err(CodecError::InvalidLength);
|
||||
}
|
||||
|
||||
let vals: Vec<i32> = data
|
||||
.chunks_exact(2)
|
||||
.map(|chunk| u16::from_be_bytes(bytes))
|
||||
}
|
||||
}
|
||||
|
||||
impl Codec<TactileAFrame> for TactileACodec {
|
||||
fn decode(&mut self, input: &[u8], session_started_at: std::time::Instant) -> Result<Vec<TactileAFrame>, CodecError> {
|
||||
self.buffer.extend_from_slice(input);
|
||||
let mut frames: Vec<TactileAFrame> = Vec::new();
|
||||
|
||||
loop {
|
||||
if self.buffer.len() < FRAME_BUFFER_MIN_LENGTH {
|
||||
break;
|
||||
}
|
||||
|
||||
let header_pos = self.buffer
|
||||
.windows(2)
|
||||
.position(|w| w == [0xAA, 0x55]);
|
||||
|
||||
let Some(pos) = header_pos else {
|
||||
self.buffer.clear();
|
||||
break;
|
||||
};
|
||||
if pos > 0 {
|
||||
self.buffer.drain(0..pos);
|
||||
}
|
||||
|
||||
if self.buffer.len() < FRAME_BUFFER_MIN_LENGTH {
|
||||
break;
|
||||
}
|
||||
|
||||
let header = [self.buffer[0], self.buffer[1]];
|
||||
let payload_len = u16::from_le_bytes([self.buffer[2], self.buffer[3]]) as usize;
|
||||
let device_addr = self.buffer[4];
|
||||
let extend_code = self.buffer[5];
|
||||
let func_code = self.buffer[6];
|
||||
let start_addr = u32::from_le_bytes([self.buffer[7],self.buffer[8],self.buffer[9],self.buffer[10]]);
|
||||
let except_data_len = u16::from_le_bytes([self.buffer[11], self.buffer[12]]) as usize;
|
||||
let status = TactileAFrameStatusCode::from(self.buffer[13]);
|
||||
let payload = self.buffer[14..14+except_data_len].to_vec();
|
||||
let crc8_itu_alg = crc::Crc::<u8>::new(&crc::CRC_8_I_432_1);
|
||||
let checksum = crc8_itu_alg.checksum(&payload.as_slice());
|
||||
let frame_length = except_data_len + FRAME_BUFFER_MIN_LENGTH;
|
||||
if self.buffer[frame_length - 1] != checksum {
|
||||
self.buffer.drain(0..1);
|
||||
continue;
|
||||
}
|
||||
let dts_ms = elapsed_millis(session_started_at);
|
||||
let meta: TactileAFrameMetaData = TactileAFrameMetaData {
|
||||
header,
|
||||
payload_len,
|
||||
device_addr,
|
||||
extend_code,
|
||||
func_code,
|
||||
start_addr,
|
||||
except_data_len,
|
||||
checksum,
|
||||
};
|
||||
frames.push(TactileAFrame::Rep({
|
||||
TactileARepFrame {
|
||||
meta,
|
||||
status,
|
||||
payload,
|
||||
dts_ms
|
||||
}
|
||||
}));
|
||||
|
||||
self.buffer.drain(0..frame_length);
|
||||
}
|
||||
|
||||
Ok(frames)
|
||||
|
||||
}
|
||||
|
||||
fn encode(&self, frame: &TactileAFrame) -> Result<Vec<u8>, crate::serial_core::error::CodecError> {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl FrameHandler<TactileAFrame, i32> for TactileAHandler {
|
||||
async fn on_frame(&mut self, frame: &TactileAFrame) -> anyhow::Result<Option<Vec<i32>>> {
|
||||
match frame {
|
||||
TactileARepFrame => {
|
||||
|
||||
}
|
||||
_ => {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,13 +1,15 @@
|
||||
use std::io::Read;
|
||||
use std::time::Instant;
|
||||
use crate::serial_core::frame::{crc8, usize_to_u16_be_bytes, FrameHandler};
|
||||
use crate::serial_core::frame::{FrameHandler};
|
||||
use crate::serial_core::utils::*;
|
||||
use crate::serial_core::{codec::Codec, error::CodecError, frame::TestFrame};
|
||||
use anyhow::anyhow;
|
||||
use async_trait::async_trait;
|
||||
use chrono::Local;
|
||||
use csv::StringRecord;
|
||||
use crate::serial_core::record::{write_csv, CsvExporter, CsvImporter, RecordedFrame, Recording};
|
||||
|
||||
use crc::{Crc, CRC_8_SMBUS};
|
||||
use crate::serial_core::utils::*;
|
||||
pub struct TestCodec {
|
||||
buffer: Vec<u8>,
|
||||
}
|
||||
@@ -52,7 +54,9 @@ impl Codec<TestFrame> for TestCodec {
|
||||
break;
|
||||
}
|
||||
let payload = self.buffer[5..5 + length].to_vec();
|
||||
let checksum = crc8(payload.as_slice());
|
||||
// let checksum = crc8(payload.as_slice());
|
||||
let crc8_alg = crc::Crc::<u8>::new(&crc::CRC_8_SMBUS);
|
||||
let checksum = crc8_alg.checksum(payload.as_slice());
|
||||
if self.buffer[frame_length - 1] != checksum {
|
||||
self.buffer.drain(0..1);
|
||||
continue;
|
||||
@@ -112,10 +116,6 @@ fn parse_data_frame(data: &[u8]) -> Result<Vec<i32>, CodecError> {
|
||||
Ok(vals)
|
||||
}
|
||||
|
||||
fn elapsed_millis(start_at: Instant) -> u64 {
|
||||
start_at.elapsed().as_millis() as u64
|
||||
}
|
||||
|
||||
pub struct TestCsvExporter;
|
||||
pub struct TestCsvImporter {
|
||||
channels: usize,
|
||||
|
||||
Reference in New Issue
Block a user