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