Node-REDを使って簡単なWebアプリを作ってみます
このサンプルのフローでは、svgでビーコンからの位置情報を可視化します。
サンプル-1:ビーコンの位置情報を可視化します
ビーコンの位置情報を可視化する
[{"id":"b85aaf79.f57bd","type":"function","z":"abfc9a76.407a1","name":"センサー値を出力","func":"if (msg.payload === \"restart\") {\n context.set(\"x0\",250);\n context.set(\"y0\",250);\n}\nvar x = context.get(\"x0\")||250;\nvar y = context.get(\"y0\")||250;\n\n//var i = context.get(\"i0\")||0;\n\n//var sampling_min_interval = 1;\nvar sampling_sec_interval = 1; // データを出力する間隔\n\n//xa = [100,120,140,160,180];\n//ya = [100,120,140,160,180];\n\nvar x1 = Math.floor(Math.random () * 10) - 5;\nvar y1 = Math.floor(Math.random () * 10) - 5;\nvar temp = 15 + Math.floor(Math.random () *100 + 1) / 10; // センサー値を生成(シミュレート)\nvar humid = 40 + 2 * Math.floor(Math.random () *100 + 1) / 10; // センサー値を生成(シミュレート)\n\n\n/*i++\nif ( i >= xa.length) { \n i = 0;\n}\ncontext.set(\"i0\", i);\n*/\nx += x1;\ncontext.set(\"x0\",x);\ny += y1;\ncontext.set(\"y0\",y);\n\nvar hour = JSON.stringify(msg.date.hour);\nvar min_org = JSON.stringify(msg.date.minute);\nvar min = ( \"0\" + min_org ).substr( -2 ); // 一桁分の場合、二桁に\nvar sec_org = JSON.stringify(msg.date.second);\nvar sec = ( \"0\" + sec_org ).substr( -2 ); // 一桁秒の場合、二桁に\nvar time = hour + \":\" + min + \":\" + sec;\n\nvar data = [[time],[x],[y],[temp],[humid]];\n//var data = [[time],[x],[y],[temp],[humid]];\nmsg.payload = data;\nif ( ( msg.date.second % sampling_sec_interval ) !== 0 ) return;\n//if ( ( msg.date.minute % sampling_min_interval ) !== 0 ) return;\nreturn msg;\n","outputs":1,"noerr":0,"x":470,"y":120,"wires":[[]]},{"id":"8d9ca6aa.37f7e","type":"template","z":"abfc9a76.407a1","name":"ws用htmlを返す","field":"payload","fieldType":"msg","format":"handlebars","syntax":"mustache","template":"<!DOCTYPE HTML>\n<html>\n <head>\n <title>センサーからの位置情報を表示</title>\n <meta charset=\"utf-8\" />\n </head>\n <body>\n\t <div id=\"a-box\" style=\"background-color: #87cefa; padding: 20px;\">\n\t\t\t <h1>位置によるIoTデータ表示</h1>\n\t\t\t <br />\n\t\t\t <p>\n\t\t\t IoTデータの位置情報を可視化します<br />\n\t\t\t </p>\n\t\t\t</div>\n\n\n<div id='example'>\n<svg id=\"svg.svg\" xmlns=\"http://www.w3.org/2000/svg\" width=\"500\" height=\"500\" viewBox=\"0 0 500 500\">\n\n <line x1=\"0\" y1=\"0\" x2=\"0\" y2=\"500\" stroke=\"black\" stroke-width=\"2\" />\n <line x1=\"0\" y1=\"0\" x2=\"500\" y2=\"0\" stroke=\"black\" stroke-width=\"2\" />\n <line x1=\"500\" y1=\"0\" x2=\"500\" y2=\"500\" stroke=\"black\" stroke-width=\"2\" />\n <line x1=\"0\" y1=\"500\" x2=\"500\" y2=\"500\" stroke=\"black\" stroke-width=\"2\" />\n\n <line x1=\"0\" y1=\"100\" x2=\"500\" y2=\"100\" stroke=\"black\" stroke-dasharray=\"2\" stroke-width=\"1\" />\n <line x1=\"0\" y1=\"200\" x2=\"500\" y2=\"200\" stroke=\"black\" stroke-dasharray=\"2\" stroke-width=\"1\" />\n <line x1=\"0\" y1=\"300\" x2=\"500\" y2=\"300\" stroke=\"black\" stroke-dasharray=\"2\" stroke-width=\"1\" />\n <line x1=\"0\" y1=\"400\" x2=\"500\" y2=\"400\" stroke=\"black\" stroke-dasharray=\"2\" stroke-width=\"1\" />\n\n <line x1=\"100\" y1=\"0\" x2=\"100\" y2=\"500\" stroke=\"black\" stroke-dasharray=\"2\" stroke-width=\"1\" />\n <line x1=\"200\" y1=\"0\" x2=\"200\" y2=\"500\" stroke=\"black\" stroke-dasharray=\"2\" stroke-width=\"1\" />\n <line x1=\"300\" y1=\"0\" x2=\"300\" y2=\"500\" stroke=\"black\" stroke-dasharray=\"2\" stroke-width=\"1\" />\n <line x1=\"400\" y1=\"0\" x2=\"400\" y2=\"500\" stroke=\"black\" stroke-dasharray=\"2\" stroke-width=\"1\" />\n\n <rect x=\"80\" y=\"80\" width=\"40\" height=\"40\" fill=\"#d2b48c\" />\n <rect x=\"180\" y=\"80\" width=\"40\" height=\"40\" fill=\"#d2b48c\" />\n <rect x=\"280\" y=\"80\" width=\"40\" height=\"40\" fill=\"#d2b48c\" />\n <rect x=\"380\" y=\"80\" width=\"40\" height=\"40\" fill=\"#d2b48c\" />\n\n <rect x=\"80\" y=\"180\" width=\"40\" height=\"40\" fill=\"#d2b48c\" />\n <rect x=\"180\" y=\"180\" width=\"40\" height=\"40\" fill=\"#d2b48c\" />\n <rect x=\"280\" y=\"180\" width=\"40\" height=\"40\" fill=\"#d2b48c\" />\n <rect x=\"380\" y=\"180\" width=\"40\" height=\"40\" fill=\"#d2b48c\" />\n\n <rect x=\"80\" y=\"280\" width=\"40\" height=\"40\" fill=\"#d2b48c\" />\n <rect x=\"180\" y=\"280\" width=\"40\" height=\"40\" fill=\"#d2b48c\" />\n <rect x=\"280\" y=\"280\" width=\"40\" height=\"40\" fill=\"#d2b48c\" />\n <rect x=\"380\" y=\"280\" width=\"40\" height=\"40\" fill=\"#d2b48c\" />\n\n <rect x=\"80\" y=\"380\" width=\"40\" height=\"40\" fill=\"#d2b48c\" />\n <rect x=\"180\" y=\"380\" width=\"40\" height=\"40\" fill=\"#d2b48c\" />\n <rect x=\"280\" y=\"380\" width=\"40\" height=\"40\" fill=\"#d2b48c\" />\n <rect x=\"380\" y=\"380\" width=\"40\" height=\"40\" fill=\"#d2b48c\" />\n\n <text id=\"t01\" x=\"70\" y=\"50\">ビーコン#1</text>\n <text id=\"t02\" x=\"70\" y=\"70\" font-size=\"12\">温度、湿度</text>\n\n <circle id=\"c01\" cx=\"50\" cy=\"50\" r=\"10\" fill=\"#98fb98\"></circle>\n\n</svg>\n</div>\n\n\n<div id=\"b-box\" style=\"background-color: #ecf2fe; padding: 20px; \">\n\n <h2>時刻</h2>\n\t\t\t<div style=\"text-align:left\" id=\"output0\"></div>\n\t\t\t<div style=\"text-align:left;font-size: 18pt\" id=\"output1\"></div>\n\t\t<h2>センサーX座標 </h2>\n\t\t\t<span style=\"text-align:left;font-size: 18pt\" id=\"output2\"></span>\n\t\t<h2>センサーY座標 </h2>\n\t\t\t<span style=\"text-align:left;font-size: 18pt\" id=\"output3\"></span>\n\t\t<h2>センサー温度 </h2>\n\t\t\t<span style=\"text-align:left;font-size: 18pt\" id=\"output4\"></span>℃\n\t\t<h2>センサー湿度 </h2>\n\t\t\t<span style=\"text-align:left;font-size: 18pt\" id=\"output5\"></span>%\n\n</div>\n\n<div id=\"c-box\" style=\"background-color: #f0e8fa; padding: 20px; \">\n <div class=\"category\">参考URL</div>\n <ul>\n <li><a href=\"http://qiita.com/egplnt/items/af867711a7191923b2ff\">Watson IoT Platformを使ってみる</a></li>\n <li><a href=\"https://internetofthings.ibmcloud.com/#/\">Watson IoT Platform</a></li>\n <li><a href=\"https://developer.ibm.com/recipes/tutorials/use-the-simulated-device-to-experience-the-iot-foundation/\">Recipe - Simulator</a></li>\n </ul>\n <div class=\"category\">マニュアル</div>\n <ul>\n <li><a href=\"http://ibm.com/iot\">IBM IoT</a></li>\n <li><a href=\"https://docs.internetofthings.ibmcloud.com/ja/\">Watson IoT Platform資料ページ</a></li>\n <li><a href=\"https://developer.ibm.com/recipes/\">Recipe</a></li>\n </ul>\n\n</div>\n<div id=\"d-box\" style=\"clear: both; background-color: #e0ce96; font-size: 18px; padding: 10px; text-align: center; padding: 20px;\">\n\tcopyright (c) abc.com All right reserved.\n</div>\n\n<script>\nvar socketname = \"ws://\" + window.location.host + \"/ws/flow36\";\nvar connection = new WebSocket(socketname);\n//var connection = new WebSocket('ws://このIoTアプリの名前.mybluemix.net/ws/flow36');\n\nconnection.onopen = function () {\n console.log(\"websocket connected\");\n};\n\n// Log errors\nconnection.onerror = function (error) {\n console.log('WebSocket Error ' + error);\n};\n\n// Log messages from the server\nconnection.onmessage = function (m) {\n //console.log('Server: ' + m.data);\n\tdoIt(m);\n};\n\n//function doIt\nfunction doIt(msg){\n console.log(\"doit:\" + msg.data);\n\tvar msgs = JSON.parse(msg.data);\n\n\t//円要素を取得し座標を指定\n\tvar c = document.querySelector('circle');\n\t(function(){\n\t\tvar c0x = parseInt(msgs[1]);\n\t\tvar c0y = parseInt(msgs[2]);\n\t c.setAttribute('cx', c0x );\n\t\tc.setAttribute('cy', c0y );\n\t})();\n\n\t//text要素を配列で取得し、各textを表示する座標を指定\n\tvar t = document.querySelectorAll('text');\n\tvar t0x = parseInt(msgs[1]) + 20;\n\tvar t0y = parseInt(msgs[2]);\n\t(function(){\n\t t[0].setAttribute('x', t0x );\n\t\tt[0].setAttribute('y', t0y );\n\t})();\n\tvar t1x = parseInt(msgs[1]) + 20;\n\tvar t1y = parseInt(msgs[2]) + 20;\n\t(function(){\n\t t[1].setAttribute('x', t1x );\n\t\tt[1].setAttribute('y', t1y );\n\t})();\n\n\t//text要素の文字列を変更\n\tvar t2 = document.getElementById('t02');\n\t(function(){\n\t t2.textContent=\"温度:\" + msgs[3] + \"℃、湿度:\" + msgs[4] + \"%\";\n\t})();\n\n\t// 各センサー要素を取り出して、画面へ表示\n\t//for (var i = 0; i < msgs.length; i++) { console.log( i + \" = \" + msgs[i]); }\n\ttarget = document.getElementById(\"output1\");\n\ttarget.innerHTML = msgs[0];\n\ttarget = document.getElementById(\"output2\");\n\ttarget.innerHTML = msgs[1];\n\ttarget = document.getElementById(\"output3\");\n\ttarget.innerHTML = msgs[2];\n\ttarget = document.getElementById(\"output4\");\n\ttarget.innerHTML = msgs[3];\n\ttarget = document.getElementById(\"output5\");\n\ttarget.innerHTML = msgs[4];\n\n};\n\n</script>\n\n</body>\n</html>\n","x":314,"y":237,"wires":[["3bda8784.05035"]]},{"id":"14f9444f.420f2c","type":"inject","z":"abfc9a76.407a1","name":"1秒毎","topic":"","payload":"","payloadType":"date","repeat":"1","crontab":"","once":false,"x":104,"y":77,"wires":[["ab84d819.daee5"]]},{"id":"1e094784.703428","type":"inject","z":"abfc9a76.407a1","name":"restart","topic":"","payload":"0","payloadType":"num","repeat":"","crontab":"","once":false,"x":104,"y":117,"wires":[["ab84d819.daee5"]]},{"id":"e02e2b33.706a1","type":"debug","z":"abfc9a76.407a1","name":"出力","active":true,"console":"false","complete":"payload","x":690,"y":80,"wires":[]},{"id":"7f142f58.3e70c8","type":"comment","z":"abfc9a76.407a1","name":"IoTセンサーからの値をシミュレート","info":"","x":194,"y":37,"wires":[]},{"id":"747b91c.be1a87","type":"http in","z":"abfc9a76.407a1","name":"","url":"/test36","method":"get","swaggerDoc":"","x":124,"y":237,"wires":[["8d9ca6aa.37f7e"]]},{"id":"3bda8784.05035","type":"http response","z":"abfc9a76.407a1","name":"","x":504,"y":237,"wires":[]},{"id":"a38629dd.1c8a7","type":"comment","z":"abfc9a76.407a1","name":"IoTセンサーからの位置情報を可視化","info":"","x":194,"y":197,"wires":[]},{"id":"ab84d819.daee5","type":"function","z":"abfc9a76.407a1","name":"日付時刻の追加","func":"var d = new Date();\nvar localTime = d.getTime();\nvar localOffset = d.getTimezoneOffset() * 60000;\nvar utc = localTime + localOffset;\nvar offset = -9.0;\nvar result = utc - (3600000 * offset);\nvar date = parseInt(new Date(result) / 1000);\nvar dt = new Date(result);\n\nvar year = dt.getFullYear();\nvar month = dt.getMonth()+1;\nvar day = dt.getDate();\nvar hour = dt.getHours();\nvar minute = dt.getMinutes();\nvar second = dt.getSeconds();\n//if (!msg.payload) {\n// msg.payload = { \"initial\": \"value\" };\n//}\nif (!msg.date) {\n msg.date = { \"initial\": \"value\" };\n}\nmsg.date = {\n \"date\": date,\n \"year\": year,\n \"month\": month,\n \"day\": day,\n \"hour\": hour,\n \"minute\": minute,\n \"second\": second\n};\nreturn msg;","outputs":1,"noerr":0,"x":274,"y":97,"wires":[["b86319e7.de2448"]]},{"id":"169306e5.7cfe21","type":"debug","z":"abfc9a76.407a1","name":"時刻の表示","active":false,"console":"false","complete":"date","x":710,"y":40,"wires":[]},{"id":"4013aa26.3ad454","type":"websocket out","z":"abfc9a76.407a1","name":"","server":"60b448ae.68bbf8","client":"","x":720,"y":120,"wires":[]},{"id":"b86319e7.de2448","type":"function","z":"abfc9a76.407a1","name":"シミュレーター","func":"var i = context.get(\"i0\")||0;\n\n//var sampling_min_interval = 1;\nvar sampling_sec_interval = 1; // データを出力する間隔\n\nxa = [50,70,90,110,130,150,150,150,150,150,150,170,190,210,230,250,250,250,250,250,250,270,290,310,330,350,350,350,350,350,350,350,350,350,350,350,330,310,290,270,250,250,250,250,250,250,250,250,250,250,230,210,190,170,150,130,110, 90, 70, 50, 50, 50, 50, 50, 50, 70, 90,110,130,150,150,150,150,150,150,150,150,150,150,150,130,110, 90, 70, 50, 50, 50, 50, 50];\nya = [50,50,50,50, 50, 50, 70, 90, 110,130,150,150,150,150,150,150,130,110, 90, 70, 50, 50, 50, 50, 50, 50, 70, 90,110,130,150,170,190,210,230,250,250,250,250,250,250,270,290,310,350,370,390,410,430,450,450,450,450,450,450,450,450,450,450,450,430,410,390,370,350,350,350,350,350,350,330,310,290,270,250,230,210,190,170,150,150,150,150,150,150,130,110, 90, 70];\n\nvar x = xa[i];\nvar y = ya[i];\nvar temp = 15 + Math.floor(Math.random () *100 + 1) / 10; // センサー値を生成(シミュレート)\nvar humid = 40 + 2 * Math.floor(Math.random () *100 + 1) / 10; // センサー値を生成(シミュレート)\n\ni++;\nif ( i >= xa.length) { \n i = 0;\n}\ncontext.set(\"i0\", i);\n\nvar hour = JSON.stringify(msg.date.hour);\nvar min_org = JSON.stringify(msg.date.minute);\nvar min = ( \"0\" + min_org ).substr( -2 ); // 一桁分の場合、二桁に\nvar sec_org = JSON.stringify(msg.date.second);\nvar sec = ( \"0\" + sec_org ).substr( -2 ); // 一桁秒の場合、二桁に\nvar time = hour + \":\" + min + \":\" + sec;\n\nvar data = [[time],[x],[y],[temp],[humid]];\n//var data = [[time],[x],[y],[temp],[humid]];\nmsg.payload = data;\nif ( ( msg.date.second % sampling_sec_interval ) !== 0 ) return;\n//if ( ( msg.date.minute % sampling_min_interval ) !== 0 ) return;\nreturn msg;\n","outputs":1,"noerr":0,"x":460,"y":80,"wires":[["4013aa26.3ad454","e02e2b33.706a1"]]},{"id":"60b448ae.68bbf8","type":"websocket-listener","z":"abfc9a76.407a1","path":"/ws/flow36","wholemsg":"false"}]
- Node-REDのフローをコピーする方法を参照して、上記のフローをコピペします。
- 上段のシミュレーターのフローを確認し、左上の「1秒毎」と表記されたInjectノードをダブルクリックで開いて適当なインターバルに設定し、ノード右側から線を引き出して後続のオレンジ色の「日付時刻の追加」ノードに接続します。(この線は常時リクエストを送付してしまうので、テスト時以外は切断しておくことをお薦めします。)
- Node-RED画面右上の赤い「Deploy」ボタンを押してクラウド側へ反映します。
- ブラウザの新しいタブを開き、
IoTアプリ名.bluemix.net/test36
へアクセスすると下記のような画面が表示されます。 - うまく表示されない場合、上段のIoTセンサー値を出力するフローのwebsocket出力ノードを一旦削除して、画面左側のパレットのoutputセクションからwebsocketノードをドラッグ&ドロップして作り直してみます。出力Pathは
/we/flow36
としてあります(html内の指定と整合すれば何でも構いません)。
サンプル-2:Area/Far/Near/Immediateを表示します
Ara/Far/Near/Immediateを表示します
[{"id":"e4835546.4173f","type":"function","z":"1f1ccf2d.e2b139","name":"センサー値を出力","func":"if (msg.payload === \"restart\") {\n context.set(\"x0\",250);\n context.set(\"y0\",250);\n}\nvar x = context.get(\"x0\")||250;\nvar y = context.get(\"y0\")||250;\n\n//var i = context.get(\"i0\")||0;\n\n//var sampling_min_interval = 1;\nvar sampling_sec_interval = 1; // データを出力する間隔\n\n//xa = [100,120,140,160,180];\n//ya = [100,120,140,160,180];\n\nvar x1 = Math.floor(Math.random () * 10) - 5;\nvar y1 = Math.floor(Math.random () * 10) - 5;\nvar temp = 15 + Math.floor(Math.random () *100 + 1) / 10; // センサー値を生成(シミュレート)\nvar humid = 40 + 2 * Math.floor(Math.random () *100 + 1) / 10; // センサー値を生成(シミュレート)\n\n\n/*i++\nif ( i >= xa.length) { \n i = 0;\n}\ncontext.set(\"i0\", i);\n*/\nx += x1;\ncontext.set(\"x0\",x);\ny += y1;\ncontext.set(\"y0\",y);\n\nvar hour = JSON.stringify(msg.date.hour);\nvar min_org = JSON.stringify(msg.date.minute);\nvar min = ( \"0\" + min_org ).substr( -2 ); // 一桁分の場合、二桁に\nvar sec_org = JSON.stringify(msg.date.second);\nvar sec = ( \"0\" + sec_org ).substr( -2 ); // 一桁秒の場合、二桁に\nvar time = hour + \":\" + min + \":\" + sec;\n\nvar data = [[time],[x],[y],[temp],[humid]];\n//var data = [[time],[x],[y],[temp],[humid]];\nmsg.payload = data;\nif ( ( msg.date.second % sampling_sec_interval ) !== 0 ) return;\n//if ( ( msg.date.minute % sampling_min_interval ) !== 0 ) return;\nreturn msg;\n","outputs":1,"noerr":0,"x":470,"y":140,"wires":[[]]},{"id":"1101965e.4c38aa","type":"template","z":"1f1ccf2d.e2b139","name":"ws用htmlを返す","field":"payload","fieldType":"msg","format":"handlebars","syntax":"mustache","template":"<!DOCTYPE HTML>\n<html>\n <head>\n <title>ビーコンの位置情報を表示</title>\n <meta charset=\"utf-8\" />\n </head>\n <body>\n\t <div id=\"a-box\" style=\"background-color: #87cefa; padding: 20px;\">\n\t\t\t <h1>位置によるIoTデータ表示</h1>\n\t\t\t <br />\n\t\t\t <p>\n\t\t\t ビーコンの位置情報を可視化します<br />\n\t\t\t\t\t\t半径の大きい円からArea/Far/Near/Immediateを表します\n\t\t\t </p>\n\t\t\t</div>\n\n\n<div id='example'>\n<svg id=\"svg.svg\" xmlns=\"http://www.w3.org/2000/svg\" width=\"500\" height=\"500\" viewBox=\"0 0 500 500\">\n\n <line x1=\"0\" y1=\"0\" x2=\"0\" y2=\"500\" stroke=\"black\" stroke-width=\"2\" />\n <line x1=\"0\" y1=\"0\" x2=\"500\" y2=\"0\" stroke=\"black\" stroke-width=\"2\" />\n <line x1=\"500\" y1=\"0\" x2=\"500\" y2=\"500\" stroke=\"black\" stroke-width=\"2\" />\n <line x1=\"0\" y1=\"500\" x2=\"500\" y2=\"500\" stroke=\"black\" stroke-width=\"2\" />\n\n <line x1=\"0\" y1=\"100\" x2=\"500\" y2=\"100\" stroke=\"black\" stroke-dasharray=\"2\" stroke-width=\"1\" />\n <line x1=\"0\" y1=\"200\" x2=\"500\" y2=\"200\" stroke=\"black\" stroke-dasharray=\"2\" stroke-width=\"1\" />\n <line x1=\"0\" y1=\"300\" x2=\"500\" y2=\"300\" stroke=\"black\" stroke-dasharray=\"2\" stroke-width=\"1\" />\n <line x1=\"0\" y1=\"400\" x2=\"500\" y2=\"400\" stroke=\"black\" stroke-dasharray=\"2\" stroke-width=\"1\" />\n\n <line x1=\"100\" y1=\"0\" x2=\"100\" y2=\"500\" stroke=\"black\" stroke-dasharray=\"2\" stroke-width=\"1\" />\n <line x1=\"200\" y1=\"0\" x2=\"200\" y2=\"500\" stroke=\"black\" stroke-dasharray=\"2\" stroke-width=\"1\" />\n <line x1=\"300\" y1=\"0\" x2=\"300\" y2=\"500\" stroke=\"black\" stroke-dasharray=\"2\" stroke-width=\"1\" />\n <line x1=\"400\" y1=\"0\" x2=\"400\" y2=\"500\" stroke=\"black\" stroke-dasharray=\"2\" stroke-width=\"1\" />\n\n <rect x=\"80\" y=\"80\" width=\"40\" height=\"40\" fill=\"#d2b48c\" />\n <rect x=\"180\" y=\"80\" width=\"40\" height=\"40\" fill=\"#d2b48c\" />\n <rect x=\"280\" y=\"80\" width=\"40\" height=\"40\" fill=\"#d2b48c\" />\n <rect x=\"380\" y=\"80\" width=\"40\" height=\"40\" fill=\"#d2b48c\" />\n\n <rect x=\"80\" y=\"180\" width=\"40\" height=\"40\" fill=\"#d2b48c\" />\n <rect x=\"180\" y=\"180\" width=\"40\" height=\"40\" fill=\"#d2b48c\" />\n <rect x=\"280\" y=\"180\" width=\"40\" height=\"40\" fill=\"#d2b48c\" />\n <rect x=\"380\" y=\"180\" width=\"40\" height=\"40\" fill=\"#d2b48c\" />\n\n <rect x=\"80\" y=\"280\" width=\"40\" height=\"40\" fill=\"#d2b48c\" />\n <rect x=\"180\" y=\"280\" width=\"40\" height=\"40\" fill=\"#d2b48c\" />\n <rect x=\"280\" y=\"280\" width=\"40\" height=\"40\" fill=\"#d2b48c\" />\n <rect x=\"380\" y=\"280\" width=\"40\" height=\"40\" fill=\"#d2b48c\" />\n\n <rect x=\"80\" y=\"380\" width=\"40\" height=\"40\" fill=\"#d2b48c\" />\n <rect x=\"180\" y=\"380\" width=\"40\" height=\"40\" fill=\"#d2b48c\" />\n <rect x=\"280\" y=\"380\" width=\"40\" height=\"40\" fill=\"#d2b48c\" />\n <rect x=\"380\" y=\"380\" width=\"40\" height=\"40\" fill=\"#d2b48c\" />\n\n <circle id=\"c00\" cx=\"10000\" cy=\"100\" r=\"60\" fill=\"#e0ffe0\"></circle>\n <circle id=\"c01\" cx=\"10000\" cy=\"100\" r=\"40\" fill=\"#98fb98\"></circle>\n <circle id=\"c02\" cx=\"10000\" cy=\"100\" r=\"20\" fill=\"#00ff00\"></circle>\n <circle id=\"c03\" cx=\"10000\" cy=\"100\" r=\"5\" fill=\"#228b22\"></circle>\n\n\t<text id=\"t01\" x=\"12000\" y=\"100\">ビーコン#1</text>\n <text id=\"t02\" x=\"12000\" y=\"120\" font-size=\"12\">検知位置</text>\n\t<text id=\"t03\" x=\"12000\" y=\"120\" font-size=\"12\">温度、湿度</text>\n\n</svg>\n</div>\n\n\n<div id=\"b-box\" style=\"background-color: #ecf2fe; padding: 20px; \">\n\n <h2>時刻</h2>\n\t\t\t<div style=\"text-align:left\" id=\"output0\"></div>\n\t\t\t<div style=\"text-align:left;font-size: 18pt\" id=\"output1\"></div>\n \t\t<h2>ビーコン位置 </h2>\n\t\t\t<span style=\"text-align:left;font-size: 18pt\" id=\"output2\"></span>\n\t\t<h2>センサー温度 </h2>\n\t\t\t<span style=\"text-align:left;font-size: 18pt\" id=\"output3\"></span>℃\n\t\t<h2>センサー湿度 </h2>\n\t\t\t<span style=\"text-align:left;font-size: 18pt\" id=\"output4\"></span>%\n\n</div>\n\n<div id=\"c-box\" style=\"background-color: #f0e8fa; padding: 20px; \">\n <div class=\"category\">参考URL</div>\n <ul>\n <li><a href=\"http://qiita.com/egplnt/items/af867711a7191923b2ff\">Watson IoT Platformを使ってみる</a></li>\n <li><a href=\"https://internetofthings.ibmcloud.com/#/\">Watson IoT Platform</a></li>\n <li><a href=\"https://developer.ibm.com/recipes/tutorials/use-the-simulated-device-to-experience-the-iot-foundation/\">Recipe - Simulator</a></li>\n </ul>\n <div class=\"category\">マニュアル</div>\n <ul>\n <li><a href=\"http://ibm.com/iot\">IBM IoT</a></li>\n <li><a href=\"https://docs.internetofthings.ibmcloud.com/ja/\">Watson IoT Platform資料ページ</a></li>\n <li><a href=\"https://developer.ibm.com/recipes/\">Recipe</a></li>\n </ul>\n\n</div>\n<div id=\"d-box\" style=\"clear: both; background-color: #e0ce96; font-size: 18px; padding: 10px; text-align: center; padding: 20px;\">\n\tcopyright (c) abc.com All right reserved.\n</div>\n\n<script>\n\nvar connection = new WebSocket('ws://このIoTアプリの名前.mybluemix.net/ws/flow38');\n\nconnection.onopen = function () {\n console.log(\"websocket connected\");\n};\n\n// Log errors\nconnection.onerror = function (error) {\n console.log('WebSocket Error ' + error);\n};\n\n// Log messages from the server\nconnection.onmessage = function (m) {\n console.log('Server: ' + m.data);\n\tdoIt(m);\n};\n\n//function doIt\nfunction doIt(msg){\n console.log(\"doit:\" + msg.data);\n\tvar msgs = JSON.parse(msg.data);\n\n\t//円要素を取得し座標を指定\n\tvar c = document.querySelectorAll('circle');\n var c0x = parseInt(msgs[1]);\n var c0y = parseInt(msgs[2]);\n\t(function(){\n\t c[0].setAttribute('cx', c0x );\n\t\tc[0].setAttribute('cy', c0y );\n\t})();\n var c1x = parseInt(msgs[3]);\n var c1y = parseInt(msgs[4]);\n\t(function(){\n\t c[1].setAttribute('cx', c1x );\n\t\tc[1].setAttribute('cy', c1y );\n\t})();\n var c2x = parseInt(msgs[5]);\n var c2y = parseInt(msgs[6]);\n\t(function(){\n\t c[2].setAttribute('cx', c2x );\n\t\tc[2].setAttribute('cy', c2y );\n\t})();\n var c3x = parseInt(msgs[7]);\n var c3y = parseInt(msgs[8]);\n\t(function(){\n\t c[3].setAttribute('cx', c3x );\n\t\tc[3].setAttribute('cy', c3y );\n\t})();\n\n\t//text要素を配列で取得し、各textを表示する座標を指定\n\tvar t = document.querySelectorAll('text');\n\tvar t0x = parseInt(msgs[9]) + 20;\n\tvar t0y = parseInt(msgs[10]);\n\t(function(){\n\t t[0].setAttribute('x', t0x );\n\t\tt[0].setAttribute('y', t0y );\n\t})();\n\tvar t1x = parseInt(msgs[9]) + 20;\n\tvar t1y = parseInt(msgs[10]) + 20;\n\t(function(){\n\t t[1].setAttribute('x', t1x );\n\t\tt[1].setAttribute('y', t1y );\n\t})();\n\tvar t2x = parseInt(msgs[9]) + 20;\n\tvar t2y = parseInt(msgs[10]) + 40;\n\t(function(){\n\t t[2].setAttribute('x', t2x );\n\t\tt[2].setAttribute('y', t2y );\n\t})();\n\n\t//text要素の文字列を変更\n\tvar t2 = document.getElementById('t02');\n\t(function(){\n\t t2.textContent=msgs[13];\n\t})();\n\tvar t3 = document.getElementById('t03');\n\t(function(){\n\t t3.textContent=\"温度:\" + msgs[11] + \"℃、湿度:\" + msgs[12] + \"%\";\n\t})();\n\n\t// 各センサー要素を取り出して、画面へ表示\n\t//for (var i = 0; i < msgs.length; i++) { console.log( i + \" = \" + msgs[i]); }\n\ttarget = document.getElementById(\"output1\");\n\ttarget.innerHTML = msgs[0];\n\ttarget = document.getElementById(\"output2\");\n\ttarget.innerHTML = msgs[13];\n\ttarget = document.getElementById(\"output3\");\n\ttarget.innerHTML = msgs[11];\n\ttarget = document.getElementById(\"output4\");\n\ttarget.innerHTML = msgs[12];\n//\ttarget = document.getElementById(\"output4\");\n//\ttarget.innerHTML = msgs[3];\n//\ttarget = document.getElementById(\"output5\");\n//\ttarget.innerHTML = msgs[4];\n\n};\n\n</script>\n\n</body>\n</html>\n","x":314,"y":257,"wires":[["34d646c1.150922"]]},{"id":"8823d830.00d258","type":"inject","z":"1f1ccf2d.e2b139","name":"1秒毎","topic":"","payload":"","payloadType":"date","repeat":"1","crontab":"","once":false,"x":104,"y":97,"wires":[[]]},{"id":"5a588ca2.eae6ac","type":"inject","z":"1f1ccf2d.e2b139","name":"restart","topic":"","payload":"0","payloadType":"num","repeat":"","crontab":"","once":false,"x":104,"y":137,"wires":[["534f5be0.e664ac"]]},{"id":"95533b1.5f338c8","type":"debug","z":"1f1ccf2d.e2b139","name":"出力","active":true,"console":"false","complete":"payload","x":690,"y":100,"wires":[]},{"id":"5e2eb54a.038a6c","type":"comment","z":"1f1ccf2d.e2b139","name":"ビーコンからの値をシミュレート","info":"","x":184,"y":57,"wires":[]},{"id":"ecd8e595.5caf4","type":"http in","z":"1f1ccf2d.e2b139","name":"","url":"/test38","method":"get","swaggerDoc":"","x":124,"y":257,"wires":[["1101965e.4c38aa"]]},{"id":"34d646c1.150922","type":"http response","z":"1f1ccf2d.e2b139","name":"","x":504,"y":257,"wires":[]},{"id":"2653adc5.275fca","type":"comment","z":"1f1ccf2d.e2b139","name":"ビーコンの位置情報を可視化","info":"","x":174,"y":217,"wires":[]},{"id":"534f5be0.e664ac","type":"function","z":"1f1ccf2d.e2b139","name":"日付時刻の追加","func":"var d = new Date();\nvar localTime = d.getTime();\nvar localOffset = d.getTimezoneOffset() * 60000;\nvar utc = localTime + localOffset;\nvar offset = -9.0;\nvar result = utc - (3600000 * offset);\nvar date = parseInt(new Date(result) / 1000);\nvar dt = new Date(result);\n\nvar year = dt.getFullYear();\nvar month = dt.getMonth()+1;\nvar day = dt.getDate();\nvar hour = dt.getHours();\nvar minute = dt.getMinutes();\nvar second = dt.getSeconds();\n//if (!msg.payload) {\n// msg.payload = { \"initial\": \"value\" };\n//}\nif (!msg.date) {\n msg.date = { \"initial\": \"value\" };\n}\nmsg.date = {\n \"date\": date,\n \"year\": year,\n \"month\": month,\n \"day\": day,\n \"hour\": hour,\n \"minute\": minute,\n \"second\": second\n};\nreturn msg;","outputs":1,"noerr":0,"x":274,"y":117,"wires":[["2f354439.37eeac"]]},{"id":"4dfca3a2.789a6c","type":"debug","z":"1f1ccf2d.e2b139","name":"時刻の表示","active":false,"console":"false","complete":"date","x":710,"y":60,"wires":[]},{"id":"2bfad213.7ed286","type":"websocket out","z":"1f1ccf2d.e2b139","name":"","server":"ddf813cc.0064d8","client":"","x":720,"y":140,"wires":[]},{"id":"2f354439.37eeac","type":"function","z":"1f1ccf2d.e2b139","name":"シミュレーター","func":"var i = context.get(\"i0\")||0;\n// 保存した各円の座標を取得\nvar c0x = context.get(\"c0x\")||0;\nvar c0y = context.get(\"c0y\")||0;\nvar c1x = context.get(\"c1x\")||0;\nvar c1y = context.get(\"c1y\")||0;\nvar c2x = context.get(\"c2x\")||0;\nvar c2y = context.get(\"c2y\")||0;\nvar c3x = context.get(\"c3x\")||0;\nvar c3y = context.get(\"c3y\")||0;\nvar tx = context.get(\"tx\")||0;\nvar ty = context.get(\"ty\")||0;\nvar tz;\n\n//var sampling_min_interval = 1;\nvar sampling_sec_interval = 1; // データを出力する間隔\n\nar = [\"g11ai\",\"g11fi\",\"g11ni\",\"g11ii\",\"g11io\",\"g11no\",\"g11fo\",\"g11ao\",\n \"g12ai\",\"g12fi\",\"g12ni\",\"g12ii\",\"g12io\",\"g12no\",\"g12fo\",\"g12ao\",\n \"g22ai\",\"g22fi\",\"g22ni\",\"g22ii\",\"g22io\",\"g22no\",\"g22fo\",\"g22ao\",\n \"g23ai\",\"g23fi\",\"g23ni\",\"g23ii\",\"g23io\",\"g23no\",\"g23fo\",\"g23ao\",\n \"g33ai\",\"g33fi\",\"g33ni\",\"g33ii\",\"g33io\",\"g33no\",\"g33fo\",\"g33ao\",\n \"g32ai\",\"g32fi\",\"g32ni\",\"g32ii\",\"g32io\",\"g32no\",\"g32fo\",\"g32ao\",\n \"g31ai\",\"g31fi\",\"g31ni\",\"g31ii\",\"g31io\",\"g31no\",\"g31fo\",\"g31ao\",\n \"g21ai\",\"g21fi\",\"g21ni\",\"g21ii\",\"g21io\",\"g21no\",\"g21fo\",\"g21ao\"];\n\nvar z = ar[i];\nvar temp = 15 + Math.floor(Math.random () *100 + 1) / 10; // センサー値を生成(シミュレート)\nvar humid = 40 + 2 * Math.floor(Math.random () *100 + 1) / 10; // センサー値を生成(シミュレート)\n\n//各ゲートウェイ位置から座標を指定\nif (z == \"g11ai\") { c0x = 100; c0y = 100; tx = 100; ty = 100; tz = \"G11, Area-In\";}\nif (z == \"g11fi\") { c1x = 100; c1y = 100; tx = 100; ty = 100; tz = \"G11, Far-In\";}\nif (z == \"g11ni\") { c2x = 100; c2y = 100; tx = 100; ty = 100; tz = \"G11, Near-In\";}\nif (z == \"g11ii\") { c3x = 100; c3y = 100; tx = 100; ty = 100; tz = \"G11, Immediate-In\";}\n\nif (z == \"g11io\") { c3x = 10000; c3y = 100; tx = 100; ty = 100; tz = \"G11, Immediate-Out\"}\nif (z == \"g11no\") { c2x = 10000; c2y = 100; tx = 100; ty = 100; tz = \"G11, Near-Out\"}\nif (z == \"g11fo\") { c1x = 10000; c1y = 100; tx = 100; ty = 100; tz = \"G11, Far-Out\"}\nif (z == \"g11ao\") { c0x = 1000; c0y = 100; tx = 10000; ty = 100; tz = \"G11, Area-Out\"}\n\n\nif (z == \"g12ai\") { c0x = 200; c0y = 100; tx = 200; ty = 100; tz = \"G12, Area-In\";}\nif (z == \"g12fi\") { c1x = 200; c1y = 100; tx = 200; ty = 100; tz = \"G12, Far-In\";}\nif (z == \"g12ni\") { c2x = 200; c2y = 100; tx = 200; ty = 100; tz = \"G12, Near-In\";}\nif (z == \"g12ii\") { c3x = 200; c3y = 100; tx = 200; ty = 100; tz = \"G12, Immediate-In\";}\n\nif (z == \"g12io\") { c3x = 10000; c3y = 100; tx = 200; ty = 100; tz = \"G12, Immediate-Out\"}\nif (z == \"g12no\") { c2x = 10000; c2y = 100; tx = 200; ty = 100; tz = \"G12, Near-Out\"}\nif (z == \"g12fo\") { c1x = 10000; c1y = 100; tx = 200; ty = 100; tz = \"G12, Far-Out\"}\nif (z == \"g12ao\") { c0x = 10000; c0y = 100; tx = 10000; ty = 100; tz = \"G12, Area-Out\"}\n\n\nif (z == \"g22ai\") { c0x = 200; c0y = 200; tx = 200; ty = 200; tz = \"G22, Area-In\";}\nif (z == \"g22fi\") { c1x = 200; c1y = 200; tx = 200; ty = 200; tz = \"G22, Far-In\";}\nif (z == \"g22ni\") { c2x = 200; c2y = 200; tx = 200; ty = 200; tz = \"G22, Near-In\";}\nif (z == \"g22ii\") { c3x = 200; c3y = 200; tx = 200; ty = 200; tz = \"G22, Immediate-In\";}\n\nif (z == \"g22io\") { c3x = 10000; c3y = 200; tx = 200; ty = 200; tz = \"G22, Immediate-Out\"}\nif (z == \"g22no\") { c2x = 10000; c2y = 200; tx = 200; ty = 200; tz = \"G22, Near-Out\"}\nif (z == \"g22fo\") { c1x = 10000; c1y = 200; tx = 200; ty = 200; tz = \"G22, Far-Out\"}\nif (z == \"g22ao\") { c0x = 10000; c0y = 200; tx = 10000; ty = 200; tz = \"G22, Area-Out\"}\n\n\nif (z == \"g23ai\") { c0x = 300; c0y = 200; tx = 300; ty = 200; tz = \"G23, Area-In\";}\nif (z == \"g23fi\") { c1x = 300; c1y = 200; tx = 300; ty = 200; tz = \"G23, Far-In\";}\nif (z == \"g23ni\") { c2x = 300; c2y = 200; tx = 300; ty = 200; tz = \"G23, Near-In\";}\nif (z == \"g23ii\") { c3x = 300; c3y = 200; tx = 300; ty = 200; tz = \"G23, Immediate-In\";}\n\nif (z == \"g23io\") { c3x = 10000; c3y = 200; tx = 300; ty = 200; tz = \"G23, Immediate-Out\"}\nif (z == \"g23no\") { c2x = 10000; c2y = 200; tx = 300; ty = 200; tz = \"G23, Near-Out\"}\nif (z == \"g23fo\") { c1x = 10000; c1y = 200; tx = 300; ty = 200; tz = \"G23, Far-Out\"}\nif (z == \"g23ao\") { c0x = 10000; c0y = 200; tx = 10000; ty = 200; tz = \"G23, Area-Out\"}\n\n\nif (z == \"g33ai\") { c0x = 300; c0y = 300; tx = 300; ty = 300; tz = \"G33, Area-In\";}\nif (z == \"g33fi\") { c1x = 300; c1y = 300; tx = 300; ty = 300; tz = \"G33, Far-In\";}\nif (z == \"g33ni\") { c2x = 300; c2y = 300; tx = 300; ty = 300; tz = \"G33, Near-In\";}\nif (z == \"g33ii\") { c3x = 300; c3y = 300; tx = 300; ty = 300; tz = \"G33, Immediate-In\";}\n\nif (z == \"g33io\") { c3x = 10000; c3y = 300; tx = 300; ty = 300; tz = \"G33, Immediate-Out\"}\nif (z == \"g33no\") { c2x = 10000; c2y = 300; tx = 300; ty = 300; tz = \"G33, Near-Out\"}\nif (z == \"g33fo\") { c1x = 10000; c1y = 300; tx = 300; ty = 300; tz = \"G33, Far-Out\"}\nif (z == \"g33ao\") { c0x = 10000; c0y = 300; tx = 10000; ty = 300; tz = \"G33, Area-Out\"}\n\n\nif (z == \"g32ai\") { c0x = 200; c0y = 300; tx = 200; ty = 300; tz = \"G32, Area-In\";}\nif (z == \"g32fi\") { c1x = 200; c1y = 300; tx = 200; ty = 300; tz = \"G32, Far-In\";}\nif (z == \"g32ni\") { c2x = 200; c2y = 300; tx = 200; ty = 300; tz = \"G32, Near-In\";}\nif (z == \"g32ii\") { c3x = 200; c3y = 300; tx = 200; ty = 300; tz = \"G32, Immediate-In\";}\n\nif (z == \"g32io\") { c3x = 10000; c3y = 300; tx = 200; ty = 300; tz = \"G32, Immediate-Out\"}\nif (z == \"g32no\") { c2x = 10000; c2y = 300; tx = 200; ty = 300; tz = \"G32, Near-Out\"}\nif (z == \"g32fo\") { c1x = 10000; c1y = 300; tx = 200; ty = 300; tz = \"G32, Far-Out\"}\nif (z == \"g32ao\") { c0x = 10000; c0y = 300; tx = 10000; ty = 300; tz = \"G32, Area-Out\"}\n\n\nif (z == \"g31ai\") { c0x = 100; c0y = 300; tx = 100; ty = 300; tz = \"G31, Area-In\";}\nif (z == \"g31fi\") { c1x = 100; c1y = 300; tx = 100; ty = 300; tz = \"G31, Far-In\";}\nif (z == \"g31ni\") { c2x = 100; c2y = 300; tx = 100; ty = 300; tz = \"G31, Near-In\";}\nif (z == \"g31ii\") { c3x = 100; c3y = 300; tx = 100; ty = 300; tz = \"G31, Immediate-In\";}\n\nif (z == \"g31io\") { c3x = 10000; c3y = 300; tx = 100; ty = 300; tz = \"G31, Immediate-Out\"}\nif (z == \"g31no\") { c2x = 10000; c2y = 300; tx = 100; ty = 300; tz = \"G31, Near-Out\"}\nif (z == \"g31fo\") { c1x = 10000; c1y = 300; tx = 100; ty = 300; tz = \"G31, Far-Out\"}\nif (z == \"g31ao\") { c0x = 10000; c0y = 300; tx = 10000; ty = 300; tz = \"G31, Area-Out\"}\n\n\nif (z == \"g21ai\") { c0x = 100; c0y = 200; tx = 100; ty = 200; tz = \"G21, Area-In\";}\nif (z == \"g21fi\") { c1x = 100; c1y = 200; tx = 100; ty = 200; tz = \"G21, Far-In\";}\nif (z == \"g21ni\") { c2x = 100; c2y = 200; tx = 100; ty = 200; tz = \"G21, Near-In\";}\nif (z == \"g21ii\") { c3x = 100; c3y = 200; tx = 100; ty = 200; tz = \"G21, Immediate-In\";}\n\nif (z == \"g21io\") { c3x = 10000; c3y = 200; tx = 100; ty = 200; tz = \"G21, Immediate-Out\"}\nif (z == \"g21no\") { c2x = 10000; c2y = 200; tx = 100; ty = 200; tz = \"G21, Near-Out\"}\nif (z == \"g21fo\") { c1x = 10000; c1y = 200; tx = 100; ty = 200; tz = \"G21, Far-Out\"}\nif (z == \"g21ao\") { c0x = 10000; c0y = 200; tx = 10000; ty = 200; tz = \"G21, Area-Out\"}\n\n\ni++;\nif ( i >= ar.length) {\n i = 0;\n}\n//座標情報を保存\ncontext.set(\"i0\", i);\ncontext.set(\"c0x\", c0x);\ncontext.set(\"c0y\", c0y);\ncontext.set(\"c1x\", c1x);\ncontext.set(\"c1y\", c1y);\ncontext.set(\"c2x\", c2x);\ncontext.set(\"c2y\", c2y);\ncontext.set(\"c3x\", c3x);\ncontext.set(\"c3y\", c3y);\ncontext.set(\"tx\", tx);\ncontext.set(\"ty\", ty);\n\nvar hour = JSON.stringify(msg.date.hour);\nvar min_org = JSON.stringify(msg.date.minute);\nvar min = ( \"0\" + min_org ).substr( -2 ); // 一桁分の場合、二桁に\nvar sec_org = JSON.stringify(msg.date.second);\nvar sec = ( \"0\" + sec_org ).substr( -2 ); // 一桁秒の場合、二桁に\nvar time = hour + \":\" + min + \":\" + sec;\n\n//座標情報を送出\nvar data = [[time],[c0x],[c0y],[c1x],[c1y],[c2x],[c2y],[c3x],[c3y],[tx],[ty],[temp],[humid],[tz]];\nmsg.payload = data;\nif ( ( msg.date.second % sampling_sec_interval ) !== 0 ) return;\n//if ( ( msg.date.minute % sampling_min_interval ) !== 0 ) return;\nreturn msg;\n","outputs":1,"noerr":0,"x":460,"y":100,"wires":[["2bfad213.7ed286","95533b1.5f338c8"]]},{"id":"ddf813cc.0064d8","type":"websocket-listener","z":"1f1ccf2d.e2b139","path":"/ws/flow38","wholemsg":"false"}]
サンプル-3:データベースに格納された位置情報を表示します
1. 位置情報を格納するデータベースを用意します
- 既に使用しているdashDBサービスが無い場合、新たに一つ作成しておきます
- IoTアプリ(Node-REDが稼働しているアプリ)に、dashDBサービスを接続します
- "Create a Table"メニューで、以下のDDLを実行し、ビーコンからの位置情報を格納する"LATEST"という名の表を用意します
ビーコンの位置情報を格納する表
CREATE TABLE "LATEST"
(
"ID" INT PRIMARY KEY NOT NULL,
"EVENT" VARCHAR(30),
"X" INT,
"Y" INT
);
- 表が作成されたら、"Run SQL"メニューなどを使用し、以下のようなSQL文でて初期値を書き込みます。
表へ初期値を書き込む
insert into dashxxxx.latest (id, event, x, y) values(1, 'Beacon#1 NearIn', 150, 100);
dashDBの表へ初期値を書き込む
[{"id":"9bdeed4c.dce98","type":"function","z":"e98e4621.ecc648","name":"表へ書き込む","func":"msg.payload = \n{ \n\tID : 1,\n\tEVENT : \"Beacon#1 NearIn\",\n\tX : 150,\n\tY : 100\n};\nreturn msg;","outputs":1,"noerr":0,"x":340,"y":80,"wires":[["aa2746c4.63c578"]]},{"id":"94270249.32d73","type":"inject","z":"e98e4621.ecc648","name":"","topic":"","payload":"","payloadType":"date","repeat":"","crontab":"","once":false,"x":140,"y":80,"wires":[["9bdeed4c.dce98"]]},{"id":"aa2746c4.63c578","type":"dashDB out","z":"e98e4621.ecc648","service":"","table":"LATEST","name":"","x":540,"y":80,"wires":[]}]
2. ビーコンから取得される位置情報を随時上記の表へ更新します
ビーコンからの位置情報をシミュレートしデータベースへ書き込む
[{"id":"bccae16c.303868","type":"inject","z":"43384da6.15b854","name":"","topic":"","payload":"","payloadType":"date","repeat":"1","crontab":"","once":false,"x":130,"y":140,"wires":[[]]},{"id":"24a8f3ce.490e94","type":"function","z":"43384da6.15b854","name":"シミュレーター","func":"var i = context.get(\"i0\")||0;\n\nvar sampling_sec_interval = 1; // データを出力する間隔\n\nxa = [150,200,250,300,350,400,450,500,550,600,650,700,750,800,850,850,850,850,850,800,750,700,650,600,550,500,450,400,350,300,250,200,150,150,150,150];\nya = [100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,150,200,250,300,300,300,300,300,300,300,300,300,300,300,300,300,300,300,250,200,150];\nmsg.x = xa[i];\nmsg.y = ya[i];\n\ni++;\nif ( i >= xa.length) {\n i = 0;\n}\ncontext.set(\"i0\", i);\n\nreturn msg;\n\n","outputs":1,"noerr":0,"x":340,"y":140,"wires":[["42fd7415.f0a0d4"]]},{"id":"5e0f9661.a423f","type":"debug","z":"43384da6.15b854","name":"","active":false,"console":"false","complete":"payload","x":730,"y":140,"wires":[]},{"id":"fa4fe98.00edf18","type":"comment","z":"43384da6.15b854","name":"ビーコンからの値をシミュレート","info":"","x":170,"y":80,"wires":[]},{"id":"42fd7415.f0a0d4","type":"dashDB in","z":"43384da6.15b854","service":"","query":"UPDATE LATEST SET X = ?, Y = ? WHERE ID=1;","params":"msg.x,msg.y","name":"","x":540,"y":140,"wires":[["5e0f9661.a423f"]]}]
- dashDBのノードを環境に合わせて更新します。上手く繋がらない場合、dashDBのノードを一旦削除し、新たに作成します
- Injectノードからは毎秒リクエストが送信されるように設定されています。テスト時以外は切断しておくことをお薦めします
3. データベースからの位置情報を可視化します
データベースの位置情報を可視化する
[{"id":"80fc02f0.c86b7","type":"comment","z":"4a5aa97c.fff478","name":"データベースからの位置情報を可視化","info":"","x":210,"y":240,"wires":[]},{"id":"c7e4293.d855d58","type":"websocket out","z":"4a5aa97c.fff478","name":"","server":"89c843d3.9f96e","client":"","x":780,"y":180,"wires":[]},{"id":"d0fa4c87.c37cd","type":"inject","z":"4a5aa97c.fff478","name":"","topic":"","payload":"","payloadType":"date","repeat":"1","crontab":"","once":false,"x":150,"y":140,"wires":[[]]},{"id":"b8686c79.31f6c","type":"comment","z":"4a5aa97c.fff478","name":"位置情報でデータベースを更新","info":"","x":190,"y":80,"wires":[]},{"id":"22796522.8e4652","type":"function","z":"4a5aa97c.fff478","name":"シミュレーター","func":"//var i = context.get(\"i0\")||0;\n\n//var sampling_min_interval = 1;\nvar sampling_sec_interval = 1; // データを出力する間隔\n\nvar x = msg.payload.X;\nvar y = msg.payload.Y;\nvar ev = msg.payload.EVENT;\n\nvar temp = 15 + Math.floor(Math.random () *100 + 1) / 10; // センサー値を生成(シミュレート)\nvar humid = 40 + 2 * Math.floor(Math.random () *100 + 1) / 10; // センサー値を生成(シミュレート)\n\n/*i++;\nif ( i >= xa.length) {\n i = 0;\n}\ncontext.set(\"i0\", i);\n*/\nvar hour = JSON.stringify(msg.date.hour);\nvar min_org = JSON.stringify(msg.date.minute);\nvar min = ( \"0\" + min_org ).substr( -2 ); // 一桁分の場合、二桁に\nvar sec_org = JSON.stringify(msg.date.second);\nvar sec = ( \"0\" + sec_org ).substr( -2 ); // 一桁秒の場合、二桁に\nvar time = hour + \":\" + min + \":\" + sec;\n\nvar data = [[time],[x],[y],[ev],[temp],[humid]];\n//var data = [[time],[x],[y],[temp],[humid]];\nmsg.payload = data;\nif ( ( msg.date.second % sampling_sec_interval ) !== 0 ) return;\n//if ( ( msg.date.minute % sampling_min_interval ) !== 0 ) return;\nreturn msg;\n","outputs":1,"noerr":0,"x":600,"y":200,"wires":[["c7e4293.d855d58","12287212.4619be"]]},{"id":"a7cd8506.ca0d58","type":"function","z":"4a5aa97c.fff478","name":"日付時刻の追加","func":"var d = new Date();\nvar localTime = d.getTime();\nvar localOffset = d.getTimezoneOffset() * 60000;\nvar utc = localTime + localOffset;\nvar offset = -9.0;\nvar result = utc - (3600000 * offset);\nvar date = parseInt(new Date(result) / 1000);\nvar dt = new Date(result);\n\nvar year = dt.getFullYear();\nvar month = dt.getMonth()+1;\nvar day = dt.getDate();\nvar hour = dt.getHours();\nvar minute = dt.getMinutes();\nvar second = dt.getSeconds();\n//if (!msg.payload) {\n// msg.payload = { \"initial\": \"value\" };\n//}\nif (!msg.date) {\n msg.date = { \"initial\": \"value\" };\n}\nmsg.date = {\n \"date\": date,\n \"year\": year,\n \"month\": month,\n \"day\": day,\n \"hour\": hour,\n \"minute\": minute,\n \"second\": second\n};\nreturn msg;","outputs":1,"noerr":0,"x":480,"y":140,"wires":[["22796522.8e4652"]]},{"id":"12287212.4619be","type":"debug","z":"4a5aa97c.fff478","name":"","active":true,"console":"false","complete":"false","x":770,"y":220,"wires":[]},{"id":"e721517c.c01fb8","type":"template","z":"4a5aa97c.fff478","name":"ws用htmlを返す","field":"payload","fieldType":"msg","format":"handlebars","syntax":"mustache","template":"<!DOCTYPE HTML>\n<html>\n <head>\n <title>センサーからの位置情報を表示</title>\n <meta charset=\"utf-8\" />\n </head>\n <body>\n\t <div id=\"a-box\" style=\"background-color: #87cefa; padding: 20px;\">\n\t\t\t <h1>位置によるIoTデータ表示</h1>\n\t\t\t <br />\n\t\t\t <p>\n\t\t\t IoTデータの位置情報を可視化します<br />\n\t\t\t </p>\n\t\t\t</div>\n\n\n<div id='example'>\n<svg id=\"svg.svg\" xmlns=\"http://www.w3.org/2000/svg\" width=\"1000\" height=\"550\" viewBox=\"0 0 1000 550\">\n\n <line x1=\"0\" y1=\"0\" x2=\"0\" y2=\"550\" stroke=\"black\" stroke-width=\"2\" />\n <line x1=\"0\" y1=\"0\" x2=\"1000\" y2=\"0\" stroke=\"black\" stroke-width=\"2\" />\n <line x1=\"1000\" y1=\"0\" x2=\"1000\" y2=\"550\" stroke=\"black\" stroke-width=\"2\" />\n <line x1=\"0\" y1=\"550\" x2=\"1000\" y2=\"550\" stroke=\"black\" stroke-width=\"2\" />\n\n\t<line x1=\"0\" y1=\"50\" x2=\"1000\" y2=\"50\" stroke=\"black\" stroke-dasharray=\"2\" stroke-width=\"1\" />\n <line x1=\"0\" y1=\"250\" x2=\"1000\" y2=\"250\" stroke=\"black\" stroke-dasharray=\"2\" stroke-width=\"1\" />\n <line x1=\"0\" y1=\"450\" x2=\"1000\" y2=\"450\" stroke=\"black\" stroke-dasharray=\"2\" stroke-width=\"1\" />\n\n <line x1=\"100\" y1=\"0\" x2=\"100\" y2=\"550\" stroke=\"black\" stroke-dasharray=\"2\" stroke-width=\"1\" />\n <line x1=\"200\" y1=\"0\" x2=\"200\" y2=\"550\" stroke=\"black\" stroke-dasharray=\"2\" stroke-width=\"1\" />\n <line x1=\"300\" y1=\"0\" x2=\"300\" y2=\"550\" stroke=\"black\" stroke-dasharray=\"2\" stroke-width=\"1\" />\n <line x1=\"400\" y1=\"0\" x2=\"400\" y2=\"550\" stroke=\"black\" stroke-dasharray=\"2\" stroke-width=\"1\" />\n\t<line x1=\"500\" y1=\"0\" x2=\"500\" y2=\"550\" stroke=\"black\" stroke-dasharray=\"2\" stroke-width=\"1\" />\n\t<line x1=\"600\" y1=\"0\" x2=\"600\" y2=\"550\" stroke=\"black\" stroke-dasharray=\"2\" stroke-width=\"1\" />\n\t<line x1=\"700\" y1=\"0\" x2=\"700\" y2=\"550\" stroke=\"black\" stroke-dasharray=\"2\" stroke-width=\"1\" />\n\t<line x1=\"800\" y1=\"0\" x2=\"800\" y2=\"550\" stroke=\"black\" stroke-dasharray=\"2\" stroke-width=\"1\" />\n\t<line x1=\"900\" y1=\"0\" x2=\"900\" y2=\"550\" stroke=\"black\" stroke-dasharray=\"2\" stroke-width=\"1\" />\n\n <rect x=\"80\" y=\"30\" width=\"40\" height=\"40\" fill=\"#d2b48c\" />\n <rect x=\"180\" y=\"30\" width=\"40\" height=\"40\" fill=\"#d2b48c\" />\n <rect x=\"280\" y=\"30\" width=\"40\" height=\"40\" fill=\"#d2b48c\" />\n <rect x=\"380\" y=\"30\" width=\"40\" height=\"40\" fill=\"#d2b48c\" />\n\t<rect x=\"480\" y=\"30\" width=\"40\" height=\"40\" fill=\"#d2b48c\" />\n\t<rect x=\"580\" y=\"30\" width=\"40\" height=\"40\" fill=\"#d2b48c\" />\n\t<rect x=\"680\" y=\"30\" width=\"40\" height=\"40\" fill=\"#d2b48c\" />\n\t<rect x=\"780\" y=\"30\" width=\"40\" height=\"40\" fill=\"#d2b48c\" />\n\t<rect x=\"880\" y=\"30\" width=\"40\" height=\"40\" fill=\"#d2b48c\" />\n\n\t<rect x=\"80\" y=\"230\" width=\"40\" height=\"40\" fill=\"#d2b48c\" />\n <rect x=\"180\" y=\"230\" width=\"40\" height=\"40\" fill=\"#d2b48c\" />\n <rect x=\"280\" y=\"230\" width=\"40\" height=\"40\" fill=\"#d2b48c\" />\n <rect x=\"380\" y=\"230\" width=\"40\" height=\"40\" fill=\"#d2b48c\" />\n\t<rect x=\"480\" y=\"230\" width=\"40\" height=\"40\" fill=\"#d2b48c\" />\n\t<rect x=\"580\" y=\"230\" width=\"40\" height=\"40\" fill=\"#d2b48c\" />\n\t<rect x=\"680\" y=\"230\" width=\"40\" height=\"40\" fill=\"#d2b48c\" />\n\t<rect x=\"780\" y=\"230\" width=\"40\" height=\"40\" fill=\"#d2b48c\" />\n\t<rect x=\"880\" y=\"230\" width=\"40\" height=\"40\" fill=\"#d2b48c\" />\n\n <rect x=\"80\" y=\"430\" width=\"40\" height=\"40\" fill=\"#d2b48c\" />\n <rect x=\"180\" y=\"430\" width=\"40\" height=\"40\" fill=\"#d2b48c\" />\n <rect x=\"280\" y=\"430\" width=\"40\" height=\"40\" fill=\"#d2b48c\" />\n <rect x=\"380\" y=\"430\" width=\"40\" height=\"40\" fill=\"#d2b48c\" />\n\t<rect x=\"480\" y=\"430\" width=\"40\" height=\"40\" fill=\"#d2b48c\" />\n\t<rect x=\"580\" y=\"430\" width=\"40\" height=\"40\" fill=\"#d2b48c\" />\n\t<rect x=\"680\" y=\"430\" width=\"40\" height=\"40\" fill=\"#d2b48c\" />\n\t<rect x=\"780\" y=\"430\" width=\"40\" height=\"40\" fill=\"#d2b48c\" />\n\t<rect x=\"880\" y=\"430\" width=\"40\" height=\"40\" fill=\"#d2b48c\" />\n\t<rect x=\"880\" y=\"430\" width=\"40\" height=\"40\" fill=\"#d2b48c\" />\n\n <circle id=\"c01\" cx=\"150\" cy=\"100\" r=\"10\" fill=\"#98fb98\"></circle>\n\n\t<text id=\"t01\" x=\"170\" y=\"100\">Beacon8185</text>\n <text id=\"t02\" x=\"170\" y=\"120\" font-size=\"12\">温度、湿度</text>\n\n</svg>\n</div>\n\n\n<div id=\"b-box\" style=\"background-color: #ecf2fe; padding: 20px; \">\n\n<p>\n\t\t\t<div style=\"text-align:left\" id=\"output0\"></div>\n\t\t\t時刻:<div style=\"text-align:left;font-size: 12pt\" id=\"output1\"></div><br>\n\t\tセンサーX座標:\n\t\t\t<span style=\"text-align:left;font-size: 12pt\" id=\"output2\"></span><br>\n\t\tセンサーY座標:\n\t\t\t<span style=\"text-align:left;font-size: 12pt\" id=\"output3\"></span><br>\n\t\tイベント:\n\t\t\t<span style=\"text-align:left;font-size: 12pt\" id=\"output4\"></span><br>\n\t\tセンサー温度:\n\t\t\t<span style=\"text-align:left;font-size: 12pt\" id=\"output5\"></span>℃<br>\n\t\tセンサー湿度:\n\t\t\t<span style=\"text-align:left;font-size: 12pt\" id=\"output6\"></span>%<br>\n</p>\n<!---\n\t\t\t<h2>時刻</h2>\n\t\t\t\t<div style=\"text-align:left\" id=\"output0\"></div>\n\t\t\t\t<div style=\"text-align:left;font-size: 18pt\" id=\"output1\"></div>\n\t\t\t<h2>センサーX座標 </h2>\n\t\t\t\t<span style=\"text-align:left;font-size: 18pt\" id=\"output2\"></span>\n\t\t\t<h2>センサーY座標 </h2>\n\t\t\t\t<span style=\"text-align:left;font-size: 18pt\" id=\"output3\"></span>\n\t\t\t<h2>センサー温度 </h2>\n\t\t\t\t<span style=\"text-align:left;font-size: 18pt\" id=\"output4\"></span>℃\n\t\t\t<h2>センサー湿度 </h2>\n\t\t\t\t<span style=\"text-align:left;font-size: 18pt\" id=\"output5\"></span>%\n--->\n</div>\n\n<div id=\"c-box\" style=\"background-color: #f0e8fa; padding: 20px; \">\n <div class=\"category\">参考URL</div>\n <ul>\n <li><a href=\"http://qiita.com/egplnt/items/af867711a7191923b2ff\">Watson IoT Platformを使ってみる</a></li>\n <li><a href=\"https://internetofthings.ibmcloud.com/#/\">Watson IoT Platform</a></li>\n <li><a href=\"https://developer.ibm.com/recipes/tutorials/use-the-simulated-device-to-experience-the-iot-foundation/\">Recipe - Simulator</a></li>\n </ul>\n <div class=\"category\">マニュアル</div>\n <ul>\n <li><a href=\"http://ibm.com/iot\">IBM IoT</a></li>\n <li><a href=\"https://docs.internetofthings.ibmcloud.com/ja/\">Watson IoT Platform資料ページ</a></li>\n <li><a href=\"https://developer.ibm.com/recipes/\">Recipe</a></li>\n </ul>\n\n</div>\n<div id=\"d-box\" style=\"clear: both; background-color: #e0ce96; font-size: 18px; padding: 10px; text-align: center; padding: 20px;\">\n\tcopyright (c) abc.com All right reserved.\n</div>\n\n<script>\n\nvar connection = new WebSocket('ws://このIoTアプリ名.mybluemix.net/ws/flow38');\n\nconnection.onopen = function () {\n console.log(\"websocket connected\");\n};\n\n// Log errors\nconnection.onerror = function (error) {\n console.log('WebSocket Error ' + error);\n};\n\n// Log messages from the server\nconnection.onmessage = function (m) {\n //console.log('Server: ' + m.data);\n\tdoIt(m);\n};\n\n//function doIt\nfunction doIt(msg){\n console.log(\"doit:\" + msg.data);\n\tvar msgs = JSON.parse(msg.data);\n\n\t//円要素を取得し座標を指定\n\tvar c = document.querySelector('circle');\n\t(function(){\n\t\tvar c0x = parseInt(msgs[1]);\n\t\tvar c0y = parseInt(msgs[2]);\n\t c.setAttribute('cx', c0x );\n\t\tc.setAttribute('cy', c0y );\n\t})();\n\n\t//text要素を配列で取得し、各textを表示する座標を指定\n\tvar t = document.querySelectorAll('text');\n\tvar t0x = parseInt(msgs[1]) + 20;\n\tvar t0y = parseInt(msgs[2]);\n\t(function(){\n\t t[0].setAttribute('x', t0x );\n\t\tt[0].setAttribute('y', t0y );\n\t})();\n\tvar t1x = parseInt(msgs[1]) + 20;\n\tvar t1y = parseInt(msgs[2]) + 20;\n\t(function(){\n\t t[1].setAttribute('x', t1x );\n\t\tt[1].setAttribute('y', t1y );\n\t})();\n\n\t//text要素の文字列を変更\n\tvar t2 = document.getElementById('t02');\n\t(function(){\n\t t2.textContent=\"温度:\" + msgs[4] + \"℃、湿度:\" + msgs[5] + \"%\";\n\t})();\n\n\t// 各センサー要素を取り出して、画面へ表示\n\t//for (var i = 0; i < msgs.length; i++) { console.log( i + \" = \" + msgs[i]); }\n\ttarget = document.getElementById(\"output1\");\n\ttarget.innerHTML = msgs[0];\n\ttarget = document.getElementById(\"output2\");\n\ttarget.innerHTML = msgs[1];\n\ttarget = document.getElementById(\"output3\");\n\ttarget.innerHTML = msgs[2];\n\ttarget = document.getElementById(\"output4\");\n\ttarget.innerHTML = msgs[3];\n\ttarget = document.getElementById(\"output5\");\n\ttarget.innerHTML = msgs[4];\n\ttarget = document.getElementById(\"output6\");\n\ttarget.innerHTML = msgs[5];\n\n};\n\n</script>\n\n</body>\n</html>\n","x":340,"y":300,"wires":[["568c11f3.6cd9c8"]]},{"id":"fd5250a9.3ed978","type":"http in","z":"4a5aa97c.fff478","name":"","url":"/test38","method":"get","swaggerDoc":"","x":150,"y":300,"wires":[["e721517c.c01fb8"]]},{"id":"568c11f3.6cd9c8","type":"http response","z":"4a5aa97c.fff478","name":"","x":530,"y":300,"wires":[]},{"id":"81f6330.6d5025","type":"dashDB in","z":"4a5aa97c.fff478","service":"","query":"SELECT * FROM LATEST WHERE ID=1;","params":"","name":"","x":320,"y":140,"wires":[["a7cd8506.ca0d58"]]},{"id":"89c843d3.9f96e","type":"websocket-listener","z":"4a5aa97c.fff478","path":"/ws/flow38","wholemsg":"false"}]
-
dashDBのノードを環境に合わせて更新します。上手く繋がらない場合、dashDBのノードを一旦削除し、新たに作成します
-
"ws用htmlを返す"templateノードの131行目の次の項目を稼働させるIoTアプリ名に変更します。
new WebSocket('ws://このIoTアプリ名.mybluemix.net/ws/flow38');
-
Injectノードからは毎秒リクエストが送信されるように設定されています。テスト時以外は切断しておくことをお薦めします
-
ブラウザで
IoTアプリ名.mybluemix.net/test38
へアクセスします