use std::collections::HashSet; use std::time::Duration; use bluer::{Adapter, AdapterEvent, Address, Device, Result, Uuid}; use bluer::gatt::remote::Characteristic; use futures::{pin_mut, StreamExt}; use tokio::sync::mpsc; // const CONNECT_RETRIES: u8 = 3; // const SERVICE_UUID: bluer::Uuid = bluer::Uuid::from_u128(0xadaf0900c33242a893bd25e905756cb8); // const PIXEL_DATA_UUID: bluer::Uuid = bluer::Uuid::from_u128(0xadaf0903c33242a893bd25e905756cb8); pub(crate) async fn create_session() -> Result { let session = bluer::Session::new().await?; let adapter_names = session.adapter_names().await?; let adapter_name = adapter_names.first().expect("no Bluetooth adapter found"); let adapter = session.adapter(adapter_name)?; adapter.set_powered(true).await?; Ok(adapter) } async fn has_service(device: &Device, uuid: &Uuid) -> Result { let uuids = device.uuids().await?.unwrap_or_default(); if uuids.contains(uuid) { return Ok(true) } Ok(false) } async fn bluetooth_scan(tx: mpsc::Sender, adapter: Adapter, uuid: Uuid) -> Result<()> { println!("start bluetooth scan"); let discover = adapter.discover_devices().await?; let mut already_scanned: HashSet
= HashSet::new(); pin_mut!(discover); while let Some(evt) = discover.next().await { match evt { AdapterEvent::DeviceAdded(addr) => { println!("device adress {}", addr); if already_scanned.contains(&addr) { continue; } already_scanned.insert(addr); let device = adapter.device(addr)?; match has_service(&device, &uuid).await { Ok(service_found) => { if service_found { tx.send(device).await.unwrap(); println!("found service in device {}", addr); } } Err(_) => { continue } } } _ => {} } } println!("ended"); Ok(()) } pub(crate) async fn scan_devices(adapter: Adapter, uuid: Uuid) -> Vec { println!("start scanning devices"); let (tx, mut rx) = mpsc::channel(4); let timeout = tokio::time::timeout(Duration::from_secs(30), bluetooth_scan(tx, adapter, uuid)); let scan = tokio::spawn(timeout); println!("good"); let mut devices: Vec = Vec::new(); while let Some(device)= rx.recv().await { println!("new device received {}", device.address()); devices.push(device); println!("len {}", devices.len()); if devices.len() >= 2 { println!("drop"); drop(scan); break; } } devices } pub async fn connect(device: &Device, retries: u8) -> bluer::Result<()> { if device.is_connected().await? { return Ok(()) } for i in 0..retries { match device.connect().await { Ok(()) => return Ok(()), Err(_) => { println!("connection error ({}), retry…", i); } } } Err(bluer::Error { kind: bluer::ErrorKind::ConnectionAttemptFailed, message: "all attempts fail".parse().unwrap(), }) } pub async fn get_char(device: &Device, service_uuid: Uuid, char_uuid: Uuid) -> Result> { for service in device.services().await? { if service_uuid == service.uuid().await? { for char in service.characteristics().await? { println!("uuid : {}", &char.uuid().await?); if char_uuid == char.uuid().await? { return Ok(Some(char)); } } } } Ok(None) }