10.08.15 Introducing Bluetoe
A Bluetooth Low Energy GATT Server
Bluetoe is an open source side project of mine, and it's a Bluetooth Low Energy GATT Server. While written in modern C++ (C++11), the intended target platforms are small embedded devices without any operating systems and with memory sizes, still measured in kilobytes.
Using C++ shows to have some advantages like expressive configuration syntax, impressive amounts of compile time checks, and the ability to store a lot of data structures in ROM (most microcontrollers have much more ROM than RAM).
The Problem to be Solved (GATT)
The Generic Attribute Profile (GATT) is some kind of key value store on a remote, wireless accessible device. In GATT, a key value pair is named a characteristic, and beside the current value, a characteristic can have additional attributes like a descriptive name, data type informations, and access rights. Several characteristics are grouped into services, and a GATT server provides at least one service.
The protocol to inspect the structure of the store and to store and retrieve values from it, is designed with the low energy aspect of Bluetooth Low Energy (BLE) in mind. For example, a client who is interested in changes to a certain stored value does not need to poll the GATT server (it can subscribe to the characteristic).
A GATT server is named a server because it's where the key value pairs are stored. In most Bluetooth Low Energy applications these are small devices worn to measure blood pressure, running speed, or heart rates. In some projects, where I was involved, GATT was used to handle embedded systems for operation, to configuration, and analysis.
Design Goals
There are already established solutions out there, and while using a few of them, and their APIs, I often thought of how to improve what I had to use. When designing a piece of software it's always a good thing to have some design criteria that can be used when decisions have to be made. The Bluetooth Core Specification (4.2) served as an excellent requirement document.
This where my design goals, I hoped to achieve with Bluetoe:
Hide Unnecessary Details
As a software developer, adding a Bluetooth LE interface to a device is probably just one of our daily tasks. The current Bluetooth Core Specification compries of 2,772 pages. Only the smaller part contains informations relevant to BLE, and that's already hard enough to find out, and a few hundreds pages to read, is still to much for the task at hand.
I think it's not nessary to refer to the Bluetooth Core Specification from an API documentation. Just give me the structure of the key value store, tell me what a characteristic is, tell me what a service is. Give me the options I can use to modify a characteristic or a service. There is no need for me to know that GATT is implemented on top of ATT and that to add a descriptive name to a characteristic a "Characteristic User Description" attribute have to be used, nor is it necessary to structure the API that way!
BTW: The OS/X and iOS documentation, is a good read to get an overview about the topic.
Make Easy Things Easy
If I'm going to use some special, fancy BLE feature, I'm willing to put some effort in finding out how to achive what I'm looking for. But, when I just want to implement a vanilla integer characteristic without any additional features, I don't want to fill a C struct with 5 fields and call a couple of functions and cope with a couple of function return values.
Bluetoe tries to use reasonable defaults, where ever possible. For example: using a global constant as characteristic value automatically declares the characteristic as read only characteristic.
Prevent Error Sources by Design
Checking the return value of a function for errors is a good coding habit. Checking whether or not a function can or will ever return an error, is an even better design habit.
Especially in embedded systems, there are very few sources of errors. If it’s really an error, it’s most likely broken hardware and when it’s not an error, it’s part of the defined systems state (like a detected broken cable). Software bugs are not errors that should be communicated, they should be fixed.
If resources are limited, the best way to make sure, that the system will not run out of resources is to check that during compile and link time, not during the start of the firmware. The Bluetoe API does not use any dynamic resource schemes. So when an application compiles and links it will not run into any resource constrain during runtime.
Use as Little Resources as possible
By nature, GATT servers are deployed to very tiny systems. And as a product is usually shipped with hardware and software, there are ambitions to keep the hardware as cheap as possible (especially true in higher volume consumer products). So Bluetoe does not use exceptions, nor dynamic memory. Everything that does not change during runtime can be stored in cheap flash memory.
As Bluetoe is written in modern C++, it’s very unlikely that it will be possible to compile it to 8 bit targets (please let me know if you know of any C++11 compiler, with 8 bit target platforms). But, one of the first targets will be a Cortex-M0, the smallest CPU ARM offers.
Current State and Roadmap
Currently the GATT server is almost implemented. It could use some more convenience features and better support for GAP (the protocol used when a device advertises it’s features) and profiles defined by Bluetooth Special Interest Group. GATT needs a L2CAP layer to work on. Unfortunately, I was not able to find such a layer as open source. So currently, Bluetoe is getting its own L2CAP layer that works on the nRF51 architecture.
A latest state of implementation can be found on the github project page.