RFduino Forum

RFduino => Getting Started => Topic started by: csffsc on November 16, 2013, 12:45:06 AM

Title: Interfacing w/ BT 4.0LE in OSX / Linux -> Goal of using Python.
Post by: csffsc on November 16, 2013, 12:45:06 AM
This post / article is meant to be an information repository on understanding and communicating with Bluetooth 4.0 Low Energy devices, with the goal of using this data in Python.

As I quickly learned the RfDuino - which uses the Nordic nRF51822 chipset makes use of the BT 4.0 LE (or BT 4.0 Smart) protocol.  Bluetooth 4.0 Smart is a subset of the full Bluetooth 4.0 protocol known as Smart Ready, or sometimes Dual Mode.  In general, just about every computer, tablet, phone and usb dongle is going to be 'dual mode' or Smart Ready, if it says Bluetooth 4.0, it will be backwards compatible with BT 4/3/2.1/2/1 etc.

BT 4.0 LE works by broadcasting data - there is no pairing process.  The device identifies itself thru it's UUID, as well as a few parameters which describe the data that is being sent.  From what I understand there is a variety of agreed upon profiles, which define distribute data in a predictable way.  I believe tagging your own data can be done by calling RFduino.advertisementData in void setup().

Currently all Bluetooth Low Energy devices use the Generic Attribute Profile (GATT), which can be defined by the following concepts (refer to Bluetooth Stack, article 2):
A device that initiates GATT commands and requests, and accepts responses, for example a computer or smartphone.
A device that receives GATT commands and requests, and returns responses, for example a temperature sensor.
A data value transferred between client and server, for example the current battery voltage.
A collection of related characteristics, which operate together to perform a particular function. For instance, the Health Thermometer service includes characteristics for a temperature measurement value, and a time interval between measurements.
A descriptor provides additional information about a characteristic. For instance, a temperature value characteristic may have an indication of its units (e.g. Celsius), and the maximum and minimum values which the sensor can measure. Descriptors are optional - each characteristic can have any number of descriptors.

Collectively this information forms a Bluetooth 4.0 LE profile, generally defined using XML.  While there is a variety of pre-defined profiles, they can be just as easily modified, or created from scratch.  Profiles should be thought of as an agreed upon data structure.  (refer to Bluetooth Stack, article 4)

At the moment, I do NOT know how-to easily receive BT 4.0LE data with Python, however it is programmatically possible with Objective-C in iOS & Android.  I have however learned howto intercept the BT 4.0 LE data using my existing Bluetooth 4.0 dualmode chipsets (one was in my Macbook Retina, the other was a BT4.0 usb dongle) to monitor the bluetooth frequencies, and extract the RFduino's data.

If you have OSX, you can goto developer.apple.com and download the Hardware I/O toolkit (refer to OSX, article 1).  This toolkit provides two tools designed for the job; Bluetooth Explorer and Packet Logger.  Please look at the screenshots for details; they depict the captured data that the RFDuino's temperature sketch broadcasted.

If you have Linux, to interact with the data make sure you have the latest version of BlueZ, and investigate the commands; Hcitool, Hciconfig, lescan, and gatttool (refer to Linux article 1).  It should also be noted, that VMWare (version 6) provides some access to the bluetooth chipset, but not enough access to do any meaningful scanning or packet capture.  In my case I used a computer that boots into linux.  I'm unsure if parallels would work.

I hope this was helpful, I plan to stay and continue to add to this thread & the forum in general.  My goal is to convert a pre-existing arduino sketch that converts axial acceleration into angular motion (measured in degrees) to the RFDuino.  Instructing the RFDuino to broadcast angular motion when it occurs, but otherwise be in sleep mode.  Meanwhile using a python script to capture & graph the angular motion when it occurs.

Please review the links below, there is no shortage of available information on the topic.  I spent most of the evening (and now morning) troubleshooting & compiling this information, so while this post might be a bit thin on procedure the resources below are all highly relevant.

Articles & Downloads for OSX:
1. Hardware I/O Tools for Xcode - https://developer.apple.com/downloads/index.action
2. Apple's Bluetooth Device Access Guide (*alot* of information) - https://developer.apple.com/library/mac/documentation/DeviceDrivers/Conceptual/Bluetooth/BT_Intro/BT_Intro.html
3. Sample OSX nRF51822 Code - https://github.com/Sproutling/nRF51822-OSX-Sample

Articles & Downloads for Linux:
1. Finding & interacting with Bluetooth 4.0 LE packets (hciitool lescan, gatttool) - http://joost.damad.be/2013/08/experiments-with-bluetooth-low-energy.html
2. BlueZ - http://www.bluez.org/about/
3. Great StackExchange reply w/links - http://stackoverflow.com/questions/17835469/using-bluetooth-low-energy-in-linux-command-line

Bluetooth Programming:
1. Bluetooth For Programmers - http://people.csail.mit.edu/rudolph/Teaching/Articles/BTBook-march.pdf
2. Bluetooth Design Guidelines (Low Energy begins @ pg20) - https://developer.apple.com/hardwaredrivers/BluetoothDesignGuidelines.pdf

Chipset Information:
1. Nordic nRF51822 Specifications - http://www.nordicsemi.com/eng/Products/Bluetooth-R-low-energy/nRF51822
2. Nordic nRF51822 SDK - https://devzone.nordicsemi.com/documentation/nrf51/4.4.1/html/group__nrf518__module.html
3. nRF51822 Development Wiki - http://robolabwiki.sdu.dk/mediawiki/index.php/Nordic_Semiconductor_nRF51822_development

Bluetooth Stack:
1. Bluetooth Protocol & Stack Information - http://en.wikipedia.org/wiki/Bluetooth#Bluetooth_Smart_.28v4.0.29
2. Bluetooth 4.0 Protocol & Stack Information - http://en.wikipedia.org/wiki/Bluetooth_low_energy
3. Texas Instruments BT 4.0 LE SensorTag User Guide - http://processors.wiki.ti.com/index.php/SensorTag_User_Guide
4. Bluetooth Profile Development - http://teleorigin.com/download/Bluetooth/Low%20Energy/Profile_development_BLE.pdf
5. Bluetooth 4.0 LE Video Training Series (Texas Instruments) - http://links.mkt102.com/servlet/MailView?ms=NDIxNzc2NTAS1&r=OTE2MzA3NDc4NAS2&j=MTk2NDExMjczS0&mt=1&rt=0
Title: Re: Interfacing w/ BT 4.0LE in OSX / Linux -> Goal of using Python.
Post by: matsk on November 16, 2013, 10:32:41 AM
Awesome article!

So few hours a day and so much to learn!

Title: Re: Interfacing w/ BT 4.0LE in OSX / Linux -> Goal of using Python.
Post by: ticpu on November 26, 2013, 10:11:40 PM
For those Linux users around. I found out that to connect to RFDuino, one must usr gatttool with the -t random option or else you get "Connection Refused". Source: http://www.lairdtech.com/WorkArea/DownloadAsset.aspx?id=2147488769
Title: Re: Interfacing w/ BT 4.0LE in OSX / Linux -> Goal of using Python.
Post by: AKA on December 03, 2013, 01:02:10 PM
Just chiming in to add my findings here. I'm able to connect a Beaglebone Black (via this dongle: http://www.adafruit.com/products/1327) to RFduino and send data.
After enabling bluetooth on the BBB, I ran:
gatttool -b CB:01:F0:34:74:51 -t random --interactive
(note, I had previously discovered the MAC address by typing hcitool lescan)

...from the --interactive screen, you can then write values like so:

[CON][CB:01:F0:34:74:51][LE]> characteristics
handle: 0x0002, char properties: 0x0a, char value handle: 0x0003, uuid: 00002a00-0000-1000-8000-00805f9b34fb
handle: 0x0004, char properties: 0x02, char value handle: 0x0005, uuid: 00002a01-0000-1000-8000-00805f9b34fb
handle: 0x0006, char properties: 0x02, char value handle: 0x0007, uuid: 00002a04-0000-1000-8000-00805f9b34fb
handle: 0x0009, char properties: 0x20, char value handle: 0x000a, uuid: 00002a05-0000-1000-8000-00805f9b34fb
handle: 0x000d, char properties: 0x12, char value handle: 0x000e, uuid: 00002221-0000-1000-8000-00805f9b34fb
handle: 0x0010, char properties: 0x0c, char value handle: 0x0011, uuid: 00002222-0000-1000-8000-00805f9b34fb
handle: 0x0012, char properties: 0x0c, char value handle: 0x0013, uuid: 00002223-0000-1000-8000-00805f9b34fb
[CON][CB:01:F0:34:74:51][LE]> char-write-cmd 0x0011 01
[CON][CB:01:F0:34:74:51][LE]> char-write-cmd 0x0011 00

Before you ask, I discovered that handle 0x0011 was the one to address basically by trial and error ;-)

...I'd love to see anyone else's implementation of this kind of thing in Python! I'm pretty new to embedded Linux and am not sure how best to take what I've learned here and use it within a python script.

Hope this helps,

Title: Re: Interfacing w/ BT 4.0LE in OSX / Linux -> Goal of using Python.
Post by: csffsc on December 03, 2013, 01:20:24 PM
Great work!

I've since taken a detour and started following the Stanford CS193 iOS7 classes (available via iTunes).  Figuring it may be easier to complete the course, which should give me a good grounding for understanding the sketches RFDuino provided us.
Title: Re: Interfacing w/ BT 4.0LE in OSX / Linux -> Goal of using Python.
Post by: mistaSteve on January 23, 2014, 03:50:22 PM
Thanks  bunch for this write-up, it's great! Unfortunately on both of my MacBooks when I try to run Bluetooth Explorer it crashes. I do have a Beagle Bone Black, though, so I think I may have to kick MacOSX to the curb this time...
Title: Re: Interfacing w/ BT 4.0LE in OSX / Linux -> Goal of using Python.
Post by: grantpatterson on January 30, 2014, 11:14:09 PM
Hi all, great start here. I'd like to confirm that YES, you CAN talk to RFduino with a BLE-enabled Mac, and it's not too hard. I started with this example Xcode project:
https://developer.apple.com/library/mac/samplecode/HealthThermometer/Introduction/Intro.html (https://developer.apple.com/library/mac/samplecode/HealthThermometer/Introduction/Intro.html)
and by tweaking just a few UUIDs, I was able to connect to my RFduino and send it some data. I don't think it's worth uploading a diff, so I'll just summarize my changes to the example project, all in HealthThermometerClientAppDelegate.m:

Run the app and click Connect; RFduino should appear in the list. Select it and Choose Device. My RFduino reports the connection, then reports proper receipt of the char I sent. (Its name as reported in the app is "wef". No idea why.)

This is obviously just the very ugly beginning of making this work—sorry, it's late!—but it's enough to prove to myself that it won't be hard to implement for real. It will obviously be nice if/when the RFduino folks get around to making a tidy library for all of this, as they did for iOS.

I'll note that my Mac doesn't even have BLE built-in; I'm using this $10 dongle:
http://amzn.to/1ifRSnA (http://amzn.to/1ifRSnA)

LightBlue was helpful to browse the various services/characteristics offered by the RFduino. I haven't seen the value of RFduinoBLE.advertisementData yet.

Good luck!
Title: Re: Interfacing w/ BT 4.0LE in OSX / Linux -> Goal of using Python.
Post by: tolson on January 31, 2014, 10:00:56 AM
Also just chiming in here with my prelim notes.

Using gatttool I got a list of handles using char-desc while the ledbtn sketch was loaded.

 ** GAT **
handle: 0x0001, uuid: 2800      - 00 18                         1800 means Generic Access Service
handle: 0x0002, uuid:  2803     - 0a 03 00 00 2a                0a,0003,2a00 (WR,hnd=3,type=device name)
handle: 0x0003, uuid: 2a00      - 52 46 64 75 69 6e 6f          RFduino
handle: 0x0004, uuid:  2803     - 02 05 00 01 2a                02,0005,2a01 (R,hnd=4,type=appearance)
handle: 0x0005, uuid: 2a01      - 34 12                         1234  ? what is appearance type 1234 ?
handle: 0x0006, uuid:  2803     - 02 07 00 04 2a                02,0007,2a04 (R,hnd=5,type=peripheral preferred connection parameters
handle: 0x0007, uuid: 2a04      - 90 01 20 03 00 00 90 01       interval=500-1000ms, latency=0ms,timeout=400
 ** GATT **
handle: 0x0008, uuid: 2800      - 01 18                         1801 means Generic Attribute Service
handle: 0x0009, uuid:  2803     - 20 0a 00 05 2a                20,000a,2a05 (indicate,hnd=a,type=service changed)
handle: 0x000a, uuid: 2a05      - Attribute can't be read
handle: 0x000b, uuid: 2902      - 00 00                                         (2902 is client characteristic config)
 ** RFDUINO specific service ??
handle: 0x000c, uuid: 2800      - 20 22                         2220 means ??? -- unofficial service -- developer defined.
handle: 0x000d, uuid:  2803     - 12 0e 00 21 22                12,000e,2221 (NotifyR, hnd=e, type=unknown)
handle: 0x000e, uuid: 2221      - 01                            read DATA[]
handle: 0x000f, uuid: 2902      - 00 00                                         (2902 is client characteristic config)
handle: 0x0010, uuid:  2803     - 0c 11 00 22 22                0c,0011,2222 (W WnoResp, hnd=11, type=unknown)
handle: 0x0011, uuid: 2222      - Attribute can't be read       write DATA[]
handle: 0x0012, uuid:  2803     - 0c 13 00 23 22                0c,0013,2223 (W WnoResp, hnd= 13, type=unknown)
handle: 0x0013, uuid: 2223      - Attribute can't be read       write ????

Figuring out some of the fields, yields...

*** 2803 defines the permission and type for the indicated handle (permission,handle,type)
 the permission field bits used seems to be...
 X - X - Indicate - Notify     Write - WriteNoResponse - Read - X
Where X is not used here and I haven't figured out for sure what they represent.

The handle points to the actual variable location and type is suppose to define what type
of variable it is.

*** 2a04 defines the Peripheral Preferred Connection Parameters. It has 4 16bit fields...
  MinConnInterval(1.25ms)   MaxConnInterval(1.25ms)  Latency(ms)   TimeOut(ms)

Title: Re: Interfacing w/ BT 4.0LE in OSX / Linux -> Goal of using Python.
Post by: gazzat5 on April 27, 2014, 02:08:55 PM
Hi all, I worked on this today with the gatttool cli program and the Preloaded thermometer sketch.

the uuid for the temperature value is 2221 and the handle is 0x000e
presumably this will be the same if the sketch is modified and reused to send other float values from connected sensors.

I wrote it all up in a really long blog post here: http://kirrus.co.uk/2014/04/getting-rfduino-working-with-linux (http://kirrus.co.uk/2014/04/getting-rfduino-working-with-linux)

Hope this is useful
Title: Re: Interfacing w/ BT 4.0LE in OSX / Linux -> Goal of using Python.
Post by: notsolinear on April 29, 2014, 01:16:57 PM
I can't help you with the Python part, but my understanding is that the CoreBluetooth Obj-C library (as seen in the iOS project samples) is also available in the Mac OSX SDK.  I haven't tried it, but if so that means it should only take a few lines of code to scan for, connect to, and start receiving and sending bytes over the TX and RX characteristics exposed by the RFDuino's GATT profile.

My guess is there is probably a wealth of knowledge out there about transferring data between an OSX application and a running python script.  If there's no good direct python access to BLE, you could create a small OSX app (perhaps even running as a daemon) that implements the CoreBluetooth methods and exchanges the data with your python app.
Title: Re: Interfacing w/ BT 4.0LE in OSX / Linux -> Goal of using Python.
Post by: lsnyman on May 01, 2014, 01:03:39 PM
I am interested in just transmitting sensor data to a PC and MAC. PC could just use a Bluetooth 4.0 Dongle. So the computer would basically receive this as a serial input.
I have done this with Standard bluetooth and Arduino. Would this be possible?
Title: Re: Interfacing w/ BT 4.0LE in OSX / Linux -> Goal of using Python.
Post by: turcoale on August 21, 2014, 09:20:19 AM

how can read a button in sketch button and led??? i can turn on the led, but i can't take button value with gatttool
Title: Re: Interfacing w/ BT 4.0LE in OSX / Linux -> Goal of using Python.
Post by: tolson on August 21, 2014, 10:38:56 AM

how can read a button in sketch button and led??? i can turn on the led, but i can't take button value with gatttool
Non-interactive read
gatttool -b CF:35:AF:F4:D9:A0 -t random --char-read --handle=0x000e

Non-interactive write
gatttool -b CF:35:AF:F4:D9:A0 -t random --char-write --handle=0x0011 --value=" + RGB

Notification ON...
gatttool -b CF:35:AF:F4:D9:A0 -t random --char-write-req --handle=0x000f --value=0100 --listen

NOTE: substitute your MAC address.