什麼是藍牙service和characteristic?如何理解藍牙profile? ATT和GATT二者如何區分?什麼是attribute? attribute和characteristic的區別是什麼?藍牙的互聯互通爲何可以作的這麼成功?數據庫
本文除了闡述上述問題 ,並重點闡述藍牙協議棧中的ATT層和GATT層。瀏覽器
低功耗藍牙協議棧構架結構:安全
如圖所示,ATT和GATT是藍牙協議棧最重要的兩層,也是藍牙應用開發者打交道最多的兩層,用戶開發應用程序或者說service/profile的時候,調用的都是GATT API,而GATT又調用ATT API。在講解ATT 和 GATT以前 。咱們先看一下藍牙核心規範中一個重要概念:Client/Server (客戶端/服務端)架構。服務器
BLE client/server(c/s)架構架構
BLE採用了client/server (c/s)架構來進行數據交互,C/S架構是一種很是常見的架構,在咱們身邊隨處可見,好比咱們常用的瀏覽器和服務器也是一種C/S架構 ,這其中瀏覽器都是客戶端client ,服務器是服務端server,server好比淘寶服務器,提供商品信息,廣告,社交等服務,而瀏覽器就是客戶端,好比微軟的IE ,就能夠用來請求這些服務,並使用server提供的服務。BLE與此類似,通常而言,設備提供服務,所以設備時server,手機使用設備提供的服務,所以手機就是client。好比藍牙體溫計,它能夠提供 "體溫" 數據服務,所以是一個server,而手機則能夠請求 "體溫" 數據以顯示在手機上,所以手機是一個 client.框架
服務是以數據爲載體的,因此說server提供服務其實就是提供各類有價值的數據。函數
圖一: C/S架構spa
客戶端要訪問一個數據,就發送一個request/請求(其實就是一條命令或者PDU),服務端再把數據返回 給 客戶端(一條response/響應命令或者PDU),這就是 C/S架構。翻譯
ATT3d
講解以前咱們先講解attribute,那麼什麼是attribute? 其實就是一條條的數據。前面說過,每一個藍牙設備就是來提供服務的,而服務就是衆多數據的集合,這個集合能夠稱爲數據庫,數據庫裏面每個條目都是一個attribute。因此咱們把attribute翻譯爲數據條目。你們能夠把藍牙設備 想象稱爲一個表格,表格裏面每一行就是一個attribute。attribute能夠用下圖來表示:
因爲這個UUID衆所周知,藍牙 聯盟將本身定義的attribute或者數據只用16bit UUID來表示,好比0x1234,其實他也是128bit,完整表示爲:
Attribute type通常是由service和characteristic規格來定義,站在藍牙協議棧角度來看,ATT層定義了一個通訊的基本框架,數據的基本結構,以及通訊的指令,而GATT層就是定義serveice和characteristic,GATT層用來賦予每一個數據一個具體的含義,讓數據變得有及結構和意義。換句話說,沒有GATT層 ,低功耗藍牙也能夠通訊起來,可是會產生兼容性問題以及通訊效率低。
一個應用全部的 attribute組成一個database,也稱爲attribute table,一個attribute table示例以下 所示:
上圖:原始attribute數據庫(這個表格不能算是 原始attribute,由於它已經把bin數據 轉成字符了,你們能夠 把相關字符都當作bin數據,就當作原始attribute表格)。
設備支持的服務不一樣,attribute table就不一樣。這裏說明一下,當你添加,修改或者刪除服務時,那麼attribute table就會變,attribute table變了,它佔用的RAM空間就會變。
ATT,全稱attribute protocol(數據交互協議)。說到底,ATT是由 一羣ATT命令組成,就是上文 所述的request(請求)和response(響應)命令。ATT也是藍牙空口包中的最上層,也就是說,ATT就是你們對藍牙數據包進行分析的最多的地方。
ATT命令,正式稱謂ATT PDU (Protocol Data Unit,協議數據交互單元)包括4類:讀,寫,notify(通知)和 indicate(指示)。這些命令又能夠分紅兩種:若是它須要response,那麼會在相應命令後面加上request。相反,若是它只是須要ACK而不須要response,那麼它 的後面就不會帶request。這裏要特別強調 一點,ATT全部命令都是 "必達" 的。也就是說每一個命令發出去之後,就會立馬等ACK信息,若是收到ACK包,發送方認爲命令完成;不然發送方一直重發該命令到致使BLE鏈接斷開。換句話說,只要你的BLE鏈接沒有斷開,那麼 你以前發送的數據包,無論他是用什麼ATT PDU來發送的,它確定被對方收到了。
有時候常常會出現一種狀況,你們有時候會遇見 " 丟包 ",其實不是在空中丟包或者被幹擾了 ,而是咱們 的 發送代碼寫的有問題,致使包沒有被安全的送達到協議棧射頻 FIFO中,從而 出現所謂的 " 丟包 "。
既然每一個ATT命令都必達對方,那麼還須要request類型的命令作什麼?
若是一個命令帶有request後綴,那麼發起方就能夠收到命令的response包,這個response包在應用層是有回調事件的,而前述的ACK包在應用層是沒有回調事件的。換句話說,不帶request的命令,雖然協議棧底層確保了該命令必達對方,但應用層其實並不知道(私有實現方法除外),當你須要實現一個通訊序列的時候,這種命令就顯得不足了。而採用request/response方式的命令時,request命令發出去以後,必須等到相應的response命令回覆才能進行下一步操做,好比發送下一個request命令,這樣應用層能夠嚴格按照規定邏輯執行一系列的操做,這個在不少應用場合是很是有用的。Request/response命令對還有一個反作用:大大下降通訊的有效速率(吞吐率),由於request/response命令必須在不一樣的鏈接間隔中出現,也就是說,你在間隔1中發送了一個request命令,那麼response包必須在間隔2或者稍後間隔中回覆,而不能在間隔1中回覆,這就致使一個數據包的發送須要跨兩個鏈接間隔甚至更多。而不帶request後綴的ATT命令就沒有這個限制,ACK能夠在同一個鏈接間隔中回覆,這樣一個鏈接間隔中能夠同時發出多個數據包,這樣將大大提升通訊速率。你們能夠參考下圖來理解request和非request命令的區別:
注:第1個鏈接間隔中的藍色包爲request命令,旁邊的灰色包是該request的ACK;第2個鏈接間隔的綠色包是response包,而它的ACK是第3個鏈接間隔中的藍色包
注:圖中的綠色包就是非request命令,而緊隨其後的灰色包就是它的ACK
不帶request的命令只有2個:write command和notification,其他的命令都是帶request:全部 read命令,全部write 命令,find命令以及indicate命令,完整的ATT命令(ATT PDU)列表以下所示:
GATT,Service(服務)和Characteristic(特徵數據)
在講解GATT以前,咱們先看一下什麼是profile?
Profile是一個你們常常見到的英文單詞,可是總感受領會不到這個詞的內涵。Profile,英文本意就是 臉的側面輪廓,這裏你們注意必定要注意,臉的輪廓 不等於臉自己,可是profile自己是對臉的一種抽象,描述和定義,藍牙規範其實也是使用profile這個引伸意義而已,換句話說 ,藍牙的profile跟英文字典中的profile是同一個意思。要定義藍牙,必需要有一個規範,這就是藍牙核心規範v4.2/v5.0/v5.1……藍牙規範很是複雜和龐大 ,大部分藍牙設備只實現了藍牙規範中不多一部分,那麼沒有實現的這些規範對這個藍牙設備來講 能不能稱爲 規範?固然不能!所謂規範或者規格 ,就是強制的,就必須實現。針對這種狀況,profile能夠很好的應對。咱們把藍牙某部分規範稱爲profile,這個profile若是設備要實現它,那麼它就是強制的,若是設備不用它,也沒有關係,這就是profile。基於此,咱們能夠把profile翻譯成子規範或者條件規範或者剖面規範。「藍牙規範包含不少子規範」,這句話用中文說問題不是很大,可是你把它翻譯成英文,那就很難了!這就是 英文須要用profile的緣由(而不是spec), 以及爲何profile在規範中出現的如此頻繁。
GATT,全稱generic attribute profile,對數據進行通常化/抽象化的子規範,說白了就是對數據進行邏輯化表達的規定。前面說過了,attribute就是一條一條的數據,那麼這條數據表示什麼?如何對其進行分類?這就是GATT要作的事情,GATT將數據賦予含義,並呈現必定的邏輯結構。
Service和characteristic就是GATT層定義的,前面說過,server端提供 服務,服務就是數據,而數據就是一條一條的attribute,而service和characteristic就是數據的邏輯呈現,後者說用戶能看到的數據最終都轉化爲 service和characteristic。好比,一個數據 「37」。有多是說體溫 「37度」,也可能說心率 「37次」或者溼度 「37%」,所以必須對數據進行分類和定義。
在藍牙規格中,每個具體的藍牙應用是由多個service組成,而每個service又是多個characteristic組成,這樣咱們能夠把上面的圖一轉化爲圖3.
圖三:service和characteristic
那麼service/characteristic和attribute之間究竟是一個怎樣的關係?如前所述,service/charateristic是attribute的邏輯表現形式,而attribute是service/characteristic具體實現方式。尤爲要注意的是,一條characteristic不是對應一條attribute具體實現方式。尤爲注意的是,一條chararcteristic不是對應一條attribute,而是由多條attribute組成。雖然一個數據最有價值的部分是它的值(value )。=,可是 僅有value是不夠的,好比27,究竟是表示27°溫度仍是27%溼度;若是表示的是溫度,那麼它的單位是攝氏度仍是華氏度。同時每一個數據還有相應的讀寫屬性以及權限屬性,所以一個characteristic包含三種類型的數據條目(attribute):characteristic聲明體條目(declaration attribute),characteristic 值條目(value characteristic)以及characteristic描述符條目(descriptor attribute) (一個characteristic能夠有多個描述符條目),以下所示:
因爲一個service能夠包含多個characteristic,characteristic declaration就是每一個characteristic的分界符,解析時一旦遇到characteristic declaration,就能夠認爲接下來又是一個新的characteristic了,同時characteristic declaration還將包含value attribute的讀寫屬性等。Charateristic value就是數據的值了,他也是一個單獨的attribute,這個比較好理解就再也不說了。Charactristic descriptor就是數據的額外信息,好比 溫度的單位是什麼,數據是用小數表示仍是百分比表示等之類的數據描述信息。Descriptor屬於可選條目,也就是說,一個characteristic能夠不包含任何一條descriptor。這裏着重提一種特殊的descriptor:CCCD。通常而言,都是client來訪問server的characteristic,即經過ATT讀或者寫PDU訪問相關數據。若是server想直接把本身的characteristic的值告訴client,就須要經過notiy或者indicate PDU,跟其餘PDU相比,這兩個PUD是由server本身決定何時開始傳送,而不是被動接收client的命令請求。但client畢竟是客戶,他得有自主權,因此引入了一個CCCD來幫助client控制server的行爲。client能夠經過禁止CCCD以容許notify或者 indicate命令,client能夠經過禁止CCCD以容許notify或者indicate命令。從新總結一下。當CCCD使能的狀況下,server能夠隨時notify或者indicate數據 給client;當禁止的時候,哪怕server有數據,它也不能notify或者indicate給client。這裏強調一下。當characteristic具備notify或者indicate操做功能時,藍牙規範要求必須爲其添加CCCD attribute.
重複強調,無論是characteristic declaration,characteristic value仍是characteristic descriptor,實現的時候,都是一條數據條目,即attribute.
引入了GATT,咱們就能夠把圖2的 attribute table進行GATT化,獲得下面有內涵,有層次,有定義的數據表格:
所謂開發藍牙應用程序,其實就是開發service和characteristic。經過API,添加本身須要的characteristic和service,你本身的藍牙設備就誕生了。只要characteristic和service是符合GATT規範的,你能夠隨意添加任何characteristic和service,並將他們組合成一個專門的藍牙設備。因爲這個藍牙設備是按照規範來定義的,因此它能夠與任何其餘藍牙設備,好比手機,互聯互通,並完成所要求的的交互動做。這裏的藍牙設備,咱們還能夠進一步細分爲藍牙profile設備和非profile藍牙設備。前面也提過,profile就是一個子規範,藍牙profile設備包含的全部實際service和characteristic都是按照profile規格來添加和定義的,好比說心率計profile,就是一個藍牙聯盟定義的藍牙設備,藍牙聯盟有一份專門的spec來定義心率計profile,在這份spec中規定了心率計profile除了包含心率service,還包含電池service,設備信息service等。從這能夠看出,心率profile和心率service是包含關係,前者包含後者。