1日目 では、IBM BluemixにNode-REDを導入し、WebSocketでデータを受信して、Ambientというグラフ表示サービスにデータを連係するところまで進みました。
まだIoT Platformが届いていないので、2日目では、受信したデータをDBにとりあえず保存するのと、Webサイトを作るところまで行きたいと思います。
目次
- 受信したデータをとりあえずCloudantに保存する
- 今の状態を表示するWebサイトを作る
##受信したデータをとりあえずCloudantに保存する
これはもう超簡単です。Cloudantノードを追加して、WebSocket受信ノードから線を引っ張るだけ。Cloudantノードは2つありますが、アイコンが後ろ(右)についているのがCloudantに保存ずるノードです。
ダブルクリックして、設定を開くと、ServiceにはNode-REDの設定が保存されているCloudant DBが自動でセットされているはずです。Database名は、適当につけてください。ただし大文字はだめみたいです。(Databaseが存在しなければ、自動で作成されます。)
##今の状態を表示するWebサイトを作る
###画像ファイルの追加
現在の会議室の状態は、1日目でグローバル変数に保存しました。その状態を、Webサイトから簡単に参照できるようにしたいと思います。
画像で見せた方が一覧性がよいと思ったので、今回はいらすとやさんからドアの画像を使わせていただきます。
まず、今回利用する画像をサーバにアップします。1日目にpackage.jsonを編集したときと同じように、GitHubに作成したレポジトリ上の、/public/imagesディレクトリに、画像ファイルをアップします。
コミットすると、自動でデプロイが走るので、数分待ちます。
###html作成部分
実際にhtmlを表示する部分も、ノードの組み合わせで簡単に作れます。Inputの中のhttpから、outputの中のhttpにノードをつなげていくと、inputに指定したURLへのリクエストを出力できます。
[{"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以外の部分に情報を格納するといった使い方ができるようです。
詳しくは私もまだよく分からないので、ググっていただければ。
templateノードでは、送られてきたmsg.payloadの中身を参照して、テンプレートに当てはめることができます。見ていただけると分かるとおり、波括弧2つで囲った中に変数名を指定すると、変数が展開されます。下にあるFormatをPlain textにすると変数が展開されないので要注意。
以上で、Node-REDのURLにアクセスしてみてください。
こんな感じで、サイトが作成できたと思います。
ちなみに、Node-REDの設定画面に飛べなくなったと困った方、安心してください。
URLの後ろに /red/ をつければ大丈夫です。
3日目では、Arduinoの接続と、統計情報の更新まで行きたいのですが、果たしてIoT Platformは届くのでしょうか・・・
(ちゃんと届きました。)
##2.5日目に続く