Android-BLE藍牙原理

背景

  • 藍牙歷史

    說到藍牙,就不得不說下藍牙技術聯盟(Bluetooth SIG),它負責藍牙規范制定和推廣的國際組織。如果需要開發藍牙硬件產品,應該會和他們打交道。有些小伙伴可能只聽過藍牙1.0,藍牙2.0,藍牙3.0,藍牙4.0之類的以數字結尾的藍牙版本號。這些是以前的標準,而最新的標準中,已經不使用數字版本號來作為藍牙版本的區分了,取而代之的就是經典藍牙以及低功耗藍牙。稍微提下藍牙版本的演進過程:99年藍牙1.0發布,后面就是藍牙2.1。藍牙2.1的版本使用最廣,很多產品都是這個版本,也就是我們所謂的經典藍牙,以前非智能手機也是支持這個版本的。到了藍牙3.0,又名為高速藍牙,在2.1的基礎上大大提升了傳輸速度(24Mbps)。后面4.0/4.1引入了低功耗藍牙。藍牙5.0也已經發布。主要是在信號范圍,連接速度,以及廣播速度進行了優化,藍牙5.0還對物聯網方向做了單獨的改進。

    Ps:可能很多人會誤解藍牙4.0就是低功耗藍牙,但是完整的藍牙4.0規范實際上是包含經典藍牙和低功耗藍牙兩部分的。只是說在藍牙4.0規范,藍牙技術聯盟才引入了BLE。

  • 低功耗藍牙--BLE

    全稱是Bluetooth Low Energy,簡稱BLE。也就是說最大的一個特點就是低功耗了。有一些BLE設備一個紐扣電池可以使用一兩年。當然所有的優點和缺點都是相對的,而BLE的對立面當然就是歷史悠久的經典藍牙了。經典傳統藍牙有3個功率級別,Class1,Class2,Class3分別支持100m,10m,1m的傳輸距離,一般要求至少使用兩節3A電池。而且工作幾天或者幾周就沒電了。前面說了低功耗藍牙一個紐扣電池就可以工作一兩年,3A電池的電量一般是紐扣電池的10至12倍。這是BLE的一個很大的優點,尤其是對于現在的穿戴設備以及各種物聯網傳感器,BLE電池的續航是一個很大的突破點。正所謂有得必有失,低功耗帶來的低傳輸速率,當然BLE被設計的本來就是傳輸少量數據的,對于很多傳感器設備,例如心跳帶,血壓計等設備,是非常適合的。

  • BLE ON Android

    從Android 4.3 Jelly Bean(API 18)才開始支持低功耗藍牙,但是僅僅是支持中心(Central)模式。所謂的中心模式,即可以連接其他藍牙外設。直到2014.6.26 Android Lollipop的面世,才帶來了周邊API的支持(BluetoothLeAdvertiser)。即Android 5.0以后的手機可以作為一個外設來進行發布。Android SDK 中 BLE 相關的 API 都在 android.bluetooth.* 下面,同時在 Android 5.0 也引入了一些也需要用到 android.bluetooth.le* 下面的 API。另外,要在 APP 中使用藍牙功能,需要在 Manifest 中申請藍牙相關的權限。在 Android 6.0 及以上平臺中,還需要申請定位權限。

協議棧

藍牙4.1BLE協議棧的結構圖如下:

<div align=center>


圖片名稱

</div>

下面是詳細介紹各個層級的含義:

  1. PHY(Physical Layer):物理層,藍牙是工作在2.4GHz附近,這是工業、科學、醫療ISM的頻段,免許可證。WIFI也是工作在同一個頻段。藍牙把頻段切分為40個通道,3個廣播通道,37個數據通道,按照一個規律跳頻通信。

  2. LL(Linker Layer):鏈路層,用于控制設備的射頻狀態,設備將處于五種狀態之一:等待、廣告、掃描、初始化、連接。廣播設備不需要建立連接就可以發送數據,而掃描設備接收廣播設備發送的數據;發起連接的設備通過發送連接請求來回應廣播設備,如果廣播設備接受連接請求,那么廣播設備與發起連接的設備將會進入連接狀態。發起連接的設備稱為主機,接受連接請求的設備稱為從機。

  3. HCI(Host Controller Interface):主機和控制器就是通過這個接口來進行同學的,通信的介質就是HCI命令。這層在協議棧中是可選的,一些小型終端可能沒有,但是Android設備上肯定有,這層是藍牙上層和芯片的交互必經之路,對于藍牙硬件開發者,這里的log能夠很好的幫助解決問題。

  4. HOST部分要復雜一些,有鏈路控制和適配層(L2CAP),安全管理(SM)等。其中L2CAP和SM我們知道概念就可以了,這里就不多關注了。我們重點來看屬性協議層,也就是ATT。它是整個BLE通信的基礎。ATT負責數據封裝,向外暴露為"屬性",提供"屬性"的為服務端,獲取"屬性"的為客戶端。ATT是專門為BLE低功耗藍牙而設計的傳輸協議,結構簡單,傳輸數據短(后面會有提及)。

  5. GATT(Generic Attribute Profile):全稱叫做通用屬性配置文件,是基于ATT做進一步的邏輯封裝,定義數據的交互方式和含義,APP的開發其實就已經接觸到這一層了。GATT按照層級定義了三個非常重要的概念:服務(Service)、特征(Characteristic)、描述(Descripter)。他們之間的關系如下:

    <div align=center>


    圖片名稱

    </div>

    一個Service可以包含若干個Characteristic,一個Characteristic可以包含屬性(properties)和值(value),還可以包含多個descripter。Characteristic實際上具有讀、寫、通知等權限,我們在對一個BLE設備發起連接成功以后,對他進行讀寫,其實就是對Characteristic的讀寫或者訂閱通知。圖中所謂的Profile,實際上是一組服務的集合,這些服務被人組合起來就形成了一個特定的使用場景。比如說,小米手環,里面就有一個計算用戶當前步數的服務。這就是這個Ble可以做的事情,也就是它的profile。

  6. 第5個我們又提到一個BLE設備實際上就是一組Service的集合,那BLE藍牙以什么來標識多個Service呢。答案就是UUID。BLE中的Service,Characteristic,Descripter都是使用UUID來作為唯一標識。所以我們在讀寫BLE藍牙數據時,都要帶上相應的UUID。

  7. GAP(Generic Access Profile):通用訪問控制配置文件。定義了BLE整個通信過程中的流程,負責處理設備訪問模式和程序,包括設備發現,建立連接,終止連接,初始化安全特性,設備配置。GAP層總是作為下面四種角色之一:(1)廣播者:不可連接的廣播設備。(2)觀察者:掃描設備,但不發起建立連接。(3)外部設備:可連接的廣播設備,可以在單個鏈路層連接中作為從機。(4)集中器:掃描廣播設備并發起連接,可以在單個鏈路層連接中作為主機。

應用開發

BLE應用可以分為兩大類:基于非連接的和基于連接的。

基于非連接的:意思就是外設和周邊設備不發生連接,外設主要依賴周邊設備發出的BLE廣播,也叫做Beacon。這里有兩個角色,發送廣播的一方叫做Broadcaster。監聽廣播的一方叫做Oberver。這個在藍牙協議棧的GAP層都有相應的角色定義。

基于連接的:就是外設和周邊設備要建議顯式的GATT連接,需要雙方有通信。這個也有兩個角色,外設設備(周邊)叫做Peripheral。中心設備(一般是手機)叫做Centeral。

下面就對于這兩類應用做更詳細的解釋,其實搞懂了這些,基本上BLE藍牙開發的整個流程及原理就搞得很清楚了。

Beacon

基于非連接的BLE應用,下面是它的網絡拓撲結構:
<div align=center>


圖片名稱

</div>

由于廣播是單向的,Broadcaster向外發送廣播,Observer接受廣播。總體來說是多對多的關系。BLE廣播中也能夠帶上數據,包括某些私有協議等。所以基于這種協議也是能夠開發出獨特的應用。完全基于廣播的應用,有大名鼎鼎的iBeacon,這是蘋果公司基于BLE廣播實現的功能,可以實現廣告推送以及室內定位。包括某些商場內部柜臺尋找的功能,也是基于這種協議開發出來的。

在上圖我畫的設備都是單一的角色,而實際上有些設備是可以同時實現兩種角色的,它即可以發送廣播,也可以接受廣播。想象一下,在現在比較火的智能家居系統中,有很多的傳感器,如果一個設備接受到廣播,做了處理以后在發送出去,就形成了一個雙向的網格,是不是就有點像因特網了,這也就是有名的藍牙Mesh。有興趣的同學可以去看看。

關于Beacon應用里有一個很重要的點就是廣播包的數據結構。數據包的格式如下圖(官方圖):
<div align=center>


圖片名稱

</div>

從圖中就可以看出,每個廣播數據包包含31個字節,分為有效數據以及無效數據兩部分。

  • 無效數據部分:因為廣播包的長度必須是 31 個 byte,如果有效數據部分不到 31 自己,剩下的就用 0 補全。這部分的數據是無效的,解釋的時候,忽略即可。

  • 有效數據部分:包含若干個廣播數據單元,稱為 AD Structure。如圖中所示,AD Structure 的組成是:第一個字節是長度值 Len,表示接下來的 Len 個字節是數據部分。數據部分的第一個字節表示數據的類型 AD Type,剩下的 Len - 1 個字節是真正的數據 AD data。其中 AD type 非常關鍵,決定了 AD Data 的數據代表的是什么和怎么解析。

我們詳細來解釋一下這個有效數據部分。上面的解釋可能比較抽象,這里我用一個例子來解釋一下:

E/TAG:scandata:02011A05FFAC0134560000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000

我們只截取有效數據部分: 02011A05FFAC013456。我們按照圖中的協議進行一下分隔,02 01 1A 05 FF AC013456。我們看第一個字節為02,表示后面兩個字節為一段數據。第二個字節為01,表示就是數據的type。1A就是這個type的內容數據了。05 表示后面5個字節是一個數據段,FF表示一種數據type。AC013456就是數據。掃描的數據塊都是通過這種協議來組織的,所以這里最重要的就是這個數據type。官方解釋看這里。我稍稍做了部分整理,如下:

<div align=center>


圖片名稱

</div>

掃描的工作流程

<div align=center>


圖片名稱

</div>

對于掃描的建議:1、首先,盡可能使用新的 API,功能更強大;2、盡可能少地掃描,因為畢竟掃描是一個比較重的操作,耗電,也會減慢 BLE 連接速度;3、掃描的時候,盡量設置 ScanFilter,只掃描那些你感興趣的設備,而不是全盤掃描;4、正確使用 API,特別是合理停止掃描,防止資源泄漏,開始掃描的callback一定要和停止的callback是一個對象,防止底層句柄造成泄露。

基于連接的藍牙應用(Connection App)

網路拓撲結構:
<div align=center>


圖片名稱

</div>

拓撲結構比較簡單,一個中心設備可以連接多個外設,但是一個外設只能連接一個中心(主要是因為連接成功以后,外設就會停止對外廣播,別人則發現不了它了)。其實一個中心連接的外設設備數量也是有限的,據說是7個。原因不明,應該底層芯片做了限制。

這篇文章中我就不貼出具體的代碼了(下篇介紹藍牙連接sdk的時候會有)。先通過一個demo來了解一下GATT的結構,以求更深的理解基于連接的藍牙應用的原理。先看下面的demo圖,圖里面是一個客戶端連接服務端后返回的數據。

<div align=center>


圖片名稱

圖片名稱

</div>

圖片左邊的外設我一個私有服務都沒寫,但是藍牙聯盟預定了一些服務,分別是1801和1800。這兩個都是官方指定的service。1800和1801分別表示Generic Access和Generic Attribute,描述了設備連接相關屬性。有的設備(小米手環)還有1802這個官方服務,表示Immediate Alert,如果有這個服務,則說明外設設備支持即時提醒功能,如果向其中包含的Characteristic寫入一個值,那么設備應當可以發出對應的響聲。而右邊的圖,很明顯多了兩個私有服務,這個私有服務也只有服務提供者知道。關于這塊的代碼會在下一篇文章的藍牙連接sdk中一并發出。這里只是知道原理即可。

連接的工作流程
<div align=center>

圖片名稱

</div>

可以看出來,BLE從連接到讀寫還是比較復雜的,各種回調。客戶端先發起connect請求,不像讀寫更多的是軟件來完成,connect實際上是雙方芯片來完成然后回調給各自上層。所以不管服務端和客戶端,都會有一個onConnectStateChanged回調。參數也是一致的,對于客戶端來說,返回的BluetoothDevice就是外設設備,對于外設設備返回的就是中心設備。這里有一點需要注意,由于BLE藍牙并不想經典藍牙有永久mac地址一說,對于經典藍牙,獲取到mac地址后,這個藍牙的mac地址就是不變的,所以可以做離線連接。對于BLE,mac地址在每次重新廣播都會發生改變,從而導致當客戶端觸發onConnectionStateChanged后獲取的BluetoothDevice的mac地址都是不一樣的。這個是藍牙官方規定,無法修改。那對于BLE藍牙,如果做離線連接就要復雜的多。

圖中倒數第二和第三是BLE特有的機制,這里簡單說明一下,如果某個服務設置了Notify或者Indicate機制(UUID是固定的)。則改服務上的該屬性可以接受服務端對客戶端的notify,前提是連接完成以后客戶端需要設置改屬性為true。這樣服務端可以推送一些固定的信息給客戶端,這就比較適合那種電量推送的場景。

結語

上面我們分別介紹了BLE藍牙的一些基本概念,并且分析了藍牙的協議棧。而且也講解了Android設備作為BLE應用的四個角色:監聽者、廣播者、中心設備以及外設。也提到了一些我在從事醫療項目開發遇到的坑。

實際情況在我們平時的開發中,也許是硬件團隊丟給我們一臺設備,然后協議文檔,或許我們只需要了解兩個角色就可以了,監聽者和中心設備,然后對著API寫相關的業務代碼,但是我覺得了解協議棧或者藍牙服務端是如何工作的,才能更好的解決問題。

下篇文章中我會介紹封裝的Android藍牙連接sdk。即支持經典藍牙,也支持BLE藍牙。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,546評論 6 533
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,570評論 3 418
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,505評論 0 376
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,017評論 1 313
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,786評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,219評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,287評論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,438評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,971評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,796評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,995評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,540評論 5 359
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,230評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,662評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,918評論 1 286
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,697評論 3 392
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,991評論 2 374

推薦閱讀更多精彩內容