Docker上に構築したMeshbluへArduinoからセンシングデータを送信してみます。前回起動したコンテナではMongoDBを使わない設定なので、POSTしたデータはNeDBにJSONファイルとして保存されます。大気圧センサーモジュールはBMP180を使います。前回Intel Edisonでこのモジュールを使ったときはcylon-i2cやmraaが使えず、bmp085パッケージを使いました。Arduinoの場合cylon-firmataが動作するようです。Cylon.jsを使ってセンシングデータを取得してMeshbluにデータをPOSTしてみます。
cylon-skynetが古い
Cylon.jsからMeshbluのAPIを使う場合、Skynetモジュールを使います。名前が古いようにdependenciesのパッケージも古くなっています。
clone
とりあえずリポジトリをcloneしてmasato/cylon-skynetしました。lib/adaptor.js
とpackage.json
を修正します。
$ git diff HEAD^^ diff --git a/lib/adaptor.js b/lib/adaptor.js index 4f8a361..18aecb9 100644 --- a/lib/adaptor.js +++ b/lib/adaptor.js @@ -8,7 +8,8 @@
"use strict";
-var Skynet = require("skynet"), +//var Skynet = require("skynet"), +var Skynet = require("meshblu"), Cylon = require("cylon");
var Adaptor = module.exports = function Adaptor(opts) { @@ -48,7 +49,8 @@ Adaptor.prototype.connect = function(callback) { this.connector = Skynet.createConnection({ uuid: this.uuid, token: this.token, - host: this.host, + //host: this.host, + server: this.host, port: this.portNumber, forceNew: this.forceNew }); @@ -102,3 +104,7 @@ Adaptor.prototype.message = function(data) { Adaptor.prototype.subscribe = function(data) { return this.connector.subscribe(data); }; + +Adaptor.prototype.data = function(data,fn) { + return this.connector.data(data,fn); +}; diff --git a/package.json b/package.json index d076c05..6c0a386 100644 --- a/package.json +++ b/package.json @@ -29,6 +29,6 @@
"dependencies": { "cylon": "~0.22.0", - "skynet": "latest" + "meshblu": "latest" } }
|
Node.jsプログラムのデバイス/サービス登録
MeshbluではIoTプラットフォームにつながる、人、モノ、サービスをすべてUUIDとTOKENで管理します。そのため操作する人も、コネクテッドデバイスも、連携するWebサービスも対等にUUIDとTOKENを発行する必要があります。今回はOSXのNode.jsプログラムをサービスとして登録します。MESHBLU_URL
はTLS/SSL通信するMeshbluサーバーです。オレオレ証明書を使っているので--insecure
フラグが必要です。
$ export MESHBLU_URL=https://{Meshbluのドメイン名}:4443 $ curl -X POST \ -d "name=iot-http" \ --insecure \ "$MESHBLU_URL/devices" {"uuid":"xxx","online":false,"timestamp":"2015-03-23T03:46:19.254Z","name":"mqtt-osx","type":"host","ipAddress":"172.17.42.1","token":"xxx"}
|
BMP180のサンプル
プロジェクトを作成します。
$ mkdir -p ~/node_apps/firmata-bmp180-meshblu/ $ cd !$
|
package.jsonのcylon-skynet
はcloneして修正したリポジトリを指定します。
~/node_apps/firmata-bmp180-meshblu/package.json{ "name": "firmata-bmp180-meshblu", "version": "0.0.1", "private": true, "dependencies": { "cylon-firmata": "0.19.0", "cylon-skynet": "masato/cylon-skynet" }, "scripts": {"start": "node app.js"} }
|
app.js
Arduinoのデバイスファイルは、MacBook Proの右側のUSBポートにを挿したので/dev/tty.usbmodem1421
になりました。host
、uuid
、token
はそれぞれ上記のデバイス登録で取得した値を使います。
~/node_apps/firmata-bmp180-meshblu/app.js"use strict"; var Cylon = require("cylon"); var host = "wss://{Meshbluのドメイン名}"; var portNumber = 4443; var uuid = "{Node.jsプログラムのUUID}}"; var token = "{Node.jsプログラムのTOKEN}}"; Cylon.robot({ connections: { arduino: { adaptor: "firmata", port: "/dev/tty.usbmodem1421" }, skynet: { adaptor: 'skynet', host: host, portNumber: portNumber, uuid: uuid, token: token} }, devices: { yellow: { driver: 'led', pin: 13, connection: 'arduino' }, bmp180: { driver: "bmp180" } }, work: function(my) { my.skynet.on("message", function(data) { console.log('data: ' + JSON.stringify(data)); if(data.payload.yellow === "on") { my.yellow.turnOn(); } else if(data.payload.yellow === "off") { my.yellow.turnOff(); } });
every((5).seconds(), function() { my.bmp180.getAltitude(1, null, function(err, val) { if (err) { console.log(err); return; } my.skynet.data({ "temperature": val.temp, "pressure": val.press, "altitude": val.alt },function(data){ console.log(data); }); }); }); } }).start();
|
connections
ディレクティブにはArduinoとMeshblu(Skynet)の2つを定義します。devices
にはMeshbluからメッセージをsubscribeしてLチカするLEDと、大気圧センサーモジュールのBMP180を定義します。Arduinoがon
のメッセージを受信するとLEDが点灯し、off
で消灯します。BMP180からは5秒間隔でセンシングします。温度(temperature)、大気圧(pressure)、標高(altitude)のデータをJSON形式にフォーマットして、Meshbluに送ります。
サンプルの起動
Node.jsのサンプルプログラムを起動します。my.skynet.data()
のコールバックで実装している標準出力が表示されます。
$ nvm use 0.10 Now using node v0.10.37 $ npm start ... { timestamp: '2015-03-23T06:33:15.610Z', temperature: '28.6', pressure: '100153', altitude: '98.03716036353367' } { timestamp: '2015-03-23T06:33:20.615Z', temperature: '28.6', pressure: '100146', altitude: '98.62549086806833' } { timestamp: '2015-03-23T06:33:25.619Z', temperature: '28.6', pressure: '100150', altitude: '98.2892979312604' }
|
Meshblu側のデータベース
今回のMeshbluの構成ではMongoDBの利用をコメントアウトしているので、センシングデータはNode.jsの組み込みデータベースのNeDBにJSONファイルとして保存されました。
Meshbluコンテナを動かしているDockerホストにログインして、ボリュームにアタッチしている作業ディレクトリに移動します。
$ cd ~docker_apps/meshblu-dev
|
センシングデータはdata.db
ファイルに生のJSONとして保存されています。
$ tail data.db {"timestamp":"2015-03-23T06:33:15.610Z","temperature":"28.6","pressure":"100153","altitude":"98.03716036353367","_id":"krDon5OH6Frs17ic"} {"timestamp":"2015-03-23T06:33:20.615Z","temperature":"28.6","pressure":"100146","altitude":"98.62549086806833","_id":"JGdcd8c4ycXXlKEk"} {"timestamp":"2015-03-23T06:33:25.619Z","temperature":"28.6","pressure":"100150","altitude":"98.2892979312604","_id":"lMj4o7MaYB3RmLrW"}
|
Pub/Subのテスト
次はメッセージのPub/Subのテストをします。テストに使う環境変数を作成します。
$ export MESHBLU_URL=https://{Meshbluのドメイン名}:4443 $ export PUB_DEV_UUID={Node.jsプログラムのUUID} $ export PUB_DEV_TOKEN={Node.jsプログラムのTOKEN}
|
--header
には認証情報としてNode.jsプログラムのUUID/TOKENを指定します。送信データのdevices
キーに、メッセージ送信先デバイスのUUIDを指定します。今回は認証UUIDと送信先UUIDが同じなので自分自身にメッセージを送るサンプルになります。payload
キーにはデバイスに送信するメッセージの本文をJSON形式で指定します。on
をデバイスが受信するとLEDを点灯(my.yellow.turnOn();
)します。
$ curl --insecure -X POST \ "$MESHBLU_URL/messages" \ -d '{"devices": ["'"$PUB_DEV_UUID"'"], "payload": {"yellow":"on"}}' \ --header "meshblu_auth_uuid: $PUB_DEV_UUID" \ --header "meshblu_auth_token: $PUB_DEV_TOKEN" {"devices":["xxx"],"payload":{"yellow":"on"}}
|
off
のメッセージを受信するとLEDを消灯(my.yellow.turnOff();
)します。
$ curl --insecure -X POST \ "$MESHBLU_URL/messages" \ -d '{"devices": ["'"$PUB_DEV_UUID"'"], "payload": {"yellow":"off"}}' \ --header "meshblu_auth_uuid: $PUB_DEV_UUID" \ --header "meshblu_auth_token: $PUB_DEV_TOKEN" {"devices":["xxx"],"payload":{"yellow":"off"}}
|