This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

LAUNCHXL-CC2640R2: Add notification to characteristic

Part Number: LAUNCHXL-CC2640R2
Other Parts Discussed in Thread: CC2640R2F

Using the simple peripheral example, I have added a 6th characteristic, a struct with 2 floats. I used char4 as an example to set it up, expecting to get notifications on a simple iPhone app to consume the data. In the app I see the characteristic yet enumerating the properties for the characteristic it lists 'read ability' but not 'notify ability' whereas the char4 characteristic does list these two. Needless to say, I am not getting notifications for the characteristic I added but I do get them for char4. Using a BLE scanner app confirms that the new characteristic does not have its "can notify" flag set.

Beyond creating the necessary entries in the simpleProfileAttrTbl table (similar to char4), I modified SimpleProfile_AddService() to call GATTServApp_InitCharCfg() on the config for the characteristic. I also modified SimpleProfile_SetParameter() to call GATTServApp_ProcessCharCfg() for the new characteristic and it config parameter.

Not quite sure what am I missing...

  • Hi,

    Could you please specify which SDK version you are using and which stack (blestack or ble5stack) you are using?

    Would you like to share all the code you have added for the 6th characteristic? That way we could review it and comment on it.

    Last but not least, could you please check if the issue may be caused by a lack of stack? You could use the ROV to check this (see details here).

    Best regards,

  • simplelink_cc2640r2_sdk_5_10_00_02

    BLE5stack

    Unlikely I am running out of stack space - notice that the configuration of the new characteristic is not seen by the client - thats not a stack problem. I did poke around with the ROV tool stopping the DUT at various points during its run and saw no stack/heap issues at any time.

    Changes in simple_gantt_profile.c

    CONST uint8 simpleProfileGpsUUID[ATT_BT_UUID_SIZE]   = { LO_UINT16(SIMPLEPROFILE_GPS_UUID),   HI_UINT16(SIMPLEPROFILE_GPS_UUID) };

    static uint8        simpleProfileGpsProps = GATT_PROP_NOTIFY;

    static GpsCoords    simpleProfileGps = {0.0, 0.0};

    static uint8        simpleProfileGpsUserDesp[] = "GPS Coordinates";

    static gattCharCfg_t *simpleProfileGpsConfig;

    simpleProfileAttrTbl[] added the following lines:

        { { ATT_BT_UUID_SIZE, characterUUID },          GATT_PERMIT_READ,       0, &simpleProfileGpsProps },

        { { ATT_BT_UUID_SIZE, simpleProfileGpsUUID },   0,                      0, (uint8 *)&simpleProfileGps },

        { { ATT_BT_UUID_SIZE, clientCharCfgUUID },      GATT_PERMIT_READ | GATT_PERMIT_WRITE, 0, (uint8*) &simpleProfileGpsConfig },

        { { ATT_BT_UUID_SIZE, charUserDescUUID },       GATT_PERMIT_READ,       0, simpleProfileGpsUserDesp },

    in SimpleProfile_AddService()

      simpleProfileGpsConfig = (gattCharCfg_t*) ICall_malloc(sizeof(gattCharCfg_t) * MAX_NUM_BLE_CONNS);

      if (simpleProfileGpsConfig == NULL) {

        return ( bleMemAllocError);

      }

      GATTServApp_InitCharCfg(CONNHANDLE_INVALID, simpleProfileGpsConfig);

    in  SimpleProfile_SetParameter()

      case SIMPLEPROFILE_GPS:

        if (len == sizeof(GpsCoords)) {

          simpleProfileGps = *((GpsCoords*) value);

          // See if Notification has been enabled  simpleProfileGpsConfig

          GATTServApp_ProcessCharCfg(simpleProfileChar4Config, (uint8 *)&simpleProfileGps,

                                     FALSE, simpleProfileAttrTbl, GATT_NUM_ATTRS(simpleProfileAttrTbl), INVALID_TASK_ID, simpleProfile_ReadAttrCB);

        }

    in SimpleProfile_GetParameter():

      case SIMPLEPROFILE_GPS:   *((GpsCoords *) value) = simpleProfileGps; break;

    in simpleProfile_ReadAttrCB()

        case SIMPLEPROFILE_GPS_UUID:

          *pLen = sizeof(GpsCoords);

          VOID memcpy(pValue, pAttr->pValue, *pLen);

          break;

    in simple_peripheral.c:  added to the init function:

        SimpleProfile_SetParameter(SIMPLEPROFILE_GPS, sizeof(GpsCoords), &coords);

    and in the _performPeriodicTask() added a call to:

        SimpleProfile_SetParameter(SIMPLEPROFILE_GPS, sizeof(GpsCoords), &coords);

  • Hi,

    May I ask if you have you changed the value of SERVAPP_NUM_ATTR_SUPPORTED?

    The following should not be related to your current issue, but may require your attention.

    in  SimpleProfile_SetParameter()

      case SIMPLEPROFILE_GPS:

        if (len == sizeof(GpsCoords)) {

          simpleProfileGps = *((GpsCoords*) value);

          // See if Notification has been enabled  simpleProfileGpsConfig

          GATTServApp_ProcessCharCfg(simpleProfileChar4Config, (uint8 *)&simpleProfileGps,

                                     FALSE, simpleProfileAttrTbl, GATT_NUM_ATTRS(simpleProfileAttrTbl), INVALID_TASK_ID, simpleProfile_ReadAttrCB);

        }

    In the call to GATTServApp_ProcessCharCfg() the first parameter should rather be simpleProfileGpsConfig.

    Best regards,

  • I did not change SERVAPP_NUM_ATTR_SUPPORTED, the #define is set to 21. 

    Good catch on that first param to GATTServApp_ProcessCharCfg(), I've been experimenting with the code and that was a left over. The failures as I reported happened with using simpleProfileGpsConfig also.

    However, in all the poking and prodding around, I decided to toggle the BlueTooth switch on the iPhone I was testing with. And all of a sudden the Gps characteristic I created comes to live with notifications. I never thought to do this as changes I made to other characteristics such as description read/write access all come through just fine, just not for the Gps characteristic.  

    I don't understand what happened here. Is this an effect of the wonderful (some sarcasm here) Apple iOS?  It seems strange it would hang on to some parameters yet updates others fine. If in the future I change the collection of characteristics or functions thereof, should the BT interface be toggled to make the phone recognize it?  I'll test with Android later on but is this expected behavior on that platform also?  At least I can begin to build out the functionality now. 

  • Hi,

    Actually, a lot of things are going on behind the scene. Among others, the iPhone has probably paired and bond with the CC2640R2F device. In order to save power, the iPhone kept in cache the GATT table. Unless someone/something tells him the GATT table has been updated, it will consider having the last version of it (i.e. not try to re-discover the GATT table).

    When turning off Bluetooth on the IPhone, you may have clear the bond (there are a lot of different ways to clear the bonds that may depend on your system and OS). As a consequence, the IPhone made a new discovery.

    If you wanted to keep the bond and still warn the IPhone that the GATT table has changed, you could have used the function GAPBondMgr_ServiceChangeInd(). However, in the context of the developing phase (where you are re-flashing entirely the device) this function may be difficult to use. That being said, for your final product, it may be a good solution.

    Let me suggest two ways to avoid this next time:

    • run your tests with a system without any "memory". For example you could use a second CC2640R2F flashed with host_test and interfaced with BTool. In between the tests, make sure to mass erase the device.
    • make sure to empty the Bluetooth cache of your IPhone

    I expect the Android platform will behave the exact same way as the iOS one for this specific use case.

    I hope this will help,

    Best regards,

  • Thats good info Clement, the BT stack is entirely new to me so lots of stuff to learn.

    Since I did not call GAPBondMgr_ServiceChangeInd() nor clear out the iPhone, how is it possible that changes to other characteristics previously set up did come across? E.g., I changed the description of char4 as well as read/write of char1. Both changes were visible on the iPhone, yet the notification changes to my Gps characteristic did not.

    What is also strange is that the iPhone does not report (in its settings/bluetooth page) that it has bonded to my DUT. Though it must have as when I connect to it with the test app it does not ask for the key to pair.

  • Hi,

    As I told you, a lot is going on behind the scene. For example, I know bonding is almost always done when a device get paired. For the rest, I am not an expert of IOs (nor Android), so I guess you should rather contact their support... or live with these questions.

    Please make sure to mark the thread as resolved, that way other users will benefit from our discussion.

    Best regards,