“Not another blog post about Bluetooth Low Energy GATT!” I hear you say.
Ok, it’s true that there are quite a number of posts on this topic for BlackBerry 10 now. You can find a list here: Bluetooth Low Energy Resource Index, including the “Swiss Army Knife” of Bluetooth Low Energy GATT applications: “BlackBerry Bluetooth Explorer” which featured as the Bluetooth SIG application of the month earlier this year.
GATT is fundamental to how a BlackBerry 10 device communicates with Bluetooth Low Energy peripherals such as Heart Rate Monitors, Cycling Speed and Cadence monitors and even iBeacons™. In these use-cases, the BlackBerry device acts as a GATT client to the GATT server running in a peripheral.
If you don’t understand the concept of GATT, this is probably a good time to have a read at one of the earlier blogs in the series such as this one: BlackBerry 10 Bluetooth LE primer for developers.
However, BlackBerry 10 is also capable of hosting a GATT server, and this opens up a whole range of new use-cases. What classes of use-case am I thinking about? Well, let’s have a look.
An Example Use-Case for BlackBerry 10 Acting as a GATT Server
Let’s imagine we have a “smart watch” that acts as a Bluetooth Low Energy GATT server and that it exposes a number of services to which a BlackBerry 10 handset can connect. These services might include:
- Acceleration – so the watch can recognize when you’re walking or running;
- Heart Rate – the back of the watch may have sensors that connect to your skin and detect your heart rate;
- Temperature – the watch may be able to detect your body temperature;
- The list could go on.
The idea is that these data can be captured by the BlackBerry 10 handset and perhaps even saved and analyzed in the “cloud.” However, suppose that you also wanted the watch to be able to notify you, by perhaps vibrating, when a new email arrived; or have it be able to access the Location Services on the handset; or even have access to a custom GATT service running on the smartphone.
To do this sort of thing, the BlackBerry 10 handset has to be able to host one or more GATT services and allow the smart watch to connect back to the handset. That is, the watch acts both as a GATT server to the BlackBerry 10 handset’s client and as a GATT client to the BlackBerry 10 handset’s GATT server.
It’s important not to mix the quite distinct concepts of GATT Server and Client roles with the separate roles of Central and Peripheral Bluetooth LE devices. Because the two concepts are distinct, it’s quite legitimate to have a GATT Server run on either a central or peripheral device. The same applies to a GATT client.
I hope you can now begin to see why being able to host GATT services on a BlackBerry 10 handset is such a powerful capability.
I had a problem with demonstrating this: I didn’t have a smart watch, but what I did have was more than one BlackBerry 10 device! So here’s the model I used for this sample application:
- There is a BlackBerry 10 application running on the first device acting as a GATT server, and
- There is another BlackBerry 10 application, running on the second device, acting, in place of the “smart watch,” as a GATT client.
The GATT server application is called “GattServerRandom” and the GATT client application is called “SimpleRnsClient.” If you haven’t already guessed, the service offered by the GATT server application will generate a stream of random numbers that will be subscribed to by the GATT client application and displayed. Having the GATT server act as a random number server is a simple way to demonstrate this capability. I’m sure you can think of other more “real-world” applications based on this same pattern.
Here’s what the pair of applications looks like when random numbers are served from one device to the other. The Server is running on a Q10 on the left and the Client on a Z10 on the right. The client searches for the server and connects to it.
Once the client has connected to the server, it tells the server to start sending out a stream of random numbers, in the range 1 to 256. The server then starts using the Bluetooth Low Energy GATT Notify mechanism to send the stream of numbers. It will continue to do so until told to stop or the GATT connection is terminated.
So you can see that the principle is quite simple, but also incredibly powerful in terms of how you can use this capability.
How was this done? What code is needed to achieve this? First, let’s look at the server application.
How the GattServerRandom Application Works
This application initializes itself in the same way as all the other Bluetooth LE BlackBerry applications we’ve already talked about except that, additionally, it initializes itself as a GATT server as shown below:
The next thing it has to do is describe the GATT services and attributes that the application will host. You need to specify this information in a data structure like this:
Oh my goodness! That looks extremely intimidating doesn’t it? Let’s go through it slowly and use this as a key:
All that we’re doing here is defining an array with four entries that describe different elements of the GATT service we want to create. The BlackBerry 10 GATT Service will use this array to add your definitions to its list of services, provided the array is syntactically correct and self-consistent.
- The first entry ( _myService ) describes the overall service identified by a UUID ( “0x3759E92B-4E2C-4EFD-97B5-AABBCCDDEEAA” ). Notice that each entry is given a handle. This one has a handle of “0”.
- The next entry ( _myService ) describes a characteristic of this service identified by another UUID ( “0x3759E92B-4E2C-4EFD-97B5-000000000000” ). The handle of this entry is “1”. It states that this value can be sent using Notifications to a client that asks. It also notes that the value of this attribute is to be found at handle “2”. Notice there is no explicit definition of handle “2” since the GATT server supplies that when it is started.
- The next entry ( _myService ) describes a characteristic of this service identified by a well-known, and predefined by architecture, UUID ( “0x2902” ). Its handle is “3” (notice that we’ve skipped “2”). It’s writeable, and if a client writes 0x0001 to this attribute, the server will start notifying the value associated with the characteristic – the random number in this case. The sending of Notifications can be stopped if a client writes the value 0x0000 to this attribute.
- The final entry ( _myService ) describes a characteristic of this service identified by a well-known, and predefined by architecture, UUID ( “0x2901” ). Its handle is “4” and its value is just a human readable string identifying the attribute – namely, the “Random Number” attribute.
There is certainly scope for making a mistake in defining such a service definition. The next step is to verify the self-consistency of the definition and, if it passes the check, then to register the definition with the GATT service.
The final step is to tell the GATT Service to start running. The code below shows how this is done by instructing the GATT Service to “Start Advertising.”
Now all we need to do is wait for a GATT client to connect to the GATT service and start reading and writing attributes. The application gets called via a call-back when one of these events occurs. Let’s take a look at what happens when the client asks for Notifications of random numbers to be started by writing a value of 0x0001 into the attribute at handle “3”.
Some defensive work is needed, like checking that the client is attempting to write to the correct handle (“3”) and that the value is either 0x0000, or 0x0001. If it all checks out, we respond with a positive response to the write operation, if it’s required, and allow it to proceed or bounce it with an error. Then we start the random number generator and every second, until stopped, the code below gets executed where a new random number is generated and written into the handle “2” of the GATT service.
It’s as simple as that. Just to put the whole server side into context, let’s see what the GATT service actually looks like using the Texas Instruments “BTool” utility, which is a standard item in my toolset now. Here’s the description of the GATT service as it appears to BTool.
The highlighted column on the left shows the handles of the attributes. There are five of them in our service. We defined them as numbered “0” through “4”, but when the GATT service integrated the definitions, they were offset to handles 0x00BA through 0x00BE. You should compare this with the original GATT service definition that was defined for our service.
If you’ve been paying attention, you’ll probably have a question. If our service has been shifted up to handle 0x00BA, then what additional services is BlackBerry 10 providing that are also in the GATT? Well, let’s take a look.
We find something very interesting. When our GATT service application is running, BlackBerry 10 offers, and advertises, the following well-known services as defined by the Bluetooth SIG specifications:
- 0x1811 – Alert Notification Service
- 0x1804 – Transmit Power Service
- 0x180F – Battery Service
- 0x180A – Device information Service
- 0x1819 – Location and Navigation Service
- 0x1807 – Next DST Change Service
- 0x1805 – Current Time Service
- 0x1803 – Link Loss Service
Let’s take a look at the “Device Information Service”:
This shows that my device running the GATT service is a Q10 running 10.3.0.698. This is the same information you’d find on the device “About” page in “Settings.”
Another one is the “Location and Navigation” service:
So, a GATT client, like the “smart watch” I mentioned earlier in this article, could determine location and speed-based data on demand from the BlackBerry 10 device.
It’s important to note that these services are available only when an application is running a GATT service and that the BlackBerry 10 handset user is prompted with an Alert when a GATT client attempts to connect so that it’s not possible to read this data without the express consent of the handset’s owner.
I think you now see why I said that the potential use-cases expand enormously when you start to run GATT services on your device.
I haven’t said much about the GATT client application. Let’s take a look at it now.
How the SimpleRnsClient Application Works
In fact, there’s not much that is different in this client application compared to other GATT client applications I’ve already written about in prior blog posts, so I’ll not dwell on this one. All of the code is available on GitHub for you to examine anyway.
There is one interesting point in this GATT client application, though, that’s worth pointing out.
How does the SimpleRnsClient work out how to connect to the BlackBerry 10 device in the first place? The custom GATT random number service I’ve written about isn’t mentioned in any Bluetooth LE advertisements; only the standard ones like 0x1819, etc. that I mentioned earlier.
Also, every time the GATT server application is restarted, the BlackBerry 10 device advertises using a different random Bluetooth LE device address. This is because it uses a privacy feature that thwarts attempts to track a device through Bluetooth LE advertisements via the MAC address. The real private MAC address is only available to devices that have performed a secure key exchange and bonded.
I could have added a text field to the client’s screen where the user could have entered the current MAC address or the “name” of the device, such as “BLACKBERRY-16EE,” or “John’s Q10,” but I wanted this client to work without tedious entering of data in the application.
So what the client actually does is enumerate the various standard services that BlackBerry 10 advertises when a custom GATT service is being run in an application – the ones mentioned earlier. The client will attempt a GATT connection to the first device it finds that matches all of these services. It’s a little more user-friendly for a sample application, but maybe not viable in the real world.
In a real-world scenario, when the BlackBerry 10 handset connects to the “smart watch,” it could be designed to pass sufficient information to the watch to allow it to connect back to the handset without any need for user intervention. This would, of course, be a function of the GATT services offered by the watch.
I’ve released V1.0.0 of the GattServerRandom and SimpleRnsClient applications containing the features described in this article, so you can download, review and reuse the full source code. You can find the URL in the “Resources” section below. I hope this has been interesting and will help set you on your way to developing real-world GATT Server based applications for Blackberry 10.
Please feel free to contact me @jcmrim via Twitter if you need help on anything related to Bluetooth Low Energy.