Micro:bit : gatttoolを使ってアクセスしてみる

関連投稿
Micro:bit Bluetooth関連の調査
LinuxのBluetooth関連のコマンド
Micro:bit Raspberry Piとのペアリング

最終的には、プログラムでMicrobitとのBluetooth通信を行うつもりだが、gatttoolを使ってGATT(Generic ATTribute)プロファイルで通信をやってみて、正解となる動作を確認しておく。

関連投稿でMicrobitとBluetooth接続している場合は、一旦接続解除しておく。

[BBC micro:bit [vutaz]]# devices
Device DB:88:10:28:D8:61 BBC micro:bit [vutaz]
[BBC micro:bit [vutaz]]# disconnect
Attempting to disconnect from DB:88:10:28:D8:61
[CHG] Device DB:88:10:28:D8:61 ServicesResolved: no
Successful disconnected
[CHG] Device DB:88:10:28:D8:61 Connected: no
[CHG] Device DB:88:10:28:D8:61 Connected: yes
[BBC micro:bit [vutaz]]#

gatttoolで接続する

gatttoolでインタラクティブモードでMicrobitと接続する。-bでデバイスのMACアドレスを指定して、-tでBLEアドレスをランダム指定、-Iでインタラクティブモードになる。

>  gatttool -b DB:88:10:28:D8:61 -t random -I
[DB:88:10:28:D8:61][LE]> 

connectコマンドで接続する。また、primaryコマンドで利用できるサービスの一覧が表示できる。

[DB:88:10:28:D8:61][LE]> connect
Attempting to connect to DB:88:10:28:D8:61
Connection successful

GATTサービスの一覧

[DB:88:10:28:D8:61][LE]> primary
attr handle: 0x0001, end grp handle: 0x0007 uuid: 00001800-0000-1000-8000-00805f9b34fb
attr handle: 0x0008, end grp handle: 0x000b uuid: 00001801-0000-1000-8000-00805f9b34fb
attr handle: 0x000c, end grp handle: 0x000e uuid: e95d93b0-251d-470a-a062-fa1922dfa9a8
attr handle: 0x000f, end grp handle: 0x0015 uuid: 0000180a-0000-1000-8000-00805f9b34fb
attr handle: 0x0016, end grp handle: 0x0020 uuid: e95d93af-251d-470a-a062-fa1922dfa9a8
attr handle: 0x0021, end grp handle: 0x0027 uuid: e95d9882-251d-470a-a062-fa1922dfa9a8
attr handle: 0x0028, end grp handle: 0x0031 uuid: e95d127b-251d-470a-a062-fa1922dfa9a8
attr handle: 0x0032, end grp handle: 0xffff uuid: e95dd91d-251d-470a-a062-fa1922dfa9a8
[DB:88:10:28:D8:61][LE]>

GATT Services
BBC microbit V1_10

UUIDの最初の8桁の下4桁がサービス番号?になる。00001800Generic Accessになる。GATTはサービスに複数のキャラクタリスティックという属性が存在する。char-descコマンドと、handleのあとの16bitアドレスを指定して確認できる。

[DB:88:10:28:D8:61][LE]> char-desc 0x0001 0x0007
handle: 0x0001, uuid: 00002800-0000-1000-8000-00805f9b34fb
handle: 0x0002, uuid: 00002803-0000-1000-8000-00805f9b34fb
handle: 0x0003, uuid: 00002a00-0000-1000-8000-00805f9b34fb <--- Device Name
handle: 0x0004, uuid: 00002803-0000-1000-8000-00805f9b34fb
handle: 0x0005, uuid: 00002a01-0000-1000-8000-00805f9b34fb <--- Appearance
handle: 0x0006, uuid: 00002803-0000-1000-8000-00805f9b34fb
handle: 0x0007, uuid: 00002a04-0000-1000-8000-00805f9b34fb <--- Peripheral Preferred Connection Parameters

引数なしでchar-descを実行すると、全charactoristicがリストされる。

[DB:88:10:28:D8:61][LE]> char-desc
handle: 0x0001, uuid: 00002800-0000-1000-8000-00805f9b34fb
handle: 0x0002, uuid: 00002803-0000-1000-8000-00805f9b34fb
handle: 0x0003, uuid: 00002a00-0000-1000-8000-00805f9b34fb
handle: 0x0004, uuid: 00002803-0000-1000-8000-00805f9b34fb
handle: 0x0005, uuid: 00002a01-0000-1000-8000-00805f9b34fb
handle: 0x0006, uuid: 00002803-0000-1000-8000-00805f9b34fb
handle: 0x0007, uuid: 00002a04-0000-1000-8000-00805f9b34fb
handle: 0x0008, uuid: 00002800-0000-1000-8000-00805f9b34fb
handle: 0x0009, uuid: 00002803-0000-1000-8000-00805f9b34fb
handle: 0x000a, uuid: 00002a05-0000-1000-8000-00805f9b34fb
handle: 0x000b, uuid: 00002902-0000-1000-8000-00805f9b34fb
handle: 0x000c, uuid: 00002800-0000-1000-8000-00805f9b34fb
handle: 0x000d, uuid: 00002803-0000-1000-8000-00805f9b34fb
handle: 0x000e, uuid: e95d93b1-251d-470a-a062-fa1922dfa9a8
handle: 0x000f, uuid: 00002800-0000-1000-8000-00805f9b34fb
handle: 0x0010, uuid: 00002803-0000-1000-8000-00805f9b34fb
handle: 0x0011, uuid: 00002a24-0000-1000-8000-00805f9b34fb
handle: 0x0012, uuid: 00002803-0000-1000-8000-00805f9b34fb
handle: 0x0013, uuid: 00002a25-0000-1000-8000-00805f9b34fb
handle: 0x0014, uuid: 00002803-0000-1000-8000-00805f9b34fb
handle: 0x0015, uuid: 00002a26-0000-1000-8000-00805f9b34fb
handle: 0x0016, uuid: 00002800-0000-1000-8000-00805f9b34fb
handle: 0x0017, uuid: 00002803-0000-1000-8000-00805f9b34fb
handle: 0x0018, uuid: e95d9775-251d-470a-a062-fa1922dfa9a8
handle: 0x0019, uuid: 00002902-0000-1000-8000-00805f9b34fb
handle: 0x001a, uuid: 00002803-0000-1000-8000-00805f9b34fb
handle: 0x001b, uuid: e95d5404-251d-470a-a062-fa1922dfa9a8
handle: 0x001c, uuid: 00002803-0000-1000-8000-00805f9b34fb
handle: 0x001d, uuid: e95d23c4-251d-470a-a062-fa1922dfa9a8
handle: 0x001e, uuid: 00002803-0000-1000-8000-00805f9b34fb
handle: 0x001f, uuid: e95db84c-251d-470a-a062-fa1922dfa9a8
handle: 0x0020, uuid: 00002902-0000-1000-8000-00805f9b34fb
handle: 0x0021, uuid: 00002800-0000-1000-8000-00805f9b34fb
handle: 0x0022, uuid: 00002803-0000-1000-8000-00805f9b34fb
handle: 0x0023, uuid: e95dda90-251d-470a-a062-fa1922dfa9a8
handle: 0x0024, uuid: 00002902-0000-1000-8000-00805f9b34fb
handle: 0x0025, uuid: 00002803-0000-1000-8000-00805f9b34fb
handle: 0x0026, uuid: e95dda91-251d-470a-a062-fa1922dfa9a8
handle: 0x0027, uuid: 00002902-0000-1000-8000-00805f9b34fb
handle: 0x0028, uuid: 00002800-0000-1000-8000-00805f9b34fb
handle: 0x0029, uuid: 00002803-0000-1000-8000-00805f9b34fb
handle: 0x002a, uuid: e95d5899-251d-470a-a062-fa1922dfa9a8
handle: 0x002b, uuid: 00002803-0000-1000-8000-00805f9b34fb
handle: 0x002c, uuid: e95db9fe-251d-470a-a062-fa1922dfa9a8
handle: 0x002d, uuid: 00002803-0000-1000-8000-00805f9b34fb
handle: 0x002e, uuid: e95dd822-251d-470a-a062-fa1922dfa9a8
handle: 0x002f, uuid: 00002803-0000-1000-8000-00805f9b34fb
handle: 0x0030, uuid: e95d8d00-251d-470a-a062-fa1922dfa9a8
handle: 0x0031, uuid: 00002902-0000-1000-8000-00805f9b34fb
handle: 0x0032, uuid: 00002800-0000-1000-8000-00805f9b34fb
handle: 0x0033, uuid: 00002803-0000-1000-8000-00805f9b34fb
handle: 0x0034, uuid: e95d7b77-251d-470a-a062-fa1922dfa9a8
handle: 0x0035, uuid: 00002803-0000-1000-8000-00805f9b34fb
handle: 0x0036, uuid: e95d93ee-251d-470a-a062-fa1922dfa9a8
handle: 0x0037, uuid: 00002803-0000-1000-8000-00805f9b34fb
handle: 0x0038, uuid: e95d0d2d-251d-470a-a062-fa1922dfa9a8

キャラクタリスティックの値を取得

デバイス名を取得してみる。ハンドル指定であれば0x0003、uuidなら00002A00-0000-1000-8000-00805F9B34FBを指定すると、UTF8のHEXコードが返ってくる。(なぜかchar-read-uuidだと1文字欠けている?)

[DB:88:10:28:D8:61][LE]> char-read-hnd 0x0003
Characteristic value/descriptor: 42 42 43 20 6d 69 63 72 6f 3a 62 69 74 20 5b 76 75 74 61 7a 5d
[DB:88:10:28:D8:61][LE]> char-read-uuid 00002A00-0000-1000-8000-00805F9B34FB
handle: 0x0003   value: 42 42 43 20 6d 69 63 72 6f 3a 62 69 74 20 5b 76 75 74 61

コマンドラインからこのコードからASCII文字列に変換してみる。最良の方法が分からないので、HEXコードの前に%をつけてnkfコマンドで文字列にデコードしてみた。BBC micro:bit[vutaz]という名称であった。

> echo %42%42%43%20%6d%69%63%72%6f%3a%62%69%74%20%5b%76%75%74%61%7a%5d | nkf --url-input
BBC micro:bit [vutaz]

キャラクタ値の書き込みとNotify設定

前項で、値を取得することはできたので、今度は値を一定間隔または状態が変化したときに通知するように設定してみる。例として、TEMPERATURE SERVICE (E95D6100-251D-470A-A062-FA1922DFA9A8)の値を通知させてみる。

Temperature Serviceのキャラクタ一覧を表示する。

[DB:88:10:28:D8:61][LE]> primary E95D6100-251D-470A-A062-FA1922DFA9A8
Starting handle: 0x0048 Ending handle: 0x004d
[DB:88:10:28:D8:61][LE]> char-desc 0x0048 0x004d
handle: 0x0048, uuid: 00002800-0000-1000-8000-00805f9b34fb
handle: 0x0049, uuid: 00002803-0000-1000-8000-00805f9b34fb
handle: 0x004a, uuid: e95d9250-251d-470a-a062-fa1922dfa9a8
handle: 0x004b, uuid: 00002902-0000-1000-8000-00805f9b34fb
handle: 0x004c, uuid: 00002803-0000-1000-8000-00805f9b34fb
handle: 0x004d, uuid: e95d1b25-251d-470a-a062-fa1922dfa9a8

Bluetoothの仕様書では、1. Client Characteristic Configuration : 2902という記述があり、00002902から始まるUUIDのhandleに対して書き込みができるとのこと。現在の値をダンプしてみると、00 00になっていることがわかる。

[DB:88:10:28:D8:61][LE]> char-read-hnd 0x004b
Characteristic value/descriptor: 00 00

char-write-reqで該当するhandleに対して、0100を書き込むと、通知されるようになり、Temperature(0x004a)が1fなので31度ということになる。また0000を書き込むと、通知がオフになる。

[DB:88:10:28:D8:61][LE]> char-read-hnd 0x004b
Characteristic value/descriptor: 00 00
[DB:88:10:28:D8:61][LE]> char-write-req 0x004b 0100
Characteristic value was written successfully
Notification handle = 0x004a value: 1f
Notification handle = 0x004a value: 1f
Notification handle = 0x004a value: 1f
Notification handle = 0x004a value: 1f
Notification handle = 0x004a value: 1f
Notification handle = 0x004a value: 1f
:
[DB:88:10:28:D8:61][LE]> char-write-req 0x004b 0000
Characteristic value was written successfully
[DB:88:10:28:D8:61][LE]>

ちなみに通知されるサイクルは、e8 03なので1sec(エンディアン変換して0x03e8、10進だと1000msec)になる。試しに500msec(0x01f4)を書き込んで、再度読み取ってみると、前回よりも早く通知が来るようになる。(通信の遅延などもあるので、正確に0.5secで飛んでくるわけではない)

[DB:88:10:28:D8:61][LE]> char-read-hnd 0x004d
Characteristic value/descriptor: e8 03
[DB:88:10:28:D8:61][LE]> char-write-req 0x004d f401
Characteristic value was written successfully
[DB:88:10:28:D8:61][LE]> char-read-hnd 0x004d
Characteristic value/descriptor: f4 01
[DB:88:10:28:D8:61][LE]> char-write-req 0x004b 0100
Characteristic value was written successfully
Notification handle = 0x004a value: 1f
Notification handle = 0x004a value: 1f
:

同じようにButton Service(E95D9882-251D-470A-A062-FA1922DFA9A8)のAまたはBボタンのステートを通知させるようにして、MicrobitのAやBボタンを押してみる。

Button Serviceの場合、AとBボタンそれぞれにNotify設定を行う。0x0033がAボタン、0x0036がBボタンになる。Temperatureと同じように0100を書き込むと通知されるようになる。

[DB:88:10:28:D8:61][LE]> char-desc 0x0030 0x0036
handle: 0x0030, uuid: 00002800-0000-1000-8000-00805f9b34fb
handle: 0x0031, uuid: 00002803-0000-1000-8000-00805f9b34fb
handle: 0x0032, uuid: e95dda90-251d-470a-a062-fa1922dfa9a8
handle: 0x0033, uuid: 00002902-0000-1000-8000-00805f9b34fb
handle: 0x0034, uuid: 00002803-0000-1000-8000-00805f9b34fb
handle: 0x0035, uuid: e95dda91-251d-470a-a062-fa1922dfa9a8
handle: 0x0036, uuid: 00002902-0000-1000-8000-00805f9b34fb
[DB:88:10:28:D8:61][LE]> char-read-hnd 0x0033
Characteristic value/descriptor: 00 00
[DB:88:10:28:D8:61][LE]> char-read-hnd 0x0036
Characteristic value/descriptor: 00 00
[DB:88:10:28:D8:61][LE]> char-write-req 0x0033 0100
Characteristic value was written successfully
[DB:88:10:28:D8:61][LE]> char-write-req 0x0036 0100
Characteristic value was written successfully

この状態で、Microbitのボタンを押してみると、Aボタンのイベントが0x0032で、押下時が01、リリース時が00、同様にBボタンのhandleが0x0035になることが分かった。ちなみに長押しすると01のあとにしばらくして02が返る。

Notification handle = 0x0032 value: 01
Notification handle = 0x0032 value: 00
Notification handle = 0x0035 value: 01
Notification handle = 0x0035 value: 00