It’s a short guide to practical side of bluetooth LE using gatttool. How to read characteristics, turn on notifications and where to find more info about all those BLE numbers.
I was struggling for a while to read data from a BLE heart rate strap. It was working flawlessly with android apps, but I needed it to use it with raspberry pi and python. So, I had to dig a bit deeper under the surface of BLE. The results are below.
Prerequisites:
1. A computer with bluetooth v4.0 card or dongle
2. gatttool (part of bluez). Fedora users might have to compile bluez as there is no gatttool in bluez-5.23-1.fc21 bugreport: [1].
3. A BLE (bluetooth Low Energy, Bluetooth Smart) device – I use a Tacx heart rate belt [2]
An example command line session (red – important or info for later use, blue – value from previous steps, green – comment):
$ hciconfig hci0: Type: BR/EDR Bus: USB ^^ hci0: that's our hci device BD Address: C4:85:08:06:9F:C7 ACL MTU: 310:10 SCO MTU: 64:8 UP RUNNING PSCAN RX bytes:10243057 acl:34567 sco:0 events:5307 errors:0 TX bytes:46612 acl:737 sco:0 commands:2685 errors:0 fedora-lan:/home/przemo $ sudo hciconfig hci0 up fedora-lan:/home/przemo $ sudo hcitool -i hci0 lescan LE Scan ... <-- LE Scan was not showing anything, so Ctrl-C and hci0 reset ^Cfedora-lan:/home/przemo $ sudo hciconfig hci0 reset fedora-lan:/home/przemo $ sudo hcitool -i hci0 lescan LE Scan ... D6:90:A8:08:F0:E4 Tacx HRB 04741 ^^ D6:90:A8:08:F0:E4 that's BLE device address D6:90:A8:08:F0:E4 (unknown) D6:90:A8:08:F0:E4 Tacx HRB 04741 D6:90:A8:08:F0:E4 (unknown) ^Cfedora-lan:/home/przemo $ sudo gatttool -i hci0 -b D6:90:A8:08:F0:E4 -t random -I ^^ if you can't connect try to use "-t random" [D6:90:A8:08:F0:E4][LE]> connect Attempting to connect to D6:90:A8:08:F0:E4 Connection successful Reading value of battery level characteristic [D6:90:A8:08:F0:E4][LE]> primary attr handle: 0x0001, end grp handle: 0x0007 uuid: 00001800-0000-1000-8000-00805f9b34fb attr handle: 0x0008, end grp handle: 0x000b uuid: 00001801-0000-1000-8000-00805f9b34fb attr handle: 0x000c, end grp handle: 0x0011 uuid: 0000180d-0000-1000-8000-00805f9b34fb attr handle: 0x0012, end grp handle: 0x0015 uuid: 0000180f-0000-1000-8000-00805f9b34fb ^^^ 180f is "Battery Service", see link [3] attr handle: 0x0016, end grp handle: 0xffff uuid: 0000180a-0000-1000-8000-00805f9b34fb [D6:90:A8:08:F0:E4][LE]> characteristics 0x0012 0x0015 handle: 0x0013, char properties: 0x12, char value handle: 0x0014, uuid: 00002a19-0000-1000-8000-00805f9b34fb ^^ 2a19 is Battery Level, links [4] and [5] char properties 0x12: supports NOTIFICATION 0x10 and READ 0x02 (0x10 | 0x02 = 0x12) [D6:90:A8:08:F0:E4][LE]> char-read-hnd 0x0014 ^^ Reading handle value Characteristic value/descriptor: 64 ^^ value of battery level is 64, but it's hex, so 0x64 = 100. It's in %, link [4]
Reading heart rate [D6:90:A8:08:F0:E4][LE]> primary attr handle: 0x0001, end grp handle: 0x0007 uuid: 00001800-0000-1000-8000-00805f9b34fb attr handle: 0x0008, end grp handle: 0x000b uuid: 00001801-0000-1000-8000-00805f9b34fb attr handle: 0x000c, end grp handle: 0x0011 uuid: 0000180d-0000-1000-8000-00805f9b34fb ^^ 180d is "Heart Rate" service, link [3] attr handle: 0x0012, end grp handle: 0x0015 uuid: 0000180f-0000-1000-8000-00805f9b34fb attr handle: 0x0016, end grp handle: 0xffff uuid: 0000180a-0000-1000-8000-00805f9b34fb [D6:90:A8:08:F0:E4][LE]> characteristics 0x000c 0x0011 handle: 0x000d, char properties: 0x10, char value handle: 0x000e, uuid: 00002a37-0000-1000-8000-00805f9b34fb ^^ 2a37 is Heart Rate characteristic, links [5] and [6] char properties: 0x10: supports NOTIFICATION handle: 0x0010, char properties: 0x02, char value handle: 0x0011, uuid: 00002a38-0000-1000-8000-00805f9b34fb ^^ 2a38 is Body Sensor Location, links [6] and [7] char properties: 0x02: supports READ [D6:90:A8:08:F0:E4][LE]> char-read-hnd 0x0011 ^^ Reading Body Sensor Location Characteristic value/descriptor: 01 ^^ 0x01 it's "Chest", see link [7] for more options We need more info to switch on NOTIFICATION of heart rate [D6:90:A8:08:F0:E4][LE]> char-desc 0x000d 0x000f ^^ range of handles for heart rate: 0x000d is start of the range obtained with 'characteristics 0x000c 0x0011' 0x0010 is start of next characteristic minus 1: 0x0010 - 0x1 = 0x000f handle: 0x000d, uuid: 00002803-0000-1000-8000-00805f9b34fb handle: 0x000e, uuid: 00002a37-0000-1000-8000-00805f9b34fb handle: 0x000f, uuid: 00002902-0000-1000-8000-00805f9b34fb ^^ 2902 it is Client Characteristic Configuration, link [8] [D6:90:A8:08:F0:E4][LE]> char-write-cmd 0x000f 01 ^^ 01 comes from link [8], NOTIFICATIONS enabled Notification handle = 0x000e value: 00 3e <-- heart rate, 0x003e is 63 BPM Notification handle = 0x000e value: 00 3d <-- heart rate, 0x003d is 62 BPM Notification handle = 0x000e value: 00 3d <-- heart rate, 0x003d is 62 BPM Notification handle = 0x000e value: 00 3c <-- heart rate, 0x003c is 61 BPM [D6:90:A8:08:F0:E4][LE]> char-write-cmd 0x000f 00 ^^ 00 comes from link [8], NOTIFICATIONS disabled [D6:90:A8:08:F0:E4][LE]> disconnect <-- end of connection [D6:90:A8:08:F0:E4][LE]> fedora-lan:/home/przemo/android
[1] https://bugzilla.redhat.com/show_bug.cgi?id=1141909
[2] http://www.tacx.com/en/products/sensors/heart-rate-belt
[3] https://developer.bluetooth.org/gatt/services/Pages/ServicesHome.aspx
[5] https://developer.bluetooth.org/gatt/characteristics/Pages/CharacteristicsHome.aspx