LoginSignup
8
8

More than 5 years have passed since last update.

Raspberry Pi2からSensorTagのデータをBluebirdのCoroutineとPromiseで取得する

Last updated at Posted at 2015-09-03

BeagleBone BlackでSensorTagを使ったときのように、Raspberry Pi 2でもNode.jsのコードからデータを取得してみます。node-sensortagライブラリに付属しているtest.jsのサンプルコードはAsync.jsasync.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+ #785 SMP PREEMPT Mon May 18 17:53:02 BST 2015 armv7l GNU/Linux
$ 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"
    }
}

パッケージをインストールします。

$ npm install

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
8
8
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
8