use bacnet_client::client::BACnetClient;
use bacnet_services::who_has::WhoHasObject;
use bacnet_services::who_is::DeviceInstanceRange;
use bacnet_transport::port::TransportPort;
use crate::output::{self, device_info, DeviceInfo, OutputFormat};
async fn collect_devices<T: TransportPort + 'static>(
client: &BACnetClient<T>,
range: Option<DeviceInstanceRange>,
) -> Vec<DeviceInfo> {
let devices = client.discovered_devices().await;
devices
.iter()
.filter(|d| {
let inst = d.object_identifier.instance_number();
range.is_none_or(|range| range.contains(inst))
})
.map(device_info)
.collect()
}
pub async fn discover<T: TransportPort + 'static>(
client: &BACnetClient<T>,
range: Option<DeviceInstanceRange>,
wait_secs: u64,
format: OutputFormat,
) -> Result<(), Box<dyn std::error::Error>> {
client.who_is(range).await?;
output::print_waiting(wait_secs);
tokio::time::sleep(std::time::Duration::from_secs(wait_secs)).await;
output::print_devices(&collect_devices(client, range).await, format);
Ok(())
}
pub async fn discover_directed<T: TransportPort + 'static>(
client: &BACnetClient<T>,
target_mac: &[u8],
range: Option<DeviceInstanceRange>,
wait_secs: u64,
format: OutputFormat,
) -> Result<(), Box<dyn std::error::Error>> {
client.who_is_directed(target_mac, range).await?;
output::print_waiting(wait_secs);
tokio::time::sleep(std::time::Duration::from_secs(wait_secs)).await;
output::print_devices(&collect_devices(client, range).await, format);
Ok(())
}
pub async fn discover_network<T: TransportPort + 'static>(
client: &BACnetClient<T>,
dnet: u16,
range: Option<DeviceInstanceRange>,
wait_secs: u64,
format: OutputFormat,
) -> Result<(), Box<dyn std::error::Error>> {
client.who_is_network(dnet, range).await?;
output::print_waiting(wait_secs);
tokio::time::sleep(std::time::Duration::from_secs(wait_secs)).await;
output::print_devices(&collect_devices(client, range).await, format);
Ok(())
}
pub async fn find_by_name<T: TransportPort + 'static>(
client: &BACnetClient<T>,
name: &str,
wait_secs: u64,
format: OutputFormat,
) -> Result<(), Box<dyn std::error::Error>> {
client
.who_has(WhoHasObject::Name(name.to_string()), None)
.await?;
tokio::time::sleep(std::time::Duration::from_secs(wait_secs)).await;
output::print_success(
&format!("WhoHas broadcast sent for '{name}'. IHave response capture not yet implemented."),
format,
);
Ok(())
}