Servo-specific APIs to access various devices
Bluetooth related code is located in bluetooth.rs
.
Underlying dependency crates:
- Android platform: blurdroid
- Linux platform: blurz
- MacOS platform: blurmac
Fake
prefixed structures: blurmock
Empty
prefixed structures are located in empty.rs
.
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:
pub enum BluetoothAdapter {
Android(Arc<BluetoothAdapterAndroid>),
}
Linux:
pub enum BluetoothAdapter {
Bluez(Arc<BluetoothAdapterBluez>),
}
MacOS:
pub enum BluetoothAdapter {
Mac(Arc<BluetoothAdapterMac>),
}
unsupported platforms:
pub enum BluetoothAdapter {
Empty(Arc<BluetoothAdapterEmpty>),
}
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<BluetoothAdapterAndroid>
.
pub fn init() -> Result<BluetoothAdapter, Box<Error>> {
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:
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!");
}
The bluetooth-test
feature is not a default feature, to use it, append features = ["bluetooth-test"]
, to the device
crate dependency in the project's Cargo.toml
.
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:
pub enum BluetoothAdapter {
Android(Arc<BluetoothAdapterAndroid>),
Mock(Arc<FakeBluetoothAdapter>),
}
Linux:
pub enum BluetoothAdapter {
Bluez(Arc<BluetoothAdapterBluez>),
Mock(Arc<FakeBluetoothAdapter>),
}
Mac:
pub enum BluetoothAdapter {
Mac(Arc<BluetoothAdapterMac>),
Mock(Arc<FakeBluetoothAdapter>),
}
unsupported platforms:
pub enum BluetoothAdapter {
Empty(Arc<BluetoothAdapterEmpty>),
Mock(Arc<FakeBluetoothAdapter>),
}
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()
.
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!
.