版權聲明:本文為博主原創文章,轉載請注明作者和出處。 作者:強光手電[艾克姆科技-無線事業部]
在使用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 P2584的2.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算法感興趣的朋友可以研究一下: