Thursday, 18 December 2014

All about Bluetooth Smart Custom Profiles

One of the things I've turned my attention to recently is the world of 'custom profiles'. The result is a blog post and video blog on the subject which has just been published on the SIG web site. Check it out:

http://blog.bluetooth.com/the-best-of-both-worlds-with-custom-profiles-for-bluetooth-smart-technology/

Tuesday, 9 December 2014

Customizing a Texas Instruments SensorTag

Introduction

The Texas Instruments SensorTag is a development kit for Bluetooth Smart developers. It has half a dozen sensors built in (temperature, humidity, pressure, accelerometer, gyroscope and magnetometer) and exposes their data as a series of Bluetooth Smart services. It can also act as a beacon.

See www.ti.com/sensortag for more information on SensorTag.

I was wondering if it might be possible to change the firmware on a SensorTag so I could add my own Bluetooth Smart GATT services. I set about researching and ultimately achieved my goal. This blog post documents my experience. I hope you find it useful.

By the way.... this is not a product recommendation. It's just one developer sharing knowledge with other, like minded people! I'll write about other Bluetooth developer tools in the future.

Goals

To give myself something concrete to do, I decided to pursue the following goal:
Add two new custom services to Texas Instruments SensorTag named the Counter Service and the Random Number Service and defined as follows:

Counter Service: this service has a single characteristic with an 8 bit numeric value. It is possible to write a value directly to the characteristic but more importantly, every time the characteristic is read, its value must be incremented by 1, wrapping back around to 0x00 when at 0xFF.

Random Number Service: This service also has a single characteristic but this one is a 16 bit numeric value. Reading the characteristic returns a random 16 bit number but notifications are also supported and, with notifications enabled, a random value is generated and delivered to the connected GATT client as a notification, once every second.

Tools

To proceed with my project, I needed the right tools. SensorTag contains a Texas Instruments CC2541 chip which can be programmed using the IAR Workbench IDE. To work with SensorTag you need to use version 8.2, which is not the latest version. 8.3 is currently the latest version and it does not work seamlessly “out of the box” with SensorTag.

Figure 1 - IAR Workbench IDE version 8.2
Source code for the SensorTag firmware is included in the “Texas Instruments Bluetooth low energy stack and tools” download from http://www.ti.com/tool/ble-stack so I grabbed that.


I also used BLE Device Monitor for testing and Smart RF Studio for flashing the SensorTag with my custom firmware, built using IAR Workbench. The SensorTag Wiki (link at the end) provides links to other resources you may find useful.

The hardware I used was my laptop, a SensorTag of course and a CC Debugger to allow me to flash the board over USB.


Figure 2 - SensorTag with a CC Debugger connected to it




Coding

My first task was to find the SensorTag source code in the BLE stack download. On my machine it’s in C:\Texas Instruments\BLE-CC254x-1.4.0\Projects\ble\SensorTag. I copied it to a new location so I could make changes whilst retaining the original.

I changed the device name used in advertising packets to make it easy to identify the customized device as my own.

static uint8 scanRspData[] =  
 {  
  // complete name  
  0x0A,  // length of this data  
  GAP_ADTYPE_LOCAL_NAME_COMPLETE,  
  0x4D,  // 'M'  
  0x61,  // 'a'  
  0x72,  // 'r'  
  0x74,  // 't'  
  0x69,  // 'i'  
  0x6E,  // 'n'  
  0x54,  // 'T'  
  0x61,  // 'a'  
  0x67,  // 'g'  
Figure 3 – Device name changed to ‘MartinTag’ in SensorTag.c


Next, using the structure of the standard SensorTag project as a guide, I created source files for each of my two new services; counterservice.c and counterservice.h for the Counter Service and of course randomnumberservice.c and randomnumberservice.h for the Random Number Service.


I then set about defining each service and implementing their respective behaviours.

Service Definition

This is achieved by creating a C array containing pre-defined constants and other values and then making a function call to register them. I needed to do this for each of the two custom services. Let’s look at the definition of each and then how they were registered.


static gattAttribute_t counterAttrTable[] =
{
  {
    // Service declaration
    { ATT_BT_UUID_SIZE, primaryServiceUUID },   /* type */
      GATT_PERMIT_READ,                         /* permissions */
      0,                                        /* handle */
      (uint8 *)&counterService                  /* pValue */
    },

    // Characteristic Declaration
    {
      { ATT_BT_UUID_SIZE, characterUUID },
        GATT_PERMIT_READ,
        0,
        &counterDataProps
    },

    // Characteristic Value "Data"
    {
      { MW_UUID_SIZE, counterDataUUID },
        GATT_PERMIT_READ | GATT_PERMIT_WRITE,
        0,
        counterData
    }
};

Figure 4 – Counter Service definition in counterservice.c


static gattAttribute_t randomNumberAttrTable[] =
{
  {
    // Service declaration
    { ATT_BT_UUID_SIZE, primaryServiceUUID },   /* type */
      GATT_PERMIT_READ,                         /* permissions */
      0,                                        /* handle */
      (uint8 *)&randomNumberService             /* pValue */
    },

    // Characteristic Declaration
    {
      { ATT_BT_UUID_SIZE, characterUUID },
        GATT_PERMIT_READ,
        0,
        &randomNumberDataProps
    },

    // Characteristic Value "Data"
    {
      { MW_UUID_SIZE, randomNumberDataUUID },
        GATT_PERMIT_READ | GATT_PERMIT_WRITE,
        0,
        randomNumberData
    },
    
    // Random Number Client Characteristic Configuration
    { 
      { ATT_BT_UUID_SIZE, clientCharCfgUUID },
      GATT_PERMIT_READ | GATT_PERMIT_WRITE, 
      0, 
      (uint8 *) &randomNumberClientCharCfg 
    },      

};
Figure 5 – Random NumberService definition in randomnumberservice.c


typedef struct attAttribute_t
{
  gattAttrType_t type; //!< Attribute type (2 or 16 octet UUIDs)
  uint8 permissions;   //!< Attribute permissions
  uint16 handle;       //!< Attribute handle - assigned internally by attribute server
  uint8* const pValue; //!< Attribute value - encoding of the octet array is defined in 
                       //!< the applicable profile. The maximum length of an attribute 
                       //!< value shall be 512 octets.
} gattAttribute_t;
Figure 6 – The gattAttribute_t type

For example the characteristic containing the Counter Service’s counter value looks like this:


    {
      { MW_UUID_SIZE, counterDataUUID },
        GATT_PERMIT_READ | GATT_PERMIT_WRITE,
        0,
        counterData
    }

Figure 7 – Counter value characteristic

MW_UUID_SIZE has a value of 16, meaning 16 octets. It indicates the UUID is a 128 bit UUID in other words.

counterDataUUID is defined as


// in counterservice.c
static CONST uint8 counterDataUUID[MW_UUID_SIZE] =
{
  MW_UUID(COUNTER_DATA_UUID),
};

// in counterservice.h
#define COUNTER_DATA_UUID              0x9915
#define MW_UUID(uuid)                  MW_BASE_UUID_128(uuid)

// MW Base 128-bit UUID: 3E09XXXX-293F-11E4-93BD-AFD0FE6D1DFD
#define MW_BASE_UUID_128( uuid )  0xFD, 0x1D, 0x6D, 0xFE, 0xD0, 0xAF, 0xBD, 0x93, \
                                  0xE4, 0x11, 0x3F, 0x29, LO_UINT16( uuid ), HI_UINT16( uuid ), 0x09, 0x3E
Figure 8 – Counter data value characteristic UUID definition

With a few handy macros, the 16 bit value of 0x9915 which I chose is mapped onto my 128 bit base value of 3E09XXXX-293F-11E4-93BD-AFD0FE6D1DFD to give the resultant 128 bit UUID for my characteristic 3E099915-293F-11E4-93BD-AFD0FE6D1DFD. Permissions are defined in gatt.h and as you can see, you can combine them with logical OR operations. Here’s the full list:

#define GATT_PERMIT_READ                 0x01 //!< Attribute is Readable
#define GATT_PERMIT_WRITE                0x02 //!< Attribute is Writable
#define GATT_PERMIT_AUTHEN_READ          0x04 //!< Read requires Authentication
#define GATT_PERMIT_AUTHEN_WRITE         0x08 //!< Write requires Authentication
#define GATT_PERMIT_AUTHOR_READ          0x10 //!< Read requires Authorization
#define GATT_PERMIT_AUTHOR_WRITE         0x20 //!< Write requires Authorization
#define GATT_PERMIT_ENCRYPT_READ         0x40 //!< Read requires Encryption
#define GATT_PERMIT_ENCRYPT_WRITE        0x80 //!< Write requires Encryption
Figure 9 – Counter data value characteristic UUID definition

Handle values get allocated at run time so we just supply a default value of 0 to begin with. Finally, our value is in the local variable counterData which is defined as

#define COUNTER_DATA_LEN                       1
static uint8 counterData[COUNTER_DATA_LEN] = { 0 };
Figure 10 – Counter data value local variable

Hopefully you can see the idea. Having defined my services, I next needed to register them and this required me to make some changes to SensorTag.c:

// Add services
  GGS_AddService( GATT_ALL_SERVICES );            // GAP
  GATTServApp_AddService( GATT_ALL_SERVICES );    // GATT attributes
  DevInfo_AddService();                           // Device Information Service
  IRTemp_AddService (GATT_ALL_SERVICES );         // IR Temperature Service
  Accel_AddService (GATT_ALL_SERVICES );          // Accelerometer Service
  Humidity_AddService (GATT_ALL_SERVICES );       // Humidity Service
  Magnetometer_AddService( GATT_ALL_SERVICES );   // Magnetometer Service
  Barometer_AddService( GATT_ALL_SERVICES );      // Barometer Service
  Gyro_AddService( GATT_ALL_SERVICES );           // Gyro Service
  SK_AddService( GATT_ALL_SERVICES );             // Simple Keys Profile
  Test_AddService( GATT_ALL_SERVICES );           // Test Profile
  CcService_AddService( GATT_ALL_SERVICES );      // Connection Control Service

  Counter_AddService (GATT_ALL_SERVICES );        // Counter Service
  RandomNumber_AddService (GATT_ALL_SERVICES );   // Random Number Service
Figure 11 – Registering my new services

The xxxx_AddService functions are implemented in the C file for that service, so counterservice.c and randomnumberservice.c in my case. The function essentially makes one call to a Texas Instruments GATT API function:

    // Register GATT attribute list and CBs with GATT Server App
    status = GATTServApp_RegisterService( counterAttrTable,
                                          GATT_NUM_ATTRS( counterAttrTable ),
                                          &counterCBs );
Figure 12 – Registering the counter service definition and call back functions

GATT_NUM_ATTRS is a macro which counts the number of attributes in the service definition array. The only other thing here, which I’ve not already mentioned is the call backs referenced by &counterCBs. This provides pointers to call back functions relating to operations such as reading and writing GATT attributes that belong to this service:

CONST gattServiceCBs_t counterCBs =
{
  counter_ReadAttrCB,    // Read callback function pointer
  counter_WriteAttrCB,   // Write callback function pointer
  NULL                   // Authorization callback function pointer
};
Figure 13 – Counter service call back function pointers

When it comes to implementing service behaviours, as you’ll see, we’re largely concerned with implementing these call back functions. Let’s see what I had to do in this respect next.



Service Implementation

When the counter service’s counter value characteristic is read, I want to increment its value and return it to the client. Similarly, when the random number service’s random number characteristic is read, I want to generate a new, 16 bit random number and return this value. The code in each case is similar so let’s look at the counter service as an example.
/*********************************************************************
 * @fn          counter_ReadAttrCB
 *
 * @brief       Read an attribute. Every time a GATT client device wants to read 
 *              from an attribute in the profile, this function gets called.
 *
 * @param       connHandle - connection message was received on
 * @param       pAttr - pointer to attribute
 * @param       pValue - pointer to data to be read
 * @param       pLen - length of data to be read
 * @param       offset - offset of the first octet to be read
 * @param       maxLen - maximum length of data to be read
 *
 * @return      Success or Failure
 */
static uint8 counter_ReadAttrCB( uint16 connHandle, gattAttribute_t *pAttr,
                            uint8 *pValue, uint8 *pLen, uint16 offset, uint8 maxLen )
{
  uint16 uuid;
  bStatus_t status = SUCCESS;

  // If attribute permissions require authorization to read, return error
  if ( gattPermitAuthorRead( pAttr->permissions ) )
  {
    // Insufficient authorization
    return ( ATT_ERR_INSUFFICIENT_AUTHOR );
  }

  if (utilExtractUuid16(pAttr,&uuid) == FAILURE) {
    // Invalid handle
    *pLen = 0;
    return ATT_ERR_INVALID_HANDLE;
  }

  switch ( uuid )
  {
    // No need for "GATT_SERVICE_UUID" or "GATT_CLIENT_CHAR_CFG_UUID" cases;
    // gattserverapp handles those reads
    case COUNTER_DATA_UUID:
      *pLen = COUNTER_DATA_LEN;
      // copy current counter value in counterData[0] to the buffer pointed to by pValue
      osal_memcpy( pValue, &counterData[0], COUNTER_DATA_LEN );
      // increment the counter
      counterData[0]++;
      break;

    default:
      *pLen = 0;
      status = ATT_ERR_ATTR_NOT_FOUND;
      break;
    }

  return ( status );
}
Figure 14 – Counter service attribute reading

We first check the permissions associated with the attribute being written to. If they allow this operation, we move on to extract the “significant” 16 bit part of the UUID of the attribute and then use it in a switch statement to decide what to do next. In this case, the switch statement only really supports one UUID, that of the only characteristic the counter service has. I’ve highlighted the code involved in writing to this characteristic. It’s pretty simple; we copy the current counter value to a location in memory pointed to by a pointer we received as an argument to the function and then increment our local counter value, ready for the next read operation.

We also allow writing to the counter service’s counter value and handle this in the function counter_WriteAttrCB. Let’s save looking at characteristic writing for when we look at the random number service however.

Random Number Service Implementation

This service generates a random number whenever its one characteristic is read or whenever a notification needs to be created and sent to the connected GATT client. To enable notifications, we need to handle the associated client characteristic configuration descriptor being written to. Let’s take a look at the code for this first. I implemented it in the call back function for characteristic writing in randomnumberservice.c. The function is called RandomNumber_WriteAttrCB.

/*********************************************************************
* @fn      RandomNumber_WriteAttrCB
*
* @brief   Handles requests to write to attributes owned by this service. 
*
* @param   connHandle - connection message was received on
* @param   pAttr - pointer to attribute
* @param   pValue - pointer to data to be written
* @param   len - length of data
* @param   offset - offset of the first octet to be written
*
* @return  Success or Failure
*/
static bStatus_t RandomNumber_WriteAttrCB( uint16 connHandle, gattAttribute_t *pAttr,
                                           uint8 *pValue, uint8 len, uint16 offset )
{
  bStatus_t status = SUCCESS;
  uint16 uuid;

  // If attribute permissions require authorization to write, return error
  if ( gattPermitAuthorWrite( pAttr->permissions ) )
  {
    // Insufficient authorization
    return ( ATT_ERR_INSUFFICIENT_AUTHOR );
  }

  if (utilExtractUuid16(pAttr,&uuid) == FAILURE) {
    // Invalid handle
    return ATT_ERR_INVALID_HANDLE;
  }

  switch ( uuid )
  {
    case RANDOM_NUMBER_DATA_UUID:
      // Should not get here
      break;

    case GATT_CLIENT_CHAR_CFG_UUID:
      notifications_enabled = *pValue;
      status = GATTServApp_ProcessCCCWriteReq( connHandle, pAttr, pValue, len,
                                              offset, GATT_CLIENT_CFG_NOTIFY );
      if (notifications_enabled) {
        osal_start_timerEx( randomNumber_TaskID, RANDOM_NUMBER_PERIODIC_EVT, DEFAULT_RANDOM_NUMBER_PERIOD );
      } else {
        HalLedSet(HAL_LED_1, HAL_LED_MODE_OFF);
      }
      break;

    default:
      // Should never get here!
      status = ATT_ERR_ATTR_NOT_FOUND;
      break;
  }

  return ( status );
}
Figure 15 – Writing to the client characteristic configuration descriptor in the random number service

The three key steps steps are as follows: First I use an API function, GATTServApp_ProcessCCCWriteReq to write to the descriptor. If this has resulted in notifications being enabled, I then start a one shot timer using API function osal_start_timerEx. This specifies an event value with the constant name RANDOM_NUMBER_PERIODIC_EVT. You’ll see that this event value pops up in an event handler function elsewhere in the code shortly but basically when the timer expires after DEFAULT_RANDOM_NUMBER_PERIOD (set to 1000ms) it drops an event of this type into an event queue and makes a call back into our code to tell us the event is there.

Let’s look at this code now, which is implemented in SensorTag.c. This is a large function which handles events relating to all of the services which SensorTag imlpements, most of which are concerned with sensor data, so I’ve deleted much of that code to make it easier to see how the random number timer event is handled.

/*********************************************************************
 * @fn      SensorTag_ProcessEvent
 *
 * @brief   Simple BLE Peripheral Application Task event processor.  This function
 *          is called to process all events for the task.  Events
 *          include timers, messages and any other user defined events.
 *
 * @param   task_id  - The OSAL assigned task ID.
 * @param   events - events to process.  This is a bit map and can
 *                   contain more than one event.
 *
 * @return  events not processed
 */
uint16 SensorTag_ProcessEvent( uint8 task_id, uint16 events )
{
  VOID task_id; // OSAL required parameter that isn't used in this function

......

  //////////////////////////
  //    RANDOM NUMBER     //
  //////////////////////////
  if ( events & RANDOM_NUMBER_PERIODIC_EVT )
  {
    randomNumberPeriodicTask(gapConnHandle);
    return (events ^ RANDOM_NUMBER_PERIODIC_EVT);
  }

// other event types from other GATT services....


  // Discard unknown events
  return 0;
}
Figure 16 – Handling random number notification timer expiry events

As you can see, all I do here is call a function randomNumberPeriodicTask with an argument of the GAP connection handle. The function is implemented in randomnumberservice.c as perhaps you’d expect.

/*********************************************************************
 * @fn      randomNumberPeriodicTask
 *
 * @brief   Perform a periodic random number notification
 *
 * @param   none
 *
 * @return  none
 */
void randomNumberPeriodicTask( uint16 gapConnHandle )
{
  uint16 value = GATTServApp_ReadCharCfg( gapConnHandle, randomNumberClientCharCfg );
  
  // If notifications are already enabled start the timer running and send first notification
  if ( value & GATT_CLIENT_CFG_NOTIFY ) {
     notifications_enabled = 1;
  } else {
     notifications_enabled = 0;
  }
  
  if (getGapRoleState() == GAPROLE_CONNECTED && notifications_enabled)
  {
    // send random number notification
    randomNumberNotify(gapConnHandle);
    
    // Restart timer
    osal_start_timerEx( randomNumber_TaskID, RANDOM_NUMBER_PERIODIC_EVT, DEFAULT_RANDOM_NUMBER_PERIOD );
  }
}
Figure 17 – Initiating random notification and re-establishing the one shot timer

All I do here is call a function to actually generate a random number and send the notification and then re-establish the timer so the whole process happens again and will continue to do so until the client writes a 0 to the descriptor to disable notifications.

bStatus_t randomNumberNotify( uint16 connHandle )
{

  HalLedSet(HAL_LED_1, HAL_LED_MODE_TOGGLE);
  
  if (notifications_enabled) {
      attHandleValueNoti_t *pNoti;
      uint16 r = random_number();
      randomNumberData[0] = r & 0xff;
      randomNumberData[1] = (r >> 8);
      // Set the handle
      pNoti->handle = randomNumberAttrTable[RANDOM_NUMBER_VALUE_POS].handle;
      // Set the length
      pNoti->len = 2;
      // Set the value
      pNoti->value[0] = randomNumberData[0];
      pNoti->value[1] = randomNumberData[1];
      // Send the notification
      return GATT_Notification( connHandle, pNoti, FALSE );
  }
  
  return bleIncorrectMode;

}

static uint16 random_number( void ) {
  uint16 r = Onboard_rand();
  return r;
}
Figure 18 – Generating the random number and sending the notification

Most of what happens in randomNumberNotify is concerned with generating the random 16 bit value and preparing the arguments for the notification function call. Sending the notification itself is accomplished by calling API function GATT_Notification. Easy!

Testing and Debugging

During development, if I had a problem, I found that switching SensorTag LEDs on or off was an easy and quick way to verify a given code path was executing. The functions I used were HalLedSet(HAL_LED_1, HAL_LED_MODE_OFF ) and HalLedSet(HAL_LED_1, HAL_LED_MODE_ON ).

For testing purposes I used Texas Instruments BLE Device Monitor. I could have used any GATT explorer tool of course.

You can see a short video of BLE Device Monitor being used with my customised SensorTag here.

Summary

I hope this has been useful. Happy hacking!

For more information on SensorTag see http://processors.wiki.ti.com/index.php/Bluetooth_SensorTag?INTC=SensorTag&HQS=sensortag-wiki

My source code, with all its flaws is available here.

Provided for educational purposes only. Use at your own risk. No warranty etc etc blah.

Bluetooth Smart Starter Kit version 2.0

The Bluetooth SIG have a developer resource called the Smart Starter Kit. One of the things I've worked on since joining is the new version 2.0 release. This was a lot of fun for me as I got to do more Arduino programming, some Android programming and.... did my first ever Windows Phone coding and iOS coding. Variety is the spice of life!

Rather than describe SSK V2 here, you can read all about it at the SIG web site here. Highly recommended as a learning resource if you're new to Bluetooth Smart!

Tuesday, 25 November 2014

The London Bluetooth Hardware Developers Group

Last night I attended and presented at the London Bluetooth Hardware Developers Group's November meetup. The group are a "small but perfectly formed" bunch, some with specialist interest in and experience of Bluetooth and others who are new to the subject. Given the mixed experience levels, I kicked off with a Bluetooth 101 for Developers before moving into my main presentation during which I walked through the Bluetooth Smart Starter Kit (SSK) V2, a fantastic resource for developers from the Bluetooth SIG. I've been working on V2 of SSK for a while and it should be released very soon, so this was a sneak preview for the attendees last night. SSK helps developers learn how to develop Bluetooth Smart applications for their preferred platform, be it Android, iOS, Windows Phone or BlackBerry 10 and it's based around an Arduino project where you get to build a custom proximity device which your smartphone application will work with. Watch this space (and Twitter) for news on the availability of SSK V2.

I also showed a short video demonstration of a marvelous Bluetooth gesture controller called Myo from Thalmic Labs.


After my 1 hour session, the group's founder, Nick Brook, presented details of a project he's been working on which involves measuring the forces associated with motion and communicating them via a custom Bluetooth Smart service to an iPad application. The motion detection device was created using a Bluegiga development board, programmed with their scripting language, which resembles Basic.


Nick also gave a summary of the changes in Bluetooth 4.1 and an update on Apple's iOS 8, Home Kit and Watch Kit. Re: iOS 8, it now has a "suggested app" feature which will prompt the user to install an app that the OS thinks is relevant to some circumstance that has arisen. This is useful with respect to beacons. Apparently when loading an application to the App Store, you can provide a geofence definition which indicates the geographic region within which the application is relevant and can be used. Sounds very cool indeed.

You can download my presentation slides from here

Thursday, 20 November 2014

Bluetooth Smart and Mesh Networks

The SIG published my blog post about Bluetooth and mesh networks today. A must read topic if ever there was one :-)

http://blog.bluetooth.com/range-limitation-what-range-limitation-introducing-mesh-networks/

Londroid Meetup and the IoT

Last night I presented to the London Android Group at Skillsmatter in Barbican as part of their Internet of Things themed November meeting. "Londroid" is a large group with nearly 3,000 members. I'm told it's the largest Android related group in Europe.

The session was fully booked and on the night there were only a few "no shows". Interest in IoT is high in the Android developer community as it is elsewhere. My presentation covered some key facts about Bluetooth Smart technology and its astonishing rate of proliferation and then sequed into the main, technical section, where the goal was to equip the audience with an understanding of the key Bluetooth Smart concepts and architecture and the knowledge they need to make practical use of Bluetooth Smart from within Android applications.

I kicked off the technical section with a demo I'd not done before. This involved controlling a Bluetooth Smart equipped LED lighting strip. With a standard Android app, I was able to show the audience how I could determine the light's current state (on|off) and control it, switching it on or off, changing its colour and even kicking off a pre-programmed sequence of on, off and colour change events so that with the addition of some suitable music, the place would have been transformed into something resembling a 1970s discotecheque. Fortunately I didn't have any 1970s disco music with me so the audience were saved the trauma of watching me do the Bluetooth Smart Boogie. Yes, there are many things in this life to be thankful for :-)

Note the Bluetooth Smart lighting strip around the pillar!

After the demo, we ran through the typical application features; device discovery, device connection, state data exploration and exploitation. We learned about Bluetooth Smart architectural components GAP, GATT and the Attribute Protocol (ATT) and about the GATT data structures with which a GATT server exposes it's state, Services, Characteristics and Descriptors. And of course no developer presentation is complete without code and so Android code fragments for each use case were briefly reviewed as well.

After a quick summary of the new Bluetooth Smart APIs that Android L has introduced, we got to what had to be the highlight of the session for at least two people in the audience. Prizes! The audience were invited to answer a couple of technical questions, based on the content of my presentation. Two of the audience members that raised their hands quickly enough *and* gave good answer  (I was shockingly tough on this point!) were rewarded with a Bluetooth Smart development kit, one a Texas Instruments SensorTag and the other, a Broadcom WICED Sense.

I got lots of good questions in the Q&A section and afterwards in the pub. The questions often revealed a gratifying train of thought; "This is exciting....what can I now go and *do* with this?" People were clearly mulling over all sorts of ideas for this exciting technology, from ways to enhance multi-player gaming to ideas for helping the blind. I look forward to finding out what attendees get up to with Bluetooth Smart!

The event's second speaker was Gabor Paller. He treated the audience to his own personal take on Bluetooth Smart and some of the cool projects he's been working on, including a Bluetooth Smart, tablet controlled motor boat! Gabor wishes to stress though that no hamsters were harmed in the making of any of his projects. You had to be there for that one :-)

A PDF version of my presentation is available for download here
A video recording of the presentation is available here

Thursday, 13 November 2014

Apps World, London - Day 1

I attended the first day of Apps World in London yesterday and wandered around all the exhibitors, chatting with many of them and making a few notes. I also watched Jason Bradbury deliver an interesting and entertaining presentation about wearables (and more). I'll return to that shortly.

The exhibition hall was organised well, with companies of similar types, grouped in a logical way. So for example there were a good few companies involved in mobile payment in one way or another and they were all clustered together in one corner of the hall.

On mobile payment, most of what I saw seemed to involve cloud based payment of one sort of another. Unless I missed it, I didn't see anyone offering NFC card emulation payment solutions. I talked with Zapp for a while, a new company "owned by the UK banks" who said they were looking at beacons to enhance the in-store purchasing experience and I was shown a mock up of how this would work when buying a coffee.

Zapp's beacon payment mock-up


I also visited the Pandapay stand, where they showed me how their app allows you to split a bill after a meal (perhaps) with a little less arguing about who had what, and to pay your share with ease from your smartphone.

More interesting given my role at the Bluetooth SIG, were the number of companies whose business was based around indoor location and/or proximity. Yes, there were quite a few beacons on display. Some companies were taking a more holistic approach to location though and beacons figured as only one source of location data from several. I spoke with Indoorz, Sensewhere and Proxitee for example.
Proxitee

Blukii have an extensive range of Bluetooth products including various beacons, some running off larger batteries and some of which are mains powered. The latter could make a lot of sense in some situations and of course would eliminate the need to keep an eye on battery levels. They also have a very simple (in a 'why didn't I think of that!' way) feature which allows you to configure your beacons so that the advertising rate drops to a minimum when outside a given time period. Clearly this allows you to make sure your beacons are fully active during opening hours and put them into a kind of energy saving mode when the shop (e.g.) is closed. They have more products than you can shake a stick at, including developer kits, so check out their web site but my favourite was a proximity solution which locks your laptop when you walk away from it and unlocks it when you get close enough.
Blukii


Star were show-casing their Bluetooth POS printers, designed for retail environments where they tell me, wi-fi doesn't work too well but Bluetooth is perfect.
Star Bluetooth POS printer

"Wearables" had quite a high profile too. For example, I spoke with ebankit who are pioneering the use of smart watches in banking and also with Wear Lynx who have an interesting idea that makes wearables a central part of group communications, in conjunction with a smart phone app which has, I thought, a rather nice UI. Oh and they also have a very cool, retro adventure game (Go North!) for a Pebble smart watch. Could there be a rebirth of such games for your wrist? It would work really well I think!
Wear Lynx
The most enjoyable part of the day was without question, Jason Bradbury's presentation on wearables which in fact turned out to be an entertaining and interesting review of the exponential rate at which new technology is progressing or materialising and how this has produced wearables, amongst other things. Jason thinks we're at a point in that exponential growth where the curve is about to steepen significantly and all sorts of amazing things are just around the corner. He also made a comment to the effect that Bluetooth is having a kind of resurgence and that he's seeing it in more and more devices. I guess he's referring to the explosive adoption of Bluetooth Smart!
Jason Bradbury

All in all, a good day. Sadly I won't be able to make it to Day 2!

Tuesday, 11 November 2014

The Bluetooth Platform Capability Quick Reference

I thought it would be useful to have one place to assess the Bluetooth related capabilities that each mobile platform has, from a developers point of view. So working with colleagues at the Bluetooth SIG, we put together a new resource for developers, the Bluetooth Platform Capability Quick Ref. You can read all about it here: http://blog.bluetooth.com/an-introduction-to-the-bluetooth-platform-capability-quick-reference-guide/

Enjoy.

Droidcon 2014

Android Developers Eager to Pursue the Bluetooth Smart Opportunity

On Friday 31st October, I was delighted to have the opportunity to speak at Europe’s largest Android developer event, DroidconThe event was held in central London at the Business Design Center in Islington and was attended by around 1000 people. There was a good selection of companies exhibiting too, with Bluetooth Smart well represented in products such as wearables, beacons and developer boards.

My session, “Creating the internet of my things using Bluetooth Smart” was extremely well attended, all the more gratifying since it was scheduled at around 4pm on a Friday, and I’m sure most people had all manner of Halloween fun planned for that evening. But the level of interest in Bluetooth Smart was clearly high and people had presumably decided that Trick or Treating could, if necessary, wait.


My presentation opened with some basic scene setting about the difference between Bluetooth Classic and Bluetooth Smart, the advantage that Bluetooth’s Adaptive Frequency Hopping gives in terms of reliability and some statistics and comment regarding the remarkable growth that Bluetooth is experiencing in terms of adoption right now and is forecast to experience over the next few years.
And I made the observation that for every new Bluetooth Smart product to hit the market, there are probably 10 new smart phone and tablet applications waiting to be developed. This is, without question, an amazing time for developers to be learning about Bluetooth Smart.

Quite quickly, the session moved into a technical phase and I interleaved information about basic concepts such as GAP, GATT and ATT with concrete guidance on how to accomplish the key tasks and use cases using the Android APIs with clear code fragments to illustrate each example.

I rounded off the session with a look at the new capabilities which Android L has made available to the Bluetooth Smart developer and an exploration of the types of tools, which they might find it useful to add to their development environment, including protocol analyzers, GATT explorers and developer boards.

The 5 minutes I retained for Q&A at the end were fully utilized and it’s no exaggeration to say I was “mobbed” by people wanting to ask more questions and discuss their ideas as I came off stage. We moved the highly enjoyable discussion which ensued outside the room to avoid delaying the final speaker of the day.

It was exciting for me to see the way in which Android developers recognised the huge potential for Bluetooth Smart, a key enabling technology for the Internet of Things, and the enormous opportunity it affords them as mobile application developers.

I will be delivering a similar presentation on the 19th November to the London Android Group. If you're interested in attending, check here for details: http://www.meetup.com/android/events/208993142/