use canlink_hal::monitor::{ConnectionMonitor, ConnectionState, ReconnectConfig};
use canlink_hal::{BackendConfig, CanBackend, CanMessage};
use canlink_mock::MockBackend;
use std::time::Duration;
fn main() -> Result<(), Box<dyn std::error::Error>> {
println!("=== CANLink HAL - Connection Monitor Example ===\n");
println!("1. Creating and initializing backend...");
let mut backend = MockBackend::new();
let config = BackendConfig::new("mock");
backend.initialize(&config)?;
backend.open_channel(0)?;
println!(" Backend initialized and channel opened\n");
println!("2. Creating basic connection monitor...");
let monitor = ConnectionMonitor::new(Duration::from_secs(1));
println!(" Heartbeat interval: {:?}", monitor.heartbeat_interval());
println!(
" Auto-reconnect enabled: {}",
monitor.auto_reconnect_enabled()
);
println!(" Current state: {:?}\n", monitor.state());
println!("3. Creating monitor with auto-reconnect...");
let reconnect_config = ReconnectConfig::exponential_backoff(
5, Duration::from_millis(500), 2.0, );
let monitor_with_reconnect =
ConnectionMonitor::with_reconnect(Duration::from_secs(1), reconnect_config);
println!(
" Auto-reconnect enabled: {}",
monitor_with_reconnect.auto_reconnect_enabled()
);
if let Some(config) = monitor_with_reconnect.reconnect_config() {
println!(" Max retries: {}", config.max_retries);
println!(" Initial retry interval: {:?}", config.retry_interval);
println!(" Backoff multiplier: {}", config.backoff_multiplier);
}
println!();
println!("4. Reconnect interval calculation (exponential backoff)...");
let config = ReconnectConfig::exponential_backoff(5, Duration::from_secs(1), 2.0);
for attempt in 0..5 {
let interval = config.interval_for_attempt(attempt);
println!(" Attempt {}: wait {:?}", attempt + 1, interval);
}
println!();
println!("5. Fixed interval reconnect configuration...");
let fixed_config = ReconnectConfig::fixed_interval(3, Duration::from_secs(2));
println!(" Max retries: {}", fixed_config.max_retries);
for attempt in 0..3 {
let interval = fixed_config.interval_for_attempt(attempt);
println!(" Attempt {}: wait {:?}", attempt + 1, interval);
}
println!();
println!("6. Simulating disconnect/reconnect scenario...");
let msg = CanMessage::new_standard(0x100, &[1, 2, 3, 4])?;
backend.send_message(&msg)?;
println!(" Message sent successfully");
backend.simulate_disconnect();
println!(" Simulated hardware disconnect");
println!(" Backend disconnected: {}", backend.is_disconnected());
let result = backend.send_message(&msg);
match result {
Ok(_) => println!(" Message sent (unexpected)"),
Err(e) => println!(" Send failed as expected: {}", e),
}
backend.simulate_reconnect();
println!(" Simulated hardware reconnect");
println!(" Backend disconnected: {}", backend.is_disconnected());
backend.send_message(&msg)?;
println!(" Message sent successfully after reconnect\n");
println!("7. Connection state transitions...");
let mut monitor = ConnectionMonitor::new(Duration::from_secs(1));
println!(" Initial state: {:?}", monitor.state());
monitor.set_state(ConnectionState::Disconnected);
println!(" After disconnect: {:?}", monitor.state());
monitor.set_state(ConnectionState::Reconnecting);
println!(" During reconnect: {:?}", monitor.state());
monitor.set_state(ConnectionState::Connected);
println!(" After reconnect: {:?}", monitor.state());
println!();
println!("8. Retry logic demonstration...");
let config = ReconnectConfig {
max_retries: 3,
retry_interval: Duration::from_secs(1),
backoff_multiplier: 2.0,
};
for attempt in 0..5 {
let should_retry = config.should_retry(attempt);
println!(
" Attempt {}: should_retry = {}",
attempt + 1,
should_retry
);
}
println!();
println!("9. Unlimited retries configuration...");
let unlimited_config = ReconnectConfig {
max_retries: 0, retry_interval: Duration::from_secs(5),
backoff_multiplier: 1.0,
};
println!(
" Max retries: {} (0 = unlimited)",
unlimited_config.max_retries
);
println!(
" Should retry at attempt 100: {}",
unlimited_config.should_retry(100)
);
println!(
" Should retry at attempt 1000: {}",
unlimited_config.should_retry(1000)
);
println!();
println!("10. Cleaning up...");
backend.close_channel(0)?;
backend.close()?;
println!(" Backend closed\n");
println!("=== Example completed successfully! ===");
Ok(())
}