6
7

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

BluemixでIoT 温湿度、気圧を収集・蓄積・可視化+LED制御 その8

Last updated at Posted at 2016-04-11

##0.はじめに
前回の続きです。今回はGoogle GaugeとWebSocketを使用し、センサデータの可視化を行います。

##1.必要なもの(今回準備したもの)

項目 数量 メモ

##2.参考にさせていただいたところ
Node-REDを使ってセンサーデータをWebSocketで出力する
Github (karuru6225/bme280i2c)
##3.JSONデータにデバイスIDを追加
受信したJSONデータには、デバイスIDが入っていません。将来複数のデバイスが増えた場合を考慮して、デバイスIDを付加するようにします。
①デバイスIDを追加用のfunctionノードを追加する。
Node-REDの左側にあるfunctionからfunctionノードを選択する。
image

②functionノードを編集する。
 Name項目に、「devid追加」を入力する。
 Functionに、以下の内容を入力する。

Function
devID = msg.deviceId;

msg.payload = {
    "deviceid" : devID,
    "timestamp": msg.payload.d.timestamp,
    "temp"     : msg.payload.d.temp,
    "humid"    : msg.payload.d.humid,
    "press"    : msg.payload.d.press
};

return msg;

image

##4.Websocket出力を追加
①websocket出力用のノードを追加する。
 Node-REDの左側にあるoutputからwebsocketノードを選択する。
image

②websocket出力用ノードを編集する。
 Type項目に、「Listen on」を選択する。
 Path項目に、「/ws/sensor」を入力する。
 Name項目に、「/ws/sensor」を入力する。
image

③センサ情報取得ノードとdevid追加ノードおよびwebsocket出力用ノードを接続する。また、DB蓄積前にdevidを追加するように変更する
image

##5.Google Gaugeテンプレートの作成
ここでは、HTMLで表示するGoogle GaugeのHTMLテンプレートを作成する。
①templateノードを追加する。
image

②templateノードを編集する。
 Name項目に、「Google Gauge」を入力する。
 Syntax Highlight項目に、「HTML」を選択する。
 Fomart項目に、「Plain text」を選択する。
image

Template内には、下記を入力してください。
※var wsUrl = 'ws://XXXXXX.mybluemix.net/ws/sensor';
XXXXXXの部分は、自分の環境に合わせて変更してください。

Template
<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    <title>センサデータ リアルタイム表示</title>
    <script type="text/javascript" src="//www.google.com/jsapi"></script>
    <script type="text/javascript">
      var wsUrl = 'ws://XXXXXX.mybluemix.net/ws/sensor';//XXXXXXのところは、自分の環境に合わせて変更してください。
      var socket;
      var temperatureData, humidityData, pressureData;
      var temperatureOptions, humidityOptions, pressureOptions;
      var temperatureChart, humidityChart, pressureChart;

      // Google Gauge
      google.load("visualization", "1", {packages:["gauge"]});
      google.setOnLoadCallback(drawChart);
      function drawChart() {
        // Data for temperature chart
        temperatureData = google.visualization.arrayToDataTable([
          ['Label', 'Value'],
          ['温度', 0]
        ]);

        // Data for humidity chart
        humidityData = google.visualization.arrayToDataTable([
          ['Label', 'Value'],
          ['湿度', 0]
        ]);

        // Data for Pressure chart
        pressureData = google.visualization.arrayToDataTable([
          ['Label', 'Value'],
          ['気圧', 0]
        ]);

        temperatureOptions = {
          width: 800, height: 240,
          min: 0, max: 60,
          redFrom: 50, redTo: 60,
          yellowFrom:40, yellowTo: 50,
          minorTicks: 5,
          majorTicks: ["0", "10","20", "30", "40", "50", "60"]
        };

        // Option for humidity chart
        humidityOptions = {
          width: 800, height: 240,
          min: 0, max: 100,
          redFrom: 90, redTo: 100,
          yellowFrom:75, yellowTo: 90,
          minorTicks: 5,
          majorTicks: ["0", "10","20", "30", "40", "50", "60", "70", "80", "90", "100"]
        };

        // Option for pressure chart
        pressureOptions = {
          width: 800, height: 240,
          min: 0, max: 1100,
          redFrom: 1050, redTo: 1100,
          yellowFrom:1010, yellowTo: 1050,
          minorTicks: 5,
          majorTicks: ["0", "","", "", "", "", "", "700", "800", "900", "1000", "1100"]
        };

        temperatureChart = new google.visualization.Gauge(document.getElementById('temperatureChart'));
        humidityChart = new google.visualization.Gauge(document.getElementById('humidityChart'));
        pressureChart = new google.visualization.Gauge(document.getElementById('pressureChart'));

        temperatureChart.draw(temperatureData, temperatureOptions);
        humidityChart.draw(humidityData, humidityOptions);
        pressureChart.draw(pressureData, pressureOptions);
        connect();
      };

      function connect() {
        socket = new WebSocket(wsUrl);
        socket.onmessage = function(e) {
          var sensorData = JSON.parse(e.data);

          // Update temperature data
          temperatureData.setValue(0, 1, sensorData.temp);

          // Update humidity data
          humidityData.setValue(0, 1, sensorData.humid);

          // Update pressure data
          pressureData.setValue(0, 1, sensorData.press);

          temperatureChart.draw(temperatureData, temperatureOptions);
          humidityChart.draw(humidityData, humidityOptions);
          pressureChart.draw(pressureData, pressureOptions);
        };
      };

      function disconnect() {
          socket.close();
      };


function clock() {
   var nowTime = new Date();
   var nowHour = ("0"+ nowTime.getHours()).substr(-2);
   var nowMin = ("0"+ nowTime.getMinutes()).substr(-2);
   var nowSec = ("0"+ nowTime.getSeconds()).substr(-2);
   var msg = "現在時刻:" + nowHour + ":" + nowMin + ":" + nowSec;
   document.getElementById("Clock").innerHTML = msg;
}
setInterval('clock()',1000);

    </script>
  </head>
  <body>
    <h2>温湿度気圧 リアルタイム表示(Google Gauge)</h2>
    <p id="Clock"></p>
    <div>
      <button onclick="connect()">Connect</button>
      <button onclick="disconnect()">Disconnect</button>
    </div>

    <div>
      <div id="temperatureChart" style="width: 800px; height: 0px;"></div>
      <div id="humidityChart" style="width: 800px; height: 0px; position: relative; left: 230px;"></div>
      <div id="pressureChart" style="width: 800px; height: 220px; position: relative; left: 460px;"></div>
    </div>
  </body>
</html>

③入力用HTTPノードを追加する。
Node-REDの左側にあるinputからhttpノードを選択する。
image

④入力用HTTPノードを編集する。
 Method項目に、「GET」を選択する。
 URL項目に、「/sensor」を入力する。
image

⑤出力用HTTPノードを追加する。
Node-REDの左側にあるoutputからhttp responseノードを選択する。
image

⑥入力用HTTPノードとGoogle Gaugeノードおよび出力用HTTPノードを接続する。
image

⑦右上のDeployをクリックし、変更を反映する。

##6.ブラウザで表示を確認
①任意のブラウザで下記URLに接続する。
http://XXXXXX.mybluemix.net/sensor  ※XXXXXXは、自分の環境にあわせて変更してください。

image

②Websocketの接続状況を確認する。
下図の赤枠「connected 1」になっていれば接続されています。
 ※disconnectedになっている場合は、①の添付図にあるConnectボタンを再度クリックしてください。
image

③以前作成した、mqtt.jsを使用してデータを投入する。

コマンド
pi@raspberrypi ~ $ node mqtt.js

④Google Gaugeに結果がリアルタイムに反映することを確認する。
image

⑤mqtt.jsをカスタマイズする。
 このままですと、固定の温度・湿度・気圧のため、変化がないので、ランダムに値が変化するように
 カスタマイズする。また、5秒置きにデータを発生させるように変更する。

mqtt.js
var moment = require('moment');
var Client = require("ibmiotf").IotfDevice;

var config = {
省略
};

//ランダムデータを発生させる
var getRandomData = function(value){
   return Math.floor(Math.random()*8 + (value-3));
}
var client = new Client (config);

client.connect();

client.on("connect", function () {
   setInterval(function(){
      var nowtime = moment().format("YYYY-MM-DD HH:mm:ss.SSS");
      var temp_v = getRandomData(25);
      var humid_v = getRandomData(40);
      var press_v = getRandomData(1000);
      payload = JSON.stringify({d : { timestamp : nowtime, temp : temp_v, humid : humid_v, press : press_v }});
      console.log(payload);
      client.publish ("eid", "json", payload);
   }, 5000); //5000ms置き(5秒置きにデータを発生させる)
});

⑥再度mqtt.jsを実行して、Google Gaugeがリアルタイムに変化することを確認する。

##7.BME280センサデータの連携
①githubで公開されているソースファイルを入手する。
 自力で作成する力が足りなかったため、ここGithub (karuru6225/bme280i2c)を利用させていただきました。

コマンド
pi@raspberrypi ~ $ git clone https://github.com/karuru6225/bme280i2c.git

②index.jsを参考にbme280.jsを作成する。
 index.jsをbme280.jsとしてコピーする。

コマンド
pi@raspberrypi ~ $ cp bme280i2c/index.js bme280.js

次の部分を編集する。編集個所は、ファイルの後ろにあるsetIntaval部分の3か所を編集する。

bme280.js
省略
//setInterval(function(){        //この行をコメントとし、
exports.bme = function(p_callback) {    //この行を追加する。
  async.waterfall([
      function(cb){
        readRawData(function(raws){
          cb(null, raws);
        });
      },
      function(raws, cb){
        var tbase = getTBase(raws.t, calib);
        var temp = calibrateT(tbase, calib);
        var pres = calibrateP(raws.p, tbase, calib);
        var humi = calibrateH(raws.h, tbase, calib);
        console.log('temp:' + (temp/100.0));
        console.log('pres:' + (pres/100.0));
        console.log('humi:' + (humi));
        console.log('');
        p_callback(temp/100.0, humi, pres/100.0); //この行を追加
        cb();
      }
  ]);
//},1000);  //この行をコメントとし、
};            //この行を追加する。

③bme280.jsを呼び出し、温度・湿度・気圧データを取得するように、mqtt.jsをカスタマイズする。
カスタマイズ後のmqtt.jsは、下記の通り。

mqtt.js
var f = require('./bme280.js');
var moment = require('moment');
var Client = require("ibmiotf").IotfDevice;

var config = {
 (省略)
};

function mkJson(callback) {
   f.bme(function(temp, humid, press){
      var nowtime = moment().format("YYYY-MM-DD HH:mm:ss.SSS");
      var temp_v =  temp.toFixed(1);
      var humid_v = humid.toFixed(1);
      var press_v = press.toFixed(1);
      payload = JSON.stringify({d : { timestamp : nowtime, temp : temp_v, humid : humid_v, press : press_v }});
      //console.log(payload);
      callback(payload);
   });
}

var client = new Client (config);

client.connect();

client.on("connect", function () {
   mkJson(function(payload) {
      console.log(payload);
      client.publish ("eid", "json", payload);
   });
   setInterval(function(){
        mkJson(function(payload) {
           console.log(payload);
        });
        client.publish ("eid", "json", payload);
   }, 60000);
});

④mqtt.jsを実行する。
 今回は、1分周期にしたため、適宜時間を変更して試してください。

以上で、Google GaugeとWebsocketを用いた可視化手順は終了です。

次(その9)は、chart.jsを利用しmongodbから取得した過去データを折れ線グラフで表示することを行います。

6
7
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
6
7

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?