use crate::socket_can::CanSocketTx;
use super::{DiagError, Response, ResponseSlot, frame::UdsFrame};
use embedded_can::{ExtendedId, Frame, Id};
use log::debug;
use std::sync::{Arc, LazyLock};
pub struct UdsClient<'a, T: CanSocketTx> {
channel: T, id: Id, resp: &'a Arc<ResponseSlot>, }
#[allow(dead_code)]
impl<'a, T: CanSocketTx> UdsClient<'a, T> {
pub fn new(channel: T, id: u32, resp: &'a LazyLock<Arc<ResponseSlot>>) -> Self {
let id = Id::Extended(ExtendedId::new(id).unwrap());
Self { channel, id, resp }
}
pub async fn send_command<P: Into<u8>, M: Into<u8>>(
&mut self,
pci: P,
cmd: M,
args: &[u8],
) -> Result<(), DiagError> {
let mut data = vec![pci.into(), cmd.into()];
data.extend_from_slice(args);
self.send_raw(&data).await
}
pub async fn send_frame(&mut self, frame: UdsFrame) -> Result<(), DiagError> {
self.send_raw(&frame.to_vec()?).await
}
pub async fn send_frame_with_response(
&mut self,
frame: UdsFrame,
) -> Result<UdsFrame, DiagError> {
match self.send_raw_with_response(&frame.to_vec()?).await? {
Response::Ok(items) => {
debug!("got response: {:?}", items);
Ok(items)
}
Response::Error(e) => Err(e),
}
}
pub async fn send_command_with_response<P: Into<u8>, M: Into<u8>>(
&mut self,
pci: P,
cmd: M,
args: &[u8],
) -> Result<UdsFrame, DiagError> {
let mut data = vec![pci.into(), cmd.into()];
data.extend_from_slice(args);
match self.send_raw_with_response(&data).await? {
Response::Ok(items) => {
debug!("got response: {:?}", items);
Ok(items)
}
Response::Error(e) => Err(e),
}
}
async fn send_raw(&mut self, data: &[u8]) -> Result<(), DiagError> {
let frame = T::Frame::new(self.id, data).unwrap();
println!("send raw data frame: {:?}", frame.data());
self.channel.transmit(&frame).await.unwrap();
Ok(())
}
async fn send_raw_with_response(&mut self, data: &[u8]) -> Result<Response, DiagError> {
let frame = T::Frame::new(self.id, data).unwrap();
self.channel.transmit(&frame).await.unwrap();
let response = self.resp.wait_for_response().await;
Ok(response)
}
pub async fn receive(&mut self) -> Response {
self.resp.wait_for_response().await
}
}