# Bluetooth Servo-specific APIs to access Bluetooth devices. Bluetooth related code is located in `bluetooth.rs`. ### Implementation Underlying dependency crates: - Android platform: [blurdroid](https://crates.io/crates/blurdroid) - Linux platform: [blurz](https://crates.io/crates/blurz) - macOS platform: [blurmac](https://crates.io/crates/blurmac) - `Fake` prefixed structures: [blurmock](https://crates.io/crates/blurmock) `Empty` prefixed structures are located in `empty.rs`. ### Usage #### Without the *bluetooth-test* feature There are three supported platforms (Android, Linux, macOS), on other platforms we fall back to a default (`Empty` prefixed) implementation. Each enum (`BluetoothAdapter`, `BluetoothDevice`, etc.) will contain only one variant for each targeted platform. See the following `BluetoothAdapter` example: Android: ```rust pub enum BluetoothAdapter { Android(Arc), } ``` Linux: ```rust pub enum BluetoothAdapter { Bluez(Arc), } ``` macOS: ```rust pub enum BluetoothAdapter { Mac(Arc), } ``` Unsupported platforms: ```rust pub enum BluetoothAdapter { Empty(Arc), } ``` You will have a platform specific adapter, e.g. on Android target, `BluetoothAdapter::init()` will create a `BluetoothAdapter::Android` enum variant, which wraps an `Arc`. ```rust pub fn init() -> Result> { let blurdroid_adapter = try!(BluetoothAdapterAndroid::get_adapter()); Ok(BluetoothAdapter::Android(Arc::new(blurdroid_adapter))) } ``` On each platform you can call the same functions to reach the same GATT hierarchy elements. The following code can access the same Bluetooth device on all supported platforms: ```rust use device::{BluetoothAdapter, BluetoothDevice}; fn main() { // Get the bluetooth adapter. let adapter = BluetoothAdpater::init().expect("No bluetooth adapter found!"); // Get a device with the id 01:2A:00:4D:00:04 if it exists. let device = adapter.get_device("01:2A:00:4D:00:04".to_owned() /*device address*/) .expect("No bluetooth device found!"); } ``` #### With the *bluetooth-test* feature Each enum (`BluetoothAdapter`, `BluetoothDevice`, etc.) will contain one variant of the three possible default target, and a `Mock` variant, which wraps a `Fake` structure. Android: ```rust pub enum BluetoothAdapter { Android(Arc), Mock(Arc), } ``` Linux: ```rust pub enum BluetoothAdapter { Bluez(Arc), Mock(Arc), } ``` macOS: ```rust pub enum BluetoothAdapter { Mac(Arc), Mock(Arc), } ``` Unsupported platforms: ```rust pub enum BluetoothAdapter { Empty(Arc), Mock(Arc), } ``` Beside the platform specific structures, you can create and access mock adapters, devices, services etc. These mock structures implements all the platform specific functions too. To create a mock GATT hierarchy, first you need to call the `BluetoothAdapter::init_mock()` function, insted of `BluetoothAdapter::init()`. ```rust use device::{BluetoothAdapter, BluetoothDevice}; use std::String; // This function takes a BluetoothAdapter, // and print the ids of the devices, which the adapter can find. fn print_device_ids(adapter: &BluetoothAdpater) { let devices = match adapter.get_devices().expect("No devices on the adapter!"); for device in devices { println!("{:?}", device.get_id()); } } fn main() { // This code uses a real adapter. // Get the bluetooth adapter. let adapter = BluetoothAdpater::init().expect("No bluetooth adapter found!"); // Get a device with the id 01:2A:00:4D:00:04 if it exists. let device = adapter.get_device("01:2A:00:4D:00:04".to_owned() /*device address*/) .expect("No bluetooth device found!"); // This code uses a mock adapter. // Creating a mock adapter. let mock_adapter = BluetoothAdpater::init_mock().unwrap(); // Creating a mock device. let mock_device = BluetoothDevice::create_mock_device(mock_adapter, "device_id_string_goes_here".to_owned()) .unwrap(); // Changing its device_id. let new_device_id = String::from("new_device_id_string".to_owned()); mock_device.set_id(new_device_id.clone()); // Calling the get_id function must return the last id we set. assert_equals!(new_device_id, mock_device.get_id()); // Getting the mock_device with its id // must return the same mock device object we created before. assert_equals!(Some(mock_device), mock_adapter.get_device(new_device_id.clone()).unwrap()); // The print_device_ids function accept real and mock adapters too. print_device_ids(&adapter); print_device_ids(&mock_adapter); } ``` Calling a test function on a not `Mock` structure, will result an error with the message: `Error! Test functions are not supported on real devices!`.