use super::{ble::watcher::BLEWatcher, peripheral::Peripheral, peripheral::PeripheralId};
use crate::{
api::{BDAddr, Central, CentralEvent, ScanFilter},
common::adapter_manager::AdapterManager,
Error, Result,
};
use async_trait::async_trait;
use futures::stream::Stream;
use std::convert::TryInto;
use std::fmt::{self, Debug, Formatter};
use std::pin::Pin;
use std::sync::{Arc, Mutex};
#[derive(Clone)]
pub struct Adapter {
watcher: Arc<Mutex<BLEWatcher>>,
manager: Arc<AdapterManager<Peripheral>>,
}
impl Adapter {
pub(crate) fn new() -> Self {
let watcher = Arc::new(Mutex::new(BLEWatcher::new()));
let manager = Arc::new(AdapterManager::default());
Adapter { watcher, manager }
}
}
impl Debug for Adapter {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
f.debug_struct("Adapter")
.field("manager", &self.manager)
.finish()
}
}
#[async_trait]
impl Central for Adapter {
type Peripheral = Peripheral;
async fn events(&self) -> Result<Pin<Box<dyn Stream<Item = CentralEvent> + Send>>> {
Ok(self.manager.event_stream())
}
async fn start_scan(&self, filter: ScanFilter) -> Result<()> {
let watcher = self.watcher.lock().unwrap();
let manager = self.manager.clone();
watcher.start(
filter,
Box::new(move |args| {
let bluetooth_address = args.BluetoothAddress().unwrap();
let address: BDAddr = bluetooth_address.try_into().unwrap();
if let Some(mut entry) = manager.peripheral_mut(&address.into()) {
entry.value_mut().update_properties(args);
manager.emit(CentralEvent::DeviceUpdated(address.into()));
} else {
let peripheral = Peripheral::new(Arc::downgrade(&manager), address);
peripheral.update_properties(args);
manager.add_peripheral(peripheral);
manager.emit(CentralEvent::DeviceDiscovered(address.into()));
}
}),
)
}
async fn stop_scan(&self) -> Result<()> {
let watcher = self.watcher.lock().unwrap();
watcher.stop().unwrap();
Ok(())
}
async fn peripherals(&self) -> Result<Vec<Peripheral>> {
Ok(self.manager.peripherals())
}
async fn peripheral(&self, id: &PeripheralId) -> Result<Peripheral> {
self.manager.peripheral(id).ok_or(Error::DeviceNotFound)
}
async fn add_peripheral(&self, _address: &PeripheralId) -> Result<Peripheral> {
Err(Error::NotSupported(
"Can't add a Peripheral from a BDAddr".to_string(),
))
}
async fn adapter_info(&self) -> Result<String> {
Ok("WinRT".to_string())
}
}