2015年10月29日木曜日

gatttool を使って SensorTag CC2650 の KeyPressState の Notification を受信してみた

概要

bluez の gatttool と SensorTag CC2650 を使って SensorTag 側のボタンが押されたことを gatttool 側で受信してみました
たぶんこんなニッチな記事を日本語で書いているのはこれくらいだと思う、、、

環境

  • Raspberry Pi Type B Single Board Computer 512MB
  • Raspbian 8.0 (Jessie)
  • Kernel Version 4.1.7+
  • BlueZ 5.23-2+b1

事前作業

RaspberryPi の構築 や bluez のインストール を実施して gatttool が使えるようになるようにしてください

そもそも notification とは

Bluetooth Low Energy のデバイスから情報 (GATT) を読み込みするための方法の 1 つです
読み込みするには、他に read という方法がありこれはデバイスに対して直接データを読み込みにいく方法です
対して notification はデバイス側からデータをプッシュすることで受け取り側にデータを読みこませる方法です

notification のポイントとしては初めにデバイス側に notification の受信要求を実施させる必要がある点です
この受信要求はどうやっているかと言うとデバイス側のある書き込み可能領域に 0 or 1 のフラグを書き込みます
書き込みに成功すると書き込んだ側に対して初めて notification を送信することができます

  • read
    enter image description here

  • notification
    enter image description here

gatttool で notification の受信

前置きが長くなりましたが試していきます
まずは SensorTag の電源を ON にして connection 待機状態 (Advertising) にしましょう
CC2650 であれば緑の LED が点灯すれば OK です

では gatttool で接続していきます
コマンドは以下の通りです

  • gatttool -t public -b xx:xx:xx:xx:xx:xx --char-write-req --handle=0x4a --value=0100 --listen

「-b」のあとには Mac アドレスが入るので持っている SensorTag の Mac アドレスを入力してください
その他のパラメータはそのまま使ってください

簡単に説明すると --char-write-req で notification のための書き込み要求をしています
--handle で書き込みをするアドレスを指定して、そのアドレスに--value で書き込む値を指定します
最後に --listen することで書き込み後にデバイスからの notification を待つようにしています

コマンドを実行すると以下のように書き込みが成功した旨が表示されます

Characteristic value was written successfully

これが表示されれば notification を受け取る準備ができました
SensorTag の横にある (電源とは逆の方向にある) ボタンを押してみましょう
すると以下のようにボタンが押されたイベントを受信することができると思います

Notification handle = 0x0049 value: 01
Notification handle = 0x0049 value: 00

gatttool の場合は handle と value が表示されるだけのようです
0x0049 はボタンが押されたときの状態を管理するアドレスです
value の 00, 01 はそれぞれ「ボタンから離れた時の状態」「ボタンが押された時の状態」になります
長押ししてから話すと状態の遷移の様子がよくわかると思います

そもそも、その handler が書き込めるってどうやって発見したんだ

notification の仕組み自体を理解するまでも大変でしたが、0x0049 のハンドラに書き込みを行うことでなぜボタンを押したイベントを notification で受け取れるのか・・・
ということをどうやって知ったかですが正直いろいろ調べて試しました
その経験上こうやってやると、うまく調べられるという方法も紹介します

まず BLE 機器には「ここのこのアドレスに read するとこんな値が取れるよ」というアドレス一覧表みたいなのがあります
SensorTag の一覧表は以下になります
http://processors.wiki.ti.com/images/a/a8/BLE_SensorTag_GATT_Server.pdf

SensorTag に触ったことがある人であればこの表は一度は見たことがあると思います
で、実はこの表は CC2650 には完全に当てはまりません
例えば 0x73 というハンドラは表で見ると「Test Config」とあって RW で書き込めるはずですが、実際に書き込んでみると書き込めません

ではハンドラを探す方法ですがまずこの表の中で「Key Press State」を管理している UUID を探します
すると UUID は「0xFFE1」だということがわかります
find_key_press.png

そしてその下に「Client Characteristic Configuration」が RW で存在していると思います
Client Characteristic Configuration はクライアントが書き込み可能な領域として定義されているものです
そしてその Client Characteristic Configuration の UUID を見てみると「0x2902」だということがわかります
※もしかしたら UUID も SensorTag の型で違う可能性がありますが、経験上 UUID は他の型でも同じ場合が多いです

とりあえずこの UUID を覚えておきましょう
次に primary コマンドを使って SensorTag が持つサービスの一覧を表示します
その中で Key Press State を管理するサービスを探します

attr handle: 0x0047, end grp handle: 0x004b uuid: 0000ffe0-0000-1000-8000-00805f9b34fb

「これが何で Key Press State のサービスってわかるんだ」と思う方もいると思いますが、先ほどの表で「ffe0」で検索すると「Simple Key Service」というのがあると思います
「ffe0」はどこから持ってきたかというと primary コマンドで、ずらっと表示された中に uuid が 0000ffe0 で始まるものを探しました

サービスがわかったら、このサービスが持つハンドラの範囲 (0x0047 - 0x004b) に存在する UUID を更に調べます
調べるには char-desc というコマンドを使います

  • char-desc 0x47 0x4b

すると以下のような結果が返ってくると思います

handle: 0x0047, uuid: 00002800-0000-1000-8000-00805f9b34fb
handle: 0x0048, uuid: 00002803-0000-1000-8000-00805f9b34fb
handle: 0x0049, uuid: 0000ffe1-0000-1000-8000-00805f9b34fb
handle: 0x004a, uuid: 00002902-0000-1000-8000-00805f9b34fb
handle: 0x004b, uuid: 00002901-0000-1000-8000-00805f9b34fb

この中に先ほど調べた「Client Characteristic Configuration」の uuid 「0x2902」があり、そのハンドラを見ると「0x004a」だということがわかります
また、「0x0049」というハンドラが notification 受信時に出力されたハンドラと一致することも確認できると思います

表と照らしあわせてみると分かりますが、表のハンドラは「0x6A」であるのに対して調べてみたわかったハンドラは「0x4A」でやはり CC2650 は表と違うことがわかると思います

最後に

BLE の情報は Web で探してもなかなか見つからず、解決するのに時間と根性をかなり費やすとつくづく感じさせられます

0 件のコメント:

コメントを投稿