GATT_Notification vs. GATTServApp_ProcessCharCfg

来源:互联网 发布:windows定时运行脚本 编辑:程序博客网 时间:2024/06/06 09:42

A:Notification连接后,从机向主机发送的数据包,不需要主机确认收到,适合大量数据快速发送。
从机 Notification发送方式有两种,用户根据自身要求选择:
(1)调用GATT_Notification( uint16 connHandle, attHandleValueNoti_t *pNoti, uint8 authenticated );直接发送
(2)调用GATTServApp_ProcessCharCfg函数,这个函数内部最终会导致master那边调用一个read请求,回调到simpleProfile_ReadAttrCB()。用这个函数,只有master向Peripheral的Notification允许位写1,才能使能从机,从而调用GATT_Notification向主机发送Notification。

//声明attHandleValueNoti_t这个结构体static attHandleValueNoti_t pReport ;//存放handleuint16 noti_cHandle; //读取notification对应的handlepReport.handle = simpleProfileAttrTbl[11].handle;//获取Connection HandleGAPRole_GetParameter( GAPROLE_CONNHANDLE, &noti_cHandle);pReport.len = 1;            //数据长度pReport.value[0] = 0x03;    //赋值GATT_Notification(noti_cHandle,&pReport,FALSE);
//!< Connection Handle. Read Only. Size is uint16.#define GAPROLE_CONNHANDLE          0x30E //eg: GAPRole_GetParameter( GAPROLE_CONNHANDLE, &gapConnHandle );

simpleBLECentral
1、添加notification的接收
simpleBLECentralProcessGATTMsg()
类似
if ( ( pMsg->method == ATT_READ_RSP ) || ........)
添加
else if ( ( pMsg->method == ATT_HANDLE_VALUE_NOTI ) ||......)

2、启用notification
simpleProfileAttrTbl 的位置12 是CHAR4 的Client Characteristic Configuration, 发Notification 之前, 通过master设备把这个值设置成 0x0001, 打开notification.这个handle应该是相应的characteristic value的handle的后面一个, 就是characteristic value的handle加 1 .

attWriteReq_t writeReq;writeReq.handle = 0x002f;writeReq.len = 2;writeReq.value[0] = LO_UINT16(GATT_CLIENT_CFG_NOTIFY);        //这里是 0x01writeReq.value[1] = HI_UINT16(GATT_CLIENT_CFG_NOTIFY);        //这里是 0x00writeReq.sig = 0;writeReq.cmd = 0;GATT_WriteCharValue( simpleBLEConnHandle, &writeReq, simpleBLETaskId );

这两个值目的是打开Notification功能. CCC的参数有两个, 一个Notification, 一个indication. value[0]就是打开关闭notification, value[1]是打开关闭indication.

3、使用UUID获取simpleBLEConnHandle
a. simpleBLECentralStartDiscovery
b. simpleBLECentralProcessGATTMsg
-> simpleBLEGATTDiscoveryEvent

static void simpleBLECentralStartDiscovery( void ){  uint8 uuid[ATT_BT_UUID_SIZE] = { LO_UINT16(SIMPLEPROFILE_SERV_UUID),                                   HI_UINT16(SIMPLEPROFILE_SERV_UUID) };  // Initialize cached handles  simpleBLESvcStartHdl = simpleBLESvcEndHdl = simpleBLECharHdl = 0;  simpleBLEDiscState = BLE_DISC_STATE_SVC;  // Discovery simple BLE service  GATT_DiscPrimaryServiceByUUID( simpleBLEConnHandle,                                 uuid,                                 ATT_BT_UUID_SIZE,                                 simpleBLETaskId );}static void simpleBLEGATTDiscoveryEvent( gattMsgEvent_t *pMsg ){  attReadByTypeReq_t req;  if ( simpleBLEDiscState == BLE_DISC_STATE_SVC )  {    // Service found, store handles    if ( pMsg->method == ATT_FIND_BY_TYPE_VALUE_RSP &&         pMsg->msg.findByTypeValueRsp.numInfo > 0 )    {      simpleBLESvcStartHdl = pMsg->msg.findByTypeValueRsp.handlesInfo[0].handle;      simpleBLESvcEndHdl = pMsg->msg.findByTypeValueRsp.handlesInfo[0].grpEndHandle;    }    // If procedure complete    if ( ( pMsg->method == ATT_FIND_BY_TYPE_VALUE_RSP  &&            pMsg->hdr.status == bleProcedureComplete ) ||         ( pMsg->method == ATT_ERROR_RSP ) )    {      if ( simpleBLESvcStartHdl != 0 )      {        // Discover characteristic        simpleBLEDiscState = BLE_DISC_STATE_CHAR;        req.startHandle = simpleBLESvcStartHdl;        req.endHandle = simpleBLESvcEndHdl;        req.type.len = ATT_BT_UUID_SIZE;        req.type.uuid[0] = LO_UINT16(SIMPLEPROFILE_CHAR1_UUID);        req.type.uuid[1] = HI_UINT16(SIMPLEPROFILE_CHAR1_UUID);        GATT_ReadUsingCharUUID( simpleBLEConnHandle, &req, simpleBLETaskId );      }    }  }  else if ( simpleBLEDiscState == BLE_DISC_STATE_CHAR )  {    // Characteristic found, store handle    if ( pMsg->method == ATT_READ_BY_TYPE_RSP &&          pMsg->msg.readByTypeRsp.numPairs > 0 )    {      simpleBLECharHdl = BUILD_UINT16( pMsg->msg.readByTypeRsp.dataList[0],                                       pMsg->msg.readByTypeRsp.dataList[1] );      LCD_WRITE_STRING( "Simple Svc Found", HAL_LCD_LINE_1 );      simpleBLEProcedureInProgress = FALSE;    }    simpleBLEDiscState = BLE_DISC_STATE_IDLE;  }    }

simpleBLEPeripheral
simpleGATTProfile.c
里面有个SimpleProfile_SetParameter(), 这个就是间隔性被调用的函数.里面有
case SIMPLEPROFILE_CHAR4:
调用
GATTServApp_ProcessCharCfg()
这个函数内部最终会回调到
simpleProfile_ReadAttrCB()

1、SimpleProfile_SetParameter

SimpleProfile_SetParameter( uint8 param, uint8 len, void *value ){    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;}

2、simpleProfile_ReadAttrCB()

simpleProfile_ReadAttrCB( uint16 connHandle, gattAttribute_t *pAttr,                            uint8 *pValue, uint8 *pLen, uint16 offset, uint8 maxLen ){      case SIMPLEPROFILE_CHAR4_UUID:        *pLen = 1;        pValue[0] = *pAttr->pValue;        break;}
0 0