Raspberry Pi 3 からは標準でBluetoothモジュールが搭載されているということで、他のデバイスとの接続を試してみました。
BlueZインストール
BlueZはオープンソースのBluetoothプロトコルスタックで、Linux上でBluetooth, BLEを扱う場合には標準的に使われているということなので、インストールします。
まずはソースをダウンロードして解凍します。
pi@raspberrypi:~/tmp $ wget http://www.kernel.org/pub/linux/bluetooth/bluez-5.45.tar.xz --2017-05-27 10:23:48-- http://www.kernel.org/pub/linux/bluetooth/bluez-5.45.tar.xz Resolving www.kernel.org (www.kernel.org)... 147.75.110.187 Connecting to www.kernel.org (www.kernel.org)|147.75.110.187|:80... connected. HTTP request sent, awaiting response... 301 Moved Permanently Location: https://www.kernel.org/pub/linux/bluetooth/bluez-5.45.tar.xz [following] --2017-05-27 10:23:48-- https://www.kernel.org/pub/linux/bluetooth/bluez-5.45.tar.xz Connecting to www.kernel.org (www.kernel.org)|147.75.110.187|:443... connected. HTTP request sent, awaiting response... 200 OK Length: 1672404 (1.6M) [application/x-xz] Saving to: ‘bluez-5.45.tar.xz’ bluez-5.45.tar.xz 100%[===========================================================================================================================================>] 1.59M 2.56MB/s in 0.6s 2017-05-27 10:23:49 (2.56 MB/s) - ‘bluez-5.45.tar.xz’ saved [1672404/1672404] pi@raspberrypi:~/tmp $ xz -dv bluez-5.45.tar.xz bluez-5.45.tar.xz (1/1) 100 % 1,633.2 KiB / 14.4 MiB = 0.111 pi@raspberrypi:~/tmp $ tar -xf bluez-5.45.tar pi@raspberrypi:~/tmp $ cd bluez-5.45/
ビルドに必要なライブラリをインストールします。configureしながら確認した結果、下記ライブラリをインストールしました。
pi@raspberrypi:~/tmp/bluez-5.45 $ sudo apt-get install -y libglib2.0-dev pi@raspberrypi:~/tmp/bluez-5.45 $ sudo apt-get install -y libdbus-1-dev pi@raspberrypi:~/tmp/bluez-5.45 $ sudo apt-get install -y libudev-dev pi@raspberrypi:~/tmp/bluez-5.45 $ sudo apt-get install -y libical-dev
そして下記コマンドでビルド、インストールします。
pi@raspberrypi:~/tmp/bluez-5.45 $ ./configure --enable-experimental
pi@raspberrypi:~/tmp/bluez-5.45 $ make
pi@raspberrypi:~/tmp/bluez-5.45 $ sudo make install
無事にインストールできたらひとまずBluetoothデバイスをスキャンしてみます。hcitoolというコマンドを使って、Bluetoothデバイスを検索する場合は scan、BLEデバイスを検索する場合は lescan をオプションとして渡します。
pi@raspberrypi:~ $ hcitool hcitool - HCI Tool ver 5.23 pi@raspberrypi:~ $ pi@raspberrypi:~ $ sudo hcitool lescan LE Scan ... 74:DE:1A:E6:4E:4F (unknown) 34:36:3B:C7:FB:E9 (unknown) 34:36:3B:C7:FB:E9 (unknown) 74:DE:1A:E6:4E:4F (unknown) F9:D8:AA:9A:CF:96 (unknown) F9:D8:AA:9A:CF:96 Charge HR pi@raspberrypi:~ $ pi@raspberrypi:~ $ sudo hcitool scan Scanning ... FC:E9:98:21:23:B7 Akanuma_Hiroaki_iPhone pi@raspberrypi:~ $
とりあえずデバイスの検知は行えているようです。
Bluetooth関連の各種ツール
下記サイトを参考に、各種ツールのインストールやバージョンの確認をしてみました。
BlueZをインストールすると対話型の設定ツールとしてbluetoothctlが使えるようになっていますので、バージョンを確認してみます。
pi@raspberrypi:~/tmp/bluez-5.45 $ bluetoothctl [NEW] Controller B8:27:EB:19:76:07 raspberrypi [default] [bluetooth]# version Version 5.23 [bluetooth]# quit [DEL] Controller B8:27:EB:19:76:07 raspberrypi [default]
Bluetoothデバイス間のトラフィックのキャプチャツールとして、bluez-hcidumpをインストールしておきます。
pi@raspberrypi:~/tmp/bluez-5.45 $ sudo apt-get install bluez-hcidump Reading package lists... Done Building dependency tree Reading state information... Done The following packages were automatically installed and are no longer required: libbison-dev libsigsegv2 m4 Use 'apt-get autoremove' to remove them. The following NEW packages will be installed: bluez-hcidump 0 upgraded, 1 newly installed, 0 to remove and 0 not upgraded. Need to get 157 kB of archives. After this operation, 490 kB of additional disk space will be used. Get:1 http://archive.raspberrypi.org/debian/ jessie/main bluez-hcidump armhf 5.23-2+rpi2 [157 kB] Fetched 157 kB in 1s (91.8 kB/s) Selecting previously unselected package bluez-hcidump. (Reading database ... 36730 files and directories currently installed.) Preparing to unpack .../bluez-hcidump_5.23-2+rpi2_armhf.deb ... Unpacking bluez-hcidump (5.23-2+rpi2) ... Processing triggers for man-db (2.7.0.2-5) ... Setting up bluez-hcidump (5.23-2+rpi2) ... pi@raspberrypi:~/tmp/bluez-5.45 $ pi@raspberrypi:~/tmp/bluez-5.45 $ hcidump HCI sniffer - Bluetooth packet analyzer ver 5.23 device: hci0 snap_len: 1500 filter: 0xffffffff
hciconfigではBluetoothインタフェースの状態が確認できます。
pi@raspberrypi:~/tmp/bluez-5.45 $ hciconfig hci0: Type: BR/EDR Bus: UART BD Address: B8:27:EB:19:76:07 ACL MTU: 1021:8 SCO MTU: 64:1 UP RUNNING RX bytes:710 acl:0 sco:0 events:41 errors:0 TX bytes:1496 acl:0 sco:0 commands:41 errors:0
iBeacon化してiPhoneから検知
BlueZを使ってiBeacon化するためのツールとして下記が公開されているので、Raspberry Pi上で動かしてiPhoneから検知してみます。
まずはソースをダウンロードして解凍します。
pi@raspberrypi:~/tmp $ git clone https://github.com/carsonmcdonald/bluez-ibeacon.git Cloning into 'bluez-ibeacon'... remote: Counting objects: 77, done. remote: Total 77 (delta 0), reused 0 (delta 0), pack-reused 77 Unpacking objects: 100% (77/77), done. Checking connectivity... done. pi@raspberrypi:~/tmp $ pi@raspberrypi:~/tmp $ cd bluez-ibeacon/bluez-beacon/
ビルドに必要なライブラリをインストール。
pi@raspberrypi:~/tmp/bluez-ibeacon/bluez-beacon $ sudo apt-get -y install libbluetooth-dev
そしてビルドします。
pi@raspberrypi:~/tmp/bluez-ibeacon/bluez-beacon $ make cc -g -o ibeacon ibeacon.c -lbluetooth
無事ビルドできたら起動してみます。オプションはとりあえずサンプルと同じにしています。
pi@raspberrypi:~/tmp/bluez-ibeacon/bluez-beacon $ sudo ./ibeacon 200 e2c56db5dffb48d2b060d0f5a71096e0 1 1 -29 Hit ctrl-c to stop advertising
これでRaspberry Pi側はiBeaconとして動作しているはずなので、iPhoneに下記アプリをインストールしてiBeaconを検知してみます。
距離の表示はだいぶずれてますが、ひとまず検知はされて、RSSIの情報も表示されました。
Bluetoothデバイスとペアリング&接続
自宅にBluetooth接続のキーボードがあったのでペアリング&接続してみます。まずは bluetoothctl を起動して、デフォルトagentを設定します。
pi@raspberrypi:~ $ sudo bluetoothctl --agent=DisplayYesNo [NEW] Controller B8:27:EB:19:76:07 raspberrypi [default] [NEW] Device FC:E9:98:21:23:B7 Akanuma_Hiroaki_iPhone Agent registered [Akanuma_Hiroaki_iPhone]# default-agent Default agent request successful
続いてBluetoothデバイスのスキャンを開始します。Bluetooth 3.0 Keyboard が検知されたらスキャンを停止します。
[Akanuma_Hiroaki_iPhone]# scan on Discovery started [CHG] Controller B8:27:EB:19:76:07 Discovering: yes [NEW] Device 34:36:3B:C7:FB:E9 34-36-3B-C7-FB-E9 [NEW] Device 20:16:06:23:98:85 20-16-06-23-98-85 [CHG] Device 20:16:06:23:98:85 LegacyPairing: no [CHG] Device 20:16:06:23:98:85 Name: Bluetooth 3.0 Keyboard [CHG] Device 20:16:06:23:98:85 Alias: Bluetooth 3.0 Keyboard [CHG] Device 20:16:06:23:98:85 LegacyPairing: yes [CHG] Device 34:36:3B:C7:FB:E9 RSSI: -65 [Akanuma_Hiroaki_iPhone]# scan off [CHG] Device 20:16:06:23:98:85 RSSI is nil [CHG] Device 34:36:3B:C7:FB:E9 RSSI is nil Discovery stopped [CHG] Controller B8:27:EB:19:76:07 Discovering: no
対象のデバイスのMACアドレスを指定してペアリングします。
[Akanuma_Hiroaki_iPhone]# pair 20:16:06:23:98:85 Attempting to pair with 20:16:06:23:98:85 [CHG] Device 20:16:06:23:98:85 Connected: yes [CHG] Device 20:16:06:23:98:85 Modalias: usb:v05ACp023Cd0102 [CHG] Device 20:16:06:23:98:85 UUIDs: 00001124-0000-1000-8000-00805f9b34fb [CHG] Device 20:16:06:23:98:85 UUIDs: 00001200-0000-1000-8000-00805f9b34fb [CHG] Device 20:16:06:23:98:85 ServicesResolved: yes [CHG] Device 20:16:06:23:98:85 Paired: yes Pairing successful [CHG] Device 20:16:06:23:98:85 ServicesResolved: no [CHG] Device 20:16:06:23:98:85 Connected: no [Akanuma_Hiroaki_iPhone]# connect 20:16:06:23:98:85 Attempting to connect to 20:16:06:23:98:85 [CHG] Device 20:16:06:23:98:85 Connected: yes Connection successful [CHG] Device 20:16:06:23:98:85 ServicesResolved: yes [DEL] Device 34:36:3B:C7:FB:E9 34-36-3B-C7-FB-E9 [DEL] Device 74:DE:1A:E6:4E:4F 74-DE-1A-E6-4E-4F [CHG] Device 20:16:06:23:98:85 ServicesResolved: no [CHG] Device 20:16:06:23:98:85 Connected: no
そして接続してみます。
[bluetooth]# connect 20:16:06:23:98:85 Attempting to connect to 20:16:06:23:98:85 Failed to connect: org.bluez.Error.Failed [bluetooth]# connect 20:16:06:23:98:85 Attempting to connect to 20:16:06:23:98:85 [CHG] Device 20:16:06:23:98:85 Connected: yes Connection successful [CHG] Device 20:16:06:23:98:85 ServicesResolved: yes
無事接続できたようです。正しく通信できているか確認するために、evtest というインプットイベントのモニタツールを使ってみます。
evtest
~whot/evtest - Simple tool for input event debugging.
インストールした後で下記のように実行します。evtestを起動した状態でキーボード入力してみたところ、下記のように検知され、正しく通信できていることが確認できました。
pi@raspberrypi:~/tmp/evtest $ evtest No device specified, trying to scan all of /dev/input/event* Not running as root, no devices may be available. Available devices: /dev/input/event0: FC:E9:98:21:23:B7 /dev/input/event1: Bluetooth 3.0 Keyboard Select the device event number [0-1]: 1 Input driver version is 1.0.1 Input device ID: bus 0x5 vendor 0x5ac product 0x23c version 0x102 Input device name: "Bluetooth 3.0 Keyboard" Supported events: Event type 0 (EV_SYN) Event type 1 (EV_KEY) Event code 1 (KEY_ESC) Event code 2 (KEY_1) Event code 3 (KEY_2) Event code 4 (KEY_3) Event code 5 (KEY_4) Event code 6 (KEY_5) Event code 7 (KEY_6) Event code 8 (KEY_7) Event code 9 (KEY_8) Event code 10 (KEY_9) Event code 11 (KEY_0) Event code 12 (KEY_MINUS) Event code 13 (KEY_EQUAL) Event code 14 (KEY_BACKSPACE) Event code 15 (KEY_TAB) 〜〜〜中略〜〜〜 Event code 217 (KEY_SEARCH) Event code 240 (KEY_UNKNOWN) Event code 374 (KEY_KEYBOARD) Event code 581 (?) Event type 3 (EV_ABS) Event code 40 (ABS_MISC) Value 0 Min 0 Max 255 Event code 41 (?) Value 0 Min 0 Max 1 Event code 42 (?) Value 0 Min 0 Max 1 Event code 43 (?) Value 0 Min 0 Max 1 Event type 4 (EV_MSC) Event code 4 (MSC_SCAN) Event type 17 (EV_LED) Event code 0 (LED_NUML) Event code 1 (LED_CAPSL) Event code 2 (LED_SCROLLL) Event code 3 (LED_COMPOSE) Event code 4 (LED_KANA) Event type 20 (EV_REP) Properties: Testing ... (interrupt to exit) Event: time 1495901204.274595, type 4 (EV_MSC), code 4 (MSC_SCAN), value 70004 Event: time 1495901204.274595, type 1 (EV_KEY), code 30 (KEY_A), value 1 Event: time 1495901204.274595, -------------- SYN_REPORT ------------ Event: time 1495901204.323288, type 4 (EV_MSC), code 4 (MSC_SCAN), value 70004 Event: time 1495901204.323288, type 1 (EV_KEY), code 30 (KEY_A), value 0 Event: time 1495901204.323288, -------------- SYN_REPORT ------------ Event: time 1495901206.455897, type 4 (EV_MSC), code 4 (MSC_SCAN), value 70005 Event: time 1495901206.455897, type 1 (EV_KEY), code 48 (KEY_B), value 1 Event: time 1495901206.455897, -------------- SYN_REPORT ------------ Event: time 1495901206.568359, type 4 (EV_MSC), code 4 (MSC_SCAN), value 70005 Event: time 1495901206.568359, type 1 (EV_KEY), code 48 (KEY_B), value 0 Event: time 1495901206.568359, -------------- SYN_REPORT ------------ Event: time 1495901208.728378, type 4 (EV_MSC), code 4 (MSC_SCAN), value 70006 Event: time 1495901208.728378, type 1 (EV_KEY), code 46 (KEY_C), value 1 Event: time 1495901208.728378, -------------- SYN_REPORT ------------ Event: time 1495901208.818369, type 4 (EV_MSC), code 4 (MSC_SCAN), value 70006 Event: time 1495901208.818369, type 1 (EV_KEY), code 46 (KEY_C), value 0 Event: time 1495901208.818369, -------------- SYN_REPORT ------------
RubyでBluetoothデバイスとペアリング&接続
Bluetoothデバイスの検知、ペアリング、接続までをRubyでやってみます。RubyからBLEデバイスを操作するための gem として、ruby-bleというのがあるようなのでそちらを使ってみます。
Gemfileに下記エントリを追加して、bundle installしておきます。
gem 'ble'
今回はとりあえずirbで試してみます。irbを起動して'ble'をrequireします。warningメッセージが気になるところですが、今回はスルー。
pi@raspberrypi:~ $ sudo bundle exec irb irb(main):001:0> require 'ble' /home/pi/vendor/bundle/ruby/2.4.0/gems/ruby-dbus-0.13.0/lib/dbus/marshall.rb:299: warning: constant ::Fixnum is deprecated => true
BLEアダプタのリストを表示してみます。
irb(main):002:0> BLE::Adapter.list /home/pi/vendor/bundle/ruby/2.4.0/gems/ruby-dbus-0.13.0/lib/dbus/marshall.rb:299: warning: constant ::Fixnum is deprecated => ["hci0"]
hci0というアダプタが見つかるので、インスタンスを作成します。
irb(main):003:0> adapter = BLE::Adapter.new('hci0')
Bluetoothデバイスの検知を開始します。目的のBLEデバイスのMACアドレスが検知されたら停止します。
irb(main):008:0* adapter.start_discovery => true irb(main):011:0> adapter.devices => ["20:16:06:23:98:85", "34:36:3B:C7:FB:E9", "43:19:24:21:00:5F", "74:DE:1A:E6:4E:4F", "FC:E9:98:21:23:B7"] irb(main):012:0> adapter.stop_discovery => true
該当のBluetoothデバイスのオブジェクトを取得します。
irb(main):013:0> kb = adapter['20:16:06:23:98:85']
デバイス名等を確認してみます。
irb(main):015:0* kb.name => "Bluetooth 3.0 Keyboard" irb(main):016:0> kb.alias => "Bluetooth 3.0 Keyboard" irb(main):017:0> kb.address => "20:16:06:23:98:85"
続けてペアリングします。
irb(main):020:0> kb.pair => true irb(main):021:0> kb.is_paired? => true
そして接続してみます。
irb(main):026:0> kb.connect => true irb(main):027:0> kb.is_connected? => true
無事接続できたようです。この状態で evtest を実行すると、 bluetoothctl から接続した時と同じように、キーボードの入力内容が確認できます。
ここまでだとまだBluetoothクラシックのデバイスと接続したところまでなので、次回以降でBLEデバイスとの通信を試してみたいと思います。