CC2640之添加一个自定义的特性值

来源:互联网 发布:mac能玩什么网游 编辑:程序博客网 时间:2024/06/07 20:40

测试环境


协议栈版本:BLE-STACK V2.1

IAR开发环境版本:IAR for Arm 7.40

硬件设备:Amo-SmartRF v2.0 开发板(对应TI官方的SmartRF06EB 开发板)

示例测试Demo工程:simpleBLEPeripheral工程




添加自定义特征值


我们今天一起来了解下,如何在一个现有的profile中添加一个自定义的特征值,而且该特征值具有读、写和通知权限。下面的讲解中,我们以simpleBLEPeripheral工程为例,来了解如何在其现有的profile中,添加一个具有读、写和通知功能的特征值char6。

 

首先,我们先了解下simpleBLEPeripheral工程原有的服务和特征值,该工程本身有4个服务,其中Simple Profile Service服务是我们可以添加自定义特征值的,该服务本身有5个特征值,UUID分别为FFF1,FFF2,FFF3,FFF4,FFF5,下面我们来实际看一下如何添加一个特征值char6,UUID为FFF6。


1.在C:\ti\simplelink\ble_cc26xx_2_01_00_44423\Projects\ble\Profiles\SimpleProfile目录下找到simpleGATTprofile.h文件,我们先在这个文件中定义我们要添加的新的特征值的一些声明:

[cpp] view plain copy
  1. #define SIMPLEPROFILE_CHAR6              5  // RW uint8 - Profile Characteristic 6 value  
  2.   
  3. #define SIMPLEPROFILE_CHAR6_UUID            0xFFF6  
  4.   
  5. // Length of Characteristic 6 in bytes  
  6. #define SIMPLEPROFILE_CHAR6_LEN           19    
  7.   
  8. // Position of simple char6 value in attribute array  
  9. // char6特性在属性表中的位置,根据实际情况而定,协议栈中的demo添加之后分别是18,19  
  10. #define SIMPLE_MEAS6_VALUE_POS            18  
  11. #define SIMPLE_MEAS6_CCC_POS            19  

2.在C:\ti\simplelink\ble_cc26xx_2_01_00_44423\Projects\ble\Profiles\SimpleProfile\CC26xx目录下找到simpleGATTprofile.c文件。

(1)在该文件全局变量声明UUID的地方,声明我们新添加的特征值的UUID:

[cpp] view plain copy
  1. // Characteristic 6 UUID: 0xFFF6  
  2. CONST uint8 simpleProfilechar6UUID[ATT_BT_UUID_SIZE] =  
  3. {   
  4.     LO_UINT16(SIMPLEPROFILE_CHAR6_UUID), HI_UINT16(SIMPLEPROFILE_CHAR6_UUID)  
  5. };  

(2)在该文件内部变量声明的地方,声明一下我们要添加的新特征值char6的相关变量:

[cpp] view plain copy
  1. // Simple Profile Characteristic 6 Properties  
  2. static uint8 simpleProfileChar6Props = GATT_PROP_READ | GATT_PROP_WRITE_NO_RSP | GATT_PROP_NOTIFY;  
  3.   
  4. // Characteristic 6 Value  
  5. static uint8 simpleProfileChar6[SIMPLEPROFILE_CHAR6_LEN] = { 0, 0, 0, 0, 0 };  
  6. static uint8 simpleProfileChar6Len = 0;  
  7.   
  8. // Simple Profile Characteristic 6 Configuration Each client has its own  
  9. // instantiation of the Client Characteristic Configuration. Reads of the  
  10. // Client Characteristic Configuration only shows the configuration for  
  11. // that client and writes only affect the configuration of that client.  
  12. static gattCharCfg_t *simpleProfileChar6Config;  
  13. // Simple Profile Characteristic 6 User Description  
  14. static uint8 simpleProfileChar6UserDesp[17] = "Characteristic 6";  

(3)在该Profile的属性表

static gattAttribute_t simpleProfileAttrTbl[SERVAPP_NUM_ATTR_SUPPORTED] =

中添加char6相关配置,添加的代码如下:

[cpp] view plain copy
  1. // 17 Characteristic 6 Declaration  
  2. {   
  3.     { ATT_BT_UUID_SIZE, characterUUID },  
  4.     GATT_PERMIT_READ,   
  5.     0,  
  6.     &simpleProfileChar6Props   
  7. },  
  8.   
  9. // 18 Characteristic Value 6  
  10. {   
  11.     { ATT_BT_UUID_SIZE, simpleProfilechar6UUID },  
  12.     GATT_PERMIT_READ | GATT_PERMIT_WRITE,  
  13.     0,   
  14.     simpleProfileChar6   
  15. },  
  16.   
  17. // 19 Characteristic 6 configuration  
  18. {   
  19.     { ATT_BT_UUID_SIZE, clientCharCfgUUID },  
  20.     GATT_PERMIT_READ | GATT_PERMIT_WRITE,   
  21.     0,   
  22.     (uint8 *)&simpleProfileChar6Config   
  23. },  
  24.   
  25. // 20 Characteristic 6 User Description  
  26. {   
  27.     { ATT_BT_UUID_SIZE, charUserDescUUID },  
  28.     GATT_PERMIT_READ,   
  29.     0,   
  30.     simpleProfileChar6UserDesp   
  31. },    

上面代码注释上的标号,是我自己标的,也就是属性表数组的下标,注意是从0开始,上述注释的下标就跟我之前头文件中定义的SIMPLE_MEAS6_VALUE_POS和SIMPLE_MEAS6_CCC_POS的值相对应。

 

因为增加了这4个数组成员,所以属性表SERVAPP_NUM_ATTR_SUPPORTED的值需要由原来的17修改为21,如下:

[cpp] view plain copy
  1. /********************************************************************* 
  2. * CONSTANTS 
  3. */  
  4. #define SERVAPP_NUM_ATTR_SUPPORTED        21//17  

(4)新添加的特征值char6具有通知功能,所以,我们需要在SimpleProfile_AddService函数中进行相应的初始化配置操作:

[cpp] view plain copy
  1. // Allocate Client Characteristic Configuration table  
  2. simpleProfileChar6Config = (gattCharCfg_t *)ICall_malloc( sizeof(gattCharCfg_t) *linkDBNumConns );  
  3. if ( simpleProfileChar6Config == NULL )  
  4. {  
  5.     // Free already allocated data  
  6.     ICall_free( simpleProfileChar6Config );  
  7.   
  8.     return ( bleMemAllocError );  
  9. }  
  10. ......  
  11. GATTServApp_InitCharCfg( INVALID_CONNHANDLE, simpleProfileChar6Config );  

(5)SimpleProfile_SetParameter方法中参考其他特征值的配置,添加如下代码:

[cpp] view plain copy
  1. case SIMPLEPROFILE_CHAR6:  
  2.   
  3.     if ( len <= SIMPLEPROFILE_CHAR6_LEN )   
  4.     {  
  5.         VOID memcpy( simpleProfileChar6, value, len );  
  6.         simpleProfileChar6Len = len;  
  7.         // See if Notification has been enabled  
  8.         GATTServApp_ProcessCharCfg( simpleProfileChar6Config, simpleProfileChar6, FALSE,  
  9.                         simpleProfileAttrTbl, GATT_NUM_ATTRS( simpleProfileAttrTbl ),  
  10.                         INVALID_TASK_ID, simpleProfile_ReadAttrCB );  
  11.     }  
  12.     else  
  13.     {  
  14.         ret = bleInvalidRange;  
  15.     }  
  16.     break;  

(6)SimpleProfile_GetParameter方法中参考其他特征值的配置,添加新特征值的相关配置:

[cpp] view plain copy
  1. case SIMPLEPROFILE_CHAR6:  
  2.     VOID memcpy( value, simpleProfileChar6, simpleProfileChar6Len );  
  3.     break;    

(7)simpleProfile_ReadAttrCB函数是调用读之后的回调函数,在其中添加新特征值的相应处理:

[cpp] view plain copy
  1. case SIMPLEPROFILE_CHAR6_UUID:  
  2.     *pLen = SIMPLEPROFILE_CHAR6_LEN;  
  3.     VOID memcpy( pValue, pAttr->pValue, SIMPLEPROFILE_CHAR6_LEN );  
  4.     break;  

(8)simpleProfile_WriteAttrCB函数是调用写操作之后的回调函数,在其中添加新特征值的相应处理:

[cpp] view plain copy
  1. case SIMPLEPROFILE_CHAR6_UUID:  
  2.   
  3.     if ( offset == 0 )  
  4.     {  
  5.         if ( len > SIMPLEPROFILE_CHAR6_LEN )  
  6.         {  
  7.             status = ATT_ERR_INVALID_VALUE_SIZE;  
  8.         }  
  9.     }  
  10.     else  
  11.     {  
  12.         status = ATT_ERR_ATTR_NOT_LONG;  
  13.     }  
  14.   
  15.     //Write the value  
  16.     if ( status == SUCCESS )  
  17.     {  
  18.         VOID memcpy( pAttr->pValue, pValue, SIMPLEPROFILE_CHAR6_LEN );  
  19.         //VOID memcpy( pAttr->pValue, pValue, len );  
  20.         //simpleProfileChar6Len = len;  
  21.         notifyApp = SIMPLEPROFILE_CHAR6;  
  22.         //tx_printf("pValue:%s",pAttr->pValue);  
  23.     }  
  24.   
  25.     break;  

(9)我们在该文件中封装一个通过通知功能发送数据的接口函数,源码如下:

[cpp] view plain copy
  1. /********************************************************************* 
  2. * @fn          SimpleProfile_Notification 
  3. * 
  4. * @brief       Send a notification containing a ir value 
  5. * 
  6. * @param       connHandle - connection handle 
  7. * @param       pNoti - pointer to notification structure 
  8. * 
  9. * @return      Success or Failure 
  10. */  
  11. bStatus_t SimpleProfile_Notification( uint16 connHandle, attHandleValueNoti_t *pNoti )  
  12. {  
  13.     uint16 value = GATTServApp_ReadCharCfg( connHandle, simpleProfileChar6Config );  
  14.   
  15.     // If notifications is enabled  
  16.     if ( value & GATT_CLIENT_CFG_NOTIFY )  
  17.     {  
  18.         // Set the handle  
  19.         pNoti->handle = simpleProfileAttrTbl[SIMPLE_MEAS6_VALUE_POS].handle;  
  20.   
  21.         // Send the notification  
  22.         return GATT_Notification( connHandle, pNoti, FALSE );  
  23.     }  
  24.   
  25.     return bleIncorrectMode;  
  26. }  

打开C:\ti\simplelink\ble_cc26xx_2_01_00_44423\Projects\ble\Profiles\SimpleProfile目录下的simpleGATTprofile.h文件,在其中添加该通知功能接口的声明,便于外部调用:

[cpp] view plain copy
  1. /********************************************************************* 
  2. * @fn          SimpleProfile_Notification 
  3. * 
  4. * @brief       Send a notification containing a ir value 
  5. * 
  6. * @param       connHandle - connection handle 
  7. * @param       pNoti - pointer to notification structure 
  8. * 
  9. * @return      Success or Failure 
  10. */  
  11. extern bStatus_t SimpleProfile_Notification( uint16 connHandle, attHandleValueNoti_t *pNoti );  

3.经过上面的配置,我们就在Profile中添加了自定义的特征值char6,下面我们在应用文件中添加测试程序,进行相应测试。

 

(1)定义两个内部变量,通知功能使用的变量以及连接句柄的变量:

[cpp] view plain copy
  1. static attHandleValueNoti_t simpleValue;  
  2.   
  3. // GAP connection handle  
  4. static uint16 gapConnHandle;  

(2)在初始化函数SimpleBLEPeripheral_init中对新添加的特征值char6进行初始化:

[cpp] view plain copy
  1. uint8_t charValue6[SIMPLEPROFILE_CHAR6_LEN] = { 1, 2, 3, 4, 5 };  
  2.   
  3. SimpleProfile_SetParameter(SIMPLEPROFILE_CHAR6, SIMPLEPROFILE_CHAR6_LEN,charValue6);  

(3)在连接成功的回调函数SimpleBLEPeripheral_processStateChangeEvt中添加连接句柄获取的代码:

[cpp] view plain copy
  1. GAPRole_GetParameter( GAPROLE_CONNHANDLE, &gapConnHandle );  

截图如下:



(4)然后,在写操作回调函数SimpleBLEPeripheral_processCharValueChangeEvt中添加char6写操作之后的处理代码:

[cpp] view plain copy
  1. case SIMPLEPROFILE_CHAR6:  
  2.     SimpleProfile_GetParameter(SIMPLEPROFILE_CHAR6, &newValue);  
  3.   
  4.     LCD_WRITE_STRING_VALUE("Char 6:", (uint16_t)newValue, 16, LCD_PAGE4);  
  5.     break;  

(5)最后在定期执行的事件中添加通知功能发送数据的操作代码,为了便于测试,我们直接在SimpleBLEPeripheral_performPeriodicTask定时执行的函数中将之前的函数内容屏蔽掉,添加如下测试代码:

[cpp] view plain copy
  1. simpleValue.pValue = GATT_bm_alloc(gapConnHandle,   
  2.                                            ATT_HANDLE_VALUE_NOTI,  
  3.                                            SIMPLEPROFILE_CHAR6_LEN, NULL);  
  4.     if(simpleValue.pValue != NULL)  
  5.     {  
  6.         uint8_t *p = simpleValue.pValue;  
  7.         *p++ = 0x11;  
  8.         *p++ = 0x22;  
  9.         *p++ = 0x33;  
  10.         *p++ = 0x44;  
  11.         simpleValue.len = (uint8_t)(p - simpleValue.pValue);  
  12.         //tx_printf("notify\r\n");  
  13.         if(SimpleProfile_Notification(gapConnHandle,&simpleValue) != SUCCESS)  
  14.         {  
  15.             GATT_bm_free((gattMsg_t *)&simpleValue, ATT_HANDLE_VALUE_NOTI);  
  16.         }  
  17.     }  

通过上面的应用层设置和调用,我们就可以烧录到板子中通过手机的BLE测试工具进行连接测试了,通过测试,配置正确,大家可以试一下。


原创粉丝点击