BLE通信由兩種設(shè)備類型構(gòu)成—— Client和Server。
Server提供數(shù)據(jù)服務(wù),所以一般來說設(shè)備是Server,手機(jī)是Client。Server和Client通過ATT PDU進(jìn)行交互,Server通過characteristic對數(shù)據(jù)進(jìn)行封裝。多個(gè)characteristic組成一個(gè)Service,一個(gè)Service是一個(gè)獨(dú)立的服務(wù)單元,或者說service是一個(gè)基本的BLE應(yīng)用。如果某個(gè)service是一個(gè)藍(lán)牙聯(lián)盟定義的標(biāo)準(zhǔn)服務(wù),也可以稱其為profile,比如HID/心率計(jì)/體溫計(jì)/血糖儀等,都是標(biāo)準(zhǔn)藍(lán)牙服務(wù),因此都有相應(yīng)的profile規(guī)格書。
一. characteristic
一個(gè)characteristic包含三種條目:characteristic聲明,characteristic的值以及characteristic的描述符(可以有多個(gè)描述符):
1.1 Characteristic declaration
就是每個(gè)characteristic的分界符。解析時(shí)一旦遇到characteristicdeclaration,就可以認(rèn)為接下來又是一個(gè)新的characteristic了,同時(shí)characteristic declaration還將包含value的讀寫屬性等。
1.2 Characteristic value
就是數(shù)據(jù)的值了,這個(gè)比較好理解就不再說了。
1.3 Characteristic descriptor
就是數(shù)據(jù)的額外信息。比如溫度的單位是什么,數(shù)據(jù)是用小數(shù)表示還是百分比表示等之類的數(shù)據(jù)描述信息。CCCD是一種特殊的characteristicdescriptor,當(dāng)characteristic具有notify或者indicate操作功能時(shí),那么必須為其添加相應(yīng)CCCD,以方便client來使能或者禁止notify或者indicate功能。
不管是characteristic declaration,characteristic value還是characteristic descriptor,實(shí)現(xiàn)的時(shí)候,我們都是用attribute來表達(dá)的,也就是說,他們每一個(gè)都是一個(gè)attribute,attribute可以用下圖來表示:
二. Attribute
2.1 Attribute handle
Attribute句柄。Client要訪問Server的Attribute,都是通過這個(gè)句柄來訪問的,也就是說ATT PDU一般都包含handle的值。用戶在軟件代碼添加characteristic的時(shí)候,系統(tǒng)會(huì)自動(dòng)按順序地為相關(guān)attribute生成句柄。
2.2 Attribute type
Attribute類型。在BLE中我們使用UUID來定義數(shù)據(jù)的類型,UUID是128 bit的,所以我們有足夠的UUID來表達(dá)萬事萬物。其中有一個(gè)UUID非常特殊,它被藍(lán)牙聯(lián)盟采用為官方UUID,這個(gè)UUID如下所示:0000xxxx-0000-1000-8000-00805F9B34FB, 由于這個(gè)UUID眾所周知,藍(lán)牙聯(lián)盟將自己定義的attribute或者數(shù)據(jù)只用16bit UUID來表示,比如0x1234,其實(shí)它也是128bit,完整表示為:
00001234-0000-1000-8000-00805F9B34FB = 16 bit UUID 0x1234
Attribute type一般是由service和characteristic規(guī)格來定義,站在藍(lán)牙協(xié)議棧角度來看,ATT層定義了一個(gè)通信的基本框架,數(shù)據(jù)的基本結(jié)構(gòu),以及通信的指令,而GATT層就是前文所述的service和characteristic,GATT層用來賦予每個(gè)數(shù)據(jù)一個(gè)具體的內(nèi)涵,讓數(shù)據(jù)變得有結(jié)構(gòu)和意義。換句話說,沒有GATT層,低功耗藍(lán)牙也可以通信起來,但會(huì)產(chǎn)生兼容性問題以及通信的低效率。
2.3 Attribute value
就是數(shù)據(jù)真正的值,0到512字節(jié)長。
2.4 Attribute permissions
Attribute的權(quán)限屬性,權(quán)限屬性不會(huì)直接在空中包中體現(xiàn),而是隱含在ATT命令的操作結(jié)果中。目前主要有如下四種權(quán)限屬性:
●Open,直接可以讀或者寫
●No Access,禁止讀或者寫
●Authentication,需要配對才能讀或者寫,由于配對有多種類型,因此authentication又衍生多種子類型,比如帶不帶MITM,有沒有LESC
●Authorization,跟open一樣,不過server返回attribute的值之前需要應(yīng)用先授權(quán),也就是說應(yīng)用可以在回調(diào)函數(shù)里面去修改讀或者寫的原始值。
●Signed,簽名后才能讀或者寫,這個(gè)用得比較少。
Client和Server之間是通過ATT PDU來通信的,ATT PDU主要包括4類:讀,寫,notify和indicate。如果一個(gè)命令需要response,那么會(huì)在相應(yīng)命令后面加上request;如果一個(gè)命令只需要ACK而不需要response,那么它的后面就不會(huì)帶request。這里要特別強(qiáng)調(diào)一點(diǎn),BLE所有命令都是“必達(dá)”的,也就是說每個(gè)命令發(fā)出去之后,會(huì)立馬等ACK信息,如果收到了ACK包,發(fā)起方認(rèn)為命令完成;否則發(fā)起方會(huì)一直重傳該命令直到超時(shí)導(dǎo)致BLE連接斷開。換句話說,只要你的BLE沒有斷開,那么你之前發(fā)送的數(shù)據(jù)包,不管它是用什么ATT PDU來發(fā)送的,它肯定被對方收到了。我估計(jì)很多人對此會(huì)產(chǎn)生疑問,因?yàn)樗麄兘?jīng)常碰到丟包的情況,其實(shí)大家經(jīng)常碰到的“丟包”,不是空中把包丟了或者包在空中被干擾了,而是大家發(fā)送的代碼寫得有問題,導(dǎo)致你要發(fā)送的包沒有被安全送達(dá)到協(xié)議棧射頻FIFO中,所以以后大家碰到丟包情況,請先檢查你的代碼,保證你的數(shù)據(jù)包正確完整安全地送達(dá)到協(xié)議棧射頻FIFO中,只要數(shù)據(jù)包放到了協(xié)議棧射頻FIFO中,藍(lán)牙協(xié)議棧就能保證該數(shù)據(jù)包“必達(dá)”對方。既然每個(gè)ATT命令都必達(dá)對方,那么還需要request做什么?如果一個(gè)命令帶有request后綴,那么發(fā)起方就可以收到命令的response包,這個(gè)response包在應(yīng)用層是有回調(diào)事件的,而前述的ACK包在應(yīng)用層是沒有回調(diào)事件的。所以采用request/response方式,應(yīng)用層可以按順序地發(fā)送一些數(shù)據(jù)包,這個(gè)在很多應(yīng)用場合是非常有用的。相反,如果你對應(yīng)用層數(shù)據(jù)包的順序沒有要求,那么就可以不使用request/response形式。另外Request/response有一個(gè)副作用:大大降低通信的吞吐率,因?yàn)閞equest/response必須在不同的連接間隔中出現(xiàn),也就是說,你在間隔1中發(fā)送了一個(gè)request命令,那么response包必須在間隔2或者稍后間隔中回復(fù),而不能在間隔1中回復(fù),這就導(dǎo)致兩個(gè)連接間隔最多只能發(fā)一個(gè)數(shù)據(jù)包,而不帶request后綴的ATT命令就沒有這個(gè)問題,在同一個(gè)連接間隔中,你可以同時(shí)發(fā)多個(gè)數(shù)據(jù)包,這樣將大大提高數(shù)據(jù)的吞吐率。
常用的帶request的命令:所有read命令,writerequest,indication等,而常用的不帶request的命令有write command,notification等。