一、简介
本篇介绍从机端的notify通知的两种方式。
二、实验平台
协议栈版本:BLE-CC254x-1.4.0
编译软件:IAR 8.20.2
硬件平台:Smart RF开发板
三、版权声明
博主:甜甜的大香瓜
声明:喝水不忘挖井人,转载请注明出处。
原文地址:http://blog.csdn.net/feilusia
联系方式:[email protected]
技术交流QQ群:127442605
四、简介notify通知的两种方式
1、GATT_Notification
在从机代码中使用,由从机主动通知,且不需要主机发出请求和回应。
2、GATTServApp_ProcessCharCfg
在从机代码中使用,需要主机发送一次“通知请求”给从机,从机收到“通知请求”才发送通知。
实际上这个函数里依然会调用GATT_Notification这个函数。
五、使用notify通知时的注意事项
无论是GATT_Notification,还是GATTServApp_ProcessCharCfg,都需要在定义特征值时比read、write方式的配置多一条
static gattCharCfg_t simpleProfileChar4Config[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 *)simpleProfileChar4Config
},
”
注:直接往simpleProfileChar4Config里写0x0001开通知开关也是可行的,但尽量保证这个开关由主机来开会比较合理。
六、GATT_Notification范例
本范例是我自己写的,通过按下按键S1,通知出一串从0~19的20字节的数据。
此范例的前提1:已经添加好了特征值char6,并且长度为20。(参考博文《CC2541之添加特征值》)
此范例的前提2:按键可以使用。(参考博文《CC2541之按键》)
1、添加一个“char6在属性表中的偏移值”的宏(simpleGATTprofile.c中)
#define ATTRTBL_CHAR6_IDX 18可以在属性表simpleProfileAttrTbl中一个一个地数,“Characteristic Value 6”所在的正好是属性表中第18个。
2、定义一个notify函数(simpleGATTprofile.c中)
//****************************************************************************** //name: SimpleGATTprofile_Char6_Notify //introduce: 通知len长度的数据 //parameter: connHandle:连接句柄 // pValue:要通知的数据,范围为0~SIMPLEPROFILE_CHAR6,最多20个字节 // len:要通知的数据的长度 //return: none //****************************************************************************** void SimpleGATTprofile_Char6_Notify( uint16 connHandle, uint8 *pValue, uint8 len) { attHandleValueNoti_t noti; uint16 value; value = GATTServApp_ReadCharCfg( connHandle, simpleProfileChar6Config );//读出CCC的值 if ( value & GATT_CLIENT_CFG_NOTIFY ) //判断是否打开通知开关,打开了则发送数据 { noti.handle = simpleProfileAttrTbl[ATTRTBL_CHAR6_IDX].handle; noti.len = len; osal_memcpy( noti.value, pValue, len); //数据 GATT_Notification( connHandle, ¬i, FALSE ); } }
//****************************************************************************** //name: SimpleGATTprofile_Char6_Notify //introduce: 通知len长度的数据 //parameter: connHandle:连接句柄 // pValue:要通知的数据,范围为0~SIMPLEPROFILE_CHAR6,最多20个字节 // len:要通知的数据的长度 //return: none //****************************************************************************** extern void SimpleGATTprofile_Char6_Notify( uint16 connHandle, uint8 *pValue, uint8 len);
static void simpleBLEPeripheral_HandleKeys( uint8 shift, uint8 keys ) { VOID shift; // Intentionally unreferenced parameter if ( keys & HAL_KEY_SW_6 ) { uint16 notify_Handle; uint8 *p; GAPRole_GetParameter( GAPROLE_CONNHANDLE, ¬ify_Handle); //获取Connection Handle for(uint8 i = 0; i < 20; i++) //写一个20字节的测试缓冲区的数据 { *(p+i) = i; } SimpleGATTprofile_Char6_Notify(notify_Handle, p, 20); } }
七、GATTServApp_ProcessCharCfg使用范例
注:TI提供的SimpleBLEPeripheral项目中,在周期事件里每隔5S即读取char3值一次,并把char3的值通知出去,此时用的就是GATTServApp_ProcessCharCfg方式。
1、周期事件中不停地设置char4的值
static void performPeriodicTask( void ) { uint8 valueToCopy; uint8 stat; stat = SimpleProfile_GetParameter( SIMPLEPROFILE_CHAR3, &valueToCopy); if( stat == SUCCESS ) { /* * Call to set that value of the fourth characteristic in the profile. Note * that if notifications of the fourth characteristic have been enabled by * a GATT client device, then a notification will be sent every time this * function is called. */ SimpleProfile_SetParameter( SIMPLEPROFILE_CHAR4, sizeof(uint8), &valueToCopy); } }
case SIMPLEPROFILE_CHAR4: if ( len == sizeof ( uint8 ) ) { simpleProfileChar4 = *((uint8*)value); // See if Notification has been enabled GATTServApp_ProcessCharCfg( simpleProfileChar4Config, &simpleProfileChar4, FALSE, simpleProfileAttrTbl, GATT_NUM_ATTRS( simpleProfileAttrTbl ), INVALID_TASK_ID ); } else { ret = bleInvalidRange; } break;
3、实验结果
char4不停地通知着char3的值0x03。