rust_powered_lego/
connection_manager.rs1use std::time::Duration;
2use std::str::FromStr;
3use std::collections::HashMap;
4
5use tokio::time;
6
7use btleplug::api::{BDAddr, Manager as _, Central, ScanFilter, Peripheral as _};
8use btleplug::platform::{Manager, Peripheral};
9
10use anyhow::{Result, anyhow};
11
12use crate::hub::Hub;
13
14struct PeripheralInfo {
15 address: BDAddr,
16 local_name: String,
17 }
19
20pub struct ConnectionManager {}
21
22impl ConnectionManager {
23 pub fn new() -> Self {
24 Self {}
25 }
26
27 pub async fn get_hub(
28 &self,
29 peripheral_name: Option<String>,
30 bd_add: Option<BDAddr>,
31 scan_time_seconds: u64,
32 ) -> Result<Hub> {
33 let p = self.get_peripheral(peripheral_name, bd_add, scan_time_seconds).await?;
34 Hub::new(p).await
35 }
36
37 async fn get_peripheral(
38 &self,
39 mut peripheral_name: Option<String>,
40 mut bd_add: Option<BDAddr>,
41 scan_time_seconds: u64,
42 ) -> Result<Peripheral> {
43 if bd_add.is_none() {
44 if let Ok(x) = BDAddr::from_str("00:00:00:00:00:00") {
45 bd_add = Some(x);
46 }
47 }
48 if peripheral_name.is_none() {
49 peripheral_name = Some(String::from_str("")?);
50 }
51 let peripherals = self.get_peripherals(scan_time_seconds).await?;
52 let mut peripheral_info: PeripheralInfo;
54 if !peripherals.is_empty() {
55
56 for peripheral in peripherals.into_iter() {
58 peripheral_info = self.get_peripheral_info(&peripheral).await?;
59 if peripheral_info.local_name.eq(peripheral_name.as_ref().unwrap()) || peripheral_info.address.eq(bd_add.as_ref().unwrap()) {
61 let is_connected = peripheral.is_connected().await?;
62 if !is_connected {
66 println!("Connecting to peripheral {:?}...", &peripheral_info.local_name);
67 if let Err(err) = peripheral.connect().await {
68 eprintln!("Error connecting to peripheral, skipping: {}", err);
69 continue;
70 }
71 }
72 if peripheral.is_connected().await? {
73 return Ok(peripheral);
74 }
75 }
76 }
77 }
78 Err(anyhow!("No connections found"))
79 }
80
81 async fn get_peripherals(&self, scan_time_seconds: u64) -> Result<Vec<Peripheral>> {
82 let manager = Manager::new().await?;
83 let adapter_list = manager.adapters().await?;
84 if adapter_list.is_empty() {
85 eprintln!("No Bluetooth adapters found");
86 }
87
88 let mut peripherals: Vec<Peripheral> = Vec::new();
89
90 for adapter in adapter_list.iter() {
91 adapter
93 .start_scan(ScanFilter::default())
94 .await
95 .expect("Can't scan BLE adapter for connected devices...");
96 time::sleep(Duration::from_secs(scan_time_seconds)).await;
97 peripherals.append(&mut adapter.peripherals().await?);
98 }
99 Ok(peripherals)
100 }
101
102 async fn get_peripheral_info(&self, peripheral: &Peripheral) -> Result<PeripheralInfo> {
103 let properties = peripheral.properties().await?;
104 let def_str = String::from("(peripheral name unknown)");
105 let local_name = properties.as_ref().unwrap()
106 .local_name.as_ref()
107 .unwrap_or(&def_str);
108 let address = properties.as_ref()
109 .unwrap()
110 .address;
111 let mut manufacturer_data: HashMap<u16, Vec<u8>> = HashMap::new();
112 manufacturer_data.clone_from(&properties.as_ref()
113 .unwrap()
114 .manufacturer_data);
115
116 Ok(PeripheralInfo {
117 address: address,
118 local_name: local_name.to_string(),
119 })
121
122 }
123}
124