1. 程式人生 > >BLE 廣播報文解析

BLE 廣播報文解析

感謝原創作者!

  在使用EN-Dongle捕獲和解析廣播包之前,我們先了解一下BLE報文的結構,之後,再對捕獲的廣播包進行分析。在學習BLE的時候,下面兩個文件是極其重要的,這是SIG釋出的藍芽的核心協議和核心協議增補。

  • 核心協議Core_v4.2。
  • 核心協議增補CSS v6。

  雖然這兩個文件是藍芽技術的根本,但是遺憾的是:通過這兩個文件學習藍芽並不是那麼容易的,閱讀和理解起來很費力。尤其是初學者在閱讀這兩個文件的時候,感覺無從下口。所以,本文在分析報文的過程中,會明確指出協議文件在什麼地方定義了他們,讓我們有目的的去查閱協議文件,做到知其然也知其所以然,這樣,學習起來就會輕鬆很多。

1. BLE報文結構

  BLE報文結構如下,他由下圖所示的各個域組成。因為有的域的長度超過了一個位元組,所以在傳輸的過程中就涉及到多位元組域中哪個位元組先傳輸的問題,BLE報文傳輸時的位元組序和位元序如下:

  •  位元組序:大多數多位元組域是從低位元組開始傳輸的。注意,並不是所有的多位元組域都是從低位元組開始傳輸的。
  • 位元序:各個位元組傳輸時,每個位元組都是從低位開始。

                                                             圖1:BLE報文結構

1.1 前導

  前導是一個8位元的交替序列。他不是01010101就是10101010,取決於接入地址的第一個位元。

  • 若接入地址的第一個位元為0:01010101
  • 若接入地址的第一個位元為1:10101010

  接收機可以根據前導的無線訊號強度來配置自動增益控制。

1.2 接入地址

  接入地址有兩種型別:廣播接入地址和資料接入地址。

  • 廣播接入地址:固定為0x8E89BED6,在廣播、掃描、發起連線時使用。
  • 資料接入地址:隨機值,不同的連線有不同的值。在連線建立之後的兩個裝置間使用。

  對於資料通道,資料接入地址是一個隨機值,但需要滿足下面幾點要求:

     1)  資料接入地址不能超過6個連續的“0”或“1”。

     2)  資料接入地址的值不能與廣播接入地址相同。

     3)  資料接入地址的4個位元組的值必須互補相同。

     4)  資料接入地址不能有超24次的位元翻轉(位元0到1或1到0,稱為1次位元翻轉)。

     5)  資料接入地址的最後6個位元需要至少兩次的位元翻轉。

     6)  符合上面條件的有效隨機資料接入地址大概有231個。

1.3 報頭

1.3.1 廣播報文報頭

  報頭的內容取決於該報文是廣播報文還是資料報文。廣播報文的報頭如下圖所示:

                                                            圖2:廣播報文報頭

  廣播報文的報頭包含4bit廣播報文型別、2bit保留位、1bit傳送地址型別和1bit接收地址型別。

    1) 廣播報文型別

  Core_v4.2的2583頁描述了廣播報文型別,共有7種類型,如下圖所示。

                                                               圖3:廣播報文型別

  每種廣播報文型別都具有不同的資料格式及行為。Core_v4.2的2584頁的2.3.1節詳細的描述了各個廣播報文型別大家可以閱讀此章節進一步瞭解。

     2) 傳送地址型別和接收地址型別

  傳送地址型別和接收地址型別指示了裝置使用公共地址(Public Address)還是隨機地址(Random Address)。公共地址和隨機地址的長度一樣,都包含6個位元組共48位。BLE裝置至少要擁有這兩種地址型別中的一種,當然也可以同時擁有這兩種地址型別。

  • 公共地址(Public Address)

  公共地址由兩部分組成,如下圖。公共地址由製造商從IEEE申請,由IEEE註冊機構為該製造商分配的機構唯一識別符號OUI(Organizationally Unique Identifier)。這個地址是獨一無二,不能修改的。Core_v4.2 P2576的1.3.1節描述了公共地址

                                                          圖4:公共地址結構

  • 隨機地址

  隨機地址有包含兩種:靜態地址(Static Device Address)和私有地址(PrivateDevice Address)。Core_v4.2 P2577的1.3.2.1節描述了靜態地址。

                                                                                圖5:靜態地址格式

  靜態地址有如下要求:

     a) 靜態地址的最高2位有效位必須是1。

     b) 靜態地址最高2位有效位之外的其餘部分不能全為0。

     c) 靜態地址最高2位有效位之外的其餘部分不能全為1。

  在私有地址的定義當中,又包含了兩個子類:不可解析私有地址(Non-resolvable Private Address)和可解析私有地址(Resolvable Private Address,RPA)。nRF51822使用的是靜態地址,晶片在出廠時已經設定好了48位地址,我們可以從下面兩個暫存器讀出地址型別和地址。

     a)  DEVICEADDRTYPE暫存器。

DEVICEADDR[n]暫存器:包含DEVICEADDR[0]和DEVICEADDR[1]兩個暫存器。

                                                       圖6:地址型別暫存器

                                                       圖7:地址暫存器

1.4 長度

  • 廣播報文:長度域包含6個位元,有效值的範圍是6~37。
  •  資料報文:長度域包含5個位元,有效值的範圍是0~31。

  廣播報文和和資料報文的長度域有所不同,主要原因是:廣播報文除了最多31個位元組的資料之外,還必須要包含6個位元組的廣播裝置地址。6+31=37,所以需要6位元的長度域。

  再次強調:廣播時必須要包含6個位元組的廣播裝置地址。

1.5 資料(AdvData)

  廣播和掃面響應的資料格式如下圖所示,由有效資料部分和無效資料部分組成。

                                                         圖8:廣播和掃描響應的資料格式

  1)  有效資料部分:包含N個AD Structure,每個AD Structure由Length,AD Type和AD Data組成。其中:

  • Length:AD Type和AD Data的長度。
  • AD Type:指示AD Data資料的含義。

  問題來了,我們怎麼知道有哪些AD Type?他們又表示什麼意義?可以通過下面2種方式檢視AD Type和他們表示的意義。

  • 從官網查詢,但是需要是會員才可以查詢。

  https://www.bluetooth.org/Technical/AssignedNumbers/generic_access_profile.htm

  • 檢視Nordic的SDK中的定義,AD type的定義在程式的“ble_gap.h”標頭檔案中。定義如下:
複製程式碼
 1 #define BLE_GAP_AD_TYPE_FLAGS                               0x01 /**< Flags for discoverability. */ 2 #define BLE_GAP_AD_TYPE_16BIT_SERVICE_UUID_MORE_AVAILABLE   0x02 /**< Partial list of 16 bit service UUIDs. */ 3 #define BLE_GAP_AD_TYPE_16BIT_SERVICE_UUID_COMPLETE         0x03 /**< Complete list of 16 bit service UUIDs. */ 4 #define BLE_GAP_AD_TYPE_32BIT_SERVICE_UUID_MORE_AVAILABLE   0x04 /**< Partial list of 32 bit service UUIDs. */ 5 #define BLE_GAP_AD_TYPE_32BIT_SERVICE_UUID_COMPLETE         0x05 /**< Complete list of 32 bit service UUIDs. */ 6 #define BLE_GAP_AD_TYPE_128BIT_SERVICE_UUID_MORE_AVAILABLE  0x06 /**< Partial list of 128 bit service UUIDs. */ 7 #define BLE_GAP_AD_TYPE_128BIT_SERVICE_UUID_COMPLETE        0x07 /**< Complete list of 128 bit service UUIDs. */ 8 #define BLE_GAP_AD_TYPE_SHORT_LOCAL_NAME                    0x08 /**< Short local device name. */ 9 #define BLE_GAP_AD_TYPE_COMPLETE_LOCAL_NAME                 0x09 /**< Complete local device name. */10 #define BLE_GAP_AD_TYPE_TX_POWER_LEVEL                      0x0A /**< Transmit power level. */11 #define BLE_GAP_AD_TYPE_CLASS_OF_DEVICE                     0x0D /**< Class of device. */12 #define BLE_GAP_AD_TYPE_SIMPLE_PAIRING_HASH_C               0x0E /**< Simple Pairing Hash C. */13 #define BLE_GAP_AD_TYPE_SIMPLE_PAIRING_RANDOMIZER_R         0x0F /**< Simple Pairing Randomizer R. */14 #define BLE_GAP_AD_TYPE_SECURITY_MANAGER_TK_VALUE           0x10 /**< Security Manager TK Value. */15 #define BLE_GAP_AD_TYPE_SECURITY_MANAGER_OOB_FLAGS          0x11 /**< Security Manager Out Of Band Flags. */16 #define BLE_GAP_AD_TYPE_SLAVE_CONNECTION_INTERVAL_RANGE     0x12 /**< Slave Connection Interval Range. */17 #define BLE_GAP_AD_TYPE_SOLICITED_SERVICE_UUIDS_16BIT       0x14 /**< List of 16-bit Service Solicitation UUIDs. */18 #define BLE_GAP_AD_TYPE_SOLICITED_SERVICE_UUIDS_128BIT      0x15 /**< List of 128-bit Service Solicitation UUIDs. */19 #define BLE_GAP_AD_TYPE_SERVICE_DATA                        0x16 /**< Service Data - 16-bit UUID. */20 #define BLE_GAP_AD_TYPE_PUBLIC_TARGET_ADDRESS               0x17 /**< Public Target Address. */21 #define BLE_GAP_AD_TYPE_RANDOM_TARGET_ADDRESS               0x18 /**< Random Target Address. */22 #define BLE_GAP_AD_TYPE_APPEARANCE                          0x19 /**< Appearance. */23 #define BLE_GAP_AD_TYPE_ADVERTISING_INTERVAL                0x1A /**< Advertising Interval. */ 24 #define BLE_GAP_AD_TYPE_LE_BLUETOOTH_DEVICE_ADDRESS         0x1B /**< LE Bluetooth Device Address. */25 #define BLE_GAP_AD_TYPE_LE_ROLE                             0x1C /**< LE Role. */26 #define BLE_GAP_AD_TYPE_SIMPLE_PAIRING_HASH_C256            0x1D /**< Simple Pairing Hash C-256. */27 #define BLE_GAP_AD_TYPE_SIMPLE_PAIRING_RANDOMIZER_R256      0x1E /**< Simple Pairing Randomizer R-256. */28 #define BLE_GAP_AD_TYPE_SERVICE_DATA_32BIT_UUID             0x20 /**< Service Data - 32-bit UUID. */29 #define BLE_GAP_AD_TYPE_SERVICE_DATA_128BIT_UUID            0x21 /**< Service Data - 128-bit UUID. */30 #define BLE_GAP_AD_TYPE_3D_INFORMATION_DATA                 0x3D /**< 3D Information Data. */31 #define BLE_GAP_AD_TYPE_MANUFACTURER_SPECIFIC_DATA          0xFF /**< Manufacturer Specific Data. */
複製程式碼

 1.6 校驗 

  BLE採用的是24位CRC校驗。CRC對報頭、長度和資料進行計算。24位CRC的生成多項式如下:

2.  廣播包解析

  通過上文的描述,我們對BLE廣播包有了大致的瞭解,接下來我們用EN-Dongle捕獲一個心率計的廣播包,通過對實際廣播包的分析來理解BLE報文結構和廣播。廣播包捕獲實驗的硬體連線如下。

                                                          圖9:硬體連線

2.1 心率計程式下載

2.1.1 下載協議棧

  SoftDevice必須使用nRFgo Studio下載,開啟nRFgo Studio,切換到“Program SoftDevice”選項卡。點選“Browse…”按鈕開啟SoftDevice的HEX檔案(位於“…\BLE實驗\藍芽協議棧(SoftDevice)目錄下的” s110)。點選“Program”下載程式。

2.1.1 下載應用程式

  應用程式可以用nRFgo Studio下載,也可以在MDK中直接下載除錯,在這裡我們用nRFgo Studio下載。切換到“Program Application”選項卡。點選“Browse…”按鈕開啟應用程式的HEX檔案(位於“…\BLE實驗\ ble_app_beacon \pca10028\s110\arm5\_build”目錄下的 nrf51822_xxaa_s110.hex)。點選“Program”下載程式。

2.2 捕獲廣播包

  按照《藍芽4.0BLE抓包()》中的描述進行抓包,下面是我們捕獲一個心率計的廣播包。

 

                                                    圖10:捕獲的心率計廣播包

                                       圖11:檢視廣播包傳輸的資料

2.3 分析廣播包

為了方便分析,我們先取出這個廣播包實際傳輸的資料,如圖9中所示。心率計完整的廣播報文如下:

  D6 BE 89 8E 40 21 60 BF 8A B9 CD C5 0B 09 4E 6F 72 64 69 63 5F 48 52 4D 03 19 41 03 02 01 06 07 03 0D 18 0F 18 0A 18 EF A6 F0

2.3.1 接入地址

  D6 BE 89 8E:接入地址,對廣播來說是固定值。注意一下這裡的位元組序,接入地址傳輸時是低位元組在前的。

2.3.2 PDU

  q         40:廣播報文報頭。

  l      bit0~bit3是0000,說明廣播型別是ADV_IND,即通用廣播指示。

  l      bit7(RxAdd)是0,bit7(TxAdd)是1,說明使用的是隨機地址(random address)。Core_V4.2 P25842.3.1有詳細的描述。

  q         21:長度,表示這個廣播的長度是33個位元組。

  q         9A 3F 20 FB 74 C5:裝置地址,這裡使用的是隨機靜態地址。

接下來就是廣播包最重要的部分了,稱之為AdvData,前面我們說過AdvData是N個AD Structure組層成,每個AD Structure的格式都是Length |AD Type|AD Data組成。

0B 09 4E 6F 72 64 69 63 5F 48 52 4D 03 19 41 03 02 01 06 07 03 0D 18 0F 18 0A 18

第一個位元組0B表示第一個AD Structure的長度是11個位元組,即第一個AD Structure是由0B加上緊跟著0B後面的11個位元組組成,因此,第一個AD Structure是:

0B 09 4E 6F 72 64 69 63 5F 48 52 4D

                                                  表1:第1個AD Structure的意義

Length

AD Type

AD Data

0B

09

4E 6F 72 64 69 63 5F 48 52 4D

11位元組

AD type為“完整的本地名稱”

程式中定義的為”Nordic_HRM”對應的十六進位制就是4E 6F 72 64 69 63 5F 48 52 4D

第2個AD Structure是03 19 41 03

                                      表2:第2個AD Structure的意義

Length

AD Type

AD Data

03

19

41 03

3位元組

AD type為“外觀特性”

外觀特性是一個16位的數值,由SIG定義,用來列舉裝置的外觀樣式,指示裝置是普通手機,手環什麼的。

第3個AD Structure是02 01 06

                                    表3:第3個AD Structure的意義

Length

AD Type

AD Data

02

01

06

2位元組

AD type為“Flag”

flag說明了物理連線功能,比如有限發現模式,不支援經典藍芽等。

l          bit 0: LE 有限發現模式。

l          bit 1: LE 普通發現模式。

l          bit 2: 不支援 BR/EDR。

l          bit 3: 對 Same Device Capable(Controller) 同時支援 BLE 和 BR/EDR。

l          bit 4: 對 Same Device Capable(Host) 同時支援 BLE 和 BR/EDR。

bit 5..7: 預留。

 第4個AD Structure是07 03 0D 18 0F 18 0A 18

                                   表4:第4個AD Structure的意義

Length

AD Type

AD Data

07

03

0D 18 0F 18 0A 18

7位元組

AD type為“16bit Service uuid列表”

該裝置支援的完整的16bit Service uuid列表。

l      180D:Heart Rate service UUID(心率服務UUID)

l      180F:Battery service UUID(電池服務UUID)

l      180A:Device Information service UUID(裝置資訊服務UUID)

16bit UUID:

128位的UUID相當長,裝置間為了識別資料的型別需要傳送長達16位元組的資料。為了提高傳輸效率,藍芽技術聯盟(SIG)定義了一個稱為“UUID基數”的128位通用唯一識別碼,結合一個較短的16位數使用。二者仍然遵循通用唯一識別碼的分配規則,只不過在裝置間傳輸常用的UUID時,只發送較短的16位版本,接收方收到後補上藍芽UUID基數即可。

藍芽UUID基數如下:

00000000 – 0000 – 1000 – 8000 – 008059B34FB

如要傳送的16位UUID為0x2A01,完整的128的UUID便是:

00002A01 – 0000 – 1000 – 8000 – 008059B34FB

低功耗藍芽使用的那部分UUID被分為下列幾組:

l          0x1800 ~ 0x26FF:用作服務類通用唯一識別碼。

l          0x2700 ~ 0x27FF:用於標識計量單位。

l          0x2800 ~ 0x28FF:用於區分屬性型別。

l          0x2900 ~ 0x29FF:用作特性描述。

l          0x2A00 ~ 0x7FFF:用於區分特性型別。

  在程式的“ble_srv_common.h”檔案中定義了16bit service UUID,如下,當然也可以在SIG官網上查詢:

複製程式碼
 1 #define BLE_UUID_ALERT_NOTIFICATION_SERVICE                      0x1811     /**< Alert Notification service UUID. */ 2 #define BLE_UUID_BATTERY_SERVICE                                 0x180F     /**< Battery service UUID. */ 3 #define BLE_UUID_BLOOD_PRESSURE_SERVICE                          0x1810     /**< Blood Pressure service UUID. */ 4 #define BLE_UUID_CURRENT_TIME_SERVICE                            0x1805     /**< Current Time service UUID. */ 5 #define BLE_UUID_CYCLING_SPEED_AND_CADENCE                       0x1816     /**< Cycling Speed and Cadence service UUID. */ 6 #define BLE_UUID_DEVICE_INFORMATION_SERVICE                      0x180A     /**< Device Information service UUID. */ 7 #define BLE_UUID_GLUCOSE_SERVICE                                 0x1808     /**< Glucose service UUID. */ 8 #define BLE_UUID_HEALTH_THERMOMETER_SERVICE                      0x1809     /**< Health Thermometer service UUID. */ 9 #define BLE_UUID_HEART_RATE_SERVICE                              0x180D     /**< Heart Rate service UUID. */10 #define BLE_UUID_HUMAN_INTERFACE_DEVICE_SERVICE                  0x1812     /**< Human Interface Device service UUID. */11 #define BLE_UUID_IMMEDIATE_ALERT_SERVICE                         0x1802     /**< Immediate Alert service UUID. */12 #define BLE_UUID_LINK_LOSS_SERVICE                               0x1803     /**< Link Loss service UUID. */13 #define BLE_UUID_NEXT_DST_CHANGE_SERVICE                         0x1807     /**< Next Dst Change service UUID. */14 #define BLE_UUID_PHONE_ALERT_STATUS_SERVICE                      0x180E     /**< Phone Alert Status service UUID. */15 #define BLE_UUID_REFERENCE_TIME_UPDATE_SERVICE                   0x1806     /**< Reference Time Update service UUID. */16 #define BLE_UUID_RUNNING_SPEED_AND_CADENCE                       0x1814     /**< Running Speed and Cadence service UUID. */17 #define BLE_UUID_SCAN_PARAMETERS_SERVICE                         0x1813     /**< Scan Parameters service UUID. */18 #define BLE_UUID_TX_POWER_SERVICE                                0x1804     /**< TX Power service UUID. */
複製程式碼

2.3.3 校驗

  EF A6 F0:24位CRC。24位CRC的生成多項式如下,對CRC演算法感興趣的朋友可以研究一下: