Android-BLE藍(lán)牙原理

背景

  • 藍(lán)牙歷史

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

    Ps:可能很多人會誤解藍(lán)牙4.0就是低功耗藍(lán)牙,但是完整的藍(lán)牙4.0規(guī)范實(shí)際上是包含經(jīng)典藍(lán)牙和低功耗藍(lán)牙兩部分的。只是說在藍(lán)牙4.0規(guī)范,藍(lán)牙技術(shù)聯(lián)盟才引入了BLE。

  • 低功耗藍(lán)牙--BLE

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

  • BLE ON Android

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

協(xié)議棧

藍(lán)牙4.1BLE協(xié)議棧的結(jié)構(gòu)圖如下:

<div align=center>


圖片名稱

</div>

下面是詳細(xì)介紹各個層級的含義:

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

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

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

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

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

    <div align=center>


    圖片名稱

    </div>

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

  6. 第5個我們又提到一個BLE設(shè)備實(shí)際上就是一組Service的集合,那BLE藍(lán)牙以什么來標(biāo)識多個Service呢。答案就是UUID。BLE中的Service,Characteristic,Descripter都是使用UUID來作為唯一標(biāo)識。所以我們在讀寫B(tài)LE藍(lán)牙數(shù)據(jù)時,都要帶上相應(yīng)的UUID。

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

應(yīng)用開發(fā)

BLE應(yīng)用可以分為兩大類:基于非連接的和基于連接的。

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

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

下面就對于這兩類應(yīng)用做更詳細(xì)的解釋,其實(shí)搞懂了這些,基本上BLE藍(lán)牙開發(fā)的整個流程及原理就搞得很清楚了。

Beacon

基于非連接的BLE應(yīng)用,下面是它的網(wǎng)絡(luò)拓?fù)浣Y(jié)構(gòu):
<div align=center>


圖片名稱

</div>

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

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

關(guān)于Beacon應(yīng)用里有一個很重要的點(diǎn)就是廣播包的數(shù)據(jù)結(jié)構(gòu)。數(shù)據(jù)包的格式如下圖(官方圖):
<div align=center>


圖片名稱

</div>

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

  • 無效數(shù)據(jù)部分:因?yàn)閺V播包的長度必須是 31 個 byte,如果有效數(shù)據(jù)部分不到 31 自己,剩下的就用 0 補(bǔ)全。這部分的數(shù)據(jù)是無效的,解釋的時候,忽略即可。

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

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

E/TAG:scandata:02011A05FFAC0134560000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000

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

<div align=center>


圖片名稱

</div>

掃描的工作流程

<div align=center>


圖片名稱

</div>

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

基于連接的藍(lán)牙應(yīng)用(Connection App)

網(wǎng)路拓?fù)浣Y(jié)構(gòu):
<div align=center>


圖片名稱

</div>

拓?fù)浣Y(jié)構(gòu)比較簡單,一個中心設(shè)備可以連接多個外設(shè),但是一個外設(shè)只能連接一個中心(主要是因?yàn)檫B接成功以后,外設(shè)就會停止對外廣播,別人則發(fā)現(xiàn)不了它了)。其實(shí)一個中心連接的外設(shè)設(shè)備數(shù)量也是有限的,據(jù)說是7個。原因不明,應(yīng)該底層芯片做了限制。

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

<div align=center>


圖片名稱

圖片名稱

</div>

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

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

圖片名稱

</div>

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

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

結(jié)語

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

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

下篇文章中我會介紹封裝的Android藍(lán)牙連接sdk。即支持經(jīng)典藍(lán)牙,也支持BLE藍(lán)牙。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容