Raspberry Piでbluezを使ってBLESerialとつなぐ


Arduino + 浅草技研さんの[BLESerial](http://www.robotsfx.com/robot/BLESerial.html)で自作した温湿度センサーから取得した値を飛ばし、Raspberry Piで受信していろいろやるのが目的。
Bluezに依存しているが、Raspberry Piには依存していないのでLinuxならいけるはず。

まずはbluezを
http://qiita.com/u_one/items/9b6f6bd37c0e221bfa16
等を参考にしてソースをDL、ビルドしてインストール。
インストールしたのはBluez-5.29[^1]
[^1]: apt-getでもbluezはインストールできるもののVer.が古くてBLEに対応していないのか、BLESerialにconnectできない。gatttoolで接続する時に-tでLEアドレスをランダムにする必要があるが、古いバージョンはそれがない。それが原因かどうかは不明だが…
BLEドングルはiBUFFALOの[BSBT4D09BK](http://www.amazon.co.jp/gp/product/B0096FIF0C/ref=as_li_ss_tl?ie=UTF8&camp=247&creative=7399&creativeASIN=B0096FIF0C&linkCode=as2&tag=yu0b-22 "BSBT4D09BK")を使用。

```
$ sudo hcitool lescan
LE Scan ...
XX:XX:XX:XX:XX:XX (BLESerial)
```

↑用意したBLESerialのMACアドレスが表示されればOK

gatttoolでとりあえずInteractiveモードで接続。gatttoolのtの数に気をつける。

```
$ ./attrib/gatttool -b XX:XX:XX:XX:XX:XX -t random -I
[XX:XX:XX:XX:XX:XX][LE]>
```

Interactiveモードではこのようなコマンド待ち画面になるので、connectする。

```
[XX:XX:XX:XX:XX:XX][LE]> connect
Attempting to connect to XX:XX:XX:XX:XX:XX
Connection successful
```

BLESerialのAndroid版サンプルソースを参考にBLESerialで使用するサービスのハンドルを調べる。
primaryコマンドでBLESerialのサービスUUIDを調べてサンプルソースと一致するものを探す。

```
[XX:XX:XX:XX:XX:XX][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: 0x0018 uuid: 0000180a-0000-1000-8000-00805f9b34fb
attr handle: 0x0019, end grp handle: 0xffff uuid: 569a1101-b87f-490c-92cb-11ba5ea5167c
```

AndroidのサンプルソースではBLESerialのサービスUUIDは569a1101-b87f-490c-92cb-11ba5ea5167cと書かれているので、これを探す。すると対応するhandleは0x0019と判明。
次にhandleを使用してchar-descコマンドで0x0019を調べる。

```
[XX:XX:XX:XX:XX:XX][LE]> char-desc 0x0019
handle: 0x0019, uuid: 00002800-0000-1000-8000-00805f9b34fb
handle: 0x001a, uuid: 00002803-0000-1000-8000-00805f9b34fb
handle: 0x001b, uuid: 569a2000-b87f-490c-92cb-11ba5ea5167c
handle: 0x001c, uuid: 00002902-0000-1000-8000-00805f9b34fb
handle: 0x001d, uuid: 00002803-0000-1000-8000-00805f9b34fb
handle: 0x001e, uuid: 569a2001-b87f-490c-92cb-11ba5ea5167c
handle: 0x001f, uuid: 00002803-0000-1000-8000-00805f9b34fb
handle: 0x0020, uuid: 569a2002-b87f-490c-92cb-11ba5ea5167c
handle: 0x0021, uuid: 00002902-0000-1000-8000-00805f9b34fb
handle: 0x0022, uuid: 00002803-0000-1000-8000-00805f9b34fb
handle: 0x0023, uuid: 569a2003-b87f-490c-92cb-11ba5ea5167c
```

たくさん出てきたが、サンプルソースによるとキャラクタリスティック設定UUIDは00002902-0000-1000-8000-00805f9b34fbとあるので、とりあえず読んでみる。

```
[XX:XX:XX:XX:XX:XX][LE]> char-read-uuid 00002902-0000-1000-8000-00805f9b34fb
handle: 0x000b   value: 01 00
handle: 0x001c   value: 00 00
handle: 0x0021   value: 00 00
```

するとハンドルが三つほど取得できた。
これのどれかにENABLE_NOTIFICATION_VALUE = 01 00を書き込むと、BLESerialからNotificationが降ってくるようになるようなので、上から順番にWriteする。が、一番上はすでに01 00になっているので、0x001cに書き込んでみる。

```
[XX:XX:XX:XX:XX:XX][LE]> char-write-req 0x001c 0100
Characteristic value was written successfully
```

すると、BLESerialで送信するようにしていれば、下記のようにデータが降ってくるようになる。
valueはセンサ情報を表す独自データ。

```
Notification handle = 0x001b value: 00 03 ad 01 02 00 02 01 ee 03 02 c0 04 01 13 05 01 96 06 27
Notification handle = 0x001b value: 59 00 03 b2 01 02 00 02 01 ee 03 02 c0 04 01 13 05 01 94 06
Notification handle = 0x001b value: 27 5a 00 03 b0 01 01 fd 02 01 ef 03 02 c0 04 01 13 05 01 94
Notification handle = 0x001b value: 06 27 59 00 03 b3 01 01 fd 02 01 ef 03 02 c1 04 01 13 05 01
Notification handle = 0x001b value: 93 06 27 5b 00 03 b4 01 02 00 02 01 ee 03 02 c0 04 01 13 05
Notification handle = 0x001b value: 01 93 06 27 5b 00 03 aa 01 01 ff 02 01 ee 03 02 c0 04 01 14
Notification handle = 0x001b value: 05 01 92 06 27 59 00 03 59
Notification handle = 0x001b value: 00 03 b0 01 01 ff 02 01 ee 03 02 c1
Notification handle = 0x001b value: 04 01 1a 05 01 79 06 27 5a
Notification handle = 0x001b value: 00 03 af 01 01 ff 02 01 ee 03 02 c0
Notification handle = 0x001b value: 04 01 1a 05 01 79 06 27 59
Notification handle = 0x001b value: 00 03 b8 01 01 ff 02 01 ef 03 02 c0
Notification handle = 0x001b value: 04 01 1a 05 01 79 06 27 59
Notification handle = 0x001b value: 00 03 b8 01 01 fe 02 01 ee 03 02 c2
```

これでBLESerialから受信できた。
一旦NotificationをDisableにする。

```
[XX:XX:XX:XX:XX:XX][LE]> char-write-req 0x001c 0000
Characteristic value was written successfully
```

あとは、gatttoolのInteractiveモードではなく、1 commandでこれができるようになれば、ラズパイで受信していろいろ処理できるようになる。

gatttoolのhelpを見ながら、このようなコマンドでいけることがわかった。

```
$ ./attrib/gatttool -b XX:XX:XX:XX:XX:XX -t random --char-write-req -a 0x001c -n 0100 --listen
```

ハンドル0x001cに0100を書き込み、受信モードに入るコマンド。
受け取っているのはバイナリデータなので、下記のようにperlに食わせたらいい感じに取れるようになった。

```
$ ./attrib/gatttool -b XX:XX:XX:XX:XX:XX -t random --char-write-req -a 0x001c -n 0100 --listen | perl -ne 'if(/.*value: (\w+) (\w+) (\w+)/) { ($x,$y,$z) = ($1,$2,$3); \\
     printf("%f,%f,%f\n", unpack("c",pack("C",hex($x)))/64., \\
                          unpack("c",pack("C",hex($y)))/64., \\
                          unpack("c",pack("C",hex($z)))/64.); }'
```