CC2640之添加一個自定義的特性值

測試環境


協議棧版本: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文件,我們先在這個文件中定義我們要添加的新的特徵值的一些聲明:

#define SIMPLEPROFILE_CHAR6              5  // RW uint8 - Profile Characteristic 6 value

#define SIMPLEPROFILE_CHAR6_UUID            0xFFF6

// Length of Characteristic 6 in bytes
#define SIMPLEPROFILE_CHAR6_LEN           19  

// Position of simple char6 value in attribute array
// char6特性在屬性表中的位置,根據實際情況而定,協議棧中的demo添加之後分別是18,19
#define SIMPLE_MEAS6_VALUE_POS            18
#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:

// Characteristic 6 UUID: 0xFFF6
CONST uint8 simpleProfilechar6UUID[ATT_BT_UUID_SIZE] =
{ 
	LO_UINT16(SIMPLEPROFILE_CHAR6_UUID), HI_UINT16(SIMPLEPROFILE_CHAR6_UUID)
};

(2)在該文件內部變量聲明的地方,聲明一下我們要添加的新特徵值char6的相關變量:

// Simple Profile Characteristic 6 Properties
static uint8 simpleProfileChar6Props = GATT_PROP_READ | GATT_PROP_WRITE_NO_RSP | GATT_PROP_NOTIFY;

// Characteristic 6 Value
static uint8 simpleProfileChar6[SIMPLEPROFILE_CHAR6_LEN] = { 0, 0, 0, 0, 0 };
static uint8 simpleProfileChar6Len = 0;

// Simple Profile Characteristic 6 Configuration Each client has its own
// instantiation of the Client Characteristic Configuration. Reads of the
// Client Characteristic Configuration only shows the configuration for
// that client and writes only affect the configuration of that client.
static gattCharCfg_t *simpleProfileChar6Config;
// Simple Profile Characteristic 6 User Description
static uint8 simpleProfileChar6UserDesp[17] = "Characteristic 6";

(3)在該Profile的屬性表

static gattAttribute_t simpleProfileAttrTbl[SERVAPP_NUM_ATTR_SUPPORTED] =

中添加char6相關配置,添加的代碼如下:

// 17 Characteristic 6 Declaration
{ 
	{ ATT_BT_UUID_SIZE, characterUUID },
	GATT_PERMIT_READ, 
	0,
	&simpleProfileChar6Props 
},

// 18 Characteristic Value 6
{ 
	{ ATT_BT_UUID_SIZE, simpleProfilechar6UUID },
	GATT_PERMIT_READ | GATT_PERMIT_WRITE,
	0, 
	simpleProfileChar6 
},

// 19 Characteristic 6 configuration
{ 
	{ ATT_BT_UUID_SIZE, clientCharCfgUUID },
	GATT_PERMIT_READ | GATT_PERMIT_WRITE, 
	0, 
	(uint8 *)&simpleProfileChar6Config 
},

// 20 Characteristic 6 User Description
{ 
	{ ATT_BT_UUID_SIZE, charUserDescUUID },
	GATT_PERMIT_READ, 
	0, 
	simpleProfileChar6UserDesp 
},	

上面代碼註釋上的標號,是我自己標的,也就是屬性表數組的下標,注意是從0開始,上述註釋的下標就跟我之前頭文件中定義的SIMPLE_MEAS6_VALUE_POS和SIMPLE_MEAS6_CCC_POS的值相對應。

 

因爲增加了這4個數組成員,所以屬性表SERVAPP_NUM_ATTR_SUPPORTED的值需要由原來的17修改爲21,如下:

/*********************************************************************
* CONSTANTS
*/
#define SERVAPP_NUM_ATTR_SUPPORTED        21//17

(4)新添加的特徵值char6具有通知功能,所以,我們需要在SimpleProfile_AddService函數中進行相應的初始化配置操作:

// Allocate Client Characteristic Configuration table
simpleProfileChar6Config = (gattCharCfg_t *)ICall_malloc( sizeof(gattCharCfg_t) *linkDBNumConns );
if ( simpleProfileChar6Config == NULL )
{
	// Free already allocated data
	ICall_free( simpleProfileChar6Config );

	return ( bleMemAllocError );
}
......
GATTServApp_InitCharCfg( INVALID_CONNHANDLE, simpleProfileChar6Config );

(5)SimpleProfile_SetParameter方法中參考其他特徵值的配置,添加如下代碼:

case SIMPLEPROFILE_CHAR6:

	if ( len <= SIMPLEPROFILE_CHAR6_LEN ) 
	{
		VOID memcpy( simpleProfileChar6, value, len );
		simpleProfileChar6Len = len;
		// See if Notification has been enabled
		GATTServApp_ProcessCharCfg( simpleProfileChar6Config, simpleProfileChar6, FALSE,
						simpleProfileAttrTbl, GATT_NUM_ATTRS( simpleProfileAttrTbl ),
						INVALID_TASK_ID, simpleProfile_ReadAttrCB );
	}
	else
	{
		ret = bleInvalidRange;
	}
	break;

(6)SimpleProfile_GetParameter方法中參考其他特徵值的配置,添加新特徵值的相關配置:

case SIMPLEPROFILE_CHAR6:
	VOID memcpy( value, simpleProfileChar6, simpleProfileChar6Len );
	break;  

(7)simpleProfile_ReadAttrCB函數是調用讀之後的回調函數,在其中添加新特徵值的相應處理:

case SIMPLEPROFILE_CHAR6_UUID:
	*pLen = SIMPLEPROFILE_CHAR6_LEN;
	VOID memcpy( pValue, pAttr->pValue, SIMPLEPROFILE_CHAR6_LEN );
	break;

(8)simpleProfile_WriteAttrCB函數是調用寫操作之後的回調函數,在其中添加新特徵值的相應處理:

case SIMPLEPROFILE_CHAR6_UUID:

	if ( offset == 0 )
	{
		if ( len > SIMPLEPROFILE_CHAR6_LEN )
		{
			status = ATT_ERR_INVALID_VALUE_SIZE;
		}
	}
	else
	{
		status = ATT_ERR_ATTR_NOT_LONG;
	}

	//Write the value
	if ( status == SUCCESS )
	{
		VOID memcpy( pAttr->pValue, pValue, SIMPLEPROFILE_CHAR6_LEN );
		//VOID memcpy( pAttr->pValue, pValue, len );
		//simpleProfileChar6Len = len;
		notifyApp = SIMPLEPROFILE_CHAR6;
		//tx_printf("pValue:%s",pAttr->pValue);
	}

	break;

(9)我們在該文件中封裝一個通過通知功能發送數據的接口函數,源碼如下:

/*********************************************************************
* @fn          SimpleProfile_Notification
*
* @brief       Send a notification containing a ir value
*
* @param       connHandle - connection handle
* @param       pNoti - pointer to notification structure
*
* @return      Success or Failure
*/
bStatus_t SimpleProfile_Notification( uint16 connHandle, attHandleValueNoti_t *pNoti )
{
	uint16 value = GATTServApp_ReadCharCfg( connHandle, simpleProfileChar6Config );

	// If notifications is enabled
	if ( value & GATT_CLIENT_CFG_NOTIFY )
	{
		// Set the handle
		pNoti->handle = simpleProfileAttrTbl[SIMPLE_MEAS6_VALUE_POS].handle;

		// Send the notification
		return GATT_Notification( connHandle, pNoti, FALSE );
	}

	return bleIncorrectMode;
}

打開C:\ti\simplelink\ble_cc26xx_2_01_00_44423\Projects\ble\Profiles\SimpleProfile目錄下的simpleGATTprofile.h文件,在其中添加該通知功能接口的聲明,便於外部調用:

/*********************************************************************
* @fn          SimpleProfile_Notification
*
* @brief       Send a notification containing a ir value
*
* @param       connHandle - connection handle
* @param       pNoti - pointer to notification structure
*
* @return      Success or Failure
*/
extern bStatus_t SimpleProfile_Notification( uint16 connHandle, attHandleValueNoti_t *pNoti );

3.經過上面的配置,我們就在Profile中添加了自定義的特徵值char6,下面我們在應用文件中添加測試程序,進行相應測試。

 

(1)定義兩個內部變量,通知功能使用的變量以及連接句柄的變量:

static attHandleValueNoti_t simpleValue;

// GAP connection handle
static uint16 gapConnHandle;

(2)在初始化函數SimpleBLEPeripheral_init中對新添加的特徵值char6進行初始化:

uint8_t charValue6[SIMPLEPROFILE_CHAR6_LEN] = { 1, 2, 3, 4, 5 };

SimpleProfile_SetParameter(SIMPLEPROFILE_CHAR6, SIMPLEPROFILE_CHAR6_LEN,charValue6);

(3)在連接成功的回調函數SimpleBLEPeripheral_processStateChangeEvt中添加連接句柄獲取的代碼:

GAPRole_GetParameter( GAPROLE_CONNHANDLE, &gapConnHandle );

截圖如下:



(4)然後,在寫操作回調函數SimpleBLEPeripheral_processCharValueChangeEvt中添加char6寫操作之後的處理代碼:

case SIMPLEPROFILE_CHAR6:
	SimpleProfile_GetParameter(SIMPLEPROFILE_CHAR6, &newValue);

	LCD_WRITE_STRING_VALUE("Char 6:", (uint16_t)newValue, 16, LCD_PAGE4);
	break;

(5)最後在定期執行的事件中添加通知功能發送數據的操作代碼,爲了便於測試,我們直接在SimpleBLEPeripheral_performPeriodicTask定時執行的函數中將之前的函數內容屏蔽掉,添加如下測試代碼:

simpleValue.pValue = GATT_bm_alloc(gapConnHandle, 
                                           ATT_HANDLE_VALUE_NOTI,
                                           SIMPLEPROFILE_CHAR6_LEN, NULL);
	if(simpleValue.pValue != NULL)
	{
		uint8_t *p = simpleValue.pValue;
		*p++ = 0x11;
		*p++ = 0x22;
		*p++ = 0x33;
		*p++ = 0x44;
		simpleValue.len = (uint8_t)(p - simpleValue.pValue);
		//tx_printf("notify\r\n");
		if(SimpleProfile_Notification(gapConnHandle,&simpleValue) != SUCCESS)
		{
			GATT_bm_free((gattMsg_t *)&simpleValue, ATT_HANDLE_VALUE_NOTI);
		}
	}

通過上面的應用層設置和調用,我們就可以燒錄到板子中通過手機的BLE測試工具進行連接測試了,通過測試,配置正確,大家可以試一下。

















發佈了66 篇原創文章 · 獲贊 207 · 訪問量 64萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章