Linux でBLEのドングルを刺して通信させる。

http://www.adventar.org/calendars/523
mbed Advent Calendar 2014 の記事です。

Start typing in the blue box...Linuxでも開発したいので環境を整えてみました。

HW環境

1)lenovo ThinkPad x201
2)PRiNCETON PTM-UBT7 Bluetooth® USBアダプター
http://www.princeton.co.jp/product/ptmubt7.html
3)mbed HRM1017
http://www.switch-science.com/catalog/1755/

OS:Ubuntu14.04
Linux 3.13.0-32-generic #56-Ubuntu SMP Mon Jul 7 11:32:12 UTC 2014 x86_64 x86_64 x86_64 GNU/Linux
この環境です。
まず、USBドングルを刺して以下のコマンドで確認
ドングルを刺す前

kazu@kazu-develop:~$ hciconfig
hci0:	Type: BR/EDR  Bus: USB
	BD Address: 70:F3:95:48:19:CF  ACL MTU: 1021:8  SCO MTU: 64:1
	UP RUNNING PSCAN ISCAN 
	RX bytes:1050 acl:0 sco:0 events:52 errors:0
	TX bytes:1423 acl:0 sco:0 commands:52 errors:0

内臓のBTが現れています。次に、刺した後

kazu@kazu-develop:~$ hciconfig
hci1:	Type: BR/EDR  Bus: USB
	BD Address: 00:1B:DC:06:C9:6C  ACL MTU: 310:10  SCO MTU: 64:8
	UP RUNNING PSCAN 
	RX bytes:606 acl:0 sco:0 events:36 errors:0
	TX bytes:939 acl:0 sco:0 commands:36 errors:0

hci0:	Type: BR/EDR  Bus: USB
	BD Address: 70:F3:95:48:19:CF  ACL MTU: 1021:8  SCO MTU: 64:1
	UP RUNNING PSCAN ISCAN 
	RX bytes:1050 acl:0 sco:0 events:52 errors:0
	TX bytes:1423 acl:0 sco:0 commands:52 errors:0

hci1として新しいBT−USBの機器が認識されています。

1.新しいBlueZにする
https://www.kernel.org/pub/linux/bluetooth/
から最新のVerをDLします。
公式HP:http://www.bluez.org/bluez-low-energy-support-status/

$ wget https://www.kernel.org/pub/linux/bluetooth/bluez-5.21.tar.gz
$ tar -xvf bluez-5.21.tar.gz
$ cd bluez-5.21

これをビルドします。ライブラリの不足が有る場合があるので以下を実行

$ sudo apt-get install libglib2.0-dev libdbus-1-dev libudev-dev libical-dev libreadline-dev

そしてビルド

./configure --disable-systemd && make && make install

これで準備は整いました。

2.mbed HRM1017に何かサンプルプログラムを入れる
これは、他の方がとりあえず作っているサンプルプログラムを入れるか、もしくは自分で作成したプログラムを入れて下さい。
ここでは、特別に紹介しません。mbed HRM1017 から電波が発信されればOKです。主に通信確認をするためです。

3.mbed HRM1017 と接続する
mbed HRM1017と接続します。以下を実行

$ hciconfig
hci1:	Type: BR/EDR  Bus: USB
	BD Address: 00:1B:DC:06:C9:6C  ACL MTU: 310:10  SCO MTU: 64:8
	UP RUNNING PSCAN 
	RX bytes:645 acl:0 sco:0 events:40 errors:0
	TX bytes:973 acl:0 sco:0 commands:38 errors:0

hci0:	Type: BR/EDR  Bus: USB
	BD Address: 70:F3:95:48:19:CF  ACL MTU: 1021:8  SCO MTU: 64:1
	UP RUNNING PSCAN ISCAN 
	RX bytes:1050 acl:0 sco:0 events:52 errors:0
	TX bytes:1423 acl:0 sco:0 commands:52 errors:0

上記はhciconfigで新しく接続したBT4.0対応のUSBドングルのBDアドレスを確認しています。
そして以下で新しいUSBドングルであるhci1 を検索するデバイスを hcitool -i のオプションでhci1 として指定し lescan というコマンドを実施して、mbed HRM1017を検索します。
もし、複数のBT4.0機器を持っている場合は、一旦その機器の電源を落とすなりして複数のデバイスが検知されないようにすることで、間違いを防げると思います。

$ sudo hcitool -i hci1 lescan
LE Scan ...
F4:9F:B2:09:EA:FE (unknown)
F4:9F:B2:09:EA:FE (unknown)
^z
[2]+  停止                  sudo hcitool -i hci1 lescan
$ 

このコマンドはひたすらスキャンしますのでctrl+zにて停止させてください。
この情報でmbed HRM1017のアドレスがF4:9F:B2:09:EA:FEで有ることが判りました。

4.F4:9F:B2:09:EA:FEであるmbed HRM1017と接続する
gatttoolでそのドングルを指定し接続します。
gatttoolコマンドの-i オプションで新しいデバイスhci1を指定し、アドレスを-bで指定、-tでLEアドレスをランダムに、-Iでインタラクティブモードです。

$ gatttool -i hci1 -b F4:9F:B2:09:EA:FE -t random -I

このコマンドの後、以下のコマンドプロンプトに移行します。

[   ][F4:9F:B2:09:EA:FE][LE]> 

この状態で以下を入力

[   ][F4:9F:B2:09:EA:FE][LE]>  connect
[CON][F4:9F:B2:09:EA:FE][LE]>

[CON]になる事で接続が完了してるのが判ります。

5.gatttoolについて
LEのサポートのBluetoothプロトコルスタックBlueZが提供している、CLIベースのツールです。
コマンドラインベースで Bluetooth-LEやRegacy-Bluetoothのアトリビュートを読み書き出来るツールです。
今回はコマンドラインから毎回叩くのが面倒なのもあって-Iオプションでインタラクティブモードにして、シェルで使っています。

6.gatttoolで読み書き
gatttoolで読み書きしてみます。mbed HRM1017がどんなサービスを提供してるのか以下のコマンドで見ます。

[CON][F4:9F:B2:09:EA:FE][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   <handle> [offset]              Characteristics Value/Descriptor Read by handle
char-read-uuid  <UUID> [start hnd] [end hnd]   Characteristics Value/Descriptor Read by UUID
char-write-req  <handle> <new value>           Characteristic Value Write (Write Request)
char-write-cmd  <handle> <new value>           Characteristic Value Write (No response)
sec-level       [low | medium | high]          Set security level. Default: low
mtu             <value>                        Exchange MTU for GATT/ATT
[CON][F4:9F:B2:09:EA:FE][LE]>

helpを打つとgatttoolで利用出来る一覧が表示されます。
まず、Primary Service Discoveryにて何がServiceされて発信されているのか確認します。

[CON][F4:9F:B2:09:EA:FE][LE]> primary
[CON][F4:9F:B2:09:EA:FE][LE]> 
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: 0xffff uuid: 0000fff0-0000-1000-8000-00805f9b34fb
[CON][F4:9F:B2:09:EA:FE][LE]>

これでサービスされているプライマリ情報が判りました。
次に、UUIDの下位4桁16bitはGATTの仕様で制定されている規定値です。それを調べます。 https://developer.bluetooth.org/gatt/services/Pages/ServicesHome.aspx 1800=Generic Access 1801=Generic Attribute

では、Generic Accessの情報を読みだしてみます。範囲は上記でみると0x0001 から 0x0007です。
https://developer.bluetooth.org/gatt/services/Pages/ServiceViewer.aspx?u=org.bluetooth.service.generic_access.xml

[CON][F4:9F:B2:09:EA:FE][LE]> char-desc 0x0001 0x0007
[CON][F4:9F:B2:09:EA:FE][LE]> 
handle: 0x0001, uuid: 2800
handle: 0x0002, uuid: 2803
handle: 0x0003, uuid: 2a00
handle: 0x0004, uuid: 2803
handle: 0x0005, uuid: 2a01
[CON][F4:9F:B2:09:EA:FE][LE]> 

これでuuidとhandleの関係が判りました。1800はGenericAccessなので、先ほどのページを見るとDevice Nameが読めることが判ります。
Device NameのUUIDとアドレスは
https://developer.bluetooth.org/gatt/characteristics/Pages/CharacteristicViewer.aspx?u=org.bluetooth.characteristic.gap.device_name.xml
を見るとAssigned Number: 0x2A00 で定義されていることが判ります。
0x2A00 は UUIDです。それに対応するのは0x0003です。ふた通りの読む方法があります。

1つめchar-read-hndを使う方法

[CON][F4:9F:B2:09:EA:FE][LE]> char-read-hnd 0x0003
[CON][F4:9F:B2:09:EA:FE][LE]> 
Characteristic value/descriptor: 6d 62 65 64 20 48 52 4d 31 30 31 37 
[CON][F4:9F:B2:09:EA:FE][LE]> 

2つめUUIDを指定する方法

[CON][F4:9F:B2:09:EA:FE][LE]> char-read-uuid 2a00
[CON][F4:9F:B2:09:EA:FE][LE]> 
handle: 0x0003 	 value: 6d 62 65 64 20 48 52 4d 31 30 31 37 
[CON][F4:9F:B2:09:EA:FE][LE]>

返り値が同じ事が判ると思います。
これは、先ほどのHP情報よりDeviceNameであり、返り値はFormat utf8s ですので次のHPで確認します。
https://developer.bluetooth.org/gatt/Pages/FormatTypes.aspx
を見るとUTF-8 string となっています。数字の羅列であるのはASCIIコードであるからです。これを文字列に変換してみます。

$ echo " 6d 62 65 64 20 48 52 4d 31 30 31 37"| tr \  = | nkf -WwmQ
mbed HRM1017
$

これで間違いなくデバイスmbed HRM1017に接続してることが判りました。
通信のデバッグは複雑ですが、このツールを使う事により少しでも捗る事があればいいと思い駆け足ですが紹介してみました。
このコマンド以外にもgatttoolには

char-write-req  <handle> <new value>           Characteristic Value Write (Write Request)
char-write-cmd  <handle> <new value>           Characteristic Value Write (No response)

のコマンドもありますので直接叩くのも可能です。

7.Raspberry Pi への導入
ラズベリーパイでもこのドングルが使える事が判りました。
導入方法は以下の通りです。
本体は、Linux 3.10.25+ #622 PREEMPT Fri Jan 3 18:41:00 GMT 2014 armv6l GNU/Linux
先ずは本体のアップデートから。

$ sudo apt-get update
$ sudo apt-get upgrade 


そして必要なライブラリを導入します。

$ apt-get install libglib2.0-dev libdbus-1-dev libudev-dev libical-dev libreadline6-dev


最新のblueZをDLし、解凍します。

$ wget https://www.kernel.org/pub/linux/bluetooth/bluez-5.21.tar.gz
$ tar xvf bluez-5.21.tar.gz


DLしたフォルダに移動

$ cd bluez-5.21


そしてビルドします。

$ sudo ./configure --disable-systemd --enable-library && make && make install


gatttoolは自動でインストールされないのでコピーします。

$ sudo cp attrib/gatttool /usr/local/bin

これで導入が完了です。 次に刺したドングルを有効化します。

$ hciconfig
hci0:	Type: BR/EDR  Bus: USB
	BD Address: 00:1B:DC:06:C9:6C  ACL MTU: 310:10  SCO MTU: 64:8
	DOWN 
	RX bytes:2504 acl:1 sco:0 events:137 errors:0
	TX bytes:1261 acl:1 sco:0 commands:92 errors:0

hci0として認識されていますが、DOWNなのでUPさせます。

$ sudo hciconfig hci0 up


ここで一度UPしているか確認します。

$ hciconfig
hci0:	Type: BR/EDR  Bus: USB
	BD Address: 00:1B:DC:06:C9:6C  ACL MTU: 310:10  SCO MTU: 64:8
	UP RUNNING 
	RX bytes:3051 acl:1 sco:0 events:164 errors:0
	TX bytes:1645 acl:1 sco:0 commands:119 errors:0


これで準備が整ったのでmbed HRM1017 をスキャンします。

$ hcitool lescan
LE Scan ...
F4:9F:B2:09:EA:FE (unknown)
F4:9F:B2:09:EA:FE (unknown)
F4:9F:B2:09:EA:FE (unknown)
F4:9F:B2:09:EA:FE (unknown)
F4:9F:B2:09:EA:FE (unknown)
F4:9F:B2:09:EA:FE (unknown)
F4:9F:B2:09:EA:FE (unknown)
F4:9F:B2:09:EA:FE (unknown)
^C

ここからはUbuntuと同じ方法で接続します。

root@kazu:~/bluez-5.21# gatttool -i hci0 -b F4:9F:B2:09:EA:FE -t random -I

これで接続完了すると以下になります。

[F4:9F:B2:09:EA:FE][LE]> 
そして、connectを入力すると以下
[F4:9F:B2:09:EA:FE][LE]> connect
Attempting to connect to F4:9F:B2:09:EA:FE
[F4:9F:B2:09:EA:FE][LE]> 
Connection successful


この状態でコネクト完了です。
primaryすると以下が出力されますので確認します。

[F4:9F:B2:09:EA:FE][LE]> primary
[F4:9F:B2:09:EA:FE][LE]> 
attr handle: 0x0001, end grp handle: 0x0007 uuid: 00001800-0000-1000-8000-00805f9b34fb
[F4:9F:B2:09:EA:FE][LE]> 
attr handle: 0x0008, end grp handle: 0x000b uuid: 00001801-0000-1000-8000-00805f9b34fb
[F4:9F:B2:09:EA:FE][LE]> 
attr handle: 0x000c, end grp handle: 0xffff uuid: 0000fff0-0000-1000-8000-00805f9b34fb
[F4:9F:B2:09:EA:FE][LE]>

参考にさせて頂いたHP

1:Bluetoothのはなし(4)|Wireless・のおと|サイレックス・テクノロジー株式会社
http://www.silex.jp/blog/wireless/2012/12/bluetooth4.html

2:BlueZで遊んでみる - BLE大阪勉強会
http://www.slideshare.net/kobashin/ble-32572318

3:本文中にある各種HPアドレス先


1 comment on Linux でBLEのドングルを刺して通信させる。:

24 Dec 2014

http://www.adventar.org/calendars/523 の24日の記事に投稿しました。

Please log in to post comments.