iOS掃描BLE設(shè)備的方法
iOS在使用CoreBluetooth框架進(jìn)行BLE開(kāi)發(fā)時(shí)渣窜,通常作為中心設(shè)備(Master角色)存在杰刽,掃描并連接BLE從設(shè)備缀匕。
搜索的方法很簡(jiǎn)單强窖,只需要調(diào)用- (void)scanForPeripheralsWithServices:(nullable NSArray<CBUUID *> *)serviceUUIDs options:(nullable NSDictionary<NSString *, id> *)options;
接口,然后等待系統(tǒng)回調(diào)上報(bào)就可以游沿。
BLE 掃描流程
從調(diào)用iOS的scan接口饰抒,到收到系統(tǒng)回調(diào),這中間其實(shí)有下面幾步的交互:
- BLE設(shè)備端發(fā)送廣播ADV_IND
- iOS手機(jī)端收到廣播后诀黍,向該BLE設(shè)備發(fā)送SCAN_REQ
- BLE設(shè)備端收到SCAN_REQ后袋坑,發(fā)送廣播SCAN_RSP
- iOS將ADV_IND和SCAN_RSP合包后,通過(guò)系統(tǒng)回調(diào)通知調(diào)用者
如下圖所示:
按照藍(lán)牙協(xié)議眯勾,這幾個(gè)步驟是分開(kāi)的枣宫,只不過(guò)iOS底層幫我們合并了而已。下面我們考慮這幾個(gè)問(wèn)題:
- iOS收到設(shè)備端發(fā)出的ADV_IND之后吃环,是不知道還有沒(méi)有更多數(shù)據(jù)的也颤,那么SCAN_REQ的發(fā)送機(jī)制是怎樣的呢?
- iOS發(fā)出SCAN_REQ后郁轻,并不知道會(huì)不會(huì)有SCAN_RSP翅娶,那么是怎樣處理的文留?
- ADV_IND和SCAN_RSP數(shù)據(jù)是怎樣合并的?
經(jīng)過(guò)自己的測(cè)試和蘋果官方技術(shù)支持(code-level support)的溝通竭沫,初步有以下結(jié)論:
- 如果App在前臺(tái)燥翅,iOS會(huì)處于主動(dòng)搜索模式,在此情況下蜕提,iOS會(huì)盡可能的在收到ADV_IND后發(fā)送SCAN_REQ森书,這里說(shuō)盡可能的原因,是因?yàn)榘凑仗O果官方技術(shù)支持的說(shuō)法谎势,iOS會(huì)發(fā)送SCAN_REQ凛膏,但根據(jù)自己抓包顯示,有時(shí)候iOS會(huì)收到幾包ADV_IND后才會(huì)發(fā)送SCAN_REQ
- 如果App進(jìn)入后臺(tái)脏榆,iOS會(huì)進(jìn)入被動(dòng)搜索模式译柏,此時(shí),iOS會(huì)緩存SCAN_RSP姐霍,并會(huì)降低SCAN_REQ的發(fā)送頻率,即可能幾包ADV_IND后才會(huì)發(fā)送一包SCAN_REQ典唇,此時(shí)iOS會(huì)將收到的ADV_IND和緩存的SCAN_RSP合包告訴調(diào)用者镊折。
- 根據(jù)實(shí)際測(cè)試結(jié)果,發(fā)現(xiàn)App在前臺(tái)時(shí)也會(huì)有使用SCAN_RSP緩存的情況介衔。從而推測(cè)恨胚,iOS將ADV_IND和SCAN_RSP合包的機(jī)制為:
3.1 iOS收到ADV_IND
3.2 iOS發(fā)送SCAN_REQ
3.3 iOS從緩存中查找SCAN_RSP
3.4 如果有緩存,則將緩存的SCAN_RSP和ADV_IND合并通知App炎咖;如果沒(méi)有緩存赃泡,則直接將ADV_IND通知App
3.5 SCAN_RSP的緩存是有時(shí)間
由此,會(huì)產(chǎn)生一個(gè)問(wèn)題:當(dāng)設(shè)備的廣播數(shù)據(jù)發(fā)生變化(ADV_IND和SCAN_RSP都產(chǎn)生變化)乘盼,iOS可能會(huì)上報(bào)一個(gè)新的ADV_IND數(shù)據(jù)和老的SCAN_RSP數(shù)據(jù)升熊。造成數(shù)據(jù)錯(cuò)亂。但當(dāng)SCAN_RSP更新后绸栅,數(shù)據(jù)就可恢復(fù)正常级野,通常收到1-3包ADV_IND數(shù)據(jù)后可恢復(fù)正常
如:
BLE設(shè)備一直在廣播
SCAN_RSP = 3f
ADV_IND = 3f
iOS此時(shí)向App廣播的數(shù)據(jù)也是
SCAN_RSP = 3f
ADV_IND = 3f
此時(shí),BLE設(shè)備廣播發(fā)生變化粹胯,廣播數(shù)據(jù)變?yōu)?/p>
SCAN_RSP = 42
ADV_IND = 42
App在收到廣播包變化的第一個(gè)系統(tǒng)回調(diào)通常為
SCAN_RSP = 3f //老的SCAN_RSP
ADV_IND = 42 //新的ADV_IND
然后蓖柔,App通常會(huì)在收到1-3個(gè)系統(tǒng)回調(diào)后變?yōu)檎#@個(gè)取決于SCAN_RSP的更新時(shí)間风纠,所以具體什么時(shí)候數(shù)據(jù)能恢復(fù)正常是不確定的况鸣,1-3包只是經(jīng)驗(yàn)值。
所以竹观,如果你的BLE設(shè)備的廣播數(shù)據(jù)會(huì)發(fā)生變化镐捧,那么是需要考慮數(shù)據(jù)錯(cuò)亂問(wèn)題的。可以對(duì)ADV_IND+SCAN_RSP增加校驗(yàn)愤估,如果是錯(cuò)的數(shù)據(jù)就丟掉帮辟。