BeagleBone BlackでSensorTag を使ったときのように、Raspberry Pi 2でもNode.jsのコードからデータを取得してみます。node-sensortag ライブラリに付属しているtest.js のサンプルコードはAsync.js のasync.series
を使っています。最近はES6のPromiseとGenerator、Coroutineで書くようにしているのでBluebird を使うコードに書き直してみます。
必要なもの SensorTag 新しい製品のSensorTag 2015 発売されていますが、以前購入した古いSensorTag を利用します。
Bluetooth USBアダプタ BLE対応のアダプタはプラネックスのBT-Micro4 を購入しました。Raspberry Piに挿してlsusbコマンドを実行するとデバイスが認識されています。
$ lsusb ... Bus 001 Device 005: ID 0a12:0001 Cambridge Silicon Radio, Ltd Bluetooth Dongle (HCI mode)
BlueZ BlueZ はLinux用のBluetooth プロトコルスタックです。RPi Bluetooth LE によると、Raspberry Piのapt-getからインストールできるパッケージは少し古いです。
バージョンの確認 最初にRaspberry Pi 2のカーネルとRaspbianのバージョンを確認します。
$ uname -a Linux raspberrypi 3.18.13-v7+ $ cat /etc/debian_version 7.8
apt-getからインストールするbluezパッケージは4.99-2でした。
$ sudo apt-get update $ apt-cache show bluez ... Version: 4.99-2
ソースからインストール RPi Bluetooth LE に掲載されている手順でインストールしていきます。
古いパッケージがインストールされている場合は削除します。
$ sudo apt-get remove bluez
ビルドに必要なパッケージをインストールします。
$ sudo apt-get update $ sudo apt-get install libdbus-1-dev libdbus-glib-1-dev libglib2.0-dev libical-dev libreadline-dev libudev-dev libusb-dev make
最新の5.33をビルドしてインストールします。
$ mkdir -p ~/work/bluepy $ cd ~/work/bluepy $ wget https://www.kernel.org/pub/linux/bluetooth/bluez-5.33.tar.gz $ tar xzvf bluez-5.33.tar.gz $ cd bluez-5.33 $ ./configure --disable-systemd $ make $ sudo make install
hciconfigコマンドでBLEアダプタの状態をみるとDOWN
しています。
$ hciconfig hci0: Type: BR/EDR Bus: USB BD Address: 00:1B:DC:06:1C:CF ACL MTU: 310:10 SCO MTU: 64:8 DOWN RX bytes:55911 acl:1143 sco:0 events:2170 errors:0 TX bytes:20152 acl:1144 sco:0 commands:370 errors:0
sudoでupしてUP RUNNING
の状態にします。
$ sudo hciconfig hci0 up $ hciconfig hci0: Type: BR/EDR Bus: USB BD Address: 00:1B:DC:06:1C:CF ACL MTU: 310:10 SCO MTU: 64:8 UP RUNNING RX bytes:56475 acl:1143 sco:0 events:2199 errors:0 TX bytes:20270 acl:1144 sco:0 commands:399 errors:0
Node.jsのインストール Node.jsでBluebird を使う場合、--harmony
オプションと0.11+
が必要になります。node_arm から最新の0.12.6
をRaspberry Piにインストールします。
$ wget http://node-arm.herokuapp.com/node_latest_armhf.deb $ sudo dpkg -i node_latest_armhf.deb $ npm -v 2.11.2 $ node -v v0.12.6
プロジェクト nose-sensortag を使ったNode.jsのサンプルコードを書いていきます。リポジトリはこちら です。プロジェクトのディレクトリを作成して移動します。
$ mkdir -p ~/node_apps/bluebird-sensortag $ cd !$
gitignore.io から.gitignore
をダウンロードします。
$ curl https://www.gitignore.io/api/linux,node > .gitignore
package.json package.jsonに必要なパッケージをdependencies
フィールドに定義します。node-sensortagに付属しているサンプル用にAsync.jsも使います。scripts
フィールドには--harmony
フラグを追加します。
~/node_apps/bluebird-sensortag/package.json { "name" : "node-bluebird-sensortag" , "description" : "node-bluebird-sensortag" , "version" : "0.0.1" , "private" : true , "dependencies" : { "sensortag" : "~1.1.1" , "async" : "~1.4.2" , "bluebird" : "~2.9.34" }, "scripts" : { "start" : "node --harmony app.js" } }
パッケージをインストールします。
app.js Promise.coroutine で使うGenerator内部では、yieldする関数はPromiseを返す必要があります。node-sensortagのライブラリはPromiseを返さないためPromisification が必要になります。
今回はPromise.promisifyAll を使い、SensorTag
オブジェクトの関数をすべてPromisificationします。Promisificationされた関数にはAsync
がサフィックスされます。
test.js にあるように本来はsensorTag.enableIrTemperature(callback);
として、callbackに取得したデータを渡します。Promiseにするとthen
で取得することができます。非同期のコードがとても見やすくなりました。
~/node_apps/bluebird-sensortag/app.js 'use strict' ;var Promise = require ('bluebird' ), SensorTag = require ('sensortag' ); Promise .promisifyAll(SensorTag);SensorTag.discover(function (sensorTag ) { console .log('discovered: ' + sensorTag); sensorTag.on('disconnect' , function ( ) { console .log('Tag Disconnected' ); process.exit(0 ); }); Promise .coroutine(function * ( ) { console .log('connectAndSetUp' ); yield sensorTag.connectAndSetUpAsync(); console .log('enableIrTemperature' ); yield sensorTag.enableIrTemperatureAsync(); yield Promise .delay(2000 ); console .log('readIrTemperature' ); yield sensorTag.readIrTemperatureAsync() .then(function (data ) { console .log('\tobject temperature = %d °C' , data[0 ].toFixed(1 )); console .log('\tambient temperature = %d °C' , data[1 ].toFixed(1 )); }); console .log('disableIrTemperature' ); yield sensorTag.disableIrTemperatureAsync(); console .log('enableHumidity' ); yield sensorTag.enableHumidityAsync(); yield Promise .delay(2000 ); console .log('readHumidity' ); yield sensorTag.readHumidityAsync() .then(function (data ) { console .log('\ttemperature = %d °C' , data[0 ].toFixed(1 )); console .log('\thumidity = %d %' , data[1 ].toFixed(1 )); }); console .log('enableMagnetometer' ); yield sensorTag.enableMagnetometerAsync(); console .log('enableBarometricPressure' ); yield sensorTag.enableBarometricPressureAsync(); yield Promise .delay(2000 ); console .log('readBarometricPressure' ); yield sensorTag.readBarometricPressureAsync() .then(function (data ) { console .log('\tpressure = %d hPa' , data.toFixed(1 )); }); console .log('disableBarometricPressure' ); sensorTag.disableBarometricPressureAsync(); console .log('disconnect' ); yield sensorTag.disconnectAsync(); })(); });
プログラムの実行 付属のtest.js SensorTagの電源を入れてから、node-sensortag付属のtest.js をsudoで実行してみます。
$ cd ~/node_apps/node-bluebird-sensortag/node_modules/sensortag $ sudo node test.js discovered: {"id" :"b4994c34d5c0" ,"type" :"cc2540" } connectAndSetUp readDeviceName device name = TI BLE Sensor Tag readSystemId system id = b4:99:4c:00:00:34:d5:c0 readSerialNumber serial number = N.A. readFirmwareRevision firmware revision = 1.4 (Jul 12 2013) readHardwareRevision hardware revision = N.A. readSoftwareRevision software revision = N.A. readManufacturerName manufacturer name = Texas Instruments enableIrTemperature readIrTemperature object temperature = 24.6 °C ambient temperature = 27.4 °C disableIrTemperature enableAccelerometer readAccelerometer x = 0 G y = 0.2 G z = 3.9 G disableAccelerometer enableHumidity readHumidity temperature = 27.7 °C humidity = 66.4 % disableHumidity enableMagnetometer readMagnetometer x = -58.5 μT y = 89.3 μT z = 7.5 μT disableMagnetometer enableBarometricPressure readBarometricPressure pressure = 1002.9 mBar disableBarometricPressure enableGyroscope readGyroscope x = 2.3 °/s y = 2 °/s z = 0.3 °/s disableGyroscope readTestData data = 63 readTestConfiguration configuration = 0 readSimpleRead - waiting for button press ... left: false right: true disconnect disconnected!
SensorTagからBLEでRaspberry Piにデータを送信して、Node.jsのプログラムから取得することができました。
app.jsの実行 取得している環境データは減らしていますが、BluebirdのCoroutineで書いたコードも正常に動作しました。
$ sudo npm start > node-bluebird-sensortag@0.0.1 start /home/pi/node_apps/node-bluebird-sensortag > node --harmony app.js discovered: {"id" :"b4994c34d5c0" ,"type" :"cc2540" } connectAndSetUp enableIrTemperature readIrTemperature object temperature = 23.6 °C ambient temperature = 27.2 °C disableIrTemperature enableHumidity readHumidity temperature = 27.6 °C humidity = 61.4 % enableMagnetometer enableBarometricPressure readBarometricPressure pressure = 1005.8 hPa disableBarometricPressure disconnect Tag Disconnected