1
votes

I'm using Android Things 1.0.4 in a prototype where it acts as BLE peripheral device: advertising services and running a GATT server.

I encounter an issue in the BLE pairing process when trying to bond the Android Things board (Raspberry Pi 3) and a smartphone.

Since the device has no display, I set using BluetoothConfigManager:

IoCapability = BluetoothConfigManager.IO_CAPABILITY_NONE

which results in the error AUTH_FAILED every time.

Instead,

IoCapability = BluetoothConfigManager.IO_CAPABILITY_OUT

logs the pairing key and prompts the smartphone to enter it during pairing, but it results in the REMOVED error.

Questions:

  • Is Android Things in peripheral role capable of handling BLE pairing or not yet?
  • Are there more things that need to be implemented in the app's code to replicate the full-fledged Android logic?

Here's the source code of the Android Things app to test BLE pairing and bonding

The same code stripped from Android Things specific elements completes BLE pairing and bonding successfully when running on an Android phone as Peripheral (server), and an Android device or iPhone as Central (client).

1
Can you clarify the pairing process you are using a bit more? Are you initiating pairing/connection from your IoT device or from an Android phone? - devunwired
Pairing fail in both cases: - If pairing is initiated from the Android Things peripheral via createBond() - If pairing is initiated from the client's side, like if an encrypted property is present when an iPhone is connecting, iOS attempts to pair immediately. The example allows to reproduce both. - François Simond

1 Answers

0
votes

Generally speaking, if you attempt to read an encrypted GATT characteristic before pairing (which triggers the pairing logic automatically), this results in GATT error 137 returned from the read request (AUTH_FAIL). This is because the device doesn't have enough time to finish setting up the bond before a response is sent by the Bluetooth stack. Retying the read request again generally succeeds.

I have not tested this with an iOS client device, but it certainly holds true with an Android client connecting to an Android (Things) peripheral. As such, I would recommend a few things:

  1. Have the client (mobile) device explicitly initiate pairing, and Android Things should simply react to these incoming requests in the BluetoothPairingCallback. This lets the mobile device decide the pairing type based on the reported capabilities of the IoT device.

  2. Separate the pairing flow from the GATT flow. Pair to the discovered device separately from making any attempts to read the characteristics. This tends to be the best way to avoid timing problems.

Regarding capability choices, this depends on your device. In my experience, if you choose IO_CAPABILITY_NONE this results in PAIRING_VARIANT_CONSENT inside of onPairingInitiated() and the pairing operation succeeds once finishPairing() is called. If you adjust your capabilities, you should be prepared for any number of the variants requiring you to display a PIN for the mobile device to enter. I have not not personally tested these paths.