BlessTags app. gives a new meaning to your SensorTag through the Gadgets.
A fantastic app.
able to manage 6 of the most used SensorTag on the market.

Monday, July 10, 2017

Setting BLE characteristic values - a Thunderboard Sense practical approach



    Few months ago, I received a Thunderboard Sense kit from Silicon Labs Company. Analyzing the market for applications capable of working with this device, I noticed the existence of many applications capable of running on operating systems such as iOS, Android or Linux. But, I have not found a professional application, developed in Windows, able to work with this device. As a result, I decide to develop one - BLE SensorTags application. 
   Right now, the BLE (Bluetooth Low Energy) SensorTag application – BlessTags (BLE SensorTags) can work with 2 different sensor tags from Silicon Labs Company: Thunderboard React and Thunderboard Sense. 
    The BlessTags (BLE SensorTags) application has the following functionalities:
1.  To set, communicate, use and display (in graphic and numerical form) the information from all the sensors included on the SensorTags presented above. The supported sensor’s characteristics are:
a. For ThunderBoardReact: accelerometer, orientation, temperature, humidity, light (ambient & UV), keys and output LEDs. 
b. For ThunderBoardSense: accelerometer, orientation, barometer, temperature, humidity, air quality (CO2 & TVOC), light (ambient & UV), sound level, keys and output LEDs (2 x low power LEDs & 4 x power LEDs).
2.  In the developer mode the software provides the user with lots of messages obtained from the communication process with a specific SensorTag - these messages enable the user to identify the communication/configuration setbacks and some other problems.
3. The software also gives the possibility to interrogate different types of unknown BLE devices - to be able to obtain the complete GATT attribute table for the unknown BLE device. Working with an unknow Sensortag is presented the entire procedure used by me to obtain the complete GATT table for Thunderboard Sense and in the end a pdf file containing all the obtained results.
5. ... and the most exciting features: the gadgets. The gadgets are several practical applications that use one or more sensors from the SensorTag to achieve a concrete, fully functional and useful application. For instance, using the two buttons placed on Thunderboard React or Thunderboard Sense, these SensorTags are turning into wireless presenters for PowerPoint.
      For the development of the application I used: (a) intensively the documentation provided by Microsoft and (b) the source code (BluetoothLowEnergy.cpp) developed by Donald Ness and publicly offered at this address: https://gist.github.com/programmarchy/c9d02e22d58bfab3f8bb. 
    The following code sequence, developed entirely by me, will complete the program provided by Mr. Donald Ness. With this code addition, we will not only be able to read data from the descriptors of a characteristic, but we will be able also to write characteristic values - in this way we can influence the state of the SensorTag.  
     To exemplify the concepts of writing to a characteristic of a sensor, I will customize the code to be presented for the Profile User Interface service; service with the UUID: FCB89C40-C600-59F3-7DC3-5ECE444A401B. All the characteristics of this service (Profile User Interface service) are presented in the figure below. We, in this presentation, will focus only on the 0xC603 characteristic – UUID: FCB89C40-C603-59F3-7DC3-5ECE444A401B. This characteristic allow us to control the intensity and the color of the high brightness RGB LEDs placed on the SensorTag.


     In order to work correctly, the code below must be inserted after the code sequence from the Step 3, presented in ConnectBLEDevice() function, from the BluetoothLowEnergy.cpp file.  At this point and for the 0xC600 service pCharBuffer is a buffer with 4 elements. Each element stores a data structure related with one of the each of the 4 characteristics presented in the table above (UUID1: FCB89C40-C601-59F3-7DC3-5ECE444A401B, UUID2: FCB89C40-C602-59F3-7DC3-5ECE444A401B, UUID3: FCB89C40-C603-59F3-7DC3-5ECE444A401B and UUID4: FCB89C40-C604-59F3-7DC3-5ECE444A401B).

--------------------------------------------------------------------------------------------------------------------------

PBTH_LE_GATT_CHARACTERISTIC pCharBuffer   = NULL;

PBTH_LE_GATT_CHARACTERISTIC currGattCharTB;



……..



if (pCharBuffer == NULL)               //step A                                                              

                {

                free(pServiceBuffer);     pServiceBuffer = NULL;                    //free the service buffer

                CloseHandle (hLEDevice);                                                        //close the BLE device handle

                return -4;

                }



if (numChars > 4)                              //step B                                                               

                {                                                              //error we have more than 4 characteristics

                free (pCharBuffer);         pCharBuffer = NULL;                       //free the characteristics buffer

                free (pServiceBuffer);     pServiceBuffer = NULL;                   //free the service buffer

                CloseHandle (hLEDevice);                                                        //close the BLE device handle

                return -5;

                }             



//Get the specific characteristic from where the high brightness RGB LEDs can be controlled.

//Here only the first 48 bits were checked - FCB89C40-C603-59F3-7DC3-5ECE444A401B – in

//   order to identify this specific characteristic.

currGattCharTB = NULL;                //step C

for (i = 0; i< numChars; i++)

                if (pCharBuffer[i].CharacteristicUuid.IsShortUuid == 0)

                                if (pCharBuffer[i].CharacteristicUuid.Value.LongUuid.Data1 == 0xFCB89C40 &&

                                     pCharBuffer[i].CharacteristicUuid.Value.LongUuid.Data2 == 0xC603)

                                    {                                                                                                                                                                                                                  currGattCharTB = &pCharBuffer[i];                     

                                    break;

                                    }

                               

if (currGattCharTB == NULL)         //step D

                {              // if no such characteristic can be found: free all the data structures and return

                free (pCharBuffer);                         pCharBuffer       = NULL;

                free(pServiceBuffer);                     pServiceBuffer  = NULL;                

                CloseHandle (hLEDevice);            

                return -6;

                }

                               

                               

typedef union                                   //step E

                {

                BTH_LE_GATT_CHARACTERISTIC_VALUE newValue;        

                struct

                                {

                                ULONG DataSize;

                                UCHAR Data[4];

                                } myValue;

                } rezolvare;

                                               

                                                          //step F

rezolvare newValue_base;

                               

RtlZeroMemory(&newValue_base.newValue, ( sizeof(rezolvare) ));

                               

                                                          //step G

//fill the structure with the required data

newValue_base.newValue.DataSize = sizeof (UCHAR)*4;

newValue_base.myValue.Data[0] = comLED;                                       //which LEDs will be on

newValue_base.myValue.Data[1] = valR;                                              //red level     [0, 255]

newValue_base.myValue.Data[2] = valG;                                              //green level [0, 255]

newValue_base.myValue.Data[3] = valB;                                              //blue level   [0, 255]

                               

                                                          //step H

hr = BluetoothGATTSetCharacteristicValue(

                hLEDevice,

                currGattCharTB,

                &newValue_base.newValue,

                0,

                BLUETOOTH_GATT_FLAG_NONE);



                                                          //step I

if (S_OK != hr)

                {

                if (dbgMode)

                                {

                                InsertTextBoxLine (panelHandleDbg, PANEL_Dbg_TEXTBOX, -1, "Error at:

                                    BluetoothGATTSetDescriptorValue - impossible to set the I/O lines (LEDs) !");

                                HRESULTtoErrTxt (hr, buffErr); sprintf (buffDeAfisat, "                       - %s", buffErr);

                                InsertTextBoxLine (panelHandleDbg, PANEL_Dbg_TEXTBOX, -1, buffDeAfisat);

                                }

                                                               

                free (pCharBuffer);         pCharBuffer = NULL;      

                free (pServiceBuffer);    pServiceBuffer  = NULL;

                CloseHandle (hLEDevice);            

                return -4;

                }



                                                          //step J

//all is OK now and release all resources previously used                                

free (pCharBuffer);         pCharBuffer = NULL;

free (pServiceBuffer);     pServiceBuffer = NULL;


CloseHandle (hLEDevice);
-------------------------------------------------------------------------------------------------------------------------- 

     The first 2 “if” instances (steps A and B) check the correctness of the service data in accordance with our previous knowledge related to this service. If everything is correct, we go to identifying the specific characteristic capable to influences the state of the LEDs – step C, this is done in the “for” loop. 
     In D step, the software check if this specific characteristic (0xC603) was found. If this last test is passed, now we can dispatch data to the SensorTag via BluetoothGATTSetCharacteristicValue function - step H. But to do this a new data structure is defined, step E, a new variable (of this data specific type) is declared and initialized with 0, on the step F, and, in the end, the variable is initialized with the required data – step G. 
     Analyzing steps E, F, G and H, one could say that a simpler approach can be easily found.  Yes, it is true, but this approach is perfectly functional for a compiler that would support a development in C++ (like Visual Studio). The BlessTags application has been fully developed in LabVindows/CVI, which has a compiler that only supports ANSI C. And for this compiler this was the only functional solution found up to now. 
     Going further, if errors occur in the SensorTag communication process, they are treated in step I. At the end, all data structures used are released, step J. 
     For the correct operation of the previous code, make sure the device is powered from the USB port, otherwise the RGB LEDS will be disabled by the Thunderboard Sense to conserve the power from the coin cell battery. 
     And now a video to show BlessTags main functions:

     Starting with the time moment 11.28 a demonstration with the wireless presenters for PowerPoint application is presented.
     This application, blessTags (BLE SensorTags) application, can be downloaded from the Windows Store Apps: https://www.microsoft.com/store/apps/9p054xsjjr1n. For more information, demo, practical applications, examples etc. please visit the following blog: https://ble-sensortag.blogspot.ro.

No comments:

Post a Comment