12

I am starting to build up a simple BLE network with a microcontroller and a raspberry pi (tardis BLE dongle). As a starting point, I am looking for a simple C or C++ example to read/write a BLE device, similar to what I am able to do over the command line. The examples I have found so far are quite complicated. As a BLE beginner I need some very simple examples to build from before moving forward with a more complicated design. I am okay with hard-coding the BLE device name as I have in the gatttool example below.

Here is how I currently use the command line options from Bluez.

From the command line I am able to use:

$ sudo hcitool lescan
LE Scan ...
BB:A0:50:02:18:07 MyDevice

Next I am able to connect to the device on the command line with gatttool:

$ sudo gatttol -b BB:A0:50:02:18:07 -I
[BB:A0:50:02:18:07][LE]> connect
Attempting to connect to BB:A0:50:02:18:07
Connection successful

Finally I am able to read and write using the appropriate handles

[BB:A0:50:02:18:07][LE]> char-write-req 000f 0100
Characteristic value was written successfully
[BB:A0:50:02:18:07][LE]> char-write-cmd 0011 4C467A

Some sites I have used for initial research and to get started:
http://people.csail.mit.edu/albert/bluez-intro/c404.html
https://github.com/carsonmcdonald/bluez-experiments/blob/master/experiments/scantest.c

nhgrif
  • 61,578
  • 25
  • 134
  • 173
Cole Wilson
  • 121
  • 1
  • 1
  • 4
  • You can also have a look at the newest DBUS GATT api published by latest versions of Bluez (since 5.29... I think). Still experimental, but I have done some tests and it works quite fine. Of course performance may be a bit lower than access to bluez library directly but I think it worths a try... – Jorge Martinez May 22 '15 at 08:16

2 Answers2

8

Bluez (Linux official Bluetooth stack) has moved to DBUS for its API. While in the past, it was 'accepted' to 'fork' bluez code to access BLE support on Linux, now the approach is to use DBUS. Bluez DBUS API is documented here: https://git.kernel.org/pub/scm/bluetooth/bluez.git/tree/doc

Either you directly speak to DBUS for your bluetooth C/C++ application or you use a GATT library as a helper. The second one is probably the best approach for beginner (and also for non-beginner who would prefer to keep their program Bluez agnostic for instance to support other OSes or Bluez pre-DBUS API or to have their sources more readable).

One of these GATT libraries that support modern D-BUS API is gattlib (note: I am the author of this library). Here is a simple example based on this library for reading/writing a BLE device: https://github.com/labapart/gattlib/blob/master/examples/read_write/read_write.c

OlivierM
  • 2,820
  • 24
  • 41
  • @OliverM BlueZ DBUS APIs are woefully inadequate and unresponsive. This is from real experience where many many calls hang up without ever returning successfully. The standard socket read() method is most promising way of dealing with HCI. – Ace Jul 11 '19 at 15:49
  • @Ace Directly using HCI means you are rewritting Bluez without DBUS, no? Would not be faster and more clever to offer another transport protocol to Bluez rather than duplicating the job? It is quite likely you who added a '-1' on my reply but all the answers above are not much better - they suggest to fork Bluez to access Bluetooth. – OlivierM Jul 11 '19 at 16:26
  • DBUS system is not only very complicated to manipulate in low level langs like C, but it's rather poorly embraced in BlueZ. Just try to export a simple DBUS LEAdvertisement1 object, and you will see what I mean (Complexity is really e^x). Socket reading is the best solution, especially for real time embedded systems! – Ace Jul 11 '19 at 16:37
  • 2
    I have already done exporting the Bluez DBUS LEAdvertisement1 when it was still experimental. I do not remember how complex was it but I managed to do it. But it is also the reason why creating a frontend on DBUS makes sense to reduce the complexity. I do not necessary disagree with the socket API. But there is a difference of re-implementing Bluez and adding a socket transport layout (in addition of DBUS one). As you probably know writing a library based on HCI is not trivial neither. – OlivierM Jul 11 '19 at 17:39
  • @OlivierM is your answer still releavent in 2021? I would like to use c++ to create ble peripheral on my rasppberry, the stuff you recommended should work right ? – trixo Sep 01 '21 at 12:09
5

Something simple? How short is a piece of string? I personally think that the gatttool code itself is simple enough to follow and extract for your own purposes (I've done it recently). But if that's really not suitable for you then another option is libgatt. It's essentially the same code that gatttool uses but has been bundled more conveniently into a public library API. Have a look at gatt.h which has connect/read/write etc. Hopefully it should be self evident how to use that.

kaylum
  • 13,833
  • 2
  • 22
  • 31
  • Thank you for your response. gatttool.c and gatt.c seem to have what I need. Can you clarify what a GAttrib should be? For example, taking the command line operation to write, char-write-cmd, I have a known MAC address, handle, and value to send. I would like to use the gatt_write_cmd() function from gatt.c and simply pass in a set of known values, but I am stuck on the GAttrib pointer and how it relates to what I have used with the command line option. – Cole Wilson May 22 '15 at 18:32
  • where is gatttool.c and gatt.c ? how to download etc ? – peterk Feb 02 '18 at 20:11