Linux卸载蓝牙模块,Linux 下调试低功耗蓝牙的笔记
藍牙4.0版本推出了低功耗規范,簡稱BLE?(Bluetooth Low Energy),很多小型設備,例如小米手環,都是使用低功耗藍牙。要與這類模塊連接,主設備的藍牙模塊必須支持低功耗,例如intel 2230:
現在有一個BLE的透傳模塊,會不斷的發出數據,我的主機安裝了Linux,使用intel 2230接收數據。協議棧依然是BlueZ。
1. GATT協議
BLE?連接都是建立在GATT協議之上的。介紹GATT之前,需要了解GAP(Generic
Access Profile)。它在用來控制設備連接和廣播。GAP使你的設備被其他設備可見,并決定了你的設備是否可以或者怎樣與合同設備進行交互。GAP給設備定義了若干角色,其中主要的兩個是:外圍設備(Peripheral)和中心設備(Central),外設必須不停的向外廣播,讓中心設備知道它的存在。中心設備掃描到外設后,發起并建立GATT連接。
GATT 連接是獨占的,也就是一個BLE外設同時只能被一個中心設備連接。一旦外設被連接,它就會馬上停止廣播。中心設備和外設需要雙向通信的話,唯一的方式就是建立GATT連接。一個外設只能連接一個中心設備,而一個中心設備可以連接多個外設。GATT定義BLE通信的雙方是C/S關系,外設作為服務端(Server),也叫從設備(Slave),中心設備是客戶端(Client),也叫主設備(Master)。所有的通信事件,都是由Client發起請求,Server作出響應。但GATT還有兩個特性:notification和indication。這意味著server可以主動發出通知和指示,使client端不用輪詢。
GATT 是一個在藍牙連接之上的發送和接收很短的數據段的通用規范(ATT),這些很短的數據段被稱為屬性(Attribute)。一個attribute由三種元素組成:
一個16位的句柄(handle)
一個定長的值(value)
一個UUID,定義了attribute的類型,value的意義完全由UUID決定。
attribute 的handle具有唯一性,僅用作區分不用的attribute(因為可能有很多不同的attribute擁有相同的UUID)
Attribute 只存儲在Server端,多個attribute構成一個characteristic(特征值),一個或多個characteristic構成一個Service?(服務),一個BLE設備可以有多個Service,Service是把數據分成一個個的獨立邏輯項。
一個GATT?Service始于UUID為0x2800的attribute,直到下一個UUID為0x2800的attribute為止。范圍內的所有attribute都屬于該服務的。例如,一臺有三種服務的設備擁有如下所示的attribute布局:
Handle
UUID
Description
Value
0x0100
0x2800
ServiceA definition
0x1816 (UUID)
...
...
Servicedetails
...
0x0150
0x2800
ServiceB definition
0x18xx
...
...
Servicedetails
...
0x0300
0x2800
ServiceC definition
0x18xx
...
...
Servicedetails
...
handle 具有唯一性,屬于Service?B的attribute的handle范圍肯定落在0x0151和0x02ff之中。那么,我如何知道一個Service是溫度檢測,還是GPS呢?通過讀取該Service的attribute的value。UUID為0x2800的attribute作為Service的起始標志,它的value就是該服務的UUID,是該服務的唯一標識,表示了該服務的類型。UUID有16 bit的,或者128 bit的。16 bit的UUID是官方通過認證的,需要購買,128 bit是自定義的,這個就可以自己隨便設置。
每個Service都包含一個或多個characteristic(特征值)。這些characteristic負責存儲Service的數據和訪問權限。每個Characteristic用16 bit或者128
bit的UUID唯一標識。例如,一個溫度計(service)一般會有一個只讀的“溫度”characteristic,和一個可讀寫的“日期時間”characteristic:
Handle
UUID
Description
Value
0x0100
0x2800
Thermometer?service?definition
UUID 0x1816
0x0101
0x2803
Characteristic: temperature
UUID 0x2A2B,Value handle:
0x0102
0x0102
0x2A2B
Temperature value
20 degrees
0x0110
0x2803
Characteristic: date/time
UUID 0x2A08,Value handle:
0x0111
0x0111
0x2A08
Date/Time
1/1/1980 12:00
可以看到,handle 0x0101定義了一個“溫度”characteristic,該characteristic的UUID是0x2A2B,它的值位于handle 0x0102。
除了value,還可以在characteristic的附加attribute里獲取到其它信息。這些附加的attribute稱為descriptor。例如,當我們我們需要明確溫度計的計量單位時,可以通過添加一個descriptor來實現:
Handle
UUID
Description
Value
0x0100
0x2800
Thermometer?service?definition
UUID 0x1816
0x0101
0x2803
Characteristic: temperature
UUID 0x2A2B,Value handle:
0x0102
0x0102
0x2A2B
Temperature value
20 degrees
0x0104
0x2A1F
Descriptor: unit
Celsius
0x0110
0x2803
Characteristic: date/time
UUID 0x2A08,Value handle:
0x0111
0x0111
0x2A08
Date/Time
1/1/1980 12:00
GATT 知道handle 0x0104是屬于characteristic 0x0101的descriptor,因為:
它不是一個value
attribute,因為value attribute已經指明是handle 0x0102
它剛好在0x0103..0x010F的范圍內,兩個characteristic之間
每個service都可以自定義desctiptor,GATT已經預定義了一系列常用的desctiptor:
數據格式和表達方式
可讀性描述
有效范圍
擴展屬性
其中一個很重要的descriptor是client?characteristic configuration,簡稱CCC descriptor,它的UUID是0x2902,有一個可讀性的16位Value,低兩位已經被占用,用于配置characteristic的notification和indication:
Bit 0 設為1表示使能Notification
Bit 1 設為1表示使能Indication
對于具有Notify屬性的characteristic,使能Notification后,數據發生變化時會主動通知Client端,Client端只要監聽即可。
2.?Linux中的操作
在BlueZ中就要用hcitool lescan?命令掃描低功耗藍牙設備:
root@WR-IntelligentDevice:~#
hcitool lescan
LE Scan ...
20:91:48:6B:65:08 (unknown)
20:91:48:6B:65:08
SPP_2091486B6508
gatttool?是用來訪問BLE設備的命令,用gatttool -b 20:91:48:6B:65:08 -I?打開一個與遠程設備的會話,-I表示交互模式:
root@WR-IntelligentDevice:~#
gatttool -b 20:91:48:6B:65:08 -I
[?? ][20:91:48:6B:65:08][LE]> help
help?????????????????????????????????????????? Show
this help
exit??????????????????????????????????? ???????Exit interactive mode
quit?????????????????????????????????????????? Exit
interactive mode
connect???????? [address [address type]]?????? Connect to a remote device
disconnect???????????????????????????????????? Disconnect
from a remote device
primary???????? [UUID]???????????????????????? Primary Service Discovery
characteristics [start hnd [end
hnd [UUID]]]?? Characteristics Discovery
char-desc?????? [start hnd] [end hnd]????????? Characteristics Descriptor Discovery
char-read-hnd?? [offset]????????????? Characteristics Value/Descriptor
Read by handle
char-read-uuid? [start hnd] [end hnd]?? Characteristics Value/Descriptor Read by
UUID
char-write-req? Characteristic Value Write (Write
Request)
char-write-cmd? Characteristic Value Write (No
response)
sec-level?????? [low | medium | high]????????? Set security level. Default: low
mtu???????????? Exchange MTU for
GATT/ATT
[?? ][20:91:48:6B:65:08][LE]>
connect?表示連接遠程設備,連接成功后,提示符簽名的狀態會顯示"CON" :
[?? ][20:91:48:6B:65:08][LE]> connect
[CON][20:91:48:6B:65:08][LE]>
primary?命令會列出遠程設備上所有的Service,每個服務所在的handle范圍:
[CON][20:91:48:6B:65:08][LE]>
primary
[CON][20:91:48:6B:65:08][LE]>
attr handle: 0x0001, end grp
handle: 0x000b uuid: 00001800-0000-1000-8000-00805f9b34fb
attr handle: 0x000c, end grp
handle: 0x000f uuid: 00001801-0000-1000-8000-00805f9b34fb
attr handle: 0x0010, end grp
handle: 0x0017 uuid: 0000fee7-0000-1000-8000-00805f9b34fb
attr handle: 0x0018, end grp
handle: 0x001b uuid: 0000fee0-0000-1000-8000-00805f9b34fb
attr handle: 0x001c, end grp
handle: 0x0024 uuid: f000ffc0-0451-4000-b000-000000000000
attr handle: 0x0025, end grp
handle: 0x002f uuid: 0000ccc0-0000-1000-8000-00805f9b34fb
attr handle: 0x0030, end grp
handle: 0xffff uuid: 0000180a-0000-1000-8000-00805f9b34fb
用primary fee7?查看UUID為0xfee7的Service,執行characteristics 0x0010 0x0017?可以發現它有三個characteristics:
[CON][20:91:48:28:26:AF][LE]>
primary fee7
[CON][20:91:48:28:26:AF][LE]>
Starting handle: 0x0010 Ending
handle: 0x0017
[CON][20:91:48:28:26:AF][LE]>
characteristics 0x0010 0x0017
[CON][20:91:48:28:26:AF][LE]>
handle: 0x0011, char properties:
0x20, char value handle: 0x0012, uuid: 0000fec8-0000-1000-8000-00805f9b34fb
handle: 0x0014, char properties:
0x0a, char value handle: 0x0015, uuid: 0000fec7-0000-1000-8000-00805f9b34fb
handle: 0x0016, char properties:
0x02, char value handle: 0x0017, uuid: 0000fec9-0000-1000-8000-00805f9b34fb
char properties 表示characteristic的屬性,char value handle表示characteristic的值所在的attribute的handle。下面是characteristic properties的說明:
現在遠程設備上有一個透傳服務是0xFEE0,傳輸數據的特征值是0xFEE1,可以用如下方式查看:
[CON][20:91:48:6B:65:08][LE]>
primary 0xfee0
[CON][20:91:48:6B:65:08][LE]>
Starting handle: 0x0018 Ending
handle: 0x001b
[CON][20:91:48:6B:65:08][LE]>
characteristics? 0x0018 0x001b
[CON][20:91:48:6B:65:08][LE]>
handle: 0x0019, char properties:
0x14, char value handle: 0x001a, uuid: 0000fee1-0000-1000-8000-00805f9b34fb
[CON][20:91:48:6B:65:08][LE]>
char-desc 0x0018 0x001b
[CON][20:91:48:6B:65:08][LE]>
handle: 0x0018, uuid: 2800
handle: 0x0019, uuid: 2803
handle: 0x001a, uuid: fee1
handle: 0x001b, uuid: 2902
首先執行primary 0xfee0?,發現該服務包含handle
0x0018到handle 0x001b之間的attribute。然后用characteristics 0x0018 0x001b?發現該服務有一個characteristic,它的值在handle 0x001a,屬性是0x14,表示可寫無回復/通知(Write
without response/Notify)。最后用char-desc 0x0018 0x001b?列出該特征值的所有Descriptor,最后一個UUID為0x2902,是一個CCC Descriptor,讀取它當前的值:
[CON][20:91:48:28:26:AF][LE]>
char-read-hnd 0x001b
[CON][20:91:48:28:26:AF][LE]>
Characteristic value/descriptor:
00 00
通過handle讀寫的好處是準確,因為handle具有唯一性。如果執行char-read-uuid 0x2902?,就會發現列出了很多個attribute。
當前的值是0,這個characteristic的屬性是Notify,所以要向handle 0x001b寫入0x0100(X86是小端),使能Notify,然后就會不停的收到數據:
[CON][20:91:48:28:26:AF][LE]>
char-write-req 0x001b 0100
[CON][20:91:48:28:26:AF][LE]>
Characteristic value was written successfully
Notification handle = 0x001a
value: 41 47 3a 20 37 30 34 38 20 37 30 39 35 20 36 30 20 2d 31 37
[CON][20:91:48:28:26:AF][LE]>
Notification handle = 0x001a
value: 20 2d 32 31 33 20 39 34 36 20 2d 39 33 30 20 2d 31 39 36 20
[CON][20:91:48:28:26:AF][LE]>
Notification handle = 0x001a
value: 39 33 38 20 2d 39 33 30 0a 41 47 3a 20 37 30 34 31 20 37 31
[CON][20:91:48:28:26:AF][LE]>
在非交互模式下,用--listen?選項啟動監聽模式來接收通知:
root@WR-IntelligentDevice:~#
gatttool -b 20:91:48:28:26:AF --char-write-req --handle=0x001b --value=0100
--listen
Characteristic value was written
successfully
Notification handle = 0x001a
value: 32 30 37 32 20 35 33 32 39 20 34 32 39 35 20 41 47 3a 20 2d
Notification handle = 0x001a
value: 32 30 37 36 20 35 33 32 36 20 34 33 30 30 20 41 47 3a 20 2d
Notification handle = 0x001a
value: 32 30 37 38 20 35 33 32 37 20 34 33 30 35 20 41 47 3a 20 2d
3.參考
總結
以上是生活随笔為你收集整理的Linux卸载蓝牙模块,Linux 下调试低功耗蓝牙的笔记的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 如何将linux装入空白硬盘,如何将ti
- 下一篇: 幸运爱消除能提现吗