use crate::{
error::SendPgnError,
infra::codec::traits::PgnData,
protocol::transport::fast_packet::{builder::FastPacketBuilder, MAX_FAST_PACKET_PAYLOAD},
protocol::transport::traits::{can_bus::CanBus, korri_timer::KorriTimer},
protocol::transport::FAST_PACKET_INTER_FRAME_DELAY_MS,
};
pub trait PgnSender: CanBus {
async fn send_pgn<P: PgnData, T: KorriTimer>(
&mut self,
pgn_data: &P,
pgn: u32,
source_address: u8,
destination: Option<u8>,
timer: &mut T,
) -> Result<(), SendPgnError<Self::Error>>;
}
impl<C: CanBus> PgnSender for C
where
C::Error: core::fmt::Debug,
{
async fn send_pgn<P: PgnData, T: KorriTimer>(
&mut self,
pgn_data: &P,
pgn: u32,
source_address: u8,
destination: Option<u8>,
timer: &mut T,
) -> Result<(), SendPgnError<Self::Error>> {
let mut payload_buffer = [0u8; MAX_FAST_PACKET_PAYLOAD];
let len = pgn_data
.to_payload(&mut payload_buffer)
.map_err(|_| SendPgnError::Serialization)?;
let payload_slice = &payload_buffer[..len];
let builder = FastPacketBuilder::new(pgn, source_address, destination, payload_slice);
let frame_iter = builder.build();
let mut is_first_frame = true;
for frame_result in frame_iter {
let frame = frame_result.map_err(SendPgnError::Build)?;
if !is_first_frame && payload_slice.len() > 8 {
timer.delay_ms(FAST_PACKET_INTER_FRAME_DELAY_MS).await;
}
self.send(&frame).await.map_err(SendPgnError::Send)?;
is_first_frame = false;
}
Ok(())
}
}