Skip to content

Add type PeripheralId #205

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Sep 2, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 12 additions & 18 deletions examples/event_driven_discovery.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,37 +40,31 @@ async fn main() -> Result<(), Box<dyn Error>> {
// thread (not task, as this library does not yet use async channels).
while let Some(event) = events.next().await {
match event {
CentralEvent::DeviceDiscovered(bd_addr) => {
println!("DeviceDiscovered: {:?}", bd_addr);
CentralEvent::DeviceDiscovered(id) => {
println!("DeviceDiscovered: {:?}", id);
}
CentralEvent::DeviceConnected(bd_addr) => {
println!("DeviceConnected: {:?}", bd_addr);
CentralEvent::DeviceConnected(id) => {
println!("DeviceConnected: {:?}", id);
}
CentralEvent::DeviceDisconnected(bd_addr) => {
println!("DeviceDisconnected: {:?}", bd_addr);
CentralEvent::DeviceDisconnected(id) => {
println!("DeviceDisconnected: {:?}", id);
}
CentralEvent::ManufacturerDataAdvertisement {
address,
id,
manufacturer_data,
} => {
println!(
"ManufacturerDataAdvertisement: {:?}, {:?}",
address, manufacturer_data
id, manufacturer_data
);
}
CentralEvent::ServiceDataAdvertisement {
address,
service_data,
} => {
println!(
"ServiceDataAdvertisement: {:?}, {:?}",
address, service_data
);
CentralEvent::ServiceDataAdvertisement { id, service_data } => {
println!("ServiceDataAdvertisement: {:?}, {:?}", id, service_data);
}
CentralEvent::ServicesAdvertisement { address, services } => {
CentralEvent::ServicesAdvertisement { id, services } => {
let services: Vec<String> =
services.into_iter().map(|s| s.to_short_string()).collect();
println!("ServicesAdvertisement: {:?}, {:?}", address, services);
println!("ServicesAdvertisement: {:?}, {:?}", id, services);
}
_ => {}
}
Expand Down
21 changes: 13 additions & 8 deletions src/api/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ use uuid::Uuid;

pub use self::bdaddr::{BDAddr, ParseBDAddrError};

use crate::platform::PeripheralId;

#[cfg_attr(
feature = "serde",
derive(Serialize, Deserialize),
Expand Down Expand Up @@ -193,6 +195,9 @@ pub enum WriteType {
/// as well as functions for communication.
#[async_trait]
pub trait Peripheral: Send + Sync + Clone + Debug {
/// Returns the unique identifier of the peripheral.
fn id(&self) -> PeripheralId;

/// Returns the MAC address of the peripheral.
fn address(&self) -> BDAddr;

Expand Down Expand Up @@ -260,23 +265,23 @@ pub trait Peripheral: Send + Sync + Clone + Debug {
)]
#[derive(Debug, Clone)]
pub enum CentralEvent {
DeviceDiscovered(BDAddr),
DeviceUpdated(BDAddr),
DeviceConnected(BDAddr),
DeviceDisconnected(BDAddr),
DeviceDiscovered(PeripheralId),
DeviceUpdated(PeripheralId),
DeviceConnected(PeripheralId),
DeviceDisconnected(PeripheralId),
/// Emitted when a Manufacturer Data advertisement has been received from a device
ManufacturerDataAdvertisement {
address: BDAddr,
id: PeripheralId,
manufacturer_data: HashMap<u16, Vec<u8>>,
},
/// Emitted when a Service Data advertisement has been received from a device
ServiceDataAdvertisement {
address: BDAddr,
id: PeripheralId,
service_data: HashMap<Uuid, Vec<u8>>,
},
/// Emitted when the advertised services for a device has been updated
ServicesAdvertisement {
address: BDAddr,
id: PeripheralId,
services: Vec<Uuid>,
},
}
Expand Down Expand Up @@ -304,7 +309,7 @@ pub trait Central: Send + Sync + Clone {
async fn peripherals(&self) -> Result<Vec<Self::Peripheral>>;

/// Returns a particular [`Peripheral`] by its address if it has been discovered.
async fn peripheral(&self, address: BDAddr) -> Result<Self::Peripheral>;
async fn peripheral(&self, id: &PeripheralId) -> Result<Self::Peripheral>;

/// Add a [`Peripheral`] from a MAC address without a scan result. Not supported on all Bluetooth systems.
async fn add_peripheral(&self, address: BDAddr) -> Result<Self::Peripheral>;
Expand Down
14 changes: 7 additions & 7 deletions src/bluez/adapter.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use super::peripheral::Peripheral;
use super::peripheral::{Peripheral, PeripheralId};
use crate::api::{BDAddr, Central, CentralEvent};
use crate::{Error, Result};
use async_trait::async_trait;
Expand Down Expand Up @@ -37,7 +37,7 @@ impl Central for Adapter {
let initial_events = stream::iter(
devices
.into_iter()
.map(|device| CentralEvent::DeviceDiscovered(BDAddr::from(&device.mac_address))),
.map(|device| CentralEvent::DeviceDiscovered((&device.mac_address).into())),
);

let session = self.session.clone();
Expand Down Expand Up @@ -68,12 +68,12 @@ impl Central for Adapter {
.collect())
}

async fn peripheral(&self, address: BDAddr) -> Result<Peripheral> {
async fn peripheral(&self, id: &PeripheralId) -> Result<Peripheral> {
let devices = self.session.get_devices().await?;
devices
.into_iter()
.find_map(|device| {
if BDAddr::from(&device.mac_address) == address {
if PeripheralId::from(&device.mac_address) == *id {
Some(Peripheral::new(self.session.clone(), device))
} else {
None
Expand Down Expand Up @@ -130,7 +130,7 @@ async fn central_event(event: BluetoothEvent, session: BluetoothSession) -> Opti
} => {
let device = session.get_device_info(&id).await.ok()?;
Some(CentralEvent::ManufacturerDataAdvertisement {
address: (&device.mac_address).into(),
id: (&device.mac_address).into(),
manufacturer_data,
})
}
Expand All @@ -140,7 +140,7 @@ async fn central_event(event: BluetoothEvent, session: BluetoothSession) -> Opti
} => {
let device = session.get_device_info(&id).await.ok()?;
Some(CentralEvent::ServiceDataAdvertisement {
address: (&device.mac_address).into(),
id: (&device.mac_address).into(),
service_data,
})
}
Expand All @@ -150,7 +150,7 @@ async fn central_event(event: BluetoothEvent, session: BluetoothSession) -> Opti
} => {
let device = session.get_device_info(&id).await.ok()?;
Some(CentralEvent::ServicesAdvertisement {
address: (&device.mac_address).into(),
id: (&device.mac_address).into(),
services,
})
}
Expand Down
22 changes: 22 additions & 0 deletions src/bluez/peripheral.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@ use bluez_async::{
};
use futures::future::ready;
use futures::stream::{Stream, StreamExt};
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
#[cfg(feature = "serde")]
use serde_cr as serde;
use std::collections::{BTreeSet, HashMap};
use std::pin::Pin;
use std::sync::{Arc, Mutex};
Expand All @@ -22,6 +26,14 @@ struct ServiceInternal {
characteristics: HashMap<Uuid, CharacteristicInfo>,
}

#[cfg_attr(
feature = "serde",
derive(Serialize, Deserialize),
serde(crate = "serde_cr")
)]
#[derive(Clone, Debug, Eq, Hash, PartialEq)]
pub struct PeripheralId(BDAddr);

/// Implementation of [api::Peripheral](crate::api::Peripheral).
#[derive(Clone, Debug)]
pub struct Peripheral {
Expand Down Expand Up @@ -75,6 +87,10 @@ impl Peripheral {

#[async_trait]
impl api::Peripheral for Peripheral {
fn id(&self) -> PeripheralId {
PeripheralId(self.address())
}

fn address(&self) -> BDAddr {
self.mac_address
}
Expand Down Expand Up @@ -229,6 +245,12 @@ impl From<&MacAddress> for BDAddr {
}
}

impl From<&MacAddress> for PeripheralId {
fn from(mac_address: &MacAddress) -> Self {
PeripheralId(BDAddr::from(mac_address))
}
}

impl From<bluez_async::AddressType> for AddressType {
fn from(address_type: bluez_async::AddressType) -> Self {
match address_type {
Expand Down
27 changes: 15 additions & 12 deletions src/common/adapter_manager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@
// following copyright:
//
// Copyright (c) 2014 The Rust Project Developers
use crate::api::{BDAddr, CentralEvent, Peripheral};
use crate::api::{CentralEvent, Peripheral};
use crate::platform::PeripheralId;
use dashmap::{mapref::one::RefMut, DashMap};
use futures::stream::{Stream, StreamExt};
use log::trace;
Expand All @@ -30,7 +31,7 @@ where

#[derive(Debug)]
struct Shared<PeripheralType> {
peripherals: DashMap<BDAddr, PeripheralType>,
peripherals: DashMap<PeripheralId, PeripheralType>,
events_channel: broadcast::Sender<CentralEvent>,
}

Expand All @@ -52,8 +53,8 @@ where
{
pub fn emit(&self, event: CentralEvent) {
match event {
CentralEvent::DeviceDisconnected(addr) => {
self.shared.peripherals.remove(&addr);
CentralEvent::DeviceDisconnected(ref id) => {
self.shared.peripherals.remove(id);
}
_ => {}
}
Expand All @@ -74,13 +75,12 @@ where
}))
}

pub fn add_peripheral(&self, addr: BDAddr, peripheral: PeripheralType) {
pub fn add_peripheral(&self, peripheral: PeripheralType) {
assert!(
!self.shared.peripherals.contains_key(&addr),
!self.shared.peripherals.contains_key(&peripheral.id()),
"Adding a peripheral that's already in the map."
);
assert_eq!(peripheral.address(), addr, "Device has unexpected address."); // TODO remove addr argument
self.shared.peripherals.insert(addr, peripheral);
self.shared.peripherals.insert(peripheral.id(), peripheral);
}

pub fn peripherals(&self) -> Vec<PeripheralType> {
Expand All @@ -91,14 +91,17 @@ where
.collect()
}

pub fn peripheral_mut(&self, address: BDAddr) -> Option<RefMut<BDAddr, PeripheralType>> {
self.shared.peripherals.get_mut(&address)
pub fn peripheral_mut(
&self,
id: &PeripheralId,
) -> Option<RefMut<PeripheralId, PeripheralType>> {
self.shared.peripherals.get_mut(id)
}

pub fn peripheral(&self, address: BDAddr) -> Option<PeripheralType> {
pub fn peripheral(&self, id: &PeripheralId) -> Option<PeripheralType> {
self.shared
.peripherals
.get(&address)
.get(id)
.map(|val| val.value().clone())
}
}
42 changes: 14 additions & 28 deletions src/corebluetooth/adapter.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use super::internal::{run_corebluetooth_thread, CoreBluetoothEvent, CoreBluetoothMessage};
use super::peripheral::Peripheral;
use super::peripheral::{Peripheral, PeripheralId};
use crate::api::{BDAddr, Central, CentralEvent};
use crate::common::adapter_manager::AdapterManager;
use crate::{Error, Result};
Expand All @@ -19,11 +19,6 @@ pub struct Adapter {
sender: Sender<CoreBluetoothMessage>,
}

pub(crate) fn uuid_to_bdaddr(uuid: &str) -> BDAddr {
let b: [u8; 6] = uuid.as_bytes()[0..6].try_into().unwrap();
BDAddr::try_from(b).unwrap()
}

impl Adapter {
pub(crate) async fn new() -> Result<Self> {
let (sender, mut receiver) = mpsc::channel(256);
Expand Down Expand Up @@ -53,31 +48,24 @@ impl Adapter {
name,
event_receiver,
} => {
// TODO Gotta change uuid into a BDAddr for now. Expand
// library identifier type. :(
let id = uuid_to_bdaddr(&uuid.to_string());
manager_clone.add_peripheral(
id,
Peripheral::new(
uuid,
name,
manager_clone.clone(),
event_receiver,
adapter_sender_clone.clone(),
),
);
manager_clone.emit(CentralEvent::DeviceDiscovered(id));
manager_clone.add_peripheral(Peripheral::new(
uuid,
name,
manager_clone.clone(),
event_receiver,
adapter_sender_clone.clone(),
));
manager_clone.emit(CentralEvent::DeviceDiscovered(uuid.into()));
}
CoreBluetoothEvent::DeviceUpdated { uuid, name } => {
let id = uuid_to_bdaddr(&uuid.to_string());
if let Some(entry) = manager_clone.peripheral_mut(id) {
let id = uuid.into();
if let Some(entry) = manager_clone.peripheral_mut(&id) {
entry.value().update_name(&name);
manager_clone.emit(CentralEvent::DeviceUpdated(id));
}
}
CoreBluetoothEvent::DeviceDisconnected { uuid } => {
let id = uuid_to_bdaddr(&uuid.to_string());
manager_clone.emit(CentralEvent::DeviceDisconnected(id));
manager_clone.emit(CentralEvent::DeviceDisconnected(uuid.into()));
}
_ => {}
}
Expand Down Expand Up @@ -119,10 +107,8 @@ impl Central for Adapter {
Ok(self.manager.peripherals())
}

async fn peripheral(&self, address: BDAddr) -> Result<Peripheral> {
self.manager
.peripheral(address)
.ok_or(Error::DeviceNotFound)
async fn peripheral(&self, id: &PeripheralId) -> Result<Peripheral> {
self.manager.peripheral(id).ok_or(Error::DeviceNotFound)
}

async fn add_peripheral(&self, _address: BDAddr) -> Result<Peripheral> {
Expand Down
Loading