日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

蓝牙解析(part10):BLE ATT/GATT

發(fā)布時間:2025/3/21 编程问答 26 豆豆
生活随笔 收集整理的這篇文章主要介紹了 蓝牙解析(part10):BLE ATT/GATT 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

本部分是從各位前輩的學(xué)習(xí)經(jīng)驗中,總結(jié)過來的,希望對初學(xué)者有益。

從藍(lán)牙Spec 4.0開始,推出了低功耗(BLE)規(guī)范,BLE的協(xié)議可分為Bluetooth Application和Bluetooth Core兩大部分,而Bluetooth Core又包含BLE Controller和BLE Host兩部分,整體架構(gòu)如下圖所示。本章節(jié),先來看一下Host部分中的兩個核心協(xié)議:ATT(Attribute Protocol)和GATT(Generic Attribute Protocol).

1. 總綱

這兩個協(xié)議主要目標(biāo)是BLE,但是也可以運(yùn)行在傳統(tǒng)藍(lán)牙上(BR/EDR).

ATT提供了一種無線應(yīng)用協(xié)議,GATT基于ATT協(xié)議,相當(dāng)于ATT的framewrok層,而所有的BLE profile又基于GATT。同時ATT/GATT定義在host中,即協(xié)議棧里面, 而profiles則定義在應(yīng)用層,這樣的結(jié)構(gòu)決定了ATT/GATT要實(shí)現(xiàn)基本而common的功能實(shí)現(xiàn),而profiles來完善各具特色的具體應(yīng)用功能。

BLE分層使用這兩個協(xié)議的好處是:

?

  • 對于軟件實(shí)現(xiàn)的協(xié)議棧來說,ATT/GATT在協(xié)議棧里實(shí)現(xiàn),省去了應(yīng)用的麻煩。
  • 開發(fā)和實(shí)現(xiàn)新的BLE profile更加容易,因為不需要從頭實(shí)現(xiàn)wire protocol。
  • ATT針對BLE 設(shè)備進(jìn)行了特別的優(yōu)化:使用盡可能少的字節(jié),因此可能在存儲中使用定長結(jié)構(gòu)來生成PDU。
  • ATT/GATT的簡單意味著固件可能提供某種程度的協(xié)議支持,省去了微處理器軟件的麻煩。
  • 即使有的場景下,ATT/GATT不夠理想。也可以在L2CAP連接上實(shí)現(xiàn)平行于ATTchannel的協(xié)議。
  • ?

    2. ATT: Attribute Protocol

    該協(xié)議將數(shù)據(jù)以“Attribute(屬性)”的形式抽象出來,并提供一些方法,供遠(yuǎn)端設(shè)備(remote device)讀取、修改這些屬性的值(Attribute value)。ATT協(xié)議的唯一基礎(chǔ)是屬性。每個屬性由三個元素構(gòu)成:

    ?

  • one 16bits handle;
  • one 16bits/32bits/128bitsUUID來定義屬性的類型;
  • 確定長度的屬性值
  • ?

    在ATT中,屬性值可以是任意長度的byte數(shù)組。屬性值的實(shí)際意義依賴于UUID,而且ATT并不會檢查屬性值長度是否與給定的UUID定義一致。

    Handle是用來唯一識別屬性的數(shù)字,因為在一個BLE 設(shè)備中可能存在多個屬性具有相同的UUID。

    ATT協(xié)議本身沒有定義任何UUID。這部分工作留給了GATT和上層協(xié)議。

    和屬性相關(guān)的還有讀寫權(quán)限。讀寫權(quán)限存在屬性值里,由高層協(xié)議確定。ATT本身不會關(guān)心,也不會試圖解釋屬性值來確定權(quán)限。這部分工作也留給了GATT和上層協(xié)議。

    ATT有一些良好的特征,比如通過UUID來搜索屬性,通過handle區(qū)間范圍來獲取所有區(qū)間內(nèi)的屬性,因此client不需要提前獲得handle的值,也不需要高層協(xié)議硬編碼這些值。

    但是在特定的設(shè)備上handle的取值最好保持不變,這樣的話client能夠緩沖信息。在第一個discovery以后,client能夠使用緩沖信息,這樣能夠減少傳輸?shù)陌鼣?shù)量,也能夠節(jié)約能量。如果服務(wù)端的屬性布局已經(jīng)發(fā)生了變換,高層協(xié)議應(yīng)該能夠”暗示”client,比如固件升級。

    ATT有兩個角色,Client和Server,大多數(shù)情況下ATT協(xié)議都是純C/S架構(gòu),即server存儲屬性,client什么也不存儲,client主動發(fā)起請求讀寫server端的屬性,server被動響應(yīng)。但是服務(wù)端也有通知的能力,在服務(wù)端屬性發(fā)生變化時,server能夠通知client,這樣避免了client不停的poll。

    ATT協(xié)議不會顯式發(fā)送屬性值的長度,只能從PDU長度里面獲得。因此client最好能夠知道某種UUID類型所代表的屬性的精確結(jié)構(gòu)。

    不發(fā)送屬性值長度,是為了減少發(fā)送的字節(jié),因為LE的MTU只有23bytes。

    23bytes的MTU對于較長的屬性值來說是個麻煩。因此不得采用“read long”,”write long“這樣的操作。

    ATT是如此通用,意味著高層協(xié)議有太多工作要做。過度的自由也會帶來問題,比如:如果一個設(shè)備提供多個服務(wù)怎么辦?對每一個設(shè)備只有一個ATT handle空間,多個服務(wù)不得不共享同一份空間。

    幸運(yùn)地是,我們還有GATT,它為我們提供了屬性用法,并解除了這些限制。

    3.?GATT:Generic Attribute Profile

    ?

    GATT是所有LE頂層協(xié)議的基礎(chǔ)。它定義了怎么把一堆ATT屬性分組成為有意義的服務(wù)。
    縱向看,GATT Profile包含一個或多個GATT Services, 每個GATT service又包含一個或多個GATT Characteristics, 同時每個Characteristic又對應(yīng)一個或多個GATT Descriptors。

    3.1 GATT service

    ?

    GATT service的基礎(chǔ)是UUID值為0x2800的屬性。所有跟在這個屬性后面的屬性都屬于這個屬性定義的服務(wù),直到另一個0x2800屬性出現(xiàn)。

    比如說,一個設(shè)備里面的三個屬性布局如下:?

    ?

    HandleUUIDDescription
    0x01000x2800Service A definition
    ......Service details
    0x01500x2800Service B definition
    ......Service details
    0x03000x2800Service C definition
    ......Service details

    每一個屬性不知道它自己屬于哪個服務(wù),GATT需要根據(jù)0x2800屬性作為標(biāo)記來識別出哪個屬性屬于哪個服務(wù)。

    按照這個定義,handle值就有意義了。在上面的例子中,屬于service B的屬性handle必須位于0x0151和0x02ff之間。

    UUID 0x2800定義了primary服務(wù),

    也可以使用0x2801來定義secondary服務(wù)。

    Secondary服務(wù)表示包含于primary服務(wù)。

    然后我們怎么能知道一個服務(wù)是溫度計,智能鑰匙或者GPS?答案是通過讀取屬性值。服務(wù)屬值包含了一個UUID,通過這個UUID區(qū)分服務(wù)。

    因此,每個屬性定義事實(shí)上包含了兩個UUID,0x2800或者0x2801作為屬性UUID,另外一個屬性值里面存儲的UUID。后面這個UUID是服務(wù)ID。

    舉個例子:?

    ?

    HandleUUIDDescriptionValue
    0x01000x2800Thermometer service definitionUUID 0x1816
    ......Service details...
    0x01500x2800Service B definition0x18xx
    ......Service details...
    0x03000x2800Service C definition0x18xx
    ......Service details...

    ?

    在圖中,?thermometer service的UUID是0x1816。

    是不是感覺怪怪的?兩個UUID定義一個服務(wù)?這是GATT/ATT分層方式導(dǎo)致的后果。

    UUID0x2800被GATT用來尋找服務(wù)定義邊界。一旦找到了邊界,屬性值,也就是第二個UUID用來指定服務(wù)。這樣client能夠找到所有的服務(wù)而不需要知道服務(wù)的具體定義。

    3.2?GATT service characteristics

    每一個服務(wù)有幾個特征。特征存儲了有用的值以及權(quán)限。

    比如,一個溫度計可能有只讀的溫度特征,也可能有可讀寫的時間戳。

    HandleUUIDDescriptionValue
    0x01000x2800Thermometer service definitionUUID 0x1816
    0x01010x2803Characteristic: temperatureUUID 0x2A2B
    Value handle: 0x0102
    0x01020x2A2BTemperature value20 degrees
    0x01100x2803Characteristic: date/timeUUID 0x2A08
    Value handle: 0x0111
    0x01110x2A08Date/Time1/1/1980 12:00

    每一個服務(wù)可能有幾個特征,這些特征也是通過路碑屬性來發(fā)現(xiàn)的。

    主特征的UUID是0x2803,然后主特征的屬性值用來定義特征。比如圖中 0x2803用來找到特征,0x2A2B用來找到特征包含的信息。

    每一個特征至少包含兩個屬性,主屬性0x2803和真正的值屬性。主屬性知道屬性值的handle和UUID。這能夠進(jìn)行一定程度的交叉檢測。

    特征值的真正格式是由UUID決定的。因此,如果客戶端知道如何解釋UUID為 0x2A08的特征值,就能夠從包含這個特征任何服務(wù)里面讀取日期和時間。當(dāng)然如果客戶端不知道如何解釋這個UUID的話,也可以選擇忽略。

    3.3?Characteristic descriptors

    ?除了特征值,我們也可以為每個特征增加更多的屬性。在GATT語法里,這個額外的屬性成為描述符。

    ?舉個例子子,我們也許需要指定溫度的計量單位。?

    ?

    HandleUUIDDescriptionValue
    0x01000x2800Thermometer service definitionUUID 0x1816
    0x01010x2803Characteristic: temperatureUUID 0x2A2B
    Value handle: 0x0102
    0x01020x2A2BTemperature value20 degrees
    0x01040x2A1FDescriptor: unitCelsius
    0x01100x2803Characteristic: date/timeUUID 0x2A08
    Value handle: 0x0111
    0x01110x2A08Date/Time1/1/1980 12:00

    GATT知道handle 0x0104是特征0x0101的描述符,因為:

    1, 他不是特征的值,因為特征值的handle應(yīng)該是0x0102

    2, 他的handle落在了0x0103-0x010f之間,因此也不屬于下一個特征。

    描述符值的意義依賴于屬性UUID。例子中,描述符的UUID是0x2A1F,客戶端如果不能識別這個UUId,他可以選擇忽略。這樣可以實(shí)現(xiàn)向下兼容。

    每個服務(wù)可能定義自己的描述符,但是GATT已經(jīng)定義了能夠覆蓋大多數(shù)情況的標(biāo)準(zhǔn)描述符,比如:

    數(shù)值格式和表示;

    人類可讀的描述;

    合理范圍擴(kuò)展屬性等等。其中特別重要的描述符是client characteristic configuration。

    Client Characteristic Configurationdescriptor

    Client Characteristic Configurationdescriptor的UUID是0x2902,具有一個16bit的可讀寫值,作為一個bitmap來使用。

    這個屬性被server用來存儲和代表每個已經(jīng)綁定的client的獨(dú)立實(shí)例,每個client只能看到它自己的拷貝。

    前兩個bit被GATT用來定義通知和暗示。其他bit暫時未使用。

    通過設(shè)置CCC,client能夠讓server在特征發(fā)生改變時得到通知。比如包含了CCC的屬性布局如下:?

    ?

    HandleUUIDDescriptionValue
    0x01000x2800Thermometer service definitionUUID 0x1816
    0x01010x2803Characteristic: temperatureUUID 0x2A2B
    Value handle: 0x0102
    0x01020x2A2BTemperature value20 degrees
    0x01040x2A1FDescriptor: unitCelsius
    0x01050x2902Client characteristic configuration descriptor0x0000
    0x01100x2803Characteristic: date/timeUUID 0x2A08
    Value handle: 0x0111
    0x01110x2A08Date/Time1/1/1980 12:00

    ?

    3.4 Service discovery in Low Energy

    因為GATT中所有的服務(wù)細(xì)節(jié)通過ATT來描述,所以不需要像BR/EDR那樣設(shè)置專門的服務(wù)發(fā)現(xiàn)協(xié)議。ATT負(fù)責(zé)一切:發(fā)現(xiàn)服務(wù),查找特征,讀寫值等等。

    3.5?GATT and vanilla Bluetooth

    GATT也可以工作在傳統(tǒng)藍(lán)牙上面,但是規(guī)范規(guī)定傳統(tǒng)藍(lán)牙仍然使用SDP發(fā)送服務(wù),即使通過GATT來進(jìn)行實(shí)際數(shù)據(jù)交換。

    這樣的好處是在雙模設(shè)備上不用設(shè)置標(biāo)識來識別LE-only服務(wù)。如果一個服務(wù)只能通過GATT發(fā)現(xiàn),就是LE-only。如果能夠通過GATT和SDP發(fā)現(xiàn),就是雙模。

    ???????? 如果一個profile通過GATT來進(jìn)行數(shù)據(jù)交換,并且是雙模的,它必須首先發(fā)布SDP record。然后這個服務(wù)通過SDP來發(fā)現(xiàn),然后通過GATT來查找特征。

    ???????? 當(dāng)然,現(xiàn)在沒有雙模的profile。以前的profile是BR/EDR only,并且沒有適配到GATT;LE-only只有LE。

    ???????? 如果想要測試GATT而沒有LE硬件,可以修改藍(lán)牙協(xié)議棧來使BR/EDR可以進(jìn)行GATT discovery。這是規(guī)范不運(yùn)行的,但是開發(fā)者可以。

    3.6 Notification and Indication

    通知和暗示使得server可以發(fā)送消息給client。這樣客戶端不需要poll server來獲取新的數(shù)據(jù)。

    另外,典型的GATT server是“小的“外設(shè),像非常需要節(jié)能的傳感器之類。因此,外設(shè)的LE 設(shè)備不能發(fā)起連接。那么通知怎么發(fā)送呢?

    在BLE協(xié)議棧,如果server有數(shù)據(jù)發(fā)送,它就進(jìn)入廣播模式,并且發(fā)送一些信號。每個profile定義了廣播時長和頻率。時長和頻率應(yīng)該根據(jù)使用場景進(jìn)行了節(jié)能和及時性的權(quán)衡。

    處于中心模式的設(shè)備隨時處于監(jiān)聽模式。當(dāng)它監(jiān)聽到廣播后,如果發(fā)現(xiàn)廣播設(shè)備是認(rèn)識的(配對過或者白名單中的),就會向外設(shè)發(fā)起連接。

    連接建立以后,GATT通信能夠進(jìn)行,通知得以發(fā)送。所以典型的序列是:1,server發(fā)送廣播 2,client連接 3,server通知

    如果沒有更多的數(shù)據(jù)發(fā)送,server和client就會超時斷開。最佳超時時間依賴于用例;如果服務(wù)不會頻繁發(fā)送通知并且沒有實(shí)時性要求的話,可以立馬斷開。因為BLE重連是非??斓?。

    典型的GATT server是外設(shè)設(shè)備,但是不是必須的。也可以外設(shè)做client,center做server。在這種場景下,client想要讀寫數(shù)據(jù)的時候,需要先進(jìn)入廣播模式。

    總結(jié)

    以上是生活随笔為你收集整理的蓝牙解析(part10):BLE ATT/GATT的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。