LoginSignup
7
6

More than 5 years have passed since last update.

ビーコンの位置情報を可視化する

Last updated at Posted at 2016-09-30

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"}]

  1. Node-REDのフローをコピーする方法を参照して、上記のフローをコピペします。
  2. 上段のシミュレーターのフローを確認し、左上の「1秒毎」と表記されたInjectノードをダブルクリックで開いて適当なインターバルに設定し、ノード右側から線を引き出して後続のオレンジ色の「日付時刻の追加」ノードに接続します。(この線は常時リクエストを送付してしまうので、テスト時以外は切断しておくことをお薦めします。)
  3. Node-RED画面右上の赤い「Deploy」ボタンを押してクラウド側へ反映します。
  4. ブラウザの新しいタブを開き、IoTアプリ名.bluemix.net/test36へアクセスすると下記のような画面が表示されます。
  5. うまく表示されない場合、上段のIoTセンサー値を出力するフローのwebsocket出力ノードを一旦削除して、画面左側のパレットのoutputセクションからwebsocketノードをドラッグ&ドロップして作り直してみます。出力Pathは/we/flow36としてあります(html内の指定と整合すれば何でも構いません)。

スクリーンショット 2016-09-30 15.23.30.png
スクリーンショット 2016-09-30 15.23.52.png
スクリーンショット 2016-09-30 15.36.53.png

サンプル-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"}]

  1. 実際のビーコンからのシグナルに合わせ、Area/Far/Near/ImmediateのIn/Outを表示するようにしました。 スクリーンショット 2016-10-03 10.11.58.png スクリーンショット 2016-10-03 10.37.35.png スクリーンショット 2016-10-03 10.43.59.png

サンプル-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);

  • 表へのデータの書き込みはNode-REDのdashDBノードでも可能です。下記のようなフローを使用可能です スクリーンショット 2016-10-11 10.53.48.png
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. ビーコンから取得される位置情報を随時上記の表へ更新します

  • ここでは下記のフロー(シミュレーター)で位置情報を更新していきます スクリーンショット 2016-10-11 10.56.09.png
ビーコンからの位置情報をシミュレートしデータベースへ書き込む
[{"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. データベースからの位置情報を可視化します

  • 下記のフローでデータベースからの位置情報を可視化します スクリーンショット 2016-10-11 10.57.47.png
データベースの位置情報を可視化する
[{"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へアクセスします

スクリーンショット 2016-10-11 11.11.39.png

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