btleplug/bluez/
adapter.rs1use super::peripheral::{Peripheral, PeripheralId};
2use crate::api::{Central, CentralEvent, ScanFilter};
3use crate::{Error, Result};
4use async_trait::async_trait;
5use bluez_async::{
6 AdapterId, BluetoothError, BluetoothEvent, BluetoothSession, DeviceEvent, DiscoveryFilter,
7 Transport,
8};
9use futures::stream::{self, Stream, StreamExt};
10use std::pin::Pin;
11
12#[derive(Clone, Debug)]
14pub struct Adapter {
15 session: BluetoothSession,
16 adapter: AdapterId,
17}
18
19impl Adapter {
20 pub(crate) fn new(session: BluetoothSession, adapter: AdapterId) -> Self {
21 Self { session, adapter }
22 }
23}
24
25#[async_trait]
26impl Central for Adapter {
27 type Peripheral = Peripheral;
28
29 async fn events(&self) -> Result<Pin<Box<dyn Stream<Item = CentralEvent> + Send>>> {
30 let events = self.session.adapter_event_stream(&self.adapter).await?;
34
35 let devices = self.session.get_devices().await?;
37 let adapter_id = self.adapter.clone();
38 let initial_events = stream::iter(
39 devices
40 .into_iter()
41 .filter(move |device| device.id.adapter() == adapter_id)
42 .flat_map(|device| {
43 let mut events = vec![CentralEvent::DeviceDiscovered(device.id.clone().into())];
44 if device.connected {
45 events.push(CentralEvent::DeviceConnected(device.id.into()));
46 }
47 events.into_iter()
48 }),
49 );
50
51 let session = self.session.clone();
52 let adapter_id = self.adapter.clone();
53 let events = events
54 .filter_map(move |event| central_event(event, session.clone(), adapter_id.clone()));
55
56 Ok(Box::pin(initial_events.chain(events)))
57 }
58
59 async fn start_scan(&self, filter: ScanFilter) -> Result<()> {
60 let filter = DiscoveryFilter {
61 service_uuids: filter.services,
62 duplicate_data: Some(true),
63 transport: Some(Transport::Auto),
64 ..Default::default()
65 };
66 self.session
67 .start_discovery_on_adapter_with_filter(&self.adapter, &filter)
68 .await?;
69 Ok(())
70 }
71
72 async fn stop_scan(&self) -> Result<()> {
73 self.session
74 .stop_discovery_on_adapter(&self.adapter)
75 .await?;
76 Ok(())
77 }
78
79 async fn peripherals(&self) -> Result<Vec<Peripheral>> {
80 let devices = self.session.get_devices_on_adapter(&self.adapter).await?;
81 Ok(devices
82 .into_iter()
83 .map(|device| Peripheral::new(self.session.clone(), device))
84 .collect())
85 }
86
87 async fn peripheral(&self, id: &PeripheralId) -> Result<Peripheral> {
88 let device = self.session.get_device_info(&id.0).await.map_err(|e| {
89 if let BluetoothError::DbusError(_) = e {
90 Error::DeviceNotFound
91 } else {
92 e.into()
93 }
94 })?;
95 Ok(Peripheral::new(self.session.clone(), device))
96 }
97
98 async fn add_peripheral(&self, _address: &PeripheralId) -> Result<Peripheral> {
99 Err(Error::NotSupported(
100 "Can't add a Peripheral from a PeripheralId".to_string(),
101 ))
102 }
103
104 async fn adapter_info(&self) -> Result<String> {
105 let adapter_info = self.session.get_adapter_info(&self.adapter).await?;
106 Ok(format!("{} ({})", adapter_info.id, adapter_info.modalias))
107 }
108}
109
110impl From<BluetoothError> for Error {
111 fn from(error: BluetoothError) -> Self {
112 Error::Other(Box::new(error))
113 }
114}
115
116async fn central_event(
117 event: BluetoothEvent,
118 session: BluetoothSession,
119 adapter_id: AdapterId,
120) -> Option<CentralEvent> {
121 match event {
122 BluetoothEvent::Device {
123 id,
124 event: device_event,
125 } if id.adapter() == adapter_id => match device_event {
126 DeviceEvent::Discovered => {
127 let device = session.get_device_info(&id).await.ok()?;
128 Some(CentralEvent::DeviceDiscovered(device.id.into()))
129 }
130 DeviceEvent::Connected { connected } => {
131 let device = session.get_device_info(&id).await.ok()?;
132 if connected {
133 Some(CentralEvent::DeviceConnected(device.id.into()))
134 } else {
135 Some(CentralEvent::DeviceDisconnected(device.id.into()))
136 }
137 }
138 DeviceEvent::Rssi { rssi: _ } => {
139 let device = session.get_device_info(&id).await.ok()?;
140 Some(CentralEvent::DeviceUpdated(device.id.into()))
141 }
142 DeviceEvent::ManufacturerData { manufacturer_data } => {
143 let device = session.get_device_info(&id).await.ok()?;
144 Some(CentralEvent::ManufacturerDataAdvertisement {
145 id: device.id.into(),
146 manufacturer_data,
147 })
148 }
149 DeviceEvent::ServiceData { service_data } => {
150 let device = session.get_device_info(&id).await.ok()?;
151 Some(CentralEvent::ServiceDataAdvertisement {
152 id: device.id.into(),
153 service_data,
154 })
155 }
156 DeviceEvent::Services { services } => {
157 let device = session.get_device_info(&id).await.ok()?;
158 Some(CentralEvent::ServicesAdvertisement {
159 id: device.id.into(),
160 services,
161 })
162 }
163 _ => None,
164 },
165 _ => None,
166 }
167}