LoginSignup
1
2

More than 5 years have passed since last update.

さくらIoT x node-RED on Bluemix で会議室の空き状況を表示させるまでの3日間(2日目)

Last updated at Posted at 2017-01-06

1日目 では、IBM BluemixにNode-REDを導入し、WebSocketでデータを受信して、Ambientというグラフ表示サービスにデータを連係するところまで進みました。
まだIoT Platformが届いていないので、2日目では、受信したデータをDBにとりあえず保存するのと、Webサイトを作るところまで行きたいと思います。

目次

  • 受信したデータをとりあえずCloudantに保存する
  • 今の状態を表示するWebサイトを作る

受信したデータをとりあえずCloudantに保存する

これはもう超簡単です。Cloudantノードを追加して、WebSocket受信ノードから線を引っ張るだけ。Cloudantノードは2つありますが、アイコンが後ろ(右)についているのがCloudantに保存ずるノードです。
スクリーンショット 2017-01-06 18.52.36.png
ダブルクリックして、設定を開くと、ServiceにはNode-REDの設定が保存されているCloudant DBが自動でセットされているはずです。Database名は、適当につけてください。ただし大文字はだめみたいです。(Databaseが存在しなければ、自動で作成されます。)
スクリーンショット 2017-01-06 19.09.50.png


今の状態を表示するWebサイトを作る

画像ファイルの追加

現在の会議室の状態は、1日目でグローバル変数に保存しました。その状態を、Webサイトから簡単に参照できるようにしたいと思います。
画像で見せた方が一覧性がよいと思ったので、今回はいらすとやさんからドアの画像を使わせていただきます。
まず、今回利用する画像をサーバにアップします。1日目にpackage.jsonを編集したときと同じように、GitHubに作成したレポジトリ上の、/public/imagesディレクトリに、画像ファイルをアップします。
スクリーンショット 2017-01-06 19.02.45.png
コミットすると、自動でデプロイが走るので、数分待ちます。


html作成部分

実際にhtmlを表示する部分も、ノードの組み合わせで簡単に作れます。Inputの中のhttpから、outputの中のhttpにノードをつなげていくと、inputに指定したURLへのリクエストを出力できます。
スクリーンショット 2017-01-06 19.11.42.png

[{"id":"b216fb73.727028","type":"http in","z":"396465eb.1d8e22","name":"index (\"/\")","url":"/","method":"get","swaggerDoc":"","x":104,"y":1049,"wires":[["20622690.51ddba"]]},{"id":"fa304d55.42125","type":"template","z":"396465eb.1d8e22","name":"index ページのHTML","field":"payload","fieldType":"msg","format":"html","syntax":"mustache","template":"<head>\n    <meta charset=\"utf-8\" />\n    <title>会議室状況表示</title>\n    <!-- Latest compiled and minified CSS -->\n    <link rel=\"stylesheet\" href=\"https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css\" integrity=\"sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u\" crossorigin=\"anonymous\">\n    \n    <!-- Optional theme -->\n    <link rel=\"stylesheet\" href=\"https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap-theme.min.css\" integrity=\"sha384-rHyoN1iRsVXV4nD0JutlnGaslCJuC7uwjduW9SVrLvRYooPp2bWYgmgJQIXwl/Sp\" crossorigin=\"anonymous\">\n    \n    <!-- Latest compiled and minified JavaScript -->\n    <script src=\"https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js\" integrity=\"sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa\" crossorigin=\"anonymous\"></script>\n    <style type=\"text/css\">\n\n</style>\n</head>\n<body>\n    <div class=\"container\">\n\n      <div class=\"page-header\">\n        <h1>会議室状況表示</h1>\n      </div>\n     \n     <h2>現在の空き状況</h2>\n      <table class=\"table table-bordered\">\n            <thead>\n              <tr>\n                <th>会議室A</th>\n                <th>会議室B</th>\n                <th>会議室C</th>\n                <th>会議室D</th>\n                <th>会議室E</th>\n                <th>会議室F</th>\n              </tr>\n            </thead>\n            <tbody>\n\n              <tr>\n                <td><img src=\"/images/{{payload.img_0}}\" class=\"img-responsive\" /></td>\n                <td><img src=\"/images/{{payload.img_1}}\" class=\"img-responsive\" /></td>\n                <td><img src=\"/images/{{payload.img_2}}\" class=\"img-responsive\" /></td>\n                <td><img src=\"/images/{{payload.img_3}}\" class=\"img-responsive\" /></td>\n                <td><img src=\"/images/{{payload.img_4}}\" class=\"img-responsive\" /></td>\n                <td><img src=\"/images/{{payload.img_5}}\" class=\"img-responsive\" /></td>\n              </tr>\n\n              <tr>\n                <td>{{payload.status_0}}</td>\n                <td>{{payload.status_1}}</td>\n                <td>{{payload.status_2}}</td>\n                <td>{{payload.status_3}}</td>\n                <td>{{payload.status_4}}</td>\n                <td>{{payload.status_5}}</td>\n                \n              </tr>\n           \n            </tbody>\n          </table>\n   \n   </div>\n</body>","x":496.4285583496094,"y":1049.3214111328125,"wires":[["e53ef283.a18638"]]},{"id":"bca1b030.f372a8","type":"comment","z":"396465eb.1d8e22","name":"indexページ","info":"","x":93.375,"y":1003.9999961853027,"wires":[]},{"id":"20622690.51ddba","type":"function","z":"396465eb.1d8e22","name":"Arrayから値を取得","func":"var pdata = {};\nfor(var i = 0; i < 6; i++) { \n    \n    var img = \"img_\" + i;\n    var stat = \"status_\" + i;\n    \n    if(context.global.data[i]>0){\n        pdata[img] = \"room_closed.png\";\n        pdata[stat] = \"満室\";\n    }else{\n         pdata[\"img_\"+i] = \"room_open.png\";\n         pdata[\"status_\"+i] = \"空室\";\n    }\n}\n\n\nmsg.payload = pdata;\nreturn msg;","outputs":1,"noerr":0,"x":284.4285888671875,"y":1048.857177734375,"wires":[["fa304d55.42125"]]},{"id":"e53ef283.a18638","type":"http response","z":"396465eb.1d8e22","name":"","x":670.1428833007812,"y":1049.0714111328125,"wires":[]}]

こちらを例のごとくコピペしてみてください。
たぶん説明が必要になるのはfunctionノードとtemplateノードです。


functionノードでは、Global変数を参照して、html内で動的に変わる部分をmsg.payloadに格納しています。
後でも出てきますが、Node-REDでは、ノード間の連携はmsgオブジェクトを送り合うことで実現しているようです。特に重要なのがmsg.payloadというオブジェクトで、このpayloadオブジェクトにほとんどの情報が入っています。msgの中には、payload以外の情報も任意に格納できます。たとえばurl取得ノードには、msg.urlとmsg.methodを指定してあげるといった使い方をします。また、payload以外は、明示的に値を変更しなければ後ろのノードにどんどん引き継がれるので、複数のノード間で情報を連携したいときにはpayload以外の部分に情報を格納するといった使い方ができるようです。
詳しくは私もまだよく分からないので、ググっていただければ。
スクリーンショット 2017-01-06 19.16.48.png


templateノードでは、送られてきたmsg.payloadの中身を参照して、テンプレートに当てはめることができます。見ていただけると分かるとおり、波括弧2つで囲った中に変数名を指定すると、変数が展開されます。下にあるFormatをPlain textにすると変数が展開されないので要注意。
スクリーンショット 2017-01-06 19.17.49.png


以上で、Node-REDのURLにアクセスしてみてください。
こんな感じで、サイトが作成できたと思います。
スクリーンショット 2017-01-06 19.27.13.png

ちなみに、Node-REDの設定画面に飛べなくなったと困った方、安心してください。
URLの後ろに /red/ をつければ大丈夫です。

3日目では、Arduinoの接続と、統計情報の更新まで行きたいのですが、果たしてIoT Platformは届くのでしょうか・・・

(ちゃんと届きました。)


2.5日目に続く

1
2
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
1
2