btleplug/
lib.rs

1// btleplug Source Code File
2//
3// Copyright 2020 Nonpolynomial Labs LLC. All rights reserved.
4//
5// Licensed under the BSD 3-Clause license. See LICENSE file in the project root
6// for full license information.
7//
8// Some portions of this file are taken and/or modified from Rumble
9// (https://github.com/mwylde/rumble), using a dual MIT/Apache License under the
10// following copyright:
11//
12// Copyright (c) 2014 The Rust Project Developers
13
14//! btleplug is a Bluetooth Low Energy (BLE) central module library for Rust.
15//! It currently supports Windows 10, macOS (and possibly iOS) and Linux
16//! (BlueZ). Android support is planned for the future.
17//!
18//! ## Usage
19//!
20//! An example of how to use the library to control some BLE smart lights:
21//!
22//! ```rust,no_run
23//! use btleplug::api::{bleuuid::uuid_from_u16, Central, Manager as _, Peripheral as _, ScanFilter, WriteType};
24//! use btleplug::platform::{Adapter, Manager, Peripheral};
25//! use rand::{Rng, thread_rng};
26//! use std::error::Error;
27//! use std::thread;
28//! use std::time::Duration;
29//! use tokio::time;
30//! use uuid::Uuid;
31//!
32//! const LIGHT_CHARACTERISTIC_UUID: Uuid = uuid_from_u16(0xFFE9);
33//!
34//! #[tokio::main]
35//! async fn main() -> Result<(), Box<dyn Error>> {
36//!     let manager = Manager::new().await.unwrap();
37//!
38//!     // get the first bluetooth adapter
39//!     let adapters = manager.adapters().await?;
40//!     let central = adapters.into_iter().nth(0).unwrap();
41//!
42//!     // start scanning for devices
43//!     central.start_scan(ScanFilter::default()).await?;
44//!     // instead of waiting, you can use central.events() to get a stream which will
45//!     // notify you of new devices, for an example of that see examples/event_driven_discovery.rs
46//!     time::sleep(Duration::from_secs(2)).await;
47//!
48//!     // find the device we're interested in
49//!     let light = find_light(&central).await.unwrap();
50//!
51//!     // connect to the device
52//!     light.connect().await?;
53//!
54//!     // discover services and characteristics
55//!     light.discover_services().await?;
56//!
57//!     // find the characteristic we want
58//!     let chars = light.characteristics();
59//!     let cmd_char = chars.iter().find(|c| c.uuid == LIGHT_CHARACTERISTIC_UUID).unwrap();
60//!
61//!     // dance party
62//!     let mut rng = thread_rng();
63//!     for _ in 0..20 {
64//!         let color_cmd = vec![0x56, rng.gen(), rng.gen(), rng.gen(), 0x00, 0xF0, 0xAA];
65//!         light.write(&cmd_char, &color_cmd, WriteType::WithoutResponse).await?;
66//!         time::sleep(Duration::from_millis(200)).await;
67//!     }
68//!     Ok(())
69//! }
70//!
71//! async fn find_light(central: &Adapter) -> Option<Peripheral> {
72//!     for p in central.peripherals().await.unwrap() {
73//!         if p.properties()
74//!             .await
75//!             .unwrap()
76//!             .unwrap()
77//!             .local_name
78//!             .iter()
79//!             .any(|name| name.contains("LEDBlue"))
80//!         {
81//!             return Some(p);
82//!         }
83//!     }
84//!     None
85//! }
86//! ```
87
88use crate::api::ParseBDAddrError;
89use std::result;
90use std::time::Duration;
91
92pub mod api;
93#[cfg(target_os = "linux")]
94mod bluez;
95#[cfg(not(target_os = "linux"))]
96mod common;
97#[cfg(target_vendor = "apple")]
98mod corebluetooth;
99#[cfg(target_os = "android")]
100mod droidplug;
101pub mod platform;
102#[cfg(feature = "serde")]
103pub mod serde;
104#[cfg(target_os = "windows")]
105mod winrtble;
106
107/// The main error type returned by most methods in btleplug.
108#[derive(Debug, thiserror::Error)]
109pub enum Error {
110    #[error("Permission denied")]
111    PermissionDenied,
112
113    #[error("Device not found")]
114    DeviceNotFound,
115
116    #[error("Not connected")]
117    NotConnected,
118
119    #[error("Unexpected callback")]
120    UnexpectedCallback,
121
122    #[error("Unexpected characteristic")]
123    UnexpectedCharacteristic,
124
125    #[error("No such characteristic")]
126    NoSuchCharacteristic,
127
128    #[error("The operation is not supported: {}", _0)]
129    NotSupported(String),
130
131    #[error("Timed out after {:?}", _0)]
132    TimedOut(Duration),
133
134    #[error("Error parsing UUID: {0}")]
135    Uuid(#[from] uuid::Error),
136
137    #[error("Invalid Bluetooth address: {0}")]
138    InvalidBDAddr(#[from] ParseBDAddrError),
139
140    #[error("Runtime Error: {}", _0)]
141    RuntimeError(String),
142
143    #[error("{}", _0)]
144    Other(Box<dyn std::error::Error + Send + Sync>),
145}
146
147/// Convenience type for a result using the btleplug [`Error`] type.
148pub type Result<T> = result::Result<T, Error>;