Bluetooth: ConnectDevice without scanning

After discovering the nearby Bluetooth devices either using StartDiscovery without filter or with SetDiscovertFilter, next big step is to connect with the device and access the functionalities provided by the device. The connection process involves two steps,

  1. Pairing – Authenticating and trusting the end bluetooth device
  2. Connect itself

Here connection can be initiated either by the Bluetooth device or by the Bluetooth adapter itself on behalf of application. The Authentication mechanism involves accepting the device/adapter using PIN/confirmation key. We are not going in details about the Secure Simple Pairing (SSP) of Bluetooth here as bluetoothd hides all the details already. Bluez5 uses Agent style implementation of authentication in favor to the external application. To understand in details, lets assume the following use case,

  • User wants to connect to the Car Infotainment System (IVI) using bluetooth and initiates the connection from the mobile device. In this case, IVI head unit displays the PIN/confirmation code based on its Agent configurations. Then the user enters the same PIN or confirm yes/no from the mobile device. In this use case,
    • IVI wants to show up the confirmation/PIN in its own wizard or pop (e.g GTK)
    • Mobile device wants to pop up confirmation/Input field in its wizard

In favor of such implementations, Bluez5 provide Agent style API’s i.e Bluetooth Application can register it’s capability (yes/no confirmation or PIN entry) and also it’s own wizard implementation with the bluetoothd. Whenever there is a new connection from a device, bluetoothd automatically takes care to callback the registered API (where wizard or user application is implemented).

From the flow diagram, you can see,

  • UI application registers its capability with method callbacks with bluetoothd
  • StartDiscovery for scanning new devices
  • Pair with the device
    • bluetoothd callsback the API in UI for PIN/confirmation about the authentication
    • Based on the response, bluetoothd decides to proceed or not for pairing
  • Followed by Connect call to the Device1 interface (we will explore this interface in detail in next few blogs)

To get started with connection and for the completeness of the API’s coverage in adapter-api.txt, we will first explore the “ConnectDevice” API introduced in Bluez 5.49. As of this blogging date, this API is marked experimental for testing (mostly stable). To explore the below example on ConnectDevice, one must run the bluetoothd service/daemon in experimental mode by passing “-E” as argument.

Code:

ConnectDevice: This API is introduced in favor of answering following questions,

When this API is useful?

  • When you already have the MAC address of end bluetooth Device to connect with, then you don’t need to scan for the device (with or without filter) and connect it.
  • StartDiscovery + Pair + Connect => ConnectDevice

How you will have MAC address before scanning?

  • When you have other communication (wired or wireless) medium to exchange the MAC address
  • For example, NFC OOB can be used to exchange the MAC address
  • Testing Bluetooth with same device (MAC address known)

In such cases ConnectDevice can be directly called with “MAC address” of the bluetooth device to connect with as argument (as string, not as object path). In addition to the MAC address, Address Type (optional argument) can also be specified as argument to this method. For simplicity and better understanding we are going stick to only MAC address.

Before using the ConnectDevice method, we need to register our own agent which needs to be called for pairing process. Again for simplicity and for better understanding we are registering “NoInputOutput” without any method callbacks. This means, our bluetooth adapters Agen capability is similar to the one in Bluetooth headset, where user doesn’t need to care about pairing authentication. We will explore in detail about Agen API and all the methods in next blog before getting into device-api.

This example program takes the MAC address (XX:YY:ZZ:AA:BB:CC format) as argument which is directly fed into ConnectDevice method. Also note that this example uses Linux signal handler for SIGINT (Control + c from console) to gracefully handle the program exit.

-

10 Comments

  • csp23 October 24, 2018 at 4:01 am

    hi there your guys BLOG example about BLE base on GIO and Glib are amazing!!!
    Please keep going.
    Question:how can we get the Node Information and Methods ?not only the properties.
    like commod line: $ gdbus introspect –system –dest org.bluez -o /org/bluez/hci0/

    interface org.bluez.Media1 {
    methods:
    RegisterEndpoint(in o endpoint,
    in a{sv} properties);
    UnregisterEndpoint(in o endpoint);
    RegisterPlayer(in o player,
    in a{sv} properties);
    UnregisterPlayer(in o player);
    signals:
    properties:
    };
    interface org.bluez.NetworkServer1 {
    methods:
    Register(in s uuid,
    in s bridge);
    Unregister(in s uuid);
    signals:
    properties:
    };
    node dev_A4_17_31_4D_C6_7C {
    };
    node dev_C0_E6_30_BD_63_C1 {
    };

    Reply
    • Parthiban Nallathambi October 25, 2018 at 8:02 am

      dbus introspection is to find the list of available methods with its arguments (using “org.freedesktop.DBus.Introspectable.Introspect“). To find the real value of the property, you need to use “org.freedesktop.DBus.Properties.GetAll“. So both are completely different methods. So you need to use them accordingly.

      Comments in Linumiz are controlled by admins to avoid spams. So your comments with answers will appear with some delay.

      Reply
  • Julien November 22, 2018 at 4:12 pm

    Hi!
    Your posts regarding how to use DBUS for BlueZ are amazing!
    I need now to be able to retrieve the list of services and characteristics of the device I just connected to? Then I will need to write some characteristic..
    For example, using bluetoothctl, I am able to connect to a device . When it is connected, it displays all the services and characteristics of the peer like:
    [NEW] Primary Service
    /org/bluez/hci0/dev_98_7B_F3_65_83_32/service0019
    0000180a-0000-1000-8000-00805f9b34fb
    Device Information
    How can I get those information directly from my application? Then how to read/write a characteristic?

    Thank you very much!!

    Reply
  • Guillaume November 27, 2018 at 8:49 am

    Hi, i would like to pair a device which i know the adress, I can’t manage to use this code.
    Thank you.

    Reply
    • Parthiban Nallathambi November 27, 2018 at 8:58 am

      You don’t need ConnectDevice API for pairing the device. The sequence is,

        Scan for the device using StartDiscovery
        Once the device is appeared, trust the device
        Call pair API in the device

      Unfortunately the blogs cover only adapter API so far and the device API’s are in progress.

      Reply
      • Guillaume December 4, 2018 at 8:35 am

        Hi again, thank you for your quick answer ! I’m sorry I wasn’t precise enough in my question. I am trying to pair with a SensorTag from TI (http://www.ti.com/ww/en/wireless_connectivity/sensortag/), working in BLE, in order to get its informations from a PC running on Ubuntu 14.04 LTS. Your bluez_adapter_scan() function works well and actually print the SensorTag info on the terminal, with its MAC adress. We are now trying to pair with the device, and initially used your bluez_adapter_connect() function in order to do that. Now thanks to your answer we understand that we shouldn’t use the ConnectDevice API used in this program, but we are still wondering how to trust and pair with it as you said after it appears with StartDiscovery, as Trusted is only a device’s property ?
        Thank you !

        Reply
        • Parthiban Nallathambi December 4, 2018 at 10:23 am

          When a new device is appeared, you will get it’s object path. Now you need to use the device interface and object path to communicate with the device itself.

          Assuming you device mac is XX:YY:ZZ:AA:BB:ZZ and your adapter recognized as hci0, then /org/bluez/hci0/dev_xx_yy_zz_aa_bb_cc is your device path. With this,
          you should use,

          Service: org.bluez
          Interface: org.bluez.Device1
          Object Path: /org/bluez/hci0/dev_xx_yy_zz_aa_bb_cc

          these details to access all the methods and properties in device api.

          You may also need to implement bluez pairing agent if you are using PIN (either fixed or dynamic) for the pairing process using “Pair” API.

          If you have more query and request, please feel free contact us me parthiban@linumiz.com

          Reply
      • Alexander December 11, 2018 at 12:08 pm

        Hello, your post very helped for me
        Can you tell me please, when device api’s will be ready?
        Thank you!

        Reply

    Please Post Your Comments & Reviews

    Your email address will not be published. Required fields are marked *