Bluetooth Pairing with .Net/C# BlueZ and dbus

bluetooth   bluez   mono   c#   .net   pebble   linux  

At this point in the project I had a working dbus implementation to use, and it was time to begin actually implement some bluetooth functionality. The first thing I did was to attempt to convert the various interfaces defined in the bluez docs to .Net interfaces. This left a lot to be desired, the docs are not very clear as to what data type is being used in many cases. Thankfully there is a handy gui tool called d-feet which you can use to simply browse the system dbus under org.bluez and discover the interfaces, methods, properties, and events (signals) that are exposed.

I started a new project called Mono.BlueZ where I defined these interfaces and began exercising them.

One of the shortcomings of my bluez 4 implementation was that pairing had to be done with a display and keyboard on the raspberry pi, so I wanted to try and automate the pairing process if possible.

The "Entry point" of any BlueZ 5 integration is the interface org.freedesktop.DBus.ObjectManager which allows you to discover all of the interfaces that BlueZ is currently providing. After initializing dbus, the first thing that is needed is an instance of the Object Manager from BlueZ's root.


var manager = _system.GetObject("org.bluez", ObjectPath.Root);

To receive notifications as BlueZ discovers/loses devices etc, you need to register a couple events with the object manager


manager.InterfacesAdded += (p, i) => { System.Console.WriteLine (p + " Discovered");}; 
manager.InterfacesRemoved += (p, i) => { System.Console.WriteLine (p + " Lost");};

We're also going to need an instance of the the AgentManager1 object which is used to register our pairing agent.


var agentManager = _system.GetObject("org.bluez", new ObjectPath("/org/bluez"));

In order to actually do the pairing, we need to register our own agent with the agent manager. For my purposes I want it to just pair with anything that it finds at startup time, so only a bare minimum implementation is necassary


public class DemoAgent:Agent1
//removed for brevity, but it just implements the Agent1 interface (no actual functionality for now)

Next we instantiate it,register it on dbus, and register it with the agent manager.


var agent = new DemoAgent();
_system.Register(new ObjectPath("/agent"), agent);
agentManager.RegisterAgent(agentPath,"KeyboardDisplay");
agentManager.RequestDefaultAgent(agentPath);

Now when something attempts to pair, our agent will receive these method calls.

The next step is to find the desired local bluetooth adapter and start device discovery. This can be done by looping through all the BlueZ objects and selecting objects which have the Adapter1 interface.


var managedObjects = manager.GetManagedObjects();
ObjectPath adapterPath = null;
foreach (var obj in managedObjects.Keys)
{
    if(managedObjects[obj].ContainsKey("org.bluez.Adapter1"))
    {
        if (string.IsNullOrEmpty(adapterName) || obj.ToString().EndsWith(adapterName))
        {
            System.Console.WriteLine("Adapter found at" + obj);
            adapterPath = obj;
            break;
        }
    }
}

For the next step, make sure your bluetooth device is discoverable, and then


var adapter = _system.GetObject("org.bluez", adapterPath);
adapter.StartDiscovery ();

You should see the your InterfacesAdded handler fire (if the devices wasn't already discovered) and list the object path of your bluetooth device.

To pair, simply get the Device1 interface for the path and call pair and trust.


var device = _system.GetObject("org.bluez", p);
device.Pair();
device.Trusted=true;

In a future post I will cover connecting a socket to a paired device.


comments powered by Disqus
Comments powered by Disqus