use crate::api::{BDAddr, CentralEvent, Peripheral};
use dashmap::DashMap;
use std::sync::mpsc::{channel, Receiver, Sender};
use std::sync::{Arc, Mutex};
#[derive(Clone, Debug)]
pub struct AdapterManager<PeripheralType>
where
PeripheralType: Peripheral,
{
peripherals: Arc<DashMap<BDAddr, PeripheralType>>,
event_sender: Arc<Mutex<Sender<CentralEvent>>>,
event_receiver: Arc<Mutex<Option<Receiver<CentralEvent>>>>,
}
impl<PeripheralType> AdapterManager<PeripheralType>
where
PeripheralType: Peripheral + 'static,
{
pub fn new() -> Self {
let peripherals = Arc::new(DashMap::new());
let (event_sender, event_receiver) = channel();
AdapterManager {
peripherals,
event_sender: Arc::new(Mutex::new(event_sender)),
event_receiver: Arc::new(Mutex::new(Some(event_receiver))),
}
}
pub fn emit(&self, event: CentralEvent) {
match event {
CentralEvent::DeviceDisconnected(addr) => {
self.peripherals.remove(&addr);
}
CentralEvent::DeviceLost(addr) => {
self.peripherals.remove(&addr);
}
_ => {}
}
self.event_sender.lock().unwrap().send(event).unwrap();
}
pub fn event_receiver(&self) -> Option<Receiver<CentralEvent>> {
self.event_receiver.lock().unwrap().take()
}
pub fn has_peripheral(&self, addr: &BDAddr) -> bool {
self.peripherals.contains_key(addr)
}
pub fn add_peripheral(&self, addr: BDAddr, peripheral: PeripheralType) {
assert!(
!self.peripherals.contains_key(&addr),
"Adding a peripheral that's already in the map."
);
assert_eq!(peripheral.address(), addr, "Device has unexpected address."); self.peripherals.insert(addr, peripheral);
}
pub fn update_peripheral(&self, addr: BDAddr, peripheral: PeripheralType) {
assert!(
self.peripherals.contains_key(&addr),
"Updating a peripheral that's not in the map."
);
assert_eq!(peripheral.address(), addr, "Device has unexpected address."); let current_peripheral = self.peripherals.get_mut(&addr).unwrap();
if peripheral.properties().local_name.is_some()
&& current_peripheral.properties().local_name.is_none()
{
current_peripheral.properties().local_name = peripheral.properties().local_name;
}
if peripheral.properties().manufacturer_data.is_some()
&& current_peripheral.properties().manufacturer_data.is_none()
{
current_peripheral.properties().manufacturer_data =
peripheral.properties().manufacturer_data;
}
current_peripheral.properties().tx_power_level = peripheral.properties().tx_power_level;
}
pub fn peripherals(&self) -> Vec<PeripheralType> {
self.peripherals
.iter()
.map(|val| val.value().clone())
.collect()
}
pub fn peripheral(&self, address: BDAddr) -> Option<PeripheralType> {
self.peripherals
.get(&address)
.and_then(|val| Some(val.value().clone()))
}
}