一、简介
本篇介绍从机端的notify通知的两种方式,以及主机端是如何处理notify通知的。
二、实验平台
协议栈版本:BLE-CC254x-1.4.0
编译软件:IAR 8.20.2
硬件平台:Smart RF开发板
三、简介notify通知的两种方式
1、GATT_Notification
在从机代码中使用,由从机主动通知,且不需要主机发出请求和回应。
2、GATTServApp_ProcessCharCfg
在从机代码中使用,需要主机发送一次“通知请求”给从机,从机收到“通知请求”才发送通知。
实际上这个函数里依然会调用GATT_Notification这个函数。
四、使用notify通知时的注意事项
无论是GATT_Notification,还是GATTServApp_ProcessCharCfg,都需要在定义特征值时比read、write方式的配置多一条
static gattCharCfg_t simpleProfileChar3Config[GATT_MAX_NUM_CONN];
例如,需要用到char4特征值通知时,需要打开char4的通知开关,也就是要向属性表中0x2F写入0x0001进行开通知。
其中0x2F就是指向
“
// Characteristic 4 configuration
{
{ ATT_BT_UUID_SIZE, clientCharCfgUUID },
GATT_PERMIT_READ | GATT_PERMIT_WRITE,
0,
(uint8 *)simpleProfileChar3Config
},
”
注:直接往simpleProfileChar3Config里写0x0001开通知开关也是可行的,但尽量保证这个开关由主机来开会比较合理。
五、GATT_Notification范例
本范例是我自己写的,通过按下按键S1,通知发送0x01,松手发送0x00
按键中调用notify通知的函数(SimpleBLEPeripheral.c中)
{
if(KEY == 1)
{
uint8 charValue3 = 1;
SimpleProfile_SetParameter( SIMPLEPROFILE_CHAR3, sizeof ( uint8 ), &charValue3 );
}
else
{
uint8 charValue3 = 0;
SimpleProfile_SetParameter( SIMPLEPROFILE_CHAR3, sizeof ( uint8 ), &charValue3 );
}
}
SimpleProfile_SetParameter部分函数如下:
case SIMPLEPROFILE_CHAR3:
if ( len == sizeof ( uint8 ) )
{
simpleProfileChar3 = *((uint8*)value);
linkDB_PerformFunc( BUTTONNotifyCB );
#if 0
// linkDB_PerformFunc(RSSINotifyCB);
GAPRole_GetParameter( GAPROLE_CONNHANDLE, &connHandle); //获取
value0 = GATTServApp_ReadCharCfg( connHandle, simpleProfileChar3Config );//读出CCC的值
if ( value0 & GATT_CLIENT_CFG_NOTIFY ) //判断是否打开通知开关,打开了则发送数据
{
attHandleValueNoti_t noti;
noti.handle = simpleProfileAttrTbl[8].handle ;
noti.len = len;
osal_memcpy((uint8*)noti.value, (uint8 *)&simpleProfileChar3, len);
VOID GATT_Notification( 0, ¬i, FALSE);
}
#endif
}
else
{
ret = bleInvalidRange;
}
break;
每次发送数据的时候需要知道连接的handle 如上面所示:
第一种办法:
1./*********************************************************************
* @fn battNotifyCB
*
* @brief Send a notification of the level state characteristic.
*
* @param connHandle - linkDB item
*
* @return None.
*/
void BUTTONNotifyCB( linkDBItem_t *pLinkItem )
{
if ( pLinkItem->stateFlags & LINK_CONNECTED )
{
uint16 value = GATTServApp_ReadCharCfg( pLinkItem->connectionHandle,
simpleProfileChar3Config );
if ( value & GATT_CLIENT_CFG_NOTIFY )
{
attHandleValueNoti_t noti;
noti.handle = simpleProfileAttrTbl[8].handle ;
noti.len = 1;
osal_memcpy((uint8*)noti.value, (uint8 *)&simpleProfileChar3, 1);
VOID GATT_Notification( 0, ¬i, FALSE);
}
}
}
2.调用 linkDB_PerformFunc( BUTTONNotifyCB ); 可以获得当前连接的所以数据数据。
然后在判断这个handle有没有被主机使能。能使了就可以发送通知了
第二种办法:
GAPRole_GetParameter( GAPROLE_CONNHANDLE, &connHandle);
直接调用这个获取当前连接的handle,然后在判断这个handle有没有被主机使能。能使了就可以发送通知了
第三种办法:
case SIMPLEPROFILE_CHAR3:
GATTServApp_ProcessCharCfg( simpleProfileChar4Config, (uint8 *)&simpleProfileChar3, FALSE,
simpleProfileAttrTbl, GATT_NUM_ATTRS( simpleProfileAttrTbl ),
INVALID_TASK_ID );
break;
调用 GATTServApp_ProcessCharCfg();函数发送数据给主机
注:参考了 @
feilusia的博客