pub struct Adapter(/* private fields */);
Expand description
The system’s Bluetooth adapter interface.
The default adapter for the system may be accessed with the Adapter::default()
method.
Implementations§
Source§impl Adapter
impl Adapter
Sourcepub async fn default() -> Option<Self>
pub async fn default() -> Option<Self>
Creates an interface to the default Bluetooth adapter for the system
Examples found in repository?
9async fn main() -> Result<(), Box<dyn Error>> {
10 use tracing_subscriber::prelude::*;
11 use tracing_subscriber::{fmt, EnvFilter};
12
13 tracing_subscriber::registry()
14 .with(fmt::layer())
15 .with(
16 EnvFilter::builder()
17 .with_default_directive(LevelFilter::INFO.into())
18 .from_env_lossy(),
19 )
20 .init();
21
22 let adapter = Adapter::default().await.ok_or("Bluetooth adapter not found")?;
23 adapter.wait_available().await?;
24
25 info!("starting scan");
26 let mut scan = adapter.scan(&[]).await?;
27 info!("scan started");
28 while let Some(discovered_device) = scan.next().await {
29 info!(
30 "{}{}: {:?}",
31 discovered_device.device.name().as_deref().unwrap_or("(unknown)"),
32 discovered_device
33 .rssi
34 .map(|x| format!(" ({}dBm)", x))
35 .unwrap_or_default(),
36 discovered_device.adv_data.services
37 );
38 }
39
40 Ok(())
41}
More examples
10async fn main() -> Result<(), Box<dyn Error>> {
11 use tracing_subscriber::prelude::*;
12 use tracing_subscriber::{fmt, EnvFilter};
13
14 tracing_subscriber::registry()
15 .with(fmt::layer())
16 .with(
17 EnvFilter::builder()
18 .with_default_directive(LevelFilter::INFO.into())
19 .from_env_lossy(),
20 )
21 .init();
22
23 let adapter = Adapter::default().await.ok_or("Bluetooth adapter not found")?;
24 adapter.wait_available().await?;
25
26 let discovered_device = {
27 info!("starting scan");
28 let services = &[btuuid::services::USER_DATA];
29 let mut scan = adapter.scan(services).await?;
30 info!("scan started");
31 scan.next().await.ok_or("scan terminated")?
32 };
33
34 info!("{:?} {:?}", discovered_device.rssi, discovered_device.adv_data);
35 adapter.connect_device(&discovered_device.device).await?;
36 info!("connected!");
37
38 tokio::time::sleep(Duration::from_secs(30)).await;
39
40 adapter.disconnect_device(&discovered_device.device).await?;
41 info!("disconnected!");
42
43 Ok(())
44}
72async fn main() -> Result<(), Box<dyn Error>> {
73 use tracing_subscriber::prelude::*;
74 use tracing_subscriber::{fmt, EnvFilter};
75
76 tracing_subscriber::registry()
77 .with(fmt::layer())
78 .with(
79 EnvFilter::builder()
80 .with_default_directive(LevelFilter::INFO.into())
81 .from_env_lossy(),
82 )
83 .init();
84
85 let adapter = Adapter::default().await.ok_or("Bluetooth adapter not found")?;
86 adapter.wait_available().await?;
87
88 let discovered_device = {
89 info!("starting scan");
90 let mut scan = adapter.scan(&[btuuid::services::HUMAN_INTERFACE_DEVICE]).await?;
91 info!("scan started");
92 scan.next().await.ok_or("scan terminated")?
93 };
94
95 info!("{:?} {:?}", discovered_device.rssi, discovered_device.adv_data);
96 let device = discovered_device.device;
97
98 adapter.connect_device(&device).await?;
99 info!("connected!");
100
101 device.pair_with_agent(&StdioPairingAgent).await?;
102 info!("paired!");
103
104 adapter.disconnect_device(&device).await?;
105 info!("disconnected!");
106
107 Ok(())
108}
10async fn main() -> Result<(), Box<dyn Error>> {
11 use tracing_subscriber::prelude::*;
12 use tracing_subscriber::{fmt, EnvFilter};
13
14 tracing_subscriber::registry()
15 .with(fmt::layer())
16 .with(
17 EnvFilter::builder()
18 .with_default_directive(LevelFilter::INFO.into())
19 .from_env_lossy(),
20 )
21 .init();
22
23 let device_id = {
24 let adapter = Adapter::default().await.unwrap();
25 adapter.wait_available().await?;
26
27 info!("looking for device");
28 let device = adapter
29 .discover_devices(&[btuuid::services::BATTERY])
30 .await?
31 .next()
32 .await
33 .ok_or("Failed to discover device")??;
34 info!(
35 "found device: {} ({:?})",
36 device.name().as_deref().unwrap_or("(unknown)"),
37 device.id()
38 );
39
40 device.id()
41 };
42
43 info!("Time passes...");
44 tokio::time::sleep(Duration::from_secs(5)).await;
45
46 {
47 let adapter = Adapter::default().await.unwrap();
48 adapter.wait_available().await?;
49
50 info!("re-opening previously found device");
51 let device = adapter.open_device(&device_id).await?;
52 info!(
53 "re-opened device: {} ({:?})",
54 device.name().as_deref().unwrap_or("(unknown)"),
55 device.id()
56 );
57 }
58
59 Ok(())
60}
8async fn main() -> Result<(), Box<dyn Error>> {
9 use tracing_subscriber::prelude::*;
10 use tracing_subscriber::{fmt, EnvFilter};
11
12 tracing_subscriber::registry()
13 .with(fmt::layer())
14 .with(
15 EnvFilter::builder()
16 .with_default_directive(LevelFilter::INFO.into())
17 .from_env_lossy(),
18 )
19 .init();
20
21 let adapter = Adapter::default().await.ok_or("Bluetooth adapter not found")?;
22 adapter.wait_available().await?;
23
24 info!("getting connected devices");
25 let devices = adapter.connected_devices().await?;
26 for device in devices {
27 info!("found {:?}", device);
28 adapter.connect_device(&device).await?;
29 let services = device.services().await?;
30 for service in services {
31 info!(" {:?}", service);
32 let characteristics = service.characteristics().await?;
33 for characteristic in characteristics {
34 info!(" {:?}", characteristic);
35 let props = characteristic.properties().await?;
36 info!(" props: {:?}", props);
37 if props.read {
38 info!(" value: {:?}", characteristic.read().await);
39 }
40 if props.write_without_response {
41 info!(" max_write_len: {:?}", characteristic.max_write_len());
42 }
43
44 let descriptors = characteristic.descriptors().await?;
45 for descriptor in descriptors {
46 info!(" {:?}: {:?}", descriptor, descriptor.read().await);
47 }
48 }
49 }
50 }
51 info!("done");
52
53 Ok(())
54}
14async fn main() -> Result<(), Box<dyn Error>> {
15 use tracing_subscriber::prelude::*;
16 use tracing_subscriber::{fmt, EnvFilter};
17
18 tracing_subscriber::registry()
19 .with(fmt::layer())
20 .with(
21 EnvFilter::builder()
22 .with_default_directive(LevelFilter::INFO.into())
23 .from_env_lossy(),
24 )
25 .init();
26
27 let adapter = Adapter::default().await.ok_or("Bluetooth adapter not found")?;
28 adapter.wait_available().await?;
29
30 info!("looking for device");
31 let device = adapter
32 .discover_devices(&[NORDIC_LED_AND_BUTTON_SERVICE])
33 .await?
34 .next()
35 .await
36 .ok_or("Failed to discover device")??;
37 info!(
38 "found device: {} ({:?})",
39 device.name().as_deref().unwrap_or("(unknown)"),
40 device.id()
41 );
42
43 adapter.connect_device(&device).await?;
44 info!("connected!");
45
46 let service = match device
47 .discover_services_with_uuid(NORDIC_LED_AND_BUTTON_SERVICE)
48 .await?
49 .first()
50 {
51 Some(service) => service.clone(),
52 None => return Err("service not found".into()),
53 };
54 info!("found LED and button service");
55
56 let characteristics = service.characteristics().await?;
57 info!("discovered characteristics");
58
59 let button_characteristic = characteristics
60 .iter()
61 .find(|x| x.uuid() == BLINKY_BUTTON_STATE_CHARACTERISTIC)
62 .ok_or("button characteristic not found")?;
63
64 let button_fut = async {
65 info!("enabling button notifications");
66 let mut updates = button_characteristic.notify().await?;
67 info!("waiting for button changes");
68 while let Some(val) = updates.next().await {
69 info!("Button state changed: {:?}", val?);
70 }
71 Ok(())
72 };
73
74 let led_characteristic = characteristics
75 .iter()
76 .find(|x| x.uuid() == BLINKY_LED_STATE_CHARACTERISTIC)
77 .ok_or("led characteristic not found")?;
78
79 let blink_fut = async {
80 info!("blinking LED");
81 tokio::time::sleep(Duration::from_secs(1)).await;
82 loop {
83 led_characteristic.write(&[0x01]).await?;
84 info!("LED on");
85 tokio::time::sleep(Duration::from_secs(1)).await;
86 led_characteristic.write(&[0x00]).await?;
87 info!("LED off");
88 tokio::time::sleep(Duration::from_secs(1)).await;
89 }
90 };
91
92 type R = Result<(), Box<dyn Error>>;
93 let button_fut = async move {
94 let res: R = button_fut.await;
95 error!("Button task exited: {:?}", res);
96 };
97 let blink_fut = async move {
98 let res: R = blink_fut.await;
99 error!("Blink task exited: {:?}", res);
100 };
101
102 future::zip(blink_fut, button_fut).await;
103
104 Ok(())
105}
Sourcepub async fn events(
&self,
) -> Result<impl Stream<Item = Result<AdapterEvent>> + Send + Unpin + '_>
pub async fn events( &self, ) -> Result<impl Stream<Item = Result<AdapterEvent>> + Send + Unpin + '_>
A stream of AdapterEvent
which allows the application to identify when the adapter is enabled or disabled.
Sourcepub async fn wait_available(&self) -> Result<()>
pub async fn wait_available(&self) -> Result<()>
Asynchronously blocks until the adapter is available
Examples found in repository?
9async fn main() -> Result<(), Box<dyn Error>> {
10 use tracing_subscriber::prelude::*;
11 use tracing_subscriber::{fmt, EnvFilter};
12
13 tracing_subscriber::registry()
14 .with(fmt::layer())
15 .with(
16 EnvFilter::builder()
17 .with_default_directive(LevelFilter::INFO.into())
18 .from_env_lossy(),
19 )
20 .init();
21
22 let adapter = Adapter::default().await.ok_or("Bluetooth adapter not found")?;
23 adapter.wait_available().await?;
24
25 info!("starting scan");
26 let mut scan = adapter.scan(&[]).await?;
27 info!("scan started");
28 while let Some(discovered_device) = scan.next().await {
29 info!(
30 "{}{}: {:?}",
31 discovered_device.device.name().as_deref().unwrap_or("(unknown)"),
32 discovered_device
33 .rssi
34 .map(|x| format!(" ({}dBm)", x))
35 .unwrap_or_default(),
36 discovered_device.adv_data.services
37 );
38 }
39
40 Ok(())
41}
More examples
10async fn main() -> Result<(), Box<dyn Error>> {
11 use tracing_subscriber::prelude::*;
12 use tracing_subscriber::{fmt, EnvFilter};
13
14 tracing_subscriber::registry()
15 .with(fmt::layer())
16 .with(
17 EnvFilter::builder()
18 .with_default_directive(LevelFilter::INFO.into())
19 .from_env_lossy(),
20 )
21 .init();
22
23 let adapter = Adapter::default().await.ok_or("Bluetooth adapter not found")?;
24 adapter.wait_available().await?;
25
26 let discovered_device = {
27 info!("starting scan");
28 let services = &[btuuid::services::USER_DATA];
29 let mut scan = adapter.scan(services).await?;
30 info!("scan started");
31 scan.next().await.ok_or("scan terminated")?
32 };
33
34 info!("{:?} {:?}", discovered_device.rssi, discovered_device.adv_data);
35 adapter.connect_device(&discovered_device.device).await?;
36 info!("connected!");
37
38 tokio::time::sleep(Duration::from_secs(30)).await;
39
40 adapter.disconnect_device(&discovered_device.device).await?;
41 info!("disconnected!");
42
43 Ok(())
44}
72async fn main() -> Result<(), Box<dyn Error>> {
73 use tracing_subscriber::prelude::*;
74 use tracing_subscriber::{fmt, EnvFilter};
75
76 tracing_subscriber::registry()
77 .with(fmt::layer())
78 .with(
79 EnvFilter::builder()
80 .with_default_directive(LevelFilter::INFO.into())
81 .from_env_lossy(),
82 )
83 .init();
84
85 let adapter = Adapter::default().await.ok_or("Bluetooth adapter not found")?;
86 adapter.wait_available().await?;
87
88 let discovered_device = {
89 info!("starting scan");
90 let mut scan = adapter.scan(&[btuuid::services::HUMAN_INTERFACE_DEVICE]).await?;
91 info!("scan started");
92 scan.next().await.ok_or("scan terminated")?
93 };
94
95 info!("{:?} {:?}", discovered_device.rssi, discovered_device.adv_data);
96 let device = discovered_device.device;
97
98 adapter.connect_device(&device).await?;
99 info!("connected!");
100
101 device.pair_with_agent(&StdioPairingAgent).await?;
102 info!("paired!");
103
104 adapter.disconnect_device(&device).await?;
105 info!("disconnected!");
106
107 Ok(())
108}
10async fn main() -> Result<(), Box<dyn Error>> {
11 use tracing_subscriber::prelude::*;
12 use tracing_subscriber::{fmt, EnvFilter};
13
14 tracing_subscriber::registry()
15 .with(fmt::layer())
16 .with(
17 EnvFilter::builder()
18 .with_default_directive(LevelFilter::INFO.into())
19 .from_env_lossy(),
20 )
21 .init();
22
23 let device_id = {
24 let adapter = Adapter::default().await.unwrap();
25 adapter.wait_available().await?;
26
27 info!("looking for device");
28 let device = adapter
29 .discover_devices(&[btuuid::services::BATTERY])
30 .await?
31 .next()
32 .await
33 .ok_or("Failed to discover device")??;
34 info!(
35 "found device: {} ({:?})",
36 device.name().as_deref().unwrap_or("(unknown)"),
37 device.id()
38 );
39
40 device.id()
41 };
42
43 info!("Time passes...");
44 tokio::time::sleep(Duration::from_secs(5)).await;
45
46 {
47 let adapter = Adapter::default().await.unwrap();
48 adapter.wait_available().await?;
49
50 info!("re-opening previously found device");
51 let device = adapter.open_device(&device_id).await?;
52 info!(
53 "re-opened device: {} ({:?})",
54 device.name().as_deref().unwrap_or("(unknown)"),
55 device.id()
56 );
57 }
58
59 Ok(())
60}
8async fn main() -> Result<(), Box<dyn Error>> {
9 use tracing_subscriber::prelude::*;
10 use tracing_subscriber::{fmt, EnvFilter};
11
12 tracing_subscriber::registry()
13 .with(fmt::layer())
14 .with(
15 EnvFilter::builder()
16 .with_default_directive(LevelFilter::INFO.into())
17 .from_env_lossy(),
18 )
19 .init();
20
21 let adapter = Adapter::default().await.ok_or("Bluetooth adapter not found")?;
22 adapter.wait_available().await?;
23
24 info!("getting connected devices");
25 let devices = adapter.connected_devices().await?;
26 for device in devices {
27 info!("found {:?}", device);
28 adapter.connect_device(&device).await?;
29 let services = device.services().await?;
30 for service in services {
31 info!(" {:?}", service);
32 let characteristics = service.characteristics().await?;
33 for characteristic in characteristics {
34 info!(" {:?}", characteristic);
35 let props = characteristic.properties().await?;
36 info!(" props: {:?}", props);
37 if props.read {
38 info!(" value: {:?}", characteristic.read().await);
39 }
40 if props.write_without_response {
41 info!(" max_write_len: {:?}", characteristic.max_write_len());
42 }
43
44 let descriptors = characteristic.descriptors().await?;
45 for descriptor in descriptors {
46 info!(" {:?}: {:?}", descriptor, descriptor.read().await);
47 }
48 }
49 }
50 }
51 info!("done");
52
53 Ok(())
54}
14async fn main() -> Result<(), Box<dyn Error>> {
15 use tracing_subscriber::prelude::*;
16 use tracing_subscriber::{fmt, EnvFilter};
17
18 tracing_subscriber::registry()
19 .with(fmt::layer())
20 .with(
21 EnvFilter::builder()
22 .with_default_directive(LevelFilter::INFO.into())
23 .from_env_lossy(),
24 )
25 .init();
26
27 let adapter = Adapter::default().await.ok_or("Bluetooth adapter not found")?;
28 adapter.wait_available().await?;
29
30 info!("looking for device");
31 let device = adapter
32 .discover_devices(&[NORDIC_LED_AND_BUTTON_SERVICE])
33 .await?
34 .next()
35 .await
36 .ok_or("Failed to discover device")??;
37 info!(
38 "found device: {} ({:?})",
39 device.name().as_deref().unwrap_or("(unknown)"),
40 device.id()
41 );
42
43 adapter.connect_device(&device).await?;
44 info!("connected!");
45
46 let service = match device
47 .discover_services_with_uuid(NORDIC_LED_AND_BUTTON_SERVICE)
48 .await?
49 .first()
50 {
51 Some(service) => service.clone(),
52 None => return Err("service not found".into()),
53 };
54 info!("found LED and button service");
55
56 let characteristics = service.characteristics().await?;
57 info!("discovered characteristics");
58
59 let button_characteristic = characteristics
60 .iter()
61 .find(|x| x.uuid() == BLINKY_BUTTON_STATE_CHARACTERISTIC)
62 .ok_or("button characteristic not found")?;
63
64 let button_fut = async {
65 info!("enabling button notifications");
66 let mut updates = button_characteristic.notify().await?;
67 info!("waiting for button changes");
68 while let Some(val) = updates.next().await {
69 info!("Button state changed: {:?}", val?);
70 }
71 Ok(())
72 };
73
74 let led_characteristic = characteristics
75 .iter()
76 .find(|x| x.uuid() == BLINKY_LED_STATE_CHARACTERISTIC)
77 .ok_or("led characteristic not found")?;
78
79 let blink_fut = async {
80 info!("blinking LED");
81 tokio::time::sleep(Duration::from_secs(1)).await;
82 loop {
83 led_characteristic.write(&[0x01]).await?;
84 info!("LED on");
85 tokio::time::sleep(Duration::from_secs(1)).await;
86 led_characteristic.write(&[0x00]).await?;
87 info!("LED off");
88 tokio::time::sleep(Duration::from_secs(1)).await;
89 }
90 };
91
92 type R = Result<(), Box<dyn Error>>;
93 let button_fut = async move {
94 let res: R = button_fut.await;
95 error!("Button task exited: {:?}", res);
96 };
97 let blink_fut = async move {
98 let res: R = blink_fut.await;
99 error!("Blink task exited: {:?}", res);
100 };
101
102 future::zip(blink_fut, button_fut).await;
103
104 Ok(())
105}
Sourcepub async fn open_device(&self, id: &DeviceId) -> Result<Device>
pub async fn open_device(&self, id: &DeviceId) -> Result<Device>
Attempts to create the device identified by id
Examples found in repository?
10async fn main() -> Result<(), Box<dyn Error>> {
11 use tracing_subscriber::prelude::*;
12 use tracing_subscriber::{fmt, EnvFilter};
13
14 tracing_subscriber::registry()
15 .with(fmt::layer())
16 .with(
17 EnvFilter::builder()
18 .with_default_directive(LevelFilter::INFO.into())
19 .from_env_lossy(),
20 )
21 .init();
22
23 let device_id = {
24 let adapter = Adapter::default().await.unwrap();
25 adapter.wait_available().await?;
26
27 info!("looking for device");
28 let device = adapter
29 .discover_devices(&[btuuid::services::BATTERY])
30 .await?
31 .next()
32 .await
33 .ok_or("Failed to discover device")??;
34 info!(
35 "found device: {} ({:?})",
36 device.name().as_deref().unwrap_or("(unknown)"),
37 device.id()
38 );
39
40 device.id()
41 };
42
43 info!("Time passes...");
44 tokio::time::sleep(Duration::from_secs(5)).await;
45
46 {
47 let adapter = Adapter::default().await.unwrap();
48 adapter.wait_available().await?;
49
50 info!("re-opening previously found device");
51 let device = adapter.open_device(&device_id).await?;
52 info!(
53 "re-opened device: {} ({:?})",
54 device.name().as_deref().unwrap_or("(unknown)"),
55 device.id()
56 );
57 }
58
59 Ok(())
60}
Sourcepub async fn connected_devices(&self) -> Result<Vec<Device>>
pub async fn connected_devices(&self) -> Result<Vec<Device>>
Finds all connected Bluetooth LE devices
Examples found in repository?
8async fn main() -> Result<(), Box<dyn Error>> {
9 use tracing_subscriber::prelude::*;
10 use tracing_subscriber::{fmt, EnvFilter};
11
12 tracing_subscriber::registry()
13 .with(fmt::layer())
14 .with(
15 EnvFilter::builder()
16 .with_default_directive(LevelFilter::INFO.into())
17 .from_env_lossy(),
18 )
19 .init();
20
21 let adapter = Adapter::default().await.ok_or("Bluetooth adapter not found")?;
22 adapter.wait_available().await?;
23
24 info!("getting connected devices");
25 let devices = adapter.connected_devices().await?;
26 for device in devices {
27 info!("found {:?}", device);
28 adapter.connect_device(&device).await?;
29 let services = device.services().await?;
30 for service in services {
31 info!(" {:?}", service);
32 let characteristics = service.characteristics().await?;
33 for characteristic in characteristics {
34 info!(" {:?}", characteristic);
35 let props = characteristic.properties().await?;
36 info!(" props: {:?}", props);
37 if props.read {
38 info!(" value: {:?}", characteristic.read().await);
39 }
40 if props.write_without_response {
41 info!(" max_write_len: {:?}", characteristic.max_write_len());
42 }
43
44 let descriptors = characteristic.descriptors().await?;
45 for descriptor in descriptors {
46 info!(" {:?}: {:?}", descriptor, descriptor.read().await);
47 }
48 }
49 }
50 }
51 info!("done");
52
53 Ok(())
54}
Sourcepub async fn connected_devices_with_services(
&self,
services: &[Uuid],
) -> Result<Vec<Device>>
pub async fn connected_devices_with_services( &self, services: &[Uuid], ) -> Result<Vec<Device>>
Sourcepub async fn scan<'a>(
&'a self,
services: &'a [Uuid],
) -> Result<impl Stream<Item = AdvertisingDevice> + Send + Unpin + 'a>
pub async fn scan<'a>( &'a self, services: &'a [Uuid], ) -> Result<impl Stream<Item = AdvertisingDevice> + Send + Unpin + 'a>
Starts scanning for Bluetooth advertising packets.
Returns a stream of AdvertisingDevice
structs which contain the data from the advertising packet and the
Device
which sent it. Scanning is automatically stopped when the stream is dropped. Inclusion of duplicate
packets is a platform-specific implementation detail.
If services
is not empty, returns advertisements including at least one GATT service with a UUID in
services
. Otherwise returns all advertisements.
Examples found in repository?
9async fn main() -> Result<(), Box<dyn Error>> {
10 use tracing_subscriber::prelude::*;
11 use tracing_subscriber::{fmt, EnvFilter};
12
13 tracing_subscriber::registry()
14 .with(fmt::layer())
15 .with(
16 EnvFilter::builder()
17 .with_default_directive(LevelFilter::INFO.into())
18 .from_env_lossy(),
19 )
20 .init();
21
22 let adapter = Adapter::default().await.ok_or("Bluetooth adapter not found")?;
23 adapter.wait_available().await?;
24
25 info!("starting scan");
26 let mut scan = adapter.scan(&[]).await?;
27 info!("scan started");
28 while let Some(discovered_device) = scan.next().await {
29 info!(
30 "{}{}: {:?}",
31 discovered_device.device.name().as_deref().unwrap_or("(unknown)"),
32 discovered_device
33 .rssi
34 .map(|x| format!(" ({}dBm)", x))
35 .unwrap_or_default(),
36 discovered_device.adv_data.services
37 );
38 }
39
40 Ok(())
41}
More examples
10async fn main() -> Result<(), Box<dyn Error>> {
11 use tracing_subscriber::prelude::*;
12 use tracing_subscriber::{fmt, EnvFilter};
13
14 tracing_subscriber::registry()
15 .with(fmt::layer())
16 .with(
17 EnvFilter::builder()
18 .with_default_directive(LevelFilter::INFO.into())
19 .from_env_lossy(),
20 )
21 .init();
22
23 let adapter = Adapter::default().await.ok_or("Bluetooth adapter not found")?;
24 adapter.wait_available().await?;
25
26 let discovered_device = {
27 info!("starting scan");
28 let services = &[btuuid::services::USER_DATA];
29 let mut scan = adapter.scan(services).await?;
30 info!("scan started");
31 scan.next().await.ok_or("scan terminated")?
32 };
33
34 info!("{:?} {:?}", discovered_device.rssi, discovered_device.adv_data);
35 adapter.connect_device(&discovered_device.device).await?;
36 info!("connected!");
37
38 tokio::time::sleep(Duration::from_secs(30)).await;
39
40 adapter.disconnect_device(&discovered_device.device).await?;
41 info!("disconnected!");
42
43 Ok(())
44}
72async fn main() -> Result<(), Box<dyn Error>> {
73 use tracing_subscriber::prelude::*;
74 use tracing_subscriber::{fmt, EnvFilter};
75
76 tracing_subscriber::registry()
77 .with(fmt::layer())
78 .with(
79 EnvFilter::builder()
80 .with_default_directive(LevelFilter::INFO.into())
81 .from_env_lossy(),
82 )
83 .init();
84
85 let adapter = Adapter::default().await.ok_or("Bluetooth adapter not found")?;
86 adapter.wait_available().await?;
87
88 let discovered_device = {
89 info!("starting scan");
90 let mut scan = adapter.scan(&[btuuid::services::HUMAN_INTERFACE_DEVICE]).await?;
91 info!("scan started");
92 scan.next().await.ok_or("scan terminated")?
93 };
94
95 info!("{:?} {:?}", discovered_device.rssi, discovered_device.adv_data);
96 let device = discovered_device.device;
97
98 adapter.connect_device(&device).await?;
99 info!("connected!");
100
101 device.pair_with_agent(&StdioPairingAgent).await?;
102 info!("paired!");
103
104 adapter.disconnect_device(&device).await?;
105 info!("disconnected!");
106
107 Ok(())
108}
Sourcepub async fn discover_devices<'a>(
&'a self,
services: &'a [Uuid],
) -> Result<impl Stream<Item = Result<Device>> + Send + Unpin + 'a>
pub async fn discover_devices<'a>( &'a self, services: &'a [Uuid], ) -> Result<impl Stream<Item = Result<Device>> + Send + Unpin + 'a>
Finds Bluetooth devices providing any service in services
.
Returns a stream of Device
structs with matching connected devices returned first. If the stream is not
dropped before all matching connected devices are consumed then scanning will begin for devices advertising any
of the services
. Scanning will continue until the stream is dropped. Inclusion of duplicate devices is a
platform-specific implementation detail.
Examples found in repository?
10async fn main() -> Result<(), Box<dyn Error>> {
11 use tracing_subscriber::prelude::*;
12 use tracing_subscriber::{fmt, EnvFilter};
13
14 tracing_subscriber::registry()
15 .with(fmt::layer())
16 .with(
17 EnvFilter::builder()
18 .with_default_directive(LevelFilter::INFO.into())
19 .from_env_lossy(),
20 )
21 .init();
22
23 let device_id = {
24 let adapter = Adapter::default().await.unwrap();
25 adapter.wait_available().await?;
26
27 info!("looking for device");
28 let device = adapter
29 .discover_devices(&[btuuid::services::BATTERY])
30 .await?
31 .next()
32 .await
33 .ok_or("Failed to discover device")??;
34 info!(
35 "found device: {} ({:?})",
36 device.name().as_deref().unwrap_or("(unknown)"),
37 device.id()
38 );
39
40 device.id()
41 };
42
43 info!("Time passes...");
44 tokio::time::sleep(Duration::from_secs(5)).await;
45
46 {
47 let adapter = Adapter::default().await.unwrap();
48 adapter.wait_available().await?;
49
50 info!("re-opening previously found device");
51 let device = adapter.open_device(&device_id).await?;
52 info!(
53 "re-opened device: {} ({:?})",
54 device.name().as_deref().unwrap_or("(unknown)"),
55 device.id()
56 );
57 }
58
59 Ok(())
60}
More examples
14async fn main() -> Result<(), Box<dyn Error>> {
15 use tracing_subscriber::prelude::*;
16 use tracing_subscriber::{fmt, EnvFilter};
17
18 tracing_subscriber::registry()
19 .with(fmt::layer())
20 .with(
21 EnvFilter::builder()
22 .with_default_directive(LevelFilter::INFO.into())
23 .from_env_lossy(),
24 )
25 .init();
26
27 let adapter = Adapter::default().await.ok_or("Bluetooth adapter not found")?;
28 adapter.wait_available().await?;
29
30 info!("looking for device");
31 let device = adapter
32 .discover_devices(&[NORDIC_LED_AND_BUTTON_SERVICE])
33 .await?
34 .next()
35 .await
36 .ok_or("Failed to discover device")??;
37 info!(
38 "found device: {} ({:?})",
39 device.name().as_deref().unwrap_or("(unknown)"),
40 device.id()
41 );
42
43 adapter.connect_device(&device).await?;
44 info!("connected!");
45
46 let service = match device
47 .discover_services_with_uuid(NORDIC_LED_AND_BUTTON_SERVICE)
48 .await?
49 .first()
50 {
51 Some(service) => service.clone(),
52 None => return Err("service not found".into()),
53 };
54 info!("found LED and button service");
55
56 let characteristics = service.characteristics().await?;
57 info!("discovered characteristics");
58
59 let button_characteristic = characteristics
60 .iter()
61 .find(|x| x.uuid() == BLINKY_BUTTON_STATE_CHARACTERISTIC)
62 .ok_or("button characteristic not found")?;
63
64 let button_fut = async {
65 info!("enabling button notifications");
66 let mut updates = button_characteristic.notify().await?;
67 info!("waiting for button changes");
68 while let Some(val) = updates.next().await {
69 info!("Button state changed: {:?}", val?);
70 }
71 Ok(())
72 };
73
74 let led_characteristic = characteristics
75 .iter()
76 .find(|x| x.uuid() == BLINKY_LED_STATE_CHARACTERISTIC)
77 .ok_or("led characteristic not found")?;
78
79 let blink_fut = async {
80 info!("blinking LED");
81 tokio::time::sleep(Duration::from_secs(1)).await;
82 loop {
83 led_characteristic.write(&[0x01]).await?;
84 info!("LED on");
85 tokio::time::sleep(Duration::from_secs(1)).await;
86 led_characteristic.write(&[0x00]).await?;
87 info!("LED off");
88 tokio::time::sleep(Duration::from_secs(1)).await;
89 }
90 };
91
92 type R = Result<(), Box<dyn Error>>;
93 let button_fut = async move {
94 let res: R = button_fut.await;
95 error!("Button task exited: {:?}", res);
96 };
97 let blink_fut = async move {
98 let res: R = blink_fut.await;
99 error!("Blink task exited: {:?}", res);
100 };
101
102 future::zip(blink_fut, button_fut).await;
103
104 Ok(())
105}
Sourcepub async fn connect_device(&self, device: &Device) -> Result<()>
pub async fn connect_device(&self, device: &Device) -> Result<()>
Connects to the Device
§Platform specifics
§MacOS/iOS
This method must be called before any methods on the Device
which require a connection are called. After a
successful return from this method, a connection has been established with the device (if one did not already
exist) and the application can then interact with the device. This connection will be maintained until either
disconnect_device
is called or the Adapter
is dropped.
§Windows
On Windows, device connections are automatically managed by the OS. This method has no effect. Instead, a connection will automatically be established, if necessary, when methods on the device requiring a connection are called.
§Linux
If the device is not yet connected to the system, this method must be called before any methods on the
Device
which require a connection are called. After a successful return from this method, a connection has
been established with the device (if one did not already exist) and the application can then interact with the
device. This connection will be maintained until disconnect_device
is called.
Examples found in repository?
10async fn main() -> Result<(), Box<dyn Error>> {
11 use tracing_subscriber::prelude::*;
12 use tracing_subscriber::{fmt, EnvFilter};
13
14 tracing_subscriber::registry()
15 .with(fmt::layer())
16 .with(
17 EnvFilter::builder()
18 .with_default_directive(LevelFilter::INFO.into())
19 .from_env_lossy(),
20 )
21 .init();
22
23 let adapter = Adapter::default().await.ok_or("Bluetooth adapter not found")?;
24 adapter.wait_available().await?;
25
26 let discovered_device = {
27 info!("starting scan");
28 let services = &[btuuid::services::USER_DATA];
29 let mut scan = adapter.scan(services).await?;
30 info!("scan started");
31 scan.next().await.ok_or("scan terminated")?
32 };
33
34 info!("{:?} {:?}", discovered_device.rssi, discovered_device.adv_data);
35 adapter.connect_device(&discovered_device.device).await?;
36 info!("connected!");
37
38 tokio::time::sleep(Duration::from_secs(30)).await;
39
40 adapter.disconnect_device(&discovered_device.device).await?;
41 info!("disconnected!");
42
43 Ok(())
44}
More examples
72async fn main() -> Result<(), Box<dyn Error>> {
73 use tracing_subscriber::prelude::*;
74 use tracing_subscriber::{fmt, EnvFilter};
75
76 tracing_subscriber::registry()
77 .with(fmt::layer())
78 .with(
79 EnvFilter::builder()
80 .with_default_directive(LevelFilter::INFO.into())
81 .from_env_lossy(),
82 )
83 .init();
84
85 let adapter = Adapter::default().await.ok_or("Bluetooth adapter not found")?;
86 adapter.wait_available().await?;
87
88 let discovered_device = {
89 info!("starting scan");
90 let mut scan = adapter.scan(&[btuuid::services::HUMAN_INTERFACE_DEVICE]).await?;
91 info!("scan started");
92 scan.next().await.ok_or("scan terminated")?
93 };
94
95 info!("{:?} {:?}", discovered_device.rssi, discovered_device.adv_data);
96 let device = discovered_device.device;
97
98 adapter.connect_device(&device).await?;
99 info!("connected!");
100
101 device.pair_with_agent(&StdioPairingAgent).await?;
102 info!("paired!");
103
104 adapter.disconnect_device(&device).await?;
105 info!("disconnected!");
106
107 Ok(())
108}
8async fn main() -> Result<(), Box<dyn Error>> {
9 use tracing_subscriber::prelude::*;
10 use tracing_subscriber::{fmt, EnvFilter};
11
12 tracing_subscriber::registry()
13 .with(fmt::layer())
14 .with(
15 EnvFilter::builder()
16 .with_default_directive(LevelFilter::INFO.into())
17 .from_env_lossy(),
18 )
19 .init();
20
21 let adapter = Adapter::default().await.ok_or("Bluetooth adapter not found")?;
22 adapter.wait_available().await?;
23
24 info!("getting connected devices");
25 let devices = adapter.connected_devices().await?;
26 for device in devices {
27 info!("found {:?}", device);
28 adapter.connect_device(&device).await?;
29 let services = device.services().await?;
30 for service in services {
31 info!(" {:?}", service);
32 let characteristics = service.characteristics().await?;
33 for characteristic in characteristics {
34 info!(" {:?}", characteristic);
35 let props = characteristic.properties().await?;
36 info!(" props: {:?}", props);
37 if props.read {
38 info!(" value: {:?}", characteristic.read().await);
39 }
40 if props.write_without_response {
41 info!(" max_write_len: {:?}", characteristic.max_write_len());
42 }
43
44 let descriptors = characteristic.descriptors().await?;
45 for descriptor in descriptors {
46 info!(" {:?}: {:?}", descriptor, descriptor.read().await);
47 }
48 }
49 }
50 }
51 info!("done");
52
53 Ok(())
54}
14async fn main() -> Result<(), Box<dyn Error>> {
15 use tracing_subscriber::prelude::*;
16 use tracing_subscriber::{fmt, EnvFilter};
17
18 tracing_subscriber::registry()
19 .with(fmt::layer())
20 .with(
21 EnvFilter::builder()
22 .with_default_directive(LevelFilter::INFO.into())
23 .from_env_lossy(),
24 )
25 .init();
26
27 let adapter = Adapter::default().await.ok_or("Bluetooth adapter not found")?;
28 adapter.wait_available().await?;
29
30 info!("looking for device");
31 let device = adapter
32 .discover_devices(&[NORDIC_LED_AND_BUTTON_SERVICE])
33 .await?
34 .next()
35 .await
36 .ok_or("Failed to discover device")??;
37 info!(
38 "found device: {} ({:?})",
39 device.name().as_deref().unwrap_or("(unknown)"),
40 device.id()
41 );
42
43 adapter.connect_device(&device).await?;
44 info!("connected!");
45
46 let service = match device
47 .discover_services_with_uuid(NORDIC_LED_AND_BUTTON_SERVICE)
48 .await?
49 .first()
50 {
51 Some(service) => service.clone(),
52 None => return Err("service not found".into()),
53 };
54 info!("found LED and button service");
55
56 let characteristics = service.characteristics().await?;
57 info!("discovered characteristics");
58
59 let button_characteristic = characteristics
60 .iter()
61 .find(|x| x.uuid() == BLINKY_BUTTON_STATE_CHARACTERISTIC)
62 .ok_or("button characteristic not found")?;
63
64 let button_fut = async {
65 info!("enabling button notifications");
66 let mut updates = button_characteristic.notify().await?;
67 info!("waiting for button changes");
68 while let Some(val) = updates.next().await {
69 info!("Button state changed: {:?}", val?);
70 }
71 Ok(())
72 };
73
74 let led_characteristic = characteristics
75 .iter()
76 .find(|x| x.uuid() == BLINKY_LED_STATE_CHARACTERISTIC)
77 .ok_or("led characteristic not found")?;
78
79 let blink_fut = async {
80 info!("blinking LED");
81 tokio::time::sleep(Duration::from_secs(1)).await;
82 loop {
83 led_characteristic.write(&[0x01]).await?;
84 info!("LED on");
85 tokio::time::sleep(Duration::from_secs(1)).await;
86 led_characteristic.write(&[0x00]).await?;
87 info!("LED off");
88 tokio::time::sleep(Duration::from_secs(1)).await;
89 }
90 };
91
92 type R = Result<(), Box<dyn Error>>;
93 let button_fut = async move {
94 let res: R = button_fut.await;
95 error!("Button task exited: {:?}", res);
96 };
97 let blink_fut = async move {
98 let res: R = blink_fut.await;
99 error!("Blink task exited: {:?}", res);
100 };
101
102 future::zip(blink_fut, button_fut).await;
103
104 Ok(())
105}
Sourcepub async fn disconnect_device(&self, device: &Device) -> Result<()>
pub async fn disconnect_device(&self, device: &Device) -> Result<()>
Disconnects from the Device
§Platform specifics
§MacOS/iOS
Once this method is called, the application will no longer have access to the Device
and any methods
which would require a connection will fail. If no other application has a connection to the same device,
the underlying Bluetooth connection will be closed.
§Windows
On Windows, device connections are automatically managed by the OS. This method has no effect. Instead, the
connection will be closed only when the Device
and all its child objects are dropped.
§Linux
This method disconnects the device from the system, even if other applications are using the device.
Examples found in repository?
10async fn main() -> Result<(), Box<dyn Error>> {
11 use tracing_subscriber::prelude::*;
12 use tracing_subscriber::{fmt, EnvFilter};
13
14 tracing_subscriber::registry()
15 .with(fmt::layer())
16 .with(
17 EnvFilter::builder()
18 .with_default_directive(LevelFilter::INFO.into())
19 .from_env_lossy(),
20 )
21 .init();
22
23 let adapter = Adapter::default().await.ok_or("Bluetooth adapter not found")?;
24 adapter.wait_available().await?;
25
26 let discovered_device = {
27 info!("starting scan");
28 let services = &[btuuid::services::USER_DATA];
29 let mut scan = adapter.scan(services).await?;
30 info!("scan started");
31 scan.next().await.ok_or("scan terminated")?
32 };
33
34 info!("{:?} {:?}", discovered_device.rssi, discovered_device.adv_data);
35 adapter.connect_device(&discovered_device.device).await?;
36 info!("connected!");
37
38 tokio::time::sleep(Duration::from_secs(30)).await;
39
40 adapter.disconnect_device(&discovered_device.device).await?;
41 info!("disconnected!");
42
43 Ok(())
44}
More examples
72async fn main() -> Result<(), Box<dyn Error>> {
73 use tracing_subscriber::prelude::*;
74 use tracing_subscriber::{fmt, EnvFilter};
75
76 tracing_subscriber::registry()
77 .with(fmt::layer())
78 .with(
79 EnvFilter::builder()
80 .with_default_directive(LevelFilter::INFO.into())
81 .from_env_lossy(),
82 )
83 .init();
84
85 let adapter = Adapter::default().await.ok_or("Bluetooth adapter not found")?;
86 adapter.wait_available().await?;
87
88 let discovered_device = {
89 info!("starting scan");
90 let mut scan = adapter.scan(&[btuuid::services::HUMAN_INTERFACE_DEVICE]).await?;
91 info!("scan started");
92 scan.next().await.ok_or("scan terminated")?
93 };
94
95 info!("{:?} {:?}", discovered_device.rssi, discovered_device.adv_data);
96 let device = discovered_device.device;
97
98 adapter.connect_device(&device).await?;
99 info!("connected!");
100
101 device.pair_with_agent(&StdioPairingAgent).await?;
102 info!("paired!");
103
104 adapter.disconnect_device(&device).await?;
105 info!("disconnected!");
106
107 Ok(())
108}
Sourcepub async fn device_connection_events<'a>(
&'a self,
device: &'a Device,
) -> Result<impl Stream<Item = ConnectionEvent> + Send + Unpin + 'a>
pub async fn device_connection_events<'a>( &'a self, device: &'a Device, ) -> Result<impl Stream<Item = ConnectionEvent> + Send + Unpin + 'a>
Monitors a device for connection/disconnection events.
§Platform specifics
§MacOS/iOS
On MacOS connection events will only be generated for calls to connect_device
and disconnection events
will only be generated for devices that have been connected with connect_device
.
On iOS/iPadOS connection and disconnection events can be generated for any device.