CC2650 SensorTag
2015年に発売された新しいCC2650 SensorTagはBLE通信に対応したIoT開発キットです。第1世代のCC2541からバージョンアップして搭載するセンサーも増え省電力化もされているようです。搭載しているセンサーは以下の10種類です。
- 光
- デジタル・マイク
- 磁気センサ
- 湿度
- 圧力
- 加速度計
- ジャイロスコープ
- 磁力計
- 物体温度
- 周囲温度
SensorTagを使うとRaspberry PiにBlootoothのUSBアダプターが必要になりますが、面倒なブレッドボードの配線をしなくても簡単にBLE通信でセンサーデータの取得ができます。Raspberry Piで取得したデータはクラウドのメッセージブローカーに送ったり、閾値監視をしてアラートをあげたりとLinuxで好きなように加工することができます。
Raspberry PiとSensorTagを使ってMQTTブローカーとメッセージの送受信を試してみます。
Meshblu
MeshbluはOctblu社がオープンソースで開発をしているIoTメッセージングプラットフォームです。myThingsの「IDCF」チャンネルではMQTTブローカーとして採用されています。HTTP REST、WebSocket、MQTT、CoAPなど複数の通信プロトコルに対応したIoTプラットフォームがいくつかありますが、Mesubluもそのうちの一つです。
サーバー側で複数のプロトコルをブリッジしてくれるため、Raspberry PiのMQTTクライアントからパブリッシュしたメッセージをブラウザのWebSocketでサブスクライブすることもできます。
クラウドにセットアップ
Debian 8.2.0 64-bitまたはUbuntu 14.04 64-bitの仮想マシンを用意します。こちらを参考にしてMesubluをセットアップします。
list
コマンドを実行すると初期設定された「デバイス」一覧が表示されます。「デバイス」はMeshbluがIoTデバイスやWebサービス、人を抽象化したものです。「デバイス」のuuidとtokenをRaspberry PiやMQTTクライアントなどMesubluを通してコミュニケーションをとりたいものに割り当てて使います。ここでは「trigger-1」と「action-1」を使いメッセージを送受信します。
$ docker-compose run --rm iotutil list
> iotutil@0.0.1 start /app
> node app.js "list"
┌───────────┬──────────┬──────────────────────────────────────┐
│ keyword │ token │ uuid │
├───────────┼──────────┼──────────────────────────────────────┤
│ trigger-1 │ d286ba8d │ ffa6934d-f1b3-467f-98b3-766b330d436d │
├───────────┼──────────┼──────────────────────────────────────┤
...
├───────────┼──────────┼──────────────────────────────────────┤
│ action-1 │ 8a83d71f │ b61d3398-ac99-4694-9dc4-dd632faf6f6a │
├───────────┼──────────┼──────────────────────────────────────┤
...
Raspberry Pi
こちらを参考にしてRaspberry Piがインターネットに接続できる状態から作業を進めます。先ほどクラウドの仮想マシンに割り当てたパブリックIPアドレスを指定してMeshbluの起動を確認します。{"meshblu":"online"}
と出力すればMeshbluの起動に成功しています。
$ curl http://{仮想マシンのパブリックIPアドレス}/status
Node.js
Node.jsはnode-armからパッケージをダウンロードしてインストールします。執筆時点ではnode_latest_armhf.deb
のv4.xがRaspbian
Wheezyで安定して動作しないためnode_latest_armhf.deb
のv.0.12.6を使います。パッケージ名にご注意ください。
$ wget http://node-arm.herokuapp.com/node_archive_armhf.deb
$ sudo dpkg -i node_archive_armhf.deb
$ node -v
v0.12.6
Bluetooth
BlueZはLinuxで動作するオープンソースのBluetoothスタックです。Raspbian Wheezyのパッケージマネージャーからインストールできるパッケージは少し古くBLEのサポートに問題があるため、新しいバージョンをソースコードからビルドして使います。最初にビルドに必要なパッケージをインストールします。
$ 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
ソースコードをダウンロードしてビルドとインストールをします。
$ wget https://www.kernel.org/pub/linux/bluetooth/bluez-5.36.tar.gz
$ tar xvf bluez-5.36.tar.gz
$ cd bluez-5.36
$ ./configure --disable-systemd
$ make
$ sudo make install
hciconfigコマンドを使いBluetoothデバイスを有効にします。
$ sudo hciconfig hci0 up
SensorTagからBLE通信
サンプルコードをダウンロードして必要なパッケージをインストールします。
$ git clone https://github.com/masato/meshblu-sensortag.git
$ cd meshblu-sensortag
$ npm install
config.js
をMesubluのデバイス情報をもとに編集します。パブリックIPアドレスのファイアウォールは1883ポートを開き仮想マシンにポートフォワードしている必要があります。
センサーデータをMQTTブローカーに送信するクライアントにするためMeshbluのMQTTクライアントライブラリを追加します。Raspberry Piのパブリッシュするプログラムにtrigger-1のuuidを割り当て、サブスクライブするプログラムにaction-1デバイスを割り当てます。
var config = {
waitTime: 5000,
trigger_1_uuid: '{trigger-1デバイスのuuid}',
trigger_1_token: '{trigger-1デバイスのuuid}',
action_1_uuid: '{action-1デバイスのuuid}',
action_1_token: '{action-1デバイスのtoken}',
ip_address: '{仮想マシンのパブリックIPアドレス}',
port: 1883
}
module.exports = config;
以下のプログラムはRaspberry Piで物体温度(Object Temperature)、周囲温度(Ambient Temperature)、気圧(Pressure)の3つの環境データをSensorTagから取得します。データはJSON形式にフォーマットしてMeshbluのMQTTブローカーにMQTT通信でパブリッシュします。
'use strict';
var async = require('async'),
SensorTag = require('sensortag'),
Meshblu = require('meshblu-mqtt'),
config = require('./config');
var meshblu = new Meshblu({
'uuid': config.trigger_1_uuid,
'token': config.trigger_1_token,
'hostname': config.ip_address,
'port': config.port
});
SensorTag.discover(function(sensorTag) {
console.log('discovered: ' + sensorTag);
sensorTag.on('disconnect', function() {
console.log('Tag Disconnected');
process.exit(0);
});
process.on('SIGINT', function() {
sensorTag.disconnect();
});
async.waterfall([
function(callback) {
console.log('connectAndSetUp');
sensorTag.connectAndSetUp(callback);
},
function(callback) {
console.log('enableIrTemperature');
sensorTag.enableIrTemperature(callback);
},
function(callback) {
console.log('enableBarometricPressure');
sensorTag.enableBarometricPressure(callback);
},
function(callback) {
setTimeout(callback, 2000);
},
function(callback) {
meshblu.connect(function(response){
console.log('meshblu ready');
async.forever(function(callback) {
async.series([
function(callback) {
sensorTag.readIrTemperature(function(error,
objectTemperature,
ambientTemperature) {
var payload = {
objectTemperature: objectTemperature.toFixed(1),
ambientTemperature: ambientTemperature.toFixed(1)
};
callback(null, payload);
});
},
function(callback) {
sensorTag.readBarometricPressure(function(err, pressure){
var payload = {
pressure: pressure
};
callback(null, payload);
});
}
],
function(err, res) {
console.log('物体温度: '+ res[0].objectTemperature+' ℃');
console.log('周囲温度: '+ res[0].ambientTemperature+' ℃');
console.log('気圧 : '+ res[1].pressure+' mBa');
meshblu.message({
devices: [config.action_1_uuid],
topic: 'message',
payload: {
objectTemperature: res[0].objectTemperature,
ambientTemperature: res[1].ambientTemperature,
pressure: res[1].pressure
}
});
setTimeout(callback, config.waitTime);
});
},
function(err) {
if (err) throw err;
});
});
}
],
function (err) {
if (err) throw err;
});
});
SensorTag本体の横についている電源スイッチを押します。root権限でnpm start
コマンド経由でプログラムを実行するとRaspberry Piでセンサーデータが取得できます。このサンプルでは5秒間隔で計測したデータをMQTTブローカーにパブリッシュして、以下のようなログが標準出力に表示します。
$ sudo npm start
物体温度: 16.4 ℃
周囲温度: 23.9 ℃
気圧 : 1020.98 mBa
MQTTメッセージのサブスクライブ
MQTTではブローカーが仲介してクライアント間でメッセージを送受信します。まずはRaspberry PiにMQTTクライアントのMosquittoをインストールしてメッセージのサブスクライブをテストします。
$ sudo apt-get update
$ sudo apt-get mosquitto-clients
Mosquittoクライアントにも同様にデバイスのuuidを割り当てます。trigger-1が送信したメッセージを受信するため、Mosquittoクライアントにはaction-1デバイスのuuidを割り当てます。
$ mosquitto_sub \
-h {仮想マシンのパブリックIPアドレス} \
-p 1883 \
-t {action-1デバイスのuuid} \
-u {action-1デバイスのuuid} \
-P {action-1デバイスのtoken} \
-d
MQTTブローカーからサブスクライブしたメッセージが標準出力されます。
Subscribed (mid: 1): 0
Received PUBLISH (d0, q0, r0, m0, '{action-1デバイスのuuid}', ... (257 bytes))
{"topic":"message","data":{"devices":["{action-1デバイスのuuid}"],"topic":"message","payload":{"objectTemperature":"16.3","ambientTemperature":"23.1","pressure":1022.14},"callbackId":"8ebdc270-95b8-11e5-943c-e1cfdbaddec8","fromUuid":"{trigger-1デバイスのuuid}"}}
次にNode.jsのプログラムを実行して同様にセンサーデータ取得してみます。
'use strict';
var async = require('async'),
Meshblu = require('meshblu-mqtt'),
config = require('./config');
var meshblu = new Meshblu({
'uuid': config.action_1_uuid,
'token': config.action_1_token,
'hostname': config.ip_address,
'port': config.port
});
meshblu.on('message', function(message){
console.log(message);
});
Mosquittoクライアントと同様にaction-1デバイスのuuidを使いメッセージをサブスクライブしたメッセージが標準出力に表示されました。
$ npm run sub
{ devices: [ '{action-1デバイスのuuid}' ],
topic: 'message',
payload:
{ objectTemperature: '16.5',
ambientTemperature: '22.9',
pressure: 1022.19 },
callbackId: '79da6970-95be-11e5-b0c4-e15124f00dff',
fromUuid: 'trigger-1デバイスのuuid' }
いろいろなデバイスをmyThingsにつなげるために
コネクテッドデバイスをMeshbluと接続するには今回説明したようなuuidを間接的に割り当てる方法がプリミティブですが汎用的です。最後に他の方法をご紹介します。
Gatebluはインターネットに接続していないデバイスをMeshbluとコミュニケーション可能にするソフトウェアです。WindowsやOSXにインストールして使います。ホームオートメーションやAllJoynのゲートウェイとして機能するので「IDCF」チャンネルと連携すれば多くの対応デバイスをmyThingsと組み合わせることができそうです。
Tentacleはマイコン用のライブラリです。Arduino UnoやParticleのPhotonなどのArduino互換のマイコンにArduino IDEからスケッチとしてインストールします。Octoblu Disignerを使うとコードを書かずにブラウザのGUIからフローとピンの制御ができるようになります。
何かの条件を満たしたら、何かの処理を実行するというmyThingsのイベント駆動の考え方は身近なマイクロサービスの良い例です。多くのデバイスやサービスをインターネットにつなげ、もっと簡単にタスクやワーカーを実行させる方法を考えていきたいと思います。