gestura_core_ble/
scanner.rs1use btleplug::api::{Central, Manager as _, Peripheral as _, ScanFilter};
2use btleplug::platform::{Adapter, Manager, Peripheral};
3use std::time::Duration;
4use uuid::Uuid;
5
6pub async fn find_device_by_service_uuid(
9 service_uuid: Uuid,
10 polling_attempts: u8,
11 polling_interval: Duration,
12) -> Result<(Adapter, Peripheral), String> {
13 let manager = Manager::new()
14 .await
15 .map_err(|e| format!("Failed to initialize BLE Manager: {}", e))?;
16 let adapters = manager
17 .adapters()
18 .await
19 .map_err(|e| format!("Failed to get BLE adapters: {}", e))?;
20 let adapter = adapters
21 .into_iter()
22 .next()
23 .ok_or("No Bluetooth adapters found")?;
24
25 adapter
26 .start_scan(ScanFilter {
27 services: vec![service_uuid],
28 })
29 .await
30 .map_err(|e| format!("Failed to start scan: {}", e))?;
31
32 tracing::info!("Scanning for device bounding service UUID {}", service_uuid);
33
34 let mut last_scan_error: Option<String> = None;
40 let mut successful_polls: u32 = 0;
41
42 for _ in 0..polling_attempts {
43 tokio::time::sleep(polling_interval).await;
44
45 let peripherals = match adapter.peripherals().await {
46 Ok(ps) => {
47 successful_polls += 1;
48 ps
49 }
50 Err(e) => {
51 tracing::warn!(
52 "Failed to list peripherals during BLE scan (will retry): {}",
53 e
54 );
55 last_scan_error = Some(e.to_string());
56 continue;
57 }
58 };
59
60 for p in peripherals {
61 let properties = match p.properties().await {
62 Ok(Some(props)) => props,
63 Ok(None) => continue,
64 Err(e) => {
65 tracing::warn!(
66 "Failed to read peripheral properties (skipping peripheral): {}",
67 e
68 );
69 continue;
70 }
71 };
72 if properties.services.contains(&service_uuid) {
73 let _ = adapter.stop_scan().await;
74 return Ok((adapter, p));
75 }
76 }
77 }
78
79 let _ = adapter.stop_scan().await;
80
81 if successful_polls == 0
85 && let Some(err) = last_scan_error
86 {
87 return Err(format!(
88 "BLE scan failed for service {} – adapter could not list peripherals: {}",
89 service_uuid, err
90 ));
91 }
92
93 Err(format!(
94 "Device mapped to BLE service {} not found across bounds",
95 service_uuid
96 ))
97}