BLE主机的连接到收发数据的过程

BLE的连接过程,一般的典型过程是按照 "扫描>连接>服务发现>使能cccd>发送接收数据"

1,扫描(本结同样适用observer)

1.1 扫描相关的参数

//扫描窗口
//设置扫描窗口,单位0.625ms,扫描窗口要小于等于扫描间隔,默认为16
GAP_SetParamValue(TGAP_DISC_SCAN_WIND, 32);

//扫描间隔,需要>=扫描窗口
//设置扫描间隔,单位0.625ms,默认为16
GAP_SetParamValue(TGAP_DISC_SCAN_INT, 32);

//扫描持续时间
//设置扫描的超时时间,单位0.625ms,默认是16384,10.24s
//可以设置为0,为永远不超时,需要用户手动关闭扫描
GAP_SetParamValue( TGAP_DISC_SCAN, DEFAULT_SCAN_DURATION );

//开关同mac地址过滤
GAP_SetParamValue(TGAP_FILTER_ADV_REPORTS,FALSE);

1.2 扫描事件和接口

//启动扫描
//主动扫描的意思是,扫描时候发scan_request,可以获取到scan_rspone数据
bStatus_t GAPRole_CentralStartDiscovery( uint8_t mode, uint8_t activeScan, uint8_t whiteList );
//结束扫描
//执行后后会产生事件: GAP_DEVICE_DISCOVERY_EVENT
bStatus_t GAPRole_CentralCancelDiscovery( void );

1.3 得到扫描到的数据

这里的扫描,就是主机端开启扫描后,去得到从机的广播数据,能够得到的数据有:

  • MAC地址
  • 31字节广播或者扫描回复数据(名称,自定义信息都在这里面,通常需要做解析,通过eventType判断是广播还是扫描回复包)
  • 信号强度
    在如下
扫描数据回掉通过结构体给出来:
typedef struct
{
    tmos_event_hdr_t hdr;             //!< GAP_MSG_EVENT and status
    uint8_t opcode;                   //!< GAP_DEVICE_INFO_EVENT
    uint8_t eventType;                //!< Advertisement Type: @ref GAP_ADVERTISEMENT_REPORT_TYPE_DEFINES
    uint8_t addrType;                 //!< address type: @ref GAP_ADDR_TYPE_DEFINES
    uint8_t addr[B_ADDR_LEN];         //!< Address of the advertisement or SCAN_RSP
    int8_t rssi;                      //!< Advertisement or SCAN_RSP RSSI
    uint8_t dataLen;                  //!< Length (in bytes) of the data field (evtData)
    uint8_t *pEvtData;                //!< Data field of advertisement or SCAN_RSP
} gapDeviceInfoEvent_t;

//在事件 GAP_DEVICE_INFO_EVENT:下我们可以得到相关数据
//比如我们得到mac地址和rssi 以及广播内容
case GAP_DEVICE_INFO_EVENT:
            //mac地址          : pEvent->deviceInfo.addr 
            //rssi             : pEvent->deviceInfo.rssi
            //扫描到的广播内容  : pEvent->deviceInfo.pEvtData
            //扫描的广播长度    : pEvent->deviceInfo.dataLen

在扫描时候,我们既然可以得到这些数据,我们就可以根据这些来决定哪些从机是我们需要连接的从机,比如通过名称,或者自定义的信息

2,连接

这里的连接,实际上是根据上面扫描过程中,得到的MAC地址以及MAC地址类型进行连接

3,service和characteristic的发现

连上以后,要进行相关的service和characteristic发现,来得到行营的GATT handle,因为通信时候,要根据这些handle来收发数据,类似以太网的TCP/UDP 端口号之类的

4,使能cccd(开启notify)

这里的使能CCCD, 是当从机的characteristic具备notify/indicate主动发数据给主机的属性时候,这时候主机端往往需要主动去使能这些,否则从机不能够主动发送(当然从机也可以在本机主动开启)

5,接收或者发送数据

write/write_no_respone

通常是主机对从机的操作,主机给从机发数据一般用这个命令,这一步依赖上面查到的gatt handle,当然,如果是事先知道这些handle,是可以直接发送,而不需要进行service和characteristic的发现
其中write_no_respone 不需要从机协议栈回复,这样连接开销小一些,在要求速度的场景,往往使用这个.

read

通常是主机对从机的操作,这一步依赖上面查到的gatt handle,当然,如果是事先知道这些handle,是可以直接发送,而不需要进行service和characteristic的发现

notify /indicate

通常这是从机对主机的操作,从机给主机发送数据一般用这个命令,由于主机是被动接收,所以接收时候往往是根据回掉函数得到相应的数据
但是notify /indicate 往往需要事先使能cccd从机那边才能够发送出来数据,所以根据实际情况,来执行 使能cccd(开启notify)
根据上面查到的characteristic value的gatt handle 用wrtie
其中notify不需要主机协议栈回复,这样连接开销小一些,在要求速度的场景,往往使用这个