blurz 0.4.0

Bluetooth lib for Rust using blueZ/dbus
Documentation
use dbus::{Connection, Message, MessageItem, Props};
use std::error::Error;

static ADAPTER_INTERFACE: &'static str = "org.bluez.Adapter1";
static DEVICE_INTERFACE: &'static str = "org.bluez.Device1";
static SERVICE_INTERFACE: &'static str = "org.bluez.GattService1";
static CHARACTERISTIC_INTERFACE: &'static str = "org.bluez.GattCharacteristic1";
static DESCRIPTOR_INTERFACE: &'static str = "org.bluez.GattDescriptor1";
static SERVICE_NAME: &'static str = "org.bluez";

fn get_managed_objects(c: &Connection) -> Result<Vec<MessageItem>, Box<Error>> {
    let m = try!(Message::new_method_call(
        SERVICE_NAME,
        "/",
        "org.freedesktop.DBus.ObjectManager",
        "GetManagedObjects"
    ));
    let r = try!(c.send_with_reply_and_block(m, 1000));
    Ok(r.get_items())
}

pub fn get_adapters(c: &Connection) -> Result<Vec<String>, Box<Error>> {
    let mut adapters: Vec<String> = Vec::new();
    let objects: Vec<MessageItem> = try!(get_managed_objects(&c));
    let z: &[MessageItem] = objects.get(0).unwrap().inner().unwrap();
    for y in z {
        let (path, interfaces) = y.inner().unwrap();
        let x: &[MessageItem] = interfaces.inner().unwrap();
        for interface in x {
            let (i, _) = interface.inner().unwrap();
            let name: &str = i.inner().unwrap();
            if name == ADAPTER_INTERFACE {
                let p: &str = path.inner().unwrap();
                adapters.push(String::from(p));
            }
        }
    }
    Ok(adapters)
}

pub fn list_devices(c: &Connection, adapter_path: &String) -> Result<Vec<String>, Box<Error>> {
    list_item(c, DEVICE_INTERFACE, adapter_path, "Adapter")
}

pub fn list_services(c: &Connection, device_path: &String) -> Result<Vec<String>, Box<Error>> {
    list_item(c, SERVICE_INTERFACE, device_path, "Device")
}

pub fn list_characteristics(
    c: &Connection,
    device_path: &String,
) -> Result<Vec<String>, Box<Error>> {
    list_item(c, CHARACTERISTIC_INTERFACE, device_path, "Service")
}

pub fn list_descriptors(c: &Connection, device_path: &String) -> Result<Vec<String>, Box<Error>> {
    list_item(c, DESCRIPTOR_INTERFACE, device_path, "Characteristic")
}

fn list_item(
    c: &Connection,
    item_interface: &str,
    item_path: &str,
    item_property: &str,
) -> Result<Vec<String>, Box<Error>> {
    let mut v: Vec<String> = Vec::new();
    let objects: Vec<MessageItem> = try!(get_managed_objects(&c));
    let z: &[MessageItem] = objects.get(0).unwrap().inner().unwrap();
    for y in z {
        let (path, interfaces) = y.inner().unwrap();
        let x: &[MessageItem] = interfaces.inner().unwrap();
        for interface in x {
            let (i, _) = interface.inner().unwrap();
            let name: &str = i.inner().unwrap();
            if name == item_interface {
                let objpath: &str = path.inner().unwrap();
                let prop = try!(get_property(c, item_interface, objpath, item_property));
                let prop_path = prop.inner::<&str>().unwrap();
                if prop_path == item_path {
                    v.push(String::from(objpath));
                }
            }
        }
    }
    Ok(v)
}

pub fn get_property(
    c: &Connection,
    interface: &str,
    object_path: &str,
    prop: &str,
) -> Result<MessageItem, Box<Error>> {
    let p = Props::new(&c, SERVICE_NAME, object_path, interface, 1000);
    Ok(try!(p.get(prop)).clone())
}

pub fn set_property<T>(
    c: &Connection,
    interface: &str,
    object_path: &str,
    prop: &str,
    value: T,
    timeout_ms: i32,
) -> Result<(), Box<Error>>
where
    T: Into<MessageItem>,
{
    let p = Props::new(&c, SERVICE_NAME, object_path, interface, timeout_ms);
    Ok(try!(p.set(prop, value.into())))
}

pub fn call_method(
    c: &Connection,
    interface: &str,
    object_path: &str,
    method: &str,
    param: Option<&[MessageItem]>,
    timeout_ms: i32,
) -> Result<(), Box<Error>> {
    let mut m = try!(Message::new_method_call(
        SERVICE_NAME,
        object_path,
        interface,
        method
    ));
    match param {
        Some(p) => m.append_items(p),
        None => (),
    };
    try!(c.send_with_reply_and_block(m, timeout_ms));
    Ok(())
}