vcan_loopback/
vcan_loopback.rs1fn main() {
16 #[cfg(target_os = "linux")]
17 {
18 if let Err(e) = linux::run() {
19 eprintln!("vcan_loopback FAILED: {e}");
20 std::process::exit(1);
21 }
22 }
23 #[cfg(not(target_os = "linux"))]
24 {
25 eprintln!("This example requires Linux SocketCAN (vcan0); see tools/vcan_setup.sh.");
26 }
27}
28
29#[cfg(target_os = "linux")]
30mod linux {
31 use std::error::Error;
32 use std::sync::mpsc;
33 use std::thread;
34 use std::time::Duration;
35
36 use canopen_host::transport::SocketCan;
37 use canopen_rs::sdo::SdoServer;
38 use canopen_rs::{Address, DataType, Entry, NodeId, ObjectDictionary, Value};
39
40 const IFACE: &str = "vcan0";
41
42 pub fn run() -> Result<(), Box<dyn Error>> {
43 let node = NodeId::new(0x10)?;
44
45 let (ready_tx, ready_rx) = mpsc::channel::<()>();
47 thread::spawn(move || {
48 if let Err(e) = serve(node, ready_tx) {
49 eprintln!("server thread error: {e}");
50 }
51 });
52 ready_rx.recv().map_err(|_| "server failed to start")?;
54
55 let bus = SocketCan::open(IFACE)?;
57 bus.set_read_timeout(Duration::from_secs(2))?;
58
59 let device_type = bus.sdo_read(node, Address::new(0x1000, 0), DataType::Unsigned32)?;
61 println!("read 0x1000 device type = {device_type:?}");
62 assert_eq!(device_type, Value::Unsigned32(0x0004_0192));
63
64 bus.sdo_write(node, Address::new(0x1017, 0), Value::Unsigned16(2500))?;
66 let heartbeat = bus.sdo_read(node, Address::new(0x1017, 0), DataType::Unsigned16)?;
67 println!("write 0x1017 heartbeat -> read = {heartbeat:?}");
68 assert_eq!(heartbeat, Value::Unsigned16(2500));
69
70 let big = Value::Unsigned64(0x0102_0304_0506_0708);
72 bus.sdo_write(node, Address::new(0x2000, 0), big)?;
73 let back = bus.sdo_read(node, Address::new(0x2000, 0), DataType::Unsigned64)?;
74 println!("write 0x2000 (segmented) -> read = {back:?}");
75 assert_eq!(back, big);
76
77 println!("\nvcan0 loopback OK — expedited and segmented SDO round-trips succeeded.");
78 Ok(())
79 }
80
81 fn serve(node: NodeId, ready: mpsc::Sender<()>) -> Result<(), Box<dyn Error>> {
84 let bus = SocketCan::open(IFACE)?;
85 bus.set_read_timeout(Duration::from_secs(3))?;
86
87 let mut od = ObjectDictionary::<8>::new();
88 od.insert(
89 Address::new(0x1000, 0),
90 Entry::constant(Value::Unsigned32(0x0004_0192)),
91 )?;
92 od.insert(Address::new(0x1017, 0), Entry::rw(Value::Unsigned16(1000)))?;
93 od.insert(Address::new(0x2000, 0), Entry::rw(Value::Unsigned64(0)))?;
94
95 let mut server = SdoServer::new(node);
96 ready.send(()).map_err(|_| "client went away")?;
97
98 while let Ok(frame) = bus.recv() {
100 if frame.cob_id != server.request_cob_id() {
101 continue;
102 }
103 if let Some(response) = server.handle(&mut od, frame.payload()) {
104 bus.send(server.response_cob_id(), &response)?;
105 }
106 }
107 Ok(())
108 }
109}