use std::time::Duration;
use tokio::signal;
use tokio::time::sleep;
use knust::protocol::address::{Address, GroupAddress, IndividualAddress};
use knust::protocol::telegram::{Direction, Priority, Telegram, TelegramType};
use knust::{ConnectionConfig, ConnectionType, Knx};
async fn graceful_shutdown(knx: Knx) -> Result<(), Box<dyn std::error::Error>> {
println!("Shutting down gracefully...");
knx.disconnect().await?;
println!("Disconnected from KNX network");
Ok(())
}
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
const MAX_RETRIES: u32 = 3;
env_logger::init();
let config = ConnectionConfig {
connection_type: ConnectionType::Tunneling,
gateway_ip: Some("192.168.1.100".parse()?),
individual_address: IndividualAddress::new(1, 1, 240),
auto_reconnect: true,
..Default::default()
};
let knx = Knx::new(config).await?;
let knx_clone = knx.clone();
tokio::spawn(async move {
signal::ctrl_c().await.expect("Failed to listen for Ctrl+C");
println!("Received Ctrl+C, initiating graceful shutdown...");
if let Err(e) = graceful_shutdown(knx_clone).await {
eprintln!("Error during shutdown: {e}");
}
std::process::exit(0);
});
println!("Connecting to KNX network...");
let mut retry_count = 0;
loop {
match knx.connect().await {
Ok(()) => {
println!("Successfully connected to KNX network");
break;
}
Err(e) => {
retry_count += 1;
if retry_count >= MAX_RETRIES {
eprintln!("Failed to connect after {MAX_RETRIES} attempts: {e}");
return Err(e.into());
}
println!("Connection attempt {retry_count} failed: {e}. Retrying in 2 seconds...");
sleep(Duration::from_secs(2)).await;
}
}
}
let source = IndividualAddress::new(1, 1, 240);
let switch_address = GroupAddress::from_parts(1, 0, 9).expect("Valid address");
let switch_telegram = |on: bool| Telegram {
source,
destination: Address::Group(switch_address),
payload: vec![u8::from(on)],
priority: Priority::Normal,
direction: Direction::Outgoing,
telegram_type: TelegramType::GroupValueWrite,
gateway_id: None,
timestamp: std::time::SystemTime::now(),
};
println!("Performing operations...");
for i in 1..=5 {
println!("Operation {i}/5: Toggling switch");
knx.send_telegram(&switch_telegram(true)).await?;
sleep(Duration::from_secs(1)).await;
knx.send_telegram(&switch_telegram(false)).await?;
sleep(Duration::from_secs(1)).await;
}
if knx.is_connected().await {
println!("Connection is still active");
} else {
println!("Connection lost, attempting to reconnect...");
knx.connect().await?;
}
graceful_shutdown(knx).await?;
println!("Disconnect example completed successfully!");
Ok(())
}