use rs_can::{
CanDirection, CanError, CanFdFlags, CanFrame, CanId, CanKind, CanResult,
FrameFormat, Timestamp, MAX_FD_FRAME_SIZE, MAX_FRAME_SIZE,
};
use std::fmt::{Display, Formatter};
#[repr(C)]
#[derive(Debug, Clone)]
pub struct NiCanFrame {
timestamp: Option<Timestamp>,
arbitration_id: u32,
is_extended_id: bool,
is_remote_frame: bool,
is_error_frame: bool,
channel: String,
length: usize,
data: Vec<u8>,
direction: CanDirection,
bitrate_switch: bool,
error_state_indicator: bool,
}
impl CanFrame for NiCanFrame {
type Channel = String;
fn new_can(id: CanId, data: &[u8]) -> CanResult<Self> {
if data.len() > MAX_FRAME_SIZE {
return Err(CanError::InvalidDLC(data.len()));
}
Ok(Self {
timestamp: None,
arbitration_id: id.as_raw(),
is_extended_id: id.is_extended(),
is_remote_frame: false,
is_error_frame: false,
channel: Default::default(),
length: data.len(),
data: data.to_vec(),
direction: CanDirection::Transmit,
bitrate_switch: false,
error_state_indicator: false,
})
}
fn new_remote(id: CanId, dlc: u8) -> CanResult<Self> {
if dlc as usize > MAX_FRAME_SIZE {
return Err(CanError::InvalidDLC(dlc as usize));
}
Ok(Self {
timestamp: None,
arbitration_id: id.as_raw(),
is_extended_id: id.is_extended(),
is_remote_frame: true,
is_error_frame: false,
channel: Default::default(),
length: dlc as usize,
data: vec![0; dlc as usize],
direction: CanDirection::Transmit,
bitrate_switch: false,
error_state_indicator: false,
})
}
fn new_can_fd(id: CanId, data: &[u8], flags: CanFdFlags) -> CanResult<Self> {
let length = data.len();
if length > MAX_FD_FRAME_SIZE {
return Err(CanError::InvalidDLC(length));
}
Ok(Self {
timestamp: None,
arbitration_id: id.as_raw(),
is_extended_id: id.is_extended(),
is_remote_frame: false,
is_error_frame: false,
channel: Default::default(),
length,
data: data.to_vec(),
direction: CanDirection::Transmit,
bitrate_switch: flags.contains(CanFdFlags::BRS),
error_state_indicator: flags.contains(CanFdFlags::ESI),
})
}
fn id(&self) -> CanId {
CanId::from_bits(self.arbitration_id, Some(self.is_extended_id)).unwrap()
}
fn channel(&self) -> Self::Channel {
self.channel.clone()
}
fn set_channel(&mut self, v: Self::Channel) -> &mut Self {
self.channel = v;
self
}
fn kind(&self) -> CanKind {
CanKind::Classical
}
fn format(&self) -> FrameFormat {
if self.is_error_frame {
FrameFormat::Error
} else if self.is_remote_frame {
FrameFormat::Remote
} else {
FrameFormat::Data
}
}
fn data(&self) -> &[u8] {
&self.data
}
fn len(&self) -> usize {
self.length
}
fn direction(&self) -> CanDirection {
self.direction
}
fn set_direction(&mut self, d: CanDirection) -> &mut Self {
self.direction = d;
self
}
fn timestamp(&self) -> Option<Timestamp> {
self.timestamp
}
fn set_timestamp(&mut self, ts: Option<Timestamp>) -> &mut Self {
self.timestamp = ts;
self
}
fn is_bitrate_switch(&self) -> bool {
self.bitrate_switch
}
fn set_bitrate_switch(&mut self, v: bool) -> &mut Self {
self.bitrate_switch = v;
self
}
fn is_esi(&self) -> bool {
self.error_state_indicator
}
fn set_esi(&mut self, v: bool) -> &mut Self {
self.error_state_indicator = v;
self
}
}
impl Display for NiCanFrame {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
<dyn CanFrame<Channel = String> as Display>::fmt(self, f)
}
}