顯微鏡下的 BLE (ATTы GATTы...)

顯微鏡下的 BLE (ATTы GATTы...)

顯微鏡下的 BLE (ATTы GATTы...)

第 1 部分,概述

自從第一個藍牙 4.0 規範發布以來,已經過了相當長的一段時間。 而且,儘管 BLE 主題非常有趣,但由於其複雜性,它仍然讓許多開發人員望而卻步。 在我之前的文章中,我主要看的是最底層,連結層和物理層。 這使我們能夠避免求助於屬性協定 (ATT) 和通用屬性設定檔 (GATT) 等複雜且令人困惑的概念。 然而,無處可去,不了解它們,就不可能開發出相容的設備。 今天我想與大家分享這些知識。 在我的文章中我將依賴 教科書 來自 Nordic 網站的初學者。 那麼就讓我們開始吧。

為什麼一切都那麼難?

在我看來,很明顯地透過智慧型手機管理設備是一個非常有前途且持久的話題。 因此,他們決定立即最大限度地建造它。 因此,各種設備的製造商不會提出自己的協議,從而導致不相容。 因此困難就來了。 在第一階段,他們就嘗試將所有可能的內容壓縮到 BLE 協定中。 而且以後有沒有用並不重要。 此外,它們還提供了未來擴展設備清單的可能性。

我們來看看繪製BLE協定圖的圖。 它由幾層組成。 最低的實體層 (PHY) 負責設備的無線電頻道。 鏈路層 (LL) 包含傳輸訊息中的整個位元組序列。 在之前的文章中我們正是研究了這一點。 如果控制器和主機在不同的晶片上實現,則主機控制器介面 (HCI) 是 BLE 層或晶片之間的交換協定。 邏輯鏈路控制和適應協定(L2CAP)負責資料包形成、成幀、錯誤控制和資料包組裝。 安全管理器協定 (SMP) 負責加密資料包。 通用存取設定檔 (GAP) 負責設備之間的初始資料交換,以確定「誰是誰」。 它還包括掃描和廣告。 在本文中,我將重點討論協議的其餘兩個部分 - GATT 和 ATT。 GATT是ATT的上層建築,兩者緊密相連。

顯微鏡下的 BLE (ATTы GATTы...)

為了簡化這個故事,我想打個比方。我在某處聽過並且想支持它。將 BLE 設備視為有多個架子的書櫃。每個架子都是一個單獨的主題。例如,我們的書架上放著科幻小說、數學和百科全書。每個書架上都有特定主題的書。有些書甚至還有帶有筆記的紙質書籤。此外,我們還有一個包含所有書籍的小型紙質目錄。如果你還記得的話,學校圖書館是一個裝有紙卡的窄盒子。以此類比,機櫃就是我們設備的輪廓。書架是服務,書是特性,目錄是屬性表。書籍中的書籤是描述符,我稍後也會更詳細地討論。

開發過設備的人都知道,很多專案都有類似的程式碼片段。 事實上,許多設備都具有類似的功能。 例如,如果設備由電池供電,那麼充電和監控其電量的問題將是相同的。 感測器也是如此。 實際上,物件導向的程式設計方法 “提供了創建物件的能力,這些物件將屬性和行為組合成一個獨立的聯合,然後可以重複使用”。 在我看來,BLE 嘗試了類似的方法。 配置檔案由藍牙特別興趣小組 (SIG) 開發。 來自不同製造商、具有相同配置的設備應該可以毫無困難地相互協作。 反過來,設定檔由服務和特徵服務組成,並輔以描述符。 一般來說,它可能看起來像這樣:

顯微鏡下的 BLE (ATTы GATTы...)

例如,考慮心率監測器(健身手環)的輪廓圖。 它由兩項服務和幾個特徵組成。 由此,設定檔層次結構立即變得清晰。 檢查點特徵將總卡路里消耗計數重設為零。

1.心率服務包含三個特徵(0x180D):
    a) 強制心率特徵(0x2A37)
    b) 選購的身體感應器位置特性 (0x2A38)
    c) 心率控制點的條件特徵(0x2A39)
2、電池維護服務(0x180F):
    a) 強制電池充電水平特徵 (0x2A19)

UUID

為了讓我們能夠唯一地存取設定檔元素(服務、特徵和描述符),我們需要以某種方式對它們進行編號。 為此,引入了通用唯一ID(UUID)或通用唯一識別碼等概念。 UUID 在每行的括號中指示。 這裡有一個特點。 對於 UUID,我們決定使用長度為 16 和 128 位元的代碼。 為什麼問? 在BLE協定中,一切都是為了節能。 因此,16位的維度是相當合理的。 在不久的將來創建的數量不太可能超過 65 個。 獨特的服務和特色。 目前,他們可以計算的所有內容(記住這來自哪裡 - “他也計算了你”:-))編號元素 簡介, 服務, 特點 и 描述符 你可以看看連結。

不過,我想大家都還記得網路上4位元組IP位址的故事。 起初我們認為這就足夠了,但現在我們仍然無法切換到 6 位元組位址。 為了不再重蹈覆轍,並讓 DIYers 自由發揮,SIG 立即決定引入 128 位元 UUID。 這讓我個人想起了未經許可的 433 MHz 頻段,該頻段是從無線電頻道分配給各種 Kulibins 的。 在我們的例子中,服務和特徵的 128 位元識別碼被外包。 這意味著我們的服務和設備幾乎可以使用任何 128 位元值。 儘管如此,得出相同 UUID 的機率趨於零。

事實上,短 16 位元 UUID 已擴展為 128 位元值。 在規範中,此擴充稱為藍牙基本 UUID,其值為 00000000-0000-1000-8000-00805F9B34FB。 例如,如果 16 位元屬性 UUID 的值為 0x1234,則等效的 128 位元 UUID 的值為 00001234-0000-1000-8000-00805F9B34FB。 甚至還給出了相應的公式:

                                128_bit_value = 16_bit_value * 2^96 + 藍牙_Base_UUID

我不知道這個神奇的數字是從哪裡來的。 如果有讀者知道,請在評論中留言(暱稱Sinopteek的用戶已經這樣做了,請參閱評論)。 至於提出128位UUID,原則上你可以使用特殊的 發電機誰會為你做這件事。

阿蒂·蓋蒂...

事實上,然後有趣的事情就開始了。 讓我提醒您,ATT 是基於客戶端-伺服器關係。 現在我們正在研究伺服器設備。 它包含感測器值、燈開關狀態、位置資料等資訊。 現在所有「遊行參與者」都已編號,我們需要以某種方式將它們放入裝置的記憶體中。 為此,我們將它們放入一個稱為屬性表的表中。 記住這一點。 這是 BLE 的核心。 這是我們將進一步考慮的。 現在我們將每一行稱為一個屬性。 該表位於堆疊深處,通常我們無法直接存取它。 我們初始化它並訪問它,但內部發生的事情對我們來說是隱藏在七個封印後面的。

讓我們來看看規範中的圖片,但在此之前,我想立即提請注意術語(即描述符)中經常出現的混淆。 描述符的作用是補充特徵的描述。 當需要擴展其功能時,就使用描述符。 它們也是屬性,就像服務和特徵一樣,它們位於屬性表中。 我們將在本文的第二部分詳細研究它們。 然而,有時描述符會引用屬性表中的行號。 必須牢記這一點。 為了避免混淆,我們將使用術語「屬性指標」來實現這些目的。
顯微鏡下的 BLE (ATTы GATTы...)

因此,屬性是一個離散值,具有以下關聯屬性:
1、Attribute Handle是屬性對應的表索引
2. Attribute Type是描述其類型的UUID
3. 屬性值是屬性指標索引的數據
4. 屬性權限是屬性的一部分,也就是權限,不能使用屬性協定讀取或寫入

如何理解這一切? 相對來說,屬性指標就是它在我們表中的編號。
它允許客戶端在讀或寫請求中引用屬性。 我們可以將行(屬性)編號為 0x0001 到 0xFFFF。 在我們與書櫃的關聯中,這是紙本目錄中的卡號。 類似地,就像在圖書館目錄中一樣,卡片按照編號遞增的順序排列。 後續每一行的編號必須大於前一行。 就像在圖書館一樣,有時有些卡片會遺失,所以對我們來說,行編號可能會存在間隙。 這是允許的。 最主要的是他們是循序漸進的。

屬性類型決定了屬性代表什麼。 類比C語言,
其中有布林值、數值變數和字串,所以就在這裡。 透過我們識別的屬性類型
我們正在處理什麼以及我們如何繼續利用此屬性。 下面我們將看看一些特定類型的屬性。 例如,「服務聲明」(0x2800)、「特性聲明」(0x2803)、「描述符聲明」(0x2902)。

屬性的值就是它的實際意義,請原諒同義反覆。 如果屬性類型是字串,則屬性值可以是例如口號“Hello World!!!”。 如果屬性類型是“服務聲明”,那麼它的值就是服務本身。 有時,這是有關在哪裡可以找到其他屬性及其屬性的資訊。

屬性權限允許伺服器了解是否允許讀取或寫入存取。
請注意,這些權限僅適用於屬性值,而不適用於指標、類型或權限欄位本身。 那些。 如果允許屬性記錄,那麼我們可以更改,例如「Hello World !!!」這一行到「早安」這一行。 但我們不能禁止寫入新行或更改屬性類型並將該行指定為「服務聲明」。 當客戶端聯繫伺服器時,客戶端請求其屬性。 這允許客戶端知道伺服器可以提供什麼。 儘管沒有必要讀取和寫入這些值。

看起來如何

GATT 的概念是以非常具體和邏輯的順序將屬性表中的屬性分組在一起。 讓我們仔細看看下面的心率曲線。 該表最左邊的列是可選的。 它只是向我們描述了這條線(屬性)是什麼。 所有其他列我們都已經熟悉了。

顯微鏡下的 BLE (ATTы GATTы...)

在每個群組的頂部,我們始終有一個服務聲明屬性。 它的類型始終是 0x2800,指標取決於表中已經存在的屬性數量。 它的權限始終是唯讀的,沒有任何身份驗證或授權。 我們稍後會討論這些概念。 該值是另一個 UUID,用於識別服務是什麼。 表中位數為0x180D,藍牙SIG將其定義為心率服務。

發布服務後,接著發布特性。 它在形式上與服務聲明類似。 其UUID始終為0x2803,其權限始終為唯讀,無需任何身份驗證或授權。 讓我們看一下「屬性值」字段,其中包含一些資料。 它始終包含一個指標、一個 UUID 和一組屬性。 這三個元素描述了特徵值的後續聲明。 此指標自然表示特徵值聲明在屬性表中的位置。 UUID 描述了我們可以期望什麼類型的信息或值。 例如,溫度值、燈開關的狀態或一些其他任意值。 最後是屬性,它描述如何與特徵值互動。

另一個陷阱在這裡等著我們。 它與屬性權限和特性屬性相關聯。 讓我們來看看規範中位域屬性的圖片。

顯微鏡下的 BLE (ATTы GATTы...)

正如你所看到的,這裡還有提供讀寫功能的欄位。 您可能想知道為什麼我們對屬性和屬性具有讀取/寫入權限
讀/寫特徵值? 它們不應該總是一樣嗎? 事實上,特徵值的屬性其實只是針對 GATT 和應用層中使用的客戶端的建議。 這些只是關於客戶端可能期望從特徵聲明屬性中得到什麼的提示。 讓我們更詳細地看看這個。 屬性具有哪些類型的權限?

1、存取權限:
     - 讀
     - 記錄
     - 讀和寫
2、認證權限:
     - 需要身份驗證
     - 無需身份驗證
3、授權許可:
     - 需要授權
     - 無需授權

屬性解析和特徵屬性之間的主要區別在於前者適用於伺服器,後者適用於客戶端。 可以允許伺服器讀取特徵值,但可能需要認證或授權。 因此,當客戶端請求該特徵的屬性時,我們將收到允許讀取的訊息。 但是當我們嘗試讀取時,就會出現錯誤。 因此,我們可以放心地談論權限相對於屬性的優先順序。 在客戶端,我們無法了解屬性具有哪些權限。

描述符

讓我們回到我們的桌子。 聲明特徵值後,可以進行以下屬性聲明:
1.新的特徵聲明(一個服務可以有多個特徵)
2.新服務聲明(表格中可能有很多)
3. 聲明句柄

對於心率測量特徵,在我們的表中,特徵值的聲明伴隨著描述符的聲明。 描述符是具有有關特徵的附加資訊的屬性。 描述符有多種類型。 我們將在本文的第二部分詳細討論它們。 現在,我們只討論客戶端特徵配置描述符 (CCCD)。 它的 UUID 等於 0x2902。 使用此描述符,用戶端能夠在伺服器上啟用指示或通知。 它們之間的差異很小,但仍然存在。 通知不需要客戶確認收到。 指示要求這樣做,儘管它發生在關貿總協定級別,但沒有達到應用程式級別。 你問為什麼會這樣? 唉,我不知道這個。 我只想說北歐專家建議使用通知。 此外,在這兩種情況下都會檢查套件的完整性(使用 CRC)。

結論

在文章的最後我想說一下這一點。 最後一張表有點令人困惑。 然而,我選擇它是因為它給了 文章,我所依賴的。 在文章的第二部分中,我打算更深入地研究藍牙 4.0 規格。 更正確的圖表和圖畫在那裡等著我們。 在第三部分中,我想解析使用 Wireshark 程式從其中一個小工具獲取的日誌,並「即時」查看我們正在研究的所有理論。

集團公司員工 “凱撒衛星”
弗拉基米爾·佩切爾斯基赫

來源: www.habr.com

添加評論