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不需要主机协议栈回复,这样连接开销小一些,在要求速度的场景,往往使用这个