Skip to content
Open
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
50 changes: 34 additions & 16 deletions src/api/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,6 @@ use uuid::Uuid;

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

use crate::platform::PeripheralId;

/// The default MTU size for a peripheral.
pub const DEFAULT_MTU_SIZE: u16 = 23;

Expand Down Expand Up @@ -254,8 +252,10 @@ pub enum WriteType {
/// as well as functions for communication.
#[async_trait]
pub trait Peripheral: Send + Sync + Clone + Debug {
type ID: PeripheralId;

/// Returns the unique identifier of the peripheral.
fn id(&self) -> PeripheralId;
fn id(&self) -> Self::ID;

/// Returns the MAC address of the peripheral.
fn address(&self) -> BDAddr;
Expand Down Expand Up @@ -380,6 +380,14 @@ pub trait Peripheral: Send + Sync + Clone + Debug {
}
}

/// ID for a [`Peripheral`].
///
/// Different backends use different ID types.
pub trait PeripheralId:
'static + Send + Sync + Clone + Debug + PartialEq + Eq + std::hash::Hash + std::fmt::Display
{
}

#[cfg_attr(
feature = "serde",
derive(Serialize, Deserialize),
Expand All @@ -399,33 +407,33 @@ pub enum CentralState {
serde(crate = "serde_cr")
)]
#[derive(Debug, Clone)]
pub enum CentralEvent {
DeviceDiscovered(PeripheralId),
DeviceUpdated(PeripheralId),
DeviceConnected(PeripheralId),
DeviceDisconnected(PeripheralId),
pub enum CentralEvent<ID: PeripheralId> {
DeviceDiscovered(ID),
DeviceUpdated(ID),
DeviceConnected(ID),
DeviceDisconnected(ID),
/// Only emitted on the corebluetooth subsystem
DeviceServicesModified(PeripheralId),
DeviceServicesModified(ID),
/// Emitted when a Manufacturer Data advertisement has been received from a device
ManufacturerDataAdvertisement {
id: PeripheralId,
id: ID,
manufacturer_data: HashMap<u16, Vec<u8>>,
},
/// Emitted when a Service Data advertisement has been received from a device
ServiceDataAdvertisement {
id: PeripheralId,
id: ID,
service_data: HashMap<Uuid, Vec<u8>>,
},
/// Emitted when the advertised services for a device has been updated
ServicesAdvertisement {
id: PeripheralId,
id: ID,
services: Vec<Uuid>,
},
/// Emitted when an RSSI (signal strength) update is received for a device.
/// This may come from advertisements during scanning, or from an active
/// `read_rssi()` call on connected platforms.
RssiUpdate {
id: PeripheralId,
id: ID,
rssi: i16,
},
StateUpdate(CentralState),
Expand All @@ -439,7 +447,11 @@ pub trait Central: Send + Sync + Clone {

/// Retrieve a stream of `CentralEvent`s. This stream will receive notifications when events
/// occur for this Central module. See [`CentralEvent`] for the full set of possible events.
async fn events(&self) -> Result<Pin<Box<dyn Stream<Item = CentralEvent> + Send>>>;
async fn events(
&self,
) -> Result<
Pin<Box<dyn Stream<Item = CentralEvent<<Self::Peripheral as Peripheral>::ID>> + Send>>,
>;

/// Starts a scan for BLE devices. This scan will generally continue until explicitly stopped,
/// although this may depend on your Bluetooth adapter. Discovered devices will be announced
Expand All @@ -458,10 +470,16 @@ 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, id: &PeripheralId) -> Result<Self::Peripheral>;
async fn peripheral(
&self,
id: &<Self::Peripheral as Peripheral>::ID,
) -> 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: &PeripheralId) -> Result<Self::Peripheral>;
async fn add_peripheral(
&self,
address: &<Self::Peripheral as Peripheral>::ID,
) -> Result<Self::Peripheral>;

/// Clears the list of [`Peripheral`]s that have been discovered so far. Connected peripherals
/// should be disconnected before calling this method. On platforms that do not cache peripherals
Expand Down
6 changes: 4 additions & 2 deletions src/bluez/adapter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,9 @@ fn get_central_state(powered: bool) -> CentralState {
impl Central for Adapter {
type Peripheral = Peripheral;

async fn events(&self) -> Result<Pin<Box<dyn Stream<Item = CentralEvent> + Send>>> {
async fn events(
&self,
) -> Result<Pin<Box<dyn Stream<Item = CentralEvent<PeripheralId>> + Send>>> {
// There's a race between getting this event stream and getting the current set of devices.
// Get the stream first, on the basis that it's better to have a duplicate DeviceDiscovered
// event than to miss one. It's unlikely to happen in any case.
Expand Down Expand Up @@ -145,7 +147,7 @@ async fn central_events(
event: BluetoothEvent,
session: BluetoothSession,
adapter_id: AdapterId,
) -> Option<Vec<CentralEvent>> {
) -> Option<Vec<CentralEvent<PeripheralId>>> {
match event {
BluetoothEvent::Device {
id,
Expand Down
4 changes: 4 additions & 0 deletions src/bluez/peripheral.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,8 @@ impl Display for PeripheralId {
}
}

impl crate::api::PeripheralId for PeripheralId {}

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

#[async_trait]
impl api::Peripheral for Peripheral {
type ID = PeripheralId;

fn id(&self) -> PeripheralId {
PeripheralId(self.device.to_owned())
}
Expand Down
17 changes: 9 additions & 8 deletions src/common/adapter_manager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
//
// Copyright (c) 2014 The Rust Project Developers
use crate::api::{CentralEvent, Peripheral};
use crate::platform::PeripheralId;
use dashmap::{DashMap, mapref::one::RefMut};
use futures::stream::{Stream, StreamExt};
use log::trace;
Expand All @@ -25,8 +24,8 @@ pub struct AdapterManager<PeripheralType>
where
PeripheralType: Peripheral,
{
peripherals: DashMap<PeripheralId, PeripheralType>,
events_channel: broadcast::Sender<CentralEvent>,
peripherals: DashMap<PeripheralType::ID, PeripheralType>,
events_channel: broadcast::Sender<CentralEvent<PeripheralType::ID>>,
}

impl<PeripheralType: Peripheral + 'static> Default for AdapterManager<PeripheralType> {
Expand All @@ -43,7 +42,7 @@ impl<PeripheralType> AdapterManager<PeripheralType>
where
PeripheralType: Peripheral + 'static,
{
pub fn emit(&self, event: CentralEvent) {
pub fn emit(&self, event: CentralEvent<PeripheralType::ID>) {
if let CentralEvent::DeviceDisconnected(ref id) = event {
self.peripherals.remove(id);
}
Expand All @@ -53,7 +52,9 @@ where
}
}

pub fn event_stream(&self) -> Pin<Box<dyn Stream<Item = CentralEvent> + Send>> {
pub fn event_stream(
&self,
) -> Pin<Box<dyn Stream<Item = CentralEvent<PeripheralType::ID>> + Send>> {
let receiver = self.events_channel.subscribe();
Box::pin(BroadcastStream::new(receiver).filter_map(|x| async move { x.ok() }))
}
Expand Down Expand Up @@ -81,12 +82,12 @@ where
#[allow(dead_code)]
pub fn peripheral_mut(
&self,
id: &PeripheralId,
) -> Option<RefMut<'_, PeripheralId, PeripheralType>> {
id: &PeripheralType::ID,
) -> Option<RefMut<'_, PeripheralType::ID, PeripheralType>> {
self.peripherals.get_mut(id)
}

pub fn peripheral(&self, id: &PeripheralId) -> Option<PeripheralType> {
pub fn peripheral(&self, id: &PeripheralType::ID) -> Option<PeripheralType> {
self.peripherals.get(id).map(|val| val.value().clone())
}
}
4 changes: 3 additions & 1 deletion src/corebluetooth/adapter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,9 @@ impl Adapter {
impl Central for Adapter {
type Peripheral = Peripheral;

async fn events(&self) -> Result<Pin<Box<dyn Stream<Item = CentralEvent> + Send>>> {
async fn events(
&self,
) -> Result<Pin<Box<dyn Stream<Item = CentralEvent<PeripheralId>> + Send>>> {
Ok(self.manager.event_stream())
}

Expand Down
6 changes: 5 additions & 1 deletion src/corebluetooth/peripheral.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ use uuid::Uuid;
#[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub struct PeripheralId(Uuid);

impl crate::api::PeripheralId for PeripheralId {}

impl Display for PeripheralId {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
Display::fmt(&self.0, f)
Expand All @@ -71,7 +73,7 @@ struct Shared {
}

impl Shared {
fn emit_event(&self, event: CentralEvent) {
fn emit_event(&self, event: CentralEvent<PeripheralId>) {
match self.manager.upgrade() {
Some(manager) => {
manager.emit(event);
Expand Down Expand Up @@ -231,6 +233,8 @@ impl Debug for Peripheral {

#[async_trait]
impl api::Peripheral for Peripheral {
type ID = PeripheralId;

fn id(&self) -> PeripheralId {
PeripheralId(self.shared.uuid)
}
Expand Down
4 changes: 3 additions & 1 deletion src/droidplug/adapter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,9 @@ impl Central for Adapter {
Ok("Android".to_string())
}

async fn events(&self) -> Result<Pin<Box<dyn Stream<Item = CentralEvent> + Send>>> {
async fn events(
&self,
) -> Result<Pin<Box<dyn Stream<Item = CentralEvent<PeripheralId>> + Send>>> {
Ok(self.manager.event_stream())
}

Expand Down
5 changes: 4 additions & 1 deletion src/droidplug/peripheral.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,8 @@ impl Display for PeripheralId {
}
}

impl crate::api::PeripheralId for PeripheralId {}

fn get_poll_result<'a: 'b, 'b>(
env: &'b JNIEnv<'a>,
result: JPollResult<'a, 'b>,
Expand Down Expand Up @@ -229,7 +231,8 @@ impl Debug for Peripheral {

#[async_trait]
impl api::Peripheral for Peripheral {
/// Returns the unique identifier of the peripheral.
type ID = PeripheralId;

fn id(&self) -> PeripheralId {
PeripheralId(self.addr)
}
Expand Down
4 changes: 3 additions & 1 deletion src/winrtble/adapter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,9 @@ impl Debug for Adapter {
impl Central for Adapter {
type Peripheral = Peripheral;

async fn events(&self) -> Result<Pin<Box<dyn Stream<Item = CentralEvent> + Send>>> {
async fn events(
&self,
) -> Result<Pin<Box<dyn Stream<Item = CentralEvent<PeripheralId>> + Send>>> {
Ok(self.manager.event_stream())
}

Expand Down
6 changes: 5 additions & 1 deletion src/winrtble/peripheral.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,8 @@ impl Display for PeripheralId {
}
}

impl crate::api::PeripheralId for PeripheralId {}

/// Implementation of [api::Peripheral](crate::api::Peripheral).
#[derive(Clone)]
pub struct Peripheral {
Expand Down Expand Up @@ -305,7 +307,7 @@ impl Peripheral {
}
}

fn emit_event(&self, event: CentralEvent) {
fn emit_event(&self, event: CentralEvent<PeripheralId>) {
if let Some(manager) = self.shared.adapter.upgrade() {
manager.emit(event);
} else {
Expand Down Expand Up @@ -354,6 +356,8 @@ impl Debug for Peripheral {

#[async_trait]
impl ApiPeripheral for Peripheral {
type ID = PeripheralId;

fn id(&self) -> PeripheralId {
PeripheralId(self.shared.address)
}
Expand Down
Loading