假日藍芽工程師, ATT protocol
前言
搞定從Raspberry Pi讀心跳之後(by notification),下一步就是弄清楚BLE通信協定。這篇文章希望可以提供一些範例,解釋GATT/ATT是怎麼運作的。希望他能幫助社會大眾了解BLE是怎麼玩的。
ATT (Attribute)
所有BLE裝置都要支援ATT (Attribute, 屬性)協定。看起來很厲害,其實只是一個資料結構:
struct {
u16 uuid; // Universally Unique Identifier
u8 *data; // variable length data
} att[65536];
這個通訊協定就是一張表格,一個陣列。陣列允許random access,只要給個index就可以了。在BLE的術語理,這個index叫handle。表格每個單元還包括16bit的UUID作為metadata,解釋這筆資料是什麼。另外資料並不是直接嵌在表格,而是放一個指標,允許可變長度的資料。
在上篇文章,我用了gatttool和心跳表打交道。這個工具就是透過RPi的藍芽dongle和心跳表的ATT layer打交道。參考gatttool的說明功能表就可以看出ATT protocol的功能:
在工具裡,執行"char-desc"可以把藍芽裝置所有的handle和對應的UUID讀出。對應的pseudo code看起來很像這樣:
搞定從Raspberry Pi讀心跳之後(by notification),下一步就是弄清楚BLE通信協定。這篇文章希望可以提供一些範例,解釋GATT/ATT是怎麼運作的。希望他能幫助社會大眾了解BLE是怎麼玩的。
ATT (Attribute)
所有BLE裝置都要支援ATT (Attribute, 屬性)協定。看起來很厲害,其實只是一個資料結構:
struct {
u16 uuid; // Universally Unique Identifier
u8 *data; // variable length data
} att[65536];
這個通訊協定就是一張表格,一個陣列。陣列允許random access,只要給個index就可以了。在BLE的術語理,這個index叫handle。表格每個單元還包括16bit的UUID作為metadata,解釋這筆資料是什麼。另外資料並不是直接嵌在表格,而是放一個指標,允許可變長度的資料。
在上篇文章,我用了gatttool和心跳表打交道。這個工具就是透過RPi的藍芽dongle和心跳表的ATT layer打交道。參考gatttool的說明功能表就可以看出ATT protocol的功能:
在工具裡,執行"char-desc"可以把藍芽裝置所有的handle和對應的UUID讀出。對應的pseudo code看起來很像這樣:
for handle in range(1, 65535):
if att[handle] is effective:
if att[handle] is effective:
print "handler=%d, uuid=%d", i, att[i].uuid
要在8051/ARM實作ATT protocol不會很難,就是一個存資料的資料結構而已。這邊有兩點值得再注意:
* Generic Access Service
- UUID代表Universal Unique IDentifier,這個ID和資料放在一起,功能是描述這筆資料是什麼,也就是俗稱的metadata。一般去google找"Bluetooth BLE NNNN"就找得到UUID的意義。
- ATT protocol對資料長度沒有限制,實際的規範定義在上層GATT裡
以handle[0x3]當例子,這筆的UUID = 0x2A00代表裝置名稱。下面的截圖讀到0x48, 0x52, 0x4D,對照ASCII表格就查得到是"HRM"。這個字串和我在手機上看到的是一致的。
我的心跳表
要分析BLE裝置支援的功能,gatttool真的是滿好用的。我做了一些功課讀出每個handle並且找出意義。下面看得到ATT表格看起來是同樣功能的東西會集中在一起。這裡面也有一些有趣的參數,比如handle[0x1F]指出他是"Cambridge Silicon R"(CSR)的解決方案;handle[0x1b]指出開發工具的版本是"uEnergy SDK 1.4.3"。
handle: 0x0001, uuid: 2800 1800, Generic access
handle: 0x0002, uuid: 2803 0a 0003 2a00
handle: 0x0003, uuid: 2a00 Device Name, "HRM"
handle: 0x0004, uuid: 2803 02 05 2a01
handle: 0x0005, uuid: 2a01 Appearance, 0x340=832, Generic Heart Rate Sensor
handle: 0x0006, uuid: 2803 02 07 2a04, Peripheral preferred connection parameter
handle: 0x0007, uuid: 2a04 000a 0010 0064 04e2
min-connection-interval = 0xA * 1.25ms = 12.5ms
max-connection-interval = 0x10 * 1.25ms = 20ms
Slave latency = 0x64 * interval = 100*interval = 1.25s ~ 2s
Connection Superviser Timeout = 0x4E2 * interval = 1250 * interval = 15.625s ~ 25s
* Generic Attributes
handle: 0x0008, uuid: 2800 1801, Generic attributes
* Heart Rate
handle: 0x0009, uuid: 2800 180D, Heart Rate
handle: 0x000a, uuid: 2803 10 000b 2a37
handle: 0x000b, uuid: 2a37 Heart rate measurement, only notify (*)
handle: 0x000c, uuid: 2902 Control channel
handle: 0x000d, uuid: 2803 02 000e 2a38
handle: 0x000e, uuid: 2a38 01, chest
handle: 0x000f, uuid: 2803 08 0010 2a39
handle: 0x0010, uuid: 2a39 Heart rate control point
* Battery Service
handle: 0x0011, uuid: 2800 180F, Battery Service
handle: 0x0012, uuid: 2803 12 0013 2a19
handle: 0x0013, uuid: 2a19 Battery level, 0~100
handle: 0x0014, uuid: 2902 Control channel
* Device Information
handle: 0x0015, uuid: 2800 180A, Device Information
handle: 0x0016, uuid: 2803 02 0017 2a25
handle: 0x0017, uuid: 2a25 Serial Num, 34 36 58 41 36 37 39 57 44 4e 44 52 43 58 37 50 00
handle: 0x0018, uuid: 2803 02 0019 2a27
handle: 0x0019, uuid: 2a27 Hw Revision String, 41 30 34 55, “@04U"
handle: 0x001a, uuid: 2803 02 001b 2a26
handle: 0x001b, uuid: 2a26 FW Rev String, “uEnergy SDK 1.4.3”
handle: 0x001c, uuid: 2803 02 001d 2a28
handle: 0x001d, uuid: 2a28 SW Rev String, “1.4.3.1”
handle: 0x001e, uuid: 2803 02 001f 2a29
handle: 0x001f, uuid: 2a29 Manufacturer, “Cambridge Silicon R"
handle: 0x0020, uuid: 2803 02 0021 2a50
handle: 0x0021, uuid: 2a50 PnP ID, 01 000a 014c 0100, vendor-id-src, vendor-id, product-id, product-rev
下一步: GATT
根據這張表格,要搞懂GATT的意義應該會比較容易一點
留言
收益良多!!