use canlink_hal::{BackendConfig, CanBackend, CanBackendAsync, CanMessage, CanResult};
use canlink_mock::{MockBackend, MockConfig};
use std::time::Duration;
#[tokio::main]
async fn main() -> CanResult<()> {
println!("=== CANLink Async API Example ===\n");
basic_async_example().await?;
timeout_example().await?;
concurrent_example().await?;
println!("\n=== All examples completed successfully! ===");
Ok(())
}
async fn basic_async_example() -> CanResult<()> {
println!("--- Example 1: Basic Async Send/Receive ---");
let preset_messages = vec![
CanMessage::new_standard(0x100, &[0x01, 0x02, 0x03, 0x04])?,
CanMessage::new_standard(0x200, &[0xAA, 0xBB, 0xCC, 0xDD])?,
];
let config = MockConfig::with_preset_messages(preset_messages);
let mut backend = MockBackend::with_config(config);
let backend_config = BackendConfig::new("mock");
backend.initialize(&backend_config)?;
backend.open_channel(0)?;
let msg1 = CanMessage::new_standard(0x123, &[0x11, 0x22, 0x33])?;
backend.send_message_async(&msg1).await?;
println!("Sent: ID=0x123, Data=[0x11, 0x22, 0x33]");
let msg2 = CanMessage::new_extended(0x1234_5678, &[0x44, 0x55])?;
backend.send_message_async(&msg2).await?;
println!("Sent: ID=0x12345678 (extended), Data=[0x44, 0x55]");
while let Some(msg) = backend.receive_message_async(None).await? {
println!("Received: ID={:?}, Data={:?}", msg.id(), msg.data());
}
let recorded = backend.get_recorded_messages();
println!("Total messages sent: {}", recorded.len());
backend.close()?;
println!();
Ok(())
}
async fn timeout_example() -> CanResult<()> {
println!("--- Example 2: Async Receive with Timeout ---");
let preset_messages = vec![CanMessage::new_standard(0x300, &[0x30])?];
let config = MockConfig::with_preset_messages(preset_messages);
let mut backend = MockBackend::with_config(config);
let backend_config = BackendConfig::new("mock");
backend.initialize(&backend_config)?;
backend.open_channel(0)?;
println!("Waiting for message with 100ms timeout...");
match backend
.receive_message_async(Some(Duration::from_millis(100)))
.await?
{
Some(msg) => println!("Received: ID={:?}, Data={:?}", msg.id(), msg.data()),
None => println!("Timeout - no message received"),
}
println!("Waiting for another message with 50ms timeout...");
let start = std::time::Instant::now();
match backend
.receive_message_async(Some(Duration::from_millis(50)))
.await?
{
Some(msg) => println!("Received: ID={:?}", msg.id()),
None => println!("Timeout after {:?} - no message available", start.elapsed()),
}
backend.close()?;
println!();
Ok(())
}
async fn concurrent_example() -> CanResult<()> {
println!("--- Example 3: Concurrent Message Sending ---");
use std::sync::Arc;
use tokio::sync::Mutex;
let mut backend = MockBackend::new();
let backend_config = BackendConfig::new("mock");
backend.initialize(&backend_config)?;
backend.open_channel(0)?;
let backend = Arc::new(Mutex::new(backend));
let mut handles = vec![];
for task_id in 0..4u16 {
let backend_clone = Arc::clone(&backend);
let handle = tokio::spawn(async move {
for msg_id in 0..5u16 {
let can_id = 0x100 + task_id * 0x10 + msg_id;
let msg = CanMessage::new_standard(can_id, &[task_id as u8, msg_id as u8]).unwrap();
let mut backend = backend_clone.lock().await;
backend.send_message_async(&msg).await.unwrap();
println!("Task {} sent message with ID 0x{:03X}", task_id, can_id);
}
});
handles.push(handle);
}
for handle in handles {
handle.await.unwrap();
}
let backend = backend.lock().await;
let total = backend.get_recorded_messages().len();
println!("\nTotal messages sent concurrently: {}", total);
assert_eq!(total, 20, "Expected 20 messages (4 tasks × 5 messages)");
println!();
Ok(())
}