use anyhow::Context;
use embedded_can::Frame as EmbeddedFrame;
use socketcan::{CanAnyFrame, CanFdFrame, CanFdSocket, Frame, Socket};
use std::{
env,
sync::atomic::{AtomicBool, Ordering},
};
fn frame_to_string<F: Frame>(frame: &F) -> String {
let id = frame.raw_id();
let data_string = frame
.data()
.iter()
.fold(String::new(), |a, b| format!("{} {:02X}", a, b));
format!("{:08X} [{}] {}", id, frame.len(), data_string)
}
fn main() -> anyhow::Result<()> {
let iface = env::args().nth(1).unwrap_or_else(|| "vcan0".into());
let sock = CanFdSocket::open(&iface)
.with_context(|| format!("Failed to open FD socket on interface {}", iface))?;
sock.set_nonblocking(true)
.with_context(|| "Failed to make FD socket non-blocking")?;
static QUIT: AtomicBool = AtomicBool::new(false);
ctrlc::set_handler(|| {
QUIT.store(true, Ordering::Relaxed);
})
.expect("Failed to set ^C signal handler");
while !QUIT.load(Ordering::Relaxed) {
if let Ok(CanAnyFrame::Fd(frame)) = sock.read_frame() {
println!("{}", frame_to_string(&frame));
let new_id = frame.can_id() + 0x01;
if let Some(echo_frame) = CanFdFrame::new(new_id, frame.data()) {
sock.write_frame(&echo_frame)
.expect("Failed to echo received frame");
}
}
}
Ok(())
}