In a previous post, I looked at creating reliable communications using Classic Bluetooth. While that approach works well, and is a reliable way to connect devices, there may be circumstances when a Bluetooth Low Energy (BLE) connection is preferable.
As it turns out, Bluetooth and BLE are about as similar as apples and oranges. The change in transmission protocol technology is more than a trivial change in the code and its structure.
In this article I explore the difference between BT and BLE and how the previous BT AI2 app needs to be adapted.
This article does not repeat information contained in its predecessor, so it is advisable to read that first for a complete picture.
Bluetooth and Bluetooth Low Energy
It is important to understand that BLE is not at all backwards compatible with older versions of Bluetooth. For the purposes of this article, I will highlight the differences that are important in this application.
Bluetooth Low Energy (aka BLE, Bluetooth 4.0, Bluetooth Smart) is the most recent Bluetooth technology standard. Its main use is for applications that transfer small data packets at relatively low speed using low power consumption.
With BT Classic, a device must be paired in order to establish communications. With BLE there are a number of differences to the connection process:
- the target device must be advertising that it is connectable when a connection is required.
- a connection can be made without pairing. Pairing is an optional security mode only.
- a connection does not have to be made in order to get data from a remote device.
The BLE specification allows a device to take one of two roles, depending on the device’s capabilities. The two types are central or peripheral, and client or server.
- Central vs Peripheral. The role of the central device is similar the ‘master’ in BT Classic. The central device is responsible for searching for and establishing a connection with one or more peripheral devices.
The role of the peripheral device is similar to ‘slave’ in BT Classic. The peripheral device advertises whether it is connectable, and the services it might provide, so that the central device can decide if it should connect to the peripheral device.
- Client vs Server. The client and server roles relate to data ownership and transmission relationship in a BLE network. Typically, the central device will take the client role – requesting and sending data from and to one or more server devices. Peripheral devices typically take on the role of server, keeping a database of attributes a connected client can write to, read or subscribe to receive changes.
This specificity of roles means that the BLE interface is not as transparent to the application as a BT Classic one might be, as each device’s available data must be accessed in a specific way.
Generic Attribute Profiles (GATT Profiles) define the hierarchical structure of the server’s database. A profile is made up of a list of Services, each of which may contain one or more Characteristics. This web site has a list of the officially adopted GATT profiles, although manufacturers may create their own.
A service is used to group a category of characteristics and all characteristics must belong to a service. A characteristic represents one client accessible data attribute. Each characteristic stores a single value and has associated permissions such as read, write, and notify.
Services and characteristics are all assigned and referenced using a Universally Unique IDentifier (UUID).
In this application, the commonly available HM-10 BLE module is used at the Arduino end of the link. The standard module firmware exposes a BLE peripheral with a proprietary connectivity service (UUID: 0000ffe0-0000-1000-8000-00805f9b34fb) that enables bidirectional communication between the module and any central device connected to it. The service defines a single characteristic (UUID: 0000ffe1-0000-1000-8000-00805f9b34fb) that stores 20 bytes of unformatted data. When the central device wants to send data to the module, it writes the characteristic with the desired content. When the module wants to send data, it sends a notification to the central device.
We now have enough information to modify the original BT Android App for BLE applications.
AI2 Support for BLE
The Connectivity modules in AI2 include a BT Classic Server and Client object. The BLE object is an extension to the standard modules that must be loaded into the AI2 interface. The BluetoothLE extension and instructions for installation are found here.
There is a bug in the permissions of the BLE object that requires the BT Client to also be loaded in each Application, even if it is not used. This bug and the solution are described here.
The BLE module works differently from the BT module – most of the BLE functionality is implemented as event callbacks – requiring structural as well as syntax changes to the previously implemented BT code.
The Android AI2 BLE interface code (shown at right) is split into a number of functional blocks triggered from application events.
The initialization process is similar to the previous code, with the important addition of the UUID’s as global variables. As mentioned, the BT client needs to be loaded, so we may as well continue using this to detect if the BT hardware is not started.
Discovering and Connecting to a BLE Device
The first significant difference in code is in how the devices are selected. As the BT devices are not paired to the BT server, they will be discovered over a period of time once Scanning is started.
This discovery process means that devices will become progressively available, changing how the user interface is implemented. The ListPicker object does not seem to handle changes once it is displayed, so it is replaced by a ListView object. As each new device is discovered, the ListView is cleared and refreshed from the DeviceFound callback event.
There may also not be any devices to discover, so ‘Cancel’ functionality must be added to allow the user to abort the discovery process.
Once a selection is made, the App stops device Scanning, separates the IP address and connection name from the ListView selection, and starts connecting to the device using the IP address.
When a connection is confirmed through the Connected event, the App requests to be notified when there are any changes to the string data associated with the Service/Characteristic, setting up future data change events to be captured.
Sending Request Messages
Sending message to the Arduino application is essentially similar to the previous code.
However, the Timeout timer is set for the full timeout rather than increments. The previous BT module was invoked in a ‘polling’ mode, using the timer event to check for available characters. The BLE module data receive is handled via callback events. The timer is therefore is used to detect the full timeout time.
Handling Response Messages
The message receive portion of the BLE app is also different from the previous code.
The timeout is handled directly by a timer (as explained above).
The receive Finite State Machine does not run off the timer but is now part of the StringValueChange event. The code is essentially equivalent to the BT code in the polling timer event with requisite changes for the changed data source.