Skip to content

Commit

Permalink
much improving the frame parsing
Browse files Browse the repository at this point in the history
  • Loading branch information
maebli committed Nov 15, 2023
1 parent 13f7a34 commit b239e96
Showing 1 changed file with 93 additions and 58 deletions.
151 changes: 93 additions & 58 deletions src/frames/mod.rs
Original file line number Diff line number Diff line change
@@ -1,84 +1,126 @@
#[derive(Debug,PartialEq)]
pub enum FrameType {
SingleCharacter,
ShortFrame,
LongFrame,
ControlFrame,
ExtendedLinkLayer,
Unknown,
pub enum FrameType<'a> {
SingleCharacter{
character: u8
},
ShortFrame{
function: u8,
address: u8
},
LongFrame{
function: u8,
address: u8,
control_information: u8,
data: &'a [u8]},
ControlFrame{
function: u8,
address: u8,
control_information: u8
},
}

#[derive(Debug, PartialEq)]
pub enum FrameDetectionError {
pub enum FrameError {
EmptyData,
InvalidStartOrStopByte,
InvalidStartByte,
InvalidStopByte,
LengthMismatch,
WrongChecksum,
LengthShorterThanSix{
length: usize
},
WrongChecksum{
expected: u8,
actual: u8,
},
}

pub trait Frame {
fn from(data: &[u8]) -> Result<Self, FrameError>
where
Self: Sized;
}

pub fn parse(data: &[u8]) {

}

pub fn detect_frame_type(data: &[u8]) -> Result<FrameType, FrameDetectionError> {
pub fn parse_frame(data: &[u8]) -> Result<FrameType, FrameError> {

if data.is_empty() {
return Ok(FrameType::Unknown);
return Err(FrameError::EmptyData);
}

if data.len() == 1 && data[0] == 0xE5 {
return Ok(FrameType::SingleCharacter);
return Ok(FrameType::SingleCharacter{character: 0xE5});
}

let cs = calculate_checksum(data);

if cs != data[data.len() - 2] {
return Err(FrameDetectionError::WrongChecksum);
}

match data[0] {
0x68 => {
// Check for minimum length for a valid long/control frame
if data.len() < 6 || data[data.len() - 1] != 0x16 {
return Ok(FrameType::Unknown);

if data[data.len() - 1] != 0x16 {
return Err(FrameError::InvalidStopByte);
}

if data.len() < 6 {
return Err(FrameError::LengthShorterThanSix{length: data.len()});
}

validate_checksum(&data[4..])?;

let length = data[1] as usize;

// Length bytes should match and the total size should be length + 6
if data[1] != data[2] || data.len() != length + 6 {
return Err(FrameDetectionError::LengthMismatch);
return Err(FrameError::LengthMismatch);
}

// Additional checks based on control field to distinguish between ControlFrame and LongFrame
let control_field = data[4];
match control_field {
// Define specific control field values that indicate a ControlFrame
// Example: 0x53 might indicate a ControlFrame (adjust as per your protocol specs)
0x53 => Ok(FrameType::ControlFrame),

// Otherwise, assume it's a LongFrame
_ => Ok(FrameType::LongFrame),
0x53 => Ok(FrameType::ControlFrame{
function: data[4],
address: data[5],
control_information: data[6]
}),
_ => Ok(FrameType::LongFrame{
function: data[4],
address: data[5],
control_information: data[6],
data: &data[7..data.len() - 2],
}),
}
},
0x10 | 0x40 => {
if data.len() == 4 && data[3] == 0x16 {
Ok(FrameType::ShortFrame)
0x10 => {
validate_checksum(&data[1..])?;
if data.len() == 5 && data[4] == 0x16 {
Ok(FrameType::ShortFrame{
function: data[1],
address: data[2],
})
} else {
Ok(FrameType::Unknown)
Err(FrameError::LengthMismatch)
}

},
_ => Ok(FrameType::Unknown)
_ => Err(FrameError::InvalidStartByte),
}
}


// The Check Sum is calculated from the arithmetical sum of the data
// without taking carry digits into account.
fn calculate_checksum(data: &[u8]) -> u8 {

if data.len() < 2 {
panic!("Data too short to calculate checksum");
fn validate_checksum(data: &[u8]) -> Result<(), FrameError> {
// Assuming the checksum is the second to last byte in the data array.
let checksum_byte_index = data.len() - 2;
let checksum_byte = data[checksum_byte_index];

let calculated_checksum = data[..checksum_byte_index]
.iter()
.fold(0, |acc:u8, &x| acc.wrapping_add(x));

if checksum_byte == calculated_checksum {
Ok(())
} else {
Err(FrameError::WrongChecksum{
expected: checksum_byte,
actual: calculated_checksum,
})
}

data.iter()
.take(data.len() - 2) // Take all bytes except the last two
.fold(0u8, |acc, &x| acc.wrapping_add(x))
}


Expand All @@ -91,16 +133,9 @@ mod tests {
fn test_detect_frame_type() {

let single_character_frame = vec![0xE5];
let short_frame = vec![0x10, 0x7B, 0x8b, 0x16];
let long_frame = vec![0x68, 0x03, 0x03, 0x68, 0x08, 0x34, 0x12, 0x24, 0x16];
let control_frame = vec![0x68, 0x01, 0x01, 0x68, 0x53, 0x25, 0x16];
let control_frame_wrong_length= vec![0x68, 0x02, 0x02, 0x68, 0x53, 0x27, 0x16];

assert_eq!(detect_frame_type(&single_character_frame), Ok(FrameType::SingleCharacter));
assert_eq!(detect_frame_type(&short_frame), Ok(FrameType::ShortFrame));
assert_eq!(detect_frame_type(&long_frame), Ok(FrameType::LongFrame));
assert_eq!(detect_frame_type(&control_frame), Ok(FrameType::ControlFrame));
assert_eq!(detect_frame_type(&control_frame_wrong_length),Err(FrameDetectionError::LengthMismatch));
let short_frame = vec![0x10, 0x7B, 0x8b, 0x06,0x16];

assert_eq!(parse_frame(&single_character_frame), Ok(FrameType::SingleCharacter{character: 0xE5}));
assert_eq!(parse_frame(&short_frame), Ok(FrameType::ShortFrame{function: 0x7B, address: 0x8B}));
}
}

0 comments on commit b239e96

Please sign in to comment.