0%

Raspberry PiからMeshbluにDS18B20のセンシングデータを送信する

Firmata互換のIOを使い、同じセンサーモジュールからRaspberry PiでもArduinoでもセンシングデータ取得コードの抽象化を試しています。取得したデータはMeshbluに送信してMongoDBにストアします。特に1-WireのDS18B20の場合はArduinoでもAdd arduino library to Firmata or Johnny-Five #285によるとConfigurable Firmataが必要になります。GPIOのアナログとデジタルの違いもあってJohnny-Fiveを使った抽象化は難しそうです。

Raspi-ioの1-Wireは未実装

最初はJohnny-FiveのRaspi-ioを試しました。Temperature (DS18B20)のサンプルのPIN番号をRaspberry PiにあわせてGPIO4に変更します。

~/node_apps/raspi-io-led/app.js
var five = require("johnny-five");

five.Board().on("ready", function() {
// This requires OneWire support using the ConfigurableFirmata
var temperature = new five.Temperature({
controller: "DS18B20",
//pin: 2
pin: "GPIO4"
});

temperature.on("data", function(err, data) {
console.log(data.celsius + "°C", data.fahrenheit + "°F");
});
});

残念ながら実行するとエラーになりました。

$ sudo npm start

> raspi-io-led@0.0.1 start /home/pi/node_apps/raspi-io-led
> node app.js

1428295981604 Device(s) undefined
1428295981745 Connected RaspberryPi-IO
1428295981825 Repl Initialized
>>
/home/pi/node_apps/raspi-io-led/node_modules/raspi-io/lib/index.js:720
throw "sendOneWireConfig is not yet implemented";
^
sendOneWireConfig is not yet implemented

Raspi-ioのindex.js見ると1-Wireは未実装のようです。

index.js
sendOneWireConfig() {
throw 'sendOneWireConfig is not yet implemented';
}

Node.jsでw1_slaveファイルを読む

前回はデバイスのw1_slaveファイルを読んでDS18B20から温度を読むことに成功しました。Node.jsでも直接w1_slaveファイルを読むことにします。Publishing Temperature Reading From a DS18B20 1-Wire Digital Temperature Sensor Using a Raspberry Pi and node.jsを参考にします。

Rasbperry Piにログインしてプロジェクトを作成します。

$ mkdir -p ~/node_apps/meshblu-ds18B20
$ cd !$

package.jsonにmeshblu-npmのパッケージを追加します。

~/node_apps/meshblu-ds18B20/package.json
{
"name": "meshblu-ds18b20",
"version": "0.0.1",
"private": true,
"dependencies": {
"meshblu": "1.19.1"
},
"scripts": {"start": "node app.js"}
}

環境変数に定義したMeshbluへの接続情報を確認します。Raspberry Piに用意してあったmqtt-pubデバイスを認証に使います。

~/.bashrc
export MESHBLU_BROKER=xxx.xxx.xxx.x
export MESHBLU_URL=https://$MESHBLU_BROKER
export MQTT_PUB_UUID=mqtt-pub
export MQTT_PUB_TOKEN=123456

メインプログラムを書きます。DS18B20のデバイスIDはハードコードしました。Meshbluの認証が成功した後w1_slaveファイルを1分間隔で読みます。正規表現を使い温度の数字部分を抜き出します。摂氏にした温度はJSON形式にしてMeshbluへWebSocketで送信します。

~/node_apps/meshblu-ds18B20/app.js
var meshblu = require('meshblu'),
fs = require('fs');

var interval = 60*1000;
var w1Slave = '/sys/bus/w1/devices/28-0314626a2cff/w1_slave';

var conn = meshblu.createConnection({
"uuid": process.env.MQTT_PUB_UUID,
"token": process.env.MQTT_PUB_TOKEN,
"protocol": "websocket",
"server": process.env.MESHBLU_URL
});

conn.on('notReady', function(data){
console.log('UUID FAILED AUTHENTICATION!');
console.log(data);
});

conn.on('ready', function(data){
console.log('UUID AUTHENTICATED!');
console.log(data);

var readSensor = function(){
fs.readFile(w1Slave, 'utf8', function(err, data) {
if (err) throw err;
var matches = data.match(/t=(\d+)/);
var celsius = parseInt(matches[1]) / 1000;
var output = {"temperature": celsius};
console.log(output);
conn.data({
"temperature": celsius
});
});
};

setInterval(readSensor, interval);
});

プログラムを実行します。1間隔で取得した温度が標準出力されます。

$ npm start

> meshblu-ds18b20@0.0.1 start /home/pi/node_apps/meshblu-ds18B20
> node app.js

UUID AUTHENTICATED!
{ api: 'connect',
status: 201,
socketid: 'Q2mR6Ctg5UOpJJrRAAAD',
uuid: 'mqtt-pub',
token: '889346' }
...
{ temperature: 27.375 }
{ temperature: 27.5 }
{ temperature: 27.625 }
{ temperature: 27.5 }
{ temperature: 27.625 }

MeshbluコンテナのMongoDBの確認

Meshbluコンテナのシェルを起動します。

$ docker exec -it  meshblu bash

MongoDBシェルを使いRaspberry Piから送信されたセンシングデータを確認します。

$ mongo skynet
MongoDB shell version: 2.4.13
connecting to: skynet

直近の3件を表示します。1分間隔でセンシングデータが保存されています。

> db.data.find().sort({ $natural: -1 }).limit(3)
{ "timestamp" : "2015-04-06T08:52:37.899Z", "temperature" : "27.625", "_id" : ObjectId("55224955a545260b00c971b3") }
{ "timestamp" : "2015-04-06T08:51:37.863Z", "temperature" : "27.5", "_id" : ObjectId("55224919a545260b00c971b2") }
{ "timestamp" : "2015-04-06T08:50:37.851Z", "temperature" : "27.625", "_id" : ObjectId("552248dda545260b00c971b1") }