天天看点

BLE协议栈之Central事件慢慢谈

 BLE协议栈Central 工程中与广播连接建立的事件

        最近在改写BLE协议栈,需要实现实时发现周边从设备,并建立连接,获取RSSI的功能,没什么难度,但着实将各个事件好好看了一遍。曾经看到一位大神说相同的任务使用事件触发方式,不同的任务使用消息传递方式。冥冥之中突然来了感觉~

       BLE进行广播和建立连接的事件主要实现是在simpleBLECentralEventCB的回调函数中:

       所有使用到的变量都在联合体gapCentralRoleEvent_t中:

typedef union
{
  gapEventHdr_t             gap;                //!< GAP_MSG_EVENT and status.
  gapDeviceInitDoneEvent_t  initDone;           //!< GAP initialization done. 本机信息
  gapDeviceInfoEvent_t deviceInfo;//!< Discovery device information event structure. 从机信息
  gapDevDiscEvent_t      discCmpl;//!< Discovery complete event structure.从机信息(全部)
  gapEstLinkReqEvent_t      linkCmpl;           //!< Link complete event structure.
  gapLinkUpdateEvent_t      linkUpdate;         //!< Link update event structure.
  gapTerminateLinkEvent_t   linkTerminate;      //!< Link terminated event structure.
} gapCentralRoleEvent_t;      // central.h	
           

1 板级初始化事件:GAP_DEVICE_INIT_DONE_EVENT

case GAP_DEVICE_INIT_DONE_EVENT:  // 初始化    //  是本机GAP层的初始化信息  在运行到GAPCentralRole_StartDevice函数被回调
{   
   LCD_WRITE_STRING( bdAddr2Str( pEvent->initDone.devAddr ),  HAL_LCD_LINE_2 );
}
break;
           

详解:

作用:进行GAP层的初始化
详解:

/**
 * GAP_DEVICE_INIT_DONE_EVENT message format.  This message is sent to the
 * app when the Device Initialization is done [initiated by calling
 * GAP_DeviceInit()].    gap.h
 */
typedef struct
{
  osal_event_hdr_t  hdr;              //!< GAP_MSG_EVENT and status
  uint8 opcode;                       //!< GAP_DEVICE_INIT_DONE_EVENT
  uint8 devAddr[B_ADDR_LEN];          //!< Device's BD_ADDR  本机的MAC地址
  uint16 dataPktLen;                  //!< HC_LE_Data_Packet_Length    初始化长度为27 
  uint8 numDataPkts;                  //!< HC_Total_Num_LE_Data_Packets  初始化为4
} gapDeviceInitDoneEvent_t;
           

2 搜索从机事件(每搜到一个从机进入一次):GAP_DEVICE_INFO_EVENT

case GAP_DEVICE_INFO_EVENT:    //过程量  从机的广播数据  搜索到之后添加到从机列表中
      {
        char temprssiarg[4]={0};
        // if filtering device discovery results based on service UUID
        if ( DEFAULT_DEV_DISC_BY_SVC_UUID == TRUE )
        {
          if ( simpleBLEFindSvcUuid( SIMPLEPROFILE_SERV_UUID,
                                     pEvent->deviceInfo.pEvtData,
                                     pEvent->deviceInfo.dataLen ) )
          {  
           simpleBLEAddDeviceInfo( pEvent->deviceInfo.addr, pEvent->deviceInfo.addrType );
          
          }
        }
      }
           

作用:  每搜索到一个从设备时,都会进入该事件,并使用simpleBLEAddDeviceInfo加入到扫描结果列表中,deviceInfo.addr中储存着当前正被扫描到从设备地址,扫描从机的数量(simpleBLEScanRes)在simpleBLEAddDeviceInfo中增加!

详解:

**
 * GAP_DEVICE_INFO_EVENT message format.  This message is sent to the
 * app during a Device Discovery Request, when a new advertisement or scan
 * response is received.  //gap.h
 */
typedef struct
{
  osal_event_hdr_t  hdr;    //!< GAP_MSG_EVENT and status
  uint8 opcode;             //!< GAP_DEVICE_INFO_EVENT
  uint8 eventType; //!< Advertisement Type: @ref GAP_ADVERTISEMENT_TYPE_DEFINES
  uint8 addrType;           //!< address type: @ref GAP_ADDR_TYPE_DEFINES
  uint8 addr[B_ADDR_LEN];   //!< Address of the advertisement or SCAN_RSP  从机MAC地址
  int8  rssi;                //!< Advertisement or SCAN_RSP RSSI    从机RSSI值
  uint8 dataLen;            //!< Length (in bytes) of the data field (evtData)
  uint8 *pEvtData;          //!< Data field of advertisement or SCAN_RSP
} gapDeviceInfoEvent_t;
           

3 搜索从机事件(搜索完毕时进入一次):GAP_DEVICE_DISCOVERY_EVENT

case GAP_DEVICE_DISCOVERY_EVENT:       //结果量             // 搜索周边广播从机事件  显示搜索结果
      {
        // discovery complete
        simpleBLEScanning = FALSE;
        // if not filtering device discovery results based on service UUID
        if ( DEFAULT_DEV_DISC_BY_SVC_UUID == FALSE )
        {
          // Copy results
          simpleBLEScanRes = pEvent->discCmpl.numDevs;
          osal_memcpy( simpleBLEDevList, pEvent->discCmpl.pDevList,
                       (sizeof( gapDevRec_t ) * pEvent->discCmpl.numDevs) );
        }     
         char temp_simpleBLEScanRes[10]="Find :  \n";
        
        FineDeviceNum=FindDeviceNum=simpleBLEScanRes;//***************************************************************** 扫描的数量
        
         temp_simpleBLEScanRes[8] = simpleBLEScanRes+'0';
        
         Uart0Send_String(temp_simpleBLEScanRes,10);//***********************************        
        /******************************************************************************************************/

        // initialize scan index to last device
        simpleBLEScanIdx = simpleBLEScanRes;
        IsPeriodicStart=1;  
          

      }
      break;
           

作用:程序运行到这一步可以知道当前有多少个已经被扫描到的从设备,且它们的地址被保存到simpleBLEDevList里。

搜索结果列表 // Scan result list    

static gapDevRec_t simpleBLEDevList[DEFAULT_MAX_SCAN_RES]; // 扫描结果列表

详解:

/**
 * Type of device discovery (Scan) to perform.
 */
typedef struct
{
  uint8 eventType;
  //!< Indicates advertising event type used by the advertiser: @ref GAP_ADVERTISEMENT_TYPE_DEFINES
  uint8 addrType;         //!< Address Type: @ref GAP_ADDR_TYPE_DEFINES
  uint8 addr[B_ADDR_LEN]; //!< Device's Address  // 储存着当前搜索到的设备地址  最大可见扫描数量8
} gapDevRec_t;        搜索结果结构体
/**
 * GAP_DEVICE_DISCOVERY_EVENT message format. This message is sent to the
 * Application after a scan is performed.
 */
typedef struct
{
  osal_event_hdr_t  hdr; //!< GAP_MSG_EVENT and status
  uint8 opcode;          //!< GAP_DEVICE_DISCOVERY_EVENT
  uint8 numDevs;         //!< Number of devices found during scan
  gapDevRec_t *pDevList; //!< array of device records
} gapDevDiscEvent_t;     搜索结果事件结构体
           

Note: 需要知道一个从设备的RSSI值,只需知道从设备的MAC地址信息在simpleBLEDevList中即可!

4 连接建立事件:GAP_LINK_ESTABLISHED_EVENT

本事件里开起一个定时器,事件连接超时断开!

case GAP_LINK_ESTABLISHED_EVENT:
      {
        if ( pEvent->gap.hdr.status == SUCCESS )
        {          
          simpleBLEState = BLE_STATE_CONNECTED;
          simpleBLEConnHandle = pEvent->linkCmpl.connectionHandle;
          simpleBLEProcedureInProgress = TRUE;    

          // If service discovery not performed initiate service discovery
          if ( simpleBLECharHdl == 0 )
          {
            osal_start_timerEx( simpleBLETaskId, START_DISCOVERY_EVT, DEFAULT_SVC_DISCOVERY_DELAY );
          }
      //    SerialPrintString("Connected: ");
         // Uart0Send_String( bdAddr2Str( pEvent->linkCmpl.devAddr ), sizeof(bdAddr2Str( pEvent->linkCmpl.devAddr ))); 
        // for(int i=0;i<10000;i++);
          for(int i=0;i<10000;i++);
          LCD_WRITE_STRING( bdAddr2Str( pEvent->linkCmpl.devAddr ), HAL_LCD_LINE_2 );  
         for(int i=0;i<10000;i++);
       // Uart0Send_String("12222",5);
          //LCD_WRITE_STRING( "Connected", HAL_LCD_LINE_1 );
    /***********   2015年1月8日 不间断的搜寻周围的从设备 ************** 建立连接后读取当前的RSSI 值***********************************************************************************************/  
         
     if ( simpleBLEState == BLE_STATE_CONNECTED )
     {
       if ( !simpleBLERssi )
       {
        simpleBLERssi = TRUE;
        GAPCentralRole_StartRssi( simpleBLEConnHandle, DEFAULT_RSSI_PERIOD );
       }
       else
       {
        simpleBLERssi = FALSE;
        GAPCentralRole_CancelRssi( simpleBLEConnHandle );        
        LCD_WRITE_STRING( "RSSI Cancelled", HAL_LCD_LINE_1 );
         // SerialPrintString("RSSI Cancelled\r\n");
       }
     }
    /****************************************************************************************************************/ 
        }
        else
        {
          simpleBLEState = BLE_STATE_IDLE;
          simpleBLEConnHandle = GAP_CONNHANDLE_INIT;
          simpleBLERssi = FALSE;
          simpleBLEDiscState = BLE_DISC_STATE_IDLE;
          
          LCD_WRITE_STRING( "Connect Failed", HAL_LCD_LINE_1 );
       //   SerialPrintString("Connect Failed: ");
          LCD_WRITE_STRING_VALUE( "Reason:", pEvent->gap.hdr.status, 10, HAL_LCD_LINE_2 );
          
          
         GAPCentralRole_CancelRssi( simpleBLEConnHandle );       
         /***********   2015年1月8日 不间断的搜寻周围的从设备 ************** 连接错误 主机从新进行搜索***********************************************************************************************/   
              
          simpleBLEScanning = TRUE;   
        simpleBLEScanRes = 0;

        LCD_WRITE_STRING( "Discovering...", HAL_LCD_LINE_1 );
        LCD_WRITE_STRING( "", HAL_LCD_LINE_2 );

        GAPCentralRole_StartDiscovery( DEFAULT_DISCOVERY_MODE,
                                       DEFAULT_DISCOVERY_ACTIVE_SCAN,
                                       DEFAULT_DISCOVERY_WHITE_LIST );
        /*****************************************************************************************************/
       //   SerialPrintValue("Reason:",  pEvent->gap.hdr.status,10);
        }
      }
      break;
           
详解:
/**
 * GAP_LINK_ESTABLISHED_EVENT message format.  This message is sent to the app
 * when the link request is complete.<BR>
 * <BR>
 * For an Observer, this message is sent to complete the Establish Link Request.<BR>
 * For a Peripheral, this message is sent to indicate that a link has been created.
 */
typedef struct
{
  osal_event_hdr_t  hdr;     //!< GAP_MSG_EVENT and status
  uint8 opcode;              //!< GAP_LINK_ESTABLISHED_EVENT
  uint8 devAddrType;         //!< Device address type: @ref GAP_ADDR_TYPE_DEFINES
  uint8 devAddr[B_ADDR_LEN]; //!< Device address of link
  uint16 connectionHandle;   //!< Connection Handle from controller used to ref the device
  uint16 connInterval;       //!< Connection Interval
  uint16 connLatency;        //!< Conenction Latency
  uint16 connTimeout;        //!< Connection Timeout
  uint8 clockAccuracy;       //!< Clock Accuracy
} gapEstLinkReqEvent_t;
           

5 连接超时事件 : GAP_LINK_TERMINATED_EVENT

case GAP_LINK_TERMINATED_EVENT:
      {
        simpleBLEState = BLE_STATE_IDLE;
        simpleBLEConnHandle = GAP_CONNHANDLE_INIT;
        simpleBLERssi = FALSE;
        simpleBLEDiscState = BLE_DISC_STATE_IDLE;
        simpleBLECharHdl = 0;
        simpleBLEProcedureInProgress = FALSE;
          
        LCD_WRITE_STRING( "Disconnected", HAL_LCD_LINE_1 );
     //   SerialPrintString("Disconnected: ");
        LCD_WRITE_STRING_VALUE( "Reason:", pEvent->linkTerminate.reason,
                                10, HAL_LCD_LINE_2 );
        
      
     // SerialPrintValue("Reason:",  pEvent->linkTerminate.reason,10);
      }