--- title: Web×IoTメイカーズチャレンジ2019-20 ハンズオン講習会2:04 IoT試作 tags: Web×IoTメイカーズチャレンジ slideOptions: theme: white slideNumber: 'c/t' center: false transition: 'none' keyboard: true width: '93%' height: '100%' --- <style> /* basic design */ .reveal h1, .reveal h2, .reveal h3, .reveal h4, .reveal h5, .reveal h6, .reveal section, .reveal table, .reveal li, .reveal blockquote, .reveal th, .reveal td, .reveal p { font-family: 'Meiryo UI', 'Source Sans Pro', Helvetica, sans-serif, 'Helvetica Neue', 'Helvetica', 'Arial', 'Hiragino Sans', 'ヒラギノ角ゴシック', YuGothic, 'Yu Gothic'; text-align: left; line-height: 1.8; letter-spacing: normal; text-shadow: none; word-wrap: break-word; color: #444; } .reveal h1, .reveal h2, .reveal h3, .reveal h4, .reveal h5, .reveal h6 {font-weight: bold;} .reveal h1, .reveal h2, .reveal h3 {color: #2980b9;} .reveal th {background: #DDD;} .reveal section img {background:none; border:none; box-shadow:none; max-width: 95%; max-height: 95%;} .reveal blockquote {width: 90%; padding: 0.5vw 3.0vw;} .reveal table {margin: 1.0vw auto;} .reveal code {line-height: 1.2;} .reveal p, .reveal li {padding: 0vw; margin: 0vw;} .reveal .box {margin: -0.5vw 1.5vw 2.0vw -1.5vw; padding: 0.5vw 1.5vw 0.5vw 1.5vw; background: #EEE; border-radius: 1.5vw;} /* table design */ .reveal table {background: #f5f5f5;} .reveal th {background: #444; color: #fff;} .reveal td {position: relative; transition: all 300ms;} .reveal tbody:hover td { color: transparent; text-shadow: 0 0 3px #aaa;} .reveal tbody:hover tr:hover td {color: #444; text-shadow: 0 1px 0 #fff;} /* blockquote design */ .reveal blockquote { width: 90%; padding: 0.5vw 0 0.5vw 6.0vw; font-style: italic; background: #f5f5f5; } .reveal blockquote:before{ position: absolute; top: 0.1vw; left: 1vw; content: "\f10d"; font-family: FontAwesome; color: #2980b9; font-size: 3.0vw; } /* font size */ .reveal h1 {font-size: 5.0vw;} .reveal h2 {font-size: 4.0vw;} .reveal h3 {font-size: 2.8vw;} .reveal h4 {font-size: 2.6vw;} .reveal h5 {font-size: 2.4vw;} .reveal h6 {font-size: 2.2vw;} .reveal section, .reveal table, .reveal li, .reveal blockquote, .reveal th, .reveal td, .reveal p {font-size: 2.2vw;} .reveal code {font-size: 1.6vw;} /* new color */ .red {color: #EE6557;} .blue {color: #16A6B6;} /* split slide */ #right {left: -18.33%; text-align: left; float: left; width: 50%; z-index: -10;} #left {left: 31.25%; text-align: left; float: left; width: 50%; z-index: -10;} </style> <style> /* specific design */ .reveal h1 { margin: 0% -100%; padding: 2% 100% 4% 100%; color: #fff; background: #c2e59c; /* fallback for old browsers */ background: linear-gradient(-45deg, #EE7752, #E73C7E, #23A6D5, #23D5AB); background-size: 200% 200%; animation: Gradient 60s ease infinite; } @keyframes Gradient { 0% {background-position: 0% 50%} 50% {background-position: 100% 50%} 100% {background-position: 0% 50%} } .reveal h2 { text-align: center; margin: -5% -50% 2% -50%; padding: 4% 10% 1% 10%; color: #fff; background: #c2e59c; /* fallback for old browsers */ background: -webkit-linear-gradient(to right, #64b3f4, #c2e59c); /* Chrome 10-25, Safari 5.1-6 */ background: linear-gradient(to right, #64b3f4, #c2e59c); /* W3C, IE 10+/ Edge, Firefox 16+, Chrome 26+, Opera 12+, Safari 7+ */ } </style> <!-- --------------------------------------------------------------------------------------- --> #### Web×IoTメイカーズチャレンジ2019-2020 # FIWAREを使ったIoTの試作 <br> <br> #### 2019.11.3 ### 講師:香川大学 米谷雄介 --- ## 目次 1. IoTの基本要素の確認と学習方法 2. 学習の準備 3. FIWAREを使ったIoTの試作 -- Step6. FIWAREへの登録(プッシュスイッチ) -- Step7. FIWAREへの登録(温度センサー) -- Step8. IoTシステム(プッシュスイッチ→Lチカ) -- Step9. IoTシステム(温度→モーター) -- Step10. GPSセンサーの利用 -- Step11. GPSロガーを試作する -- Step12. 移動型温度センサーを試作する --- ## 1. IoTの基本要素の確認と学習方法 ### IoTの基本要素 1. センサー -- タクトスイッチ -- 温湿度センサ -- GPSセンサ 2. IoTプラットフォーム -- FIWARE 3. アクチュエータ -- LED(発光ダイオード) -- サーボモータ -- Webブラウザ --- ## 1. IoTの基本要素の確認と学習方法 ### 学習の基本的な流れ 1. アクチュエータを動かします。 2. センサーでデータを取ります。 3. IoTプラットフォームを介してセンサーとアクチュエータを連携させます。 --- ## Step0:学習の準備 ### 作業用のフォルダをデスクトップに作りましょう - 説明の都合上「web-iot」という名前のフォルダを作ってください。 - この中にプログラムを入れていきます。 --- ## Step0:学習の準備 ### プログラムを作成するエディタを開きます。 - 左上のラズベリーマークをクリックし、「プログラム」をクリック、「Geany」をクリックしてください。 - このエディタでプログラムを作っていきます。 --- ## Step0:学習の準備 ### プログラムを実行するターミナルを開きます。 - 上部のメニューバー一覧の中から黒いアイコン(LXTerninal)を開いておいてください。 --- ## Step0:学習の準備 ### 以下のような状態で作業を進めていきます。 - Geany:プログラムを作成 - Chromium:教材確認&アクチュエータプログラムを実行 - LXTerminal:センサープログラムを実行 - ファイルマネージャ:作業フォルダを見えるように ![](https://i.imgur.com/O2H4UgB.jpg) #### ウィンドウ配置はご自身が作業しやすいように工夫してください。 --- ## Step0:学習の準備 ### IoTプラットフォームの利用を助けるツール - 以下からダウンロードして解凍してください。(パスワード付) - fiware-api.zip https://drive.google.com/file/d/1skDLZNIumLGxQtT1U0CcX2UkNW3GpN5w/view?usp=sharing - 解凍した「fiware-api」フォルダを作業用フォルダ「web-iot」に入れてください。 --- ## Step6 FIWAREへの登録(プッシュスイッチ) ### 配線図 Step2と同じです。 ![](https://i.imgur.com/QjPY1e2.png) --- ## Step6 FIWAREへの登録(プッシュスイッチ) ### プログラム #### スイッチ状態送信プログラムを実行するWebアプリ(step6.html という名前で保存) ```html= <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta content="width=device-width" name="viewport"> <title>Sync-Switch</title> </head> <body> <!-- ブラウザによる動作の違いを吸収する --> <script src="https://r.chirimen.org/polyfill.js"></script> <!-- 基本ライブラリを読み込む --> <script src="https://code.jquery.com/jquery-3.3.1.min.js" integrity="sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8=" crossorigin="anonymous"></script> <!-- FIWAREのライブラリを読み込む --> <script src="fiware-api/ngsi.js"></script> <script src="fiware-api/orion.js"></script> <script src="fiware-api/config.js"></script> <!-- プッシュスイッチON/OFFプログラムを読み込む --> <script src="step6.js"></script> </body> </html> ``` --- ## Step6 FIWAREへの登録(プッシュスイッチ) ### プログラム #### スイッチ状態送信プログラムの本体(step6.js という名前で保存) ```javascript= main(); async function main() { var gpioAccess = await navigator.requestGPIOAccess(); var switchPort = gpioAccess.ports.get(5); // タクトスイッチの付いているポート await switchPort.export("in"); switchPort.onchange = function(val) { // タクトスイッチをデータとして表現する var tactSwitch = { id: "jp.kagawa.takamatsu.e-topia.tactSwitch.0001", type: "TactSwitch", location: {type: "geo:point", value: "34.353837,134.046586", metadata: {}}, name: { type: "Text", value: "Switch001", metadata: {} }, status: { type: "Number", value: val, metadata: {} } }; // ルールに従い送信データを整形する var ngsiContext = { "entities":[ tactSwitch ], "actionType" : "APPEND" }; // Orionにデータを送る orion.batchUpdate( ngsiContext , function (data, status) { console.log("STATUS : " + status + "\n"); }); }; } ``` --- ## Step6 FIWAREへの登録(プッシュスイッチ) ### 補足:データによるヒト・モノ・コトの表現の仕方 #### FIWAREで扱えるデータの構造(Key-Value形式) - 必須属性 - id:データ化されたヒト・モノ・コトを識別するための番号(他と衝突しないよう注意) - type: ヒト・モノ・コトの分類(例:ヒト=Personと表記など;国で標準化が進められている) - オプション属性:各属性にtype, value, metadataを指定 - location - type - value - metadata - name - type - value - metadata - status - type - value - metadata --- ## Step6 FIWAREへの登録(プッシュスイッチ) ### 補足:データによるヒト・モノ・コトの表現の仕方 #### FIWAREで扱えるデータの構造(Key-Value形式) - オプション属性のtype - Text(文字列) - Number(数値) - ロケーションフォーマット - 点: geo:location(形式:緯度,経度) - 線: geo:line(形式:"緯度,経度","緯度,経度","緯度,経度",・・・) - 長方形: geo:box(形式:"緯度,経度","緯度,経度";左上と右下を指定) - 多角形: geo:polygon(形式:"緯度,経度","緯度,経度","緯度,経度",・・・;最初と最後が一致) - 複数の多角形: geo:json(複数のgeo:polygonを合わせて書く) - DateTime - Boolean(0か1か) - StructuredValue(配列) - その他 --- ## Step6 FIWAREへの登録(プッシュスイッチ) ### 補足:データによるヒト・モノ・コトの表現の仕方 #### JavaScriptにおける表現 - id:jp.kagawa.takamatsu.e-topia.tactSwitch.0001 - type: TactSwitch - location: 固定値にする or GPSセンサーの値を指定する(lat,lon) - name - type: 文字列 - value: "tempSensor001" - metadata: なし - status - type: 数値 - value: 温度センサーの値を指定する - metadata: なし ```javascript= var tactSwitch = { id: "jp.kagawa.takamatsu.e-topia.tactSwitch.0001", type: "TactSwitch", location: {type: "geo:point", value: "34.353837,134.046586", metadata: {}}, name: { type: "Text", value: "Switch001", metadata: {} }, status: { type: "Number", value: val, metadata: {} } }; ``` --- ## Step6 FIWAREへの登録(プッシュスイッチ) ### データ連携のイメージ ![](https://i.imgur.com/cgRcKZL.png) --- ## Step7 FIWAREへの登録(温度センサー) ### 配線図 Step3と同じです。 ![](https://i.imgur.com/Qe0hdJs.png) --- ## Step7 FIWAREへの登録(温度センサー) ### プログラム #### 温度状態送信プログラムを実行するWebアプリ(step7.html という名前で保存) ```html= <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta content="width=device-width" name="viewport"> <title>Sync-Temp</title> </head> <body> <p id="head">TEST</p> <!-- ブラウザによる動作の違いを吸収する --> <script src="https://r.chirimen.org/polyfill.js"></script> <script src="i2c-ADT7410.js"></script> <!-- 基本ライブラリを読み込む --> <script src="https://code.jquery.com/jquery-3.3.1.min.js" integrity="sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8=" crossorigin="anonymous"></script> <!-- FIWAREのライブラリを読み込む --> <script src="fiware-api/ngsi.js"></script> <script src="fiware-api/orion.js"></script> <script src="fiware-api/config.js"></script> <!-- プッシュスイッチON/OFFプログラムを読み込む --> <script src="step7.js"></script> </body> </html> ``` --- ## Step7 FIWAREへの登録(温度センサー) ### プログラム #### スイッチ状態送信プログラムの本体(step7.js という名前で保存) ```javascript= main(); async function main() { var head = document.getElementById("head"); var i2cAccess = await navigator.requestI2CAccess(); // i2cAccessを非同期で取得 var port = i2cAccess.ports.get(1); // I2C I/Fの1番ポートを取得 var adt7410 = new ADT7410(port, 0x48); // 取得したポートの0x48アドレスをADT7410ドライバで受信する await adt7410.init(); for (;;) { // 無限ループ var value = await adt7410.read(); head.innerHTML = value ? `${value} degree` : "Measurement failure"; console.log(value + ' degree'); // 温度センサをデータとして表現する var tempSensor = { id: "jp.kagawa.takamatsu.e-topia.tempSensor.0001", type: "TempSensor", location: {type: "geo:point", value: "34.353837,134.046586", metadata: {}}, name: { type: "Text", value: "TempSensor001", metadata: {} }, status: { type: "Number", value: value, metadata: {} } }; // ルールに従い送信データを整形する var ngsiContext = { "entities":[ tempSensor ], "actionType" : "APPEND" }; // Orionにデータを送る orion.batchUpdate( ngsiContext , function (data, status) { console.log("STATUS : " + status + "\n"); }); await sleep(10000); // 10000 ミリ秒 = 10秒ごとにチェック・送信する } }; ``` --- ## Step7 FIWAREへの登録(温度センサー) ### データ連携のイメージ ![](https://i.imgur.com/TzWkvAR.png) --- ## Step8. IoTシステム(プッシュスイッチ→Lチカ) ### 配線図 #### 配線図 Step2と同じです。 ![](https://i.imgur.com/TYIACJB.png) ### プログラム #### スイッチ状態送信プログラムを実行するWebアプリ step6.htmlを使います。 #### スイッチ状態送信プログラムの本体 step6.jsを使います。 --- ## Step8. 呼び出しIoT(プッシュスイッチ→Lチカ) ### プログラム #### スイッチ状態受信プログラムを実行するWebアプリ(step8.html という名前で保存) ```html= <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta content="width=device-width" name="viewport"> <title>Sync-LED</title> </head> <body> <!-- ブラウザによる動作の違いを吸収する --> <script src="https://r.chirimen.org/polyfill.js"></script> <!-- 基本ライブラリを読み込む --> <script src="https://code.jquery.com/jquery-3.3.1.min.js" integrity="sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8=" crossorigin="anonymous"></script> <!-- FIWAREのライブラリを読み込む --> <script src="fiware-api/ngsi.js"></script> <script src="fiware-api/orion.js"></script> <script src="fiware-api/config.js"></script> <!-- プッシュスイッチON/OFFプログラムを読み込む --> <script src="step8.js"></script> </body> </html> ``` --- ## Step8. 呼び出しIoT(プッシュスイッチ→Lチカ) ### プログラム #### スイッチ状態受信プログラムの本体(step8.js という名前で保存) ```javascript= main(); async function main() { var gpioAccess = await navigator.requestGPIOAccess(); // GPIO を操作する var port = gpioAccess.ports.get(26); // 26 番ポートを操作する var v = 0; // ポートを出力モードに設定 await port.export("out"); for (;;) { // Orionにアクセスしてエンティティを取得する orion.getEntities({ id : "jp.kagawa.takamatsu.e-topia.tactSwitch.0001", type: "TactSwitch" }) .then(function(entities){ var val = entities[0].status.value; console.log(entities); // 確認のため出力する // スイッチはPullupで離すと1なので反転させる port.write(val === 0 ? 1 : 0); // LED を ON/OFF する }); await sleep(5000); // 繰り返し毎に 5000ms 待機 } } ``` --- ## Step8. IoTシステム(プッシュスイッチ→Lチカ) ### データ連携のイメージ ![](https://i.imgur.com/XxkEm8k.jpg) --- ## Step8. 呼び出しIoT(プッシュスイッチ→Lチカ) ### プログラムの実行その1 -- 受講者の皆さんは、Geany で step8.js を開き、idの値を 'jp.kagawa.takamatsu.e-topia.tactSwitch.0002' に変えてください。 -- 受講者の皆さんは、Chromium で step8.htmlを開きましょう -- 講師は、Geanyでstep6.jsを開き、上のidに合わせます。 -- 講師は、Chromiumで step6.htmlを開き、タクトスイッチを押します。 -- LEDは光りましたか? <br><br> ### プログラムの実行その2 -- 隣同士ペアになってください。 -- 左の方は、Geany で step8.js を開き、idの値を 'jp.kagawa.takamatsu.e-topia.tactSwitch.{自分の座席番号}' に変えてください。 -- そのまま、Chromium で step8.htmlを開きましょう -- 右の方は、Geanyでstep6.jsを開き、上のidに合わせます。 -- 右の方は、Chromiumで step6.htmlを開き、タクトスイッチを押します。 -- LEDは光りましたか? --- ## Step9. IoTシステム(温度センサー→モーター) ### 配線図 Step5と同じです。 ![](https://i.imgur.com/VRD56RD.png) ### プログラム #### 温度状態送信プログラムを実行するWebアプリ step7.htmlを使います。 #### 温度状態送信プログラムの本体 step7.jsを使います。 --- ## Step9. IoTシステム(温度センサー→モーター) ### プログラム Webアプリ(step9.html という名前で保存) ```html= <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta content="width=device-width" name="viewport"> <title>Motor</title> </head> <body> <p id="head">TEST</p> <!-- ブラウザによる動作の違いを吸収する --> <script src="https://r.chirimen.org/polyfill.js"></script> <!-- 基本ライブラリを読み込む --> <script src="https://code.jquery.com/jquery-3.3.1.min.js" integrity="sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8=" crossorigin="anonymous"></script> <!-- FIWAREのライブラリを読み込む --> <script src="fiware-api/ngsi.js"></script> <script src="fiware-api/orion.js"></script> <script src="fiware-api/config.js"></script> <!-- センサー値取得プログラムを読み込む --> <script src="step9.js"></script> </body> </html> ``` --- ## Step9. IoTシステム(温度センサー→モーター) ### プログラム プログラム本体(step9.js という名前で保存) ```javascript= // noprotect (JSBin の無限ループ検知・停止機能を無効化) main(); async function main() { var gpioAccess = await navigator.requestGPIOAccess(); var gatePort = gpioAccess.ports.get(26); // FET(ゲート)のポート await gatePort.export("out"); for (;;) { // 無限ループ // Orionにアクセスしてエンティティを取得する orion.getEntities({ id : "jp.kagawa.takamatsu.e-topia.tempSensor.0001", type: "TempSensor" }) .then(function(entities){ var value = entities[0].status.value; console.log(entities); // 確認のため出力する head.innerHTML = value ? `${value} degree` : "Measurement failure"; if(value > 30.0){ console.log('Over 30 ℃'); //Consoleに表示 gatePort.write(1); //30.0℃を超えたら gatePortの値を1にする。(モーター作動) }else{ console.log('30 ℃ or under'); //Consoleに表示 gatePort.write(0); //30.0℃以下なら gatePortの値を0にする。(モーター停止) } }); await sleep(5000); // 5秒間休止する } } ``` --- ## Step9. IoTシステム(温度センサー→モーター) ### データ連携のイメージ ![](https://i.imgur.com/NnrwNnp.jpg) --- ## Step9. IoTシステム(温度センサー→モーター) ### プログラムの実行その1 -- 受講者の皆さんは、Geany で step9.js を開き、idの値を 'jp.kagawa.takamatsu.e-topia.tempSensor.0002' に変えてください。 -- 受講者の皆さんは、Chromium で step9.htmlを開きましょう -- 講師は、Geanyでstep7.jsを開き、上のidに合わせます。 -- 講師は、Chromiumで step7.htmlを開き、温度センサを温めます。 -- ファンは回りましたか? <br><br> ### プログラムの実行その2 -- 隣同士ペアになってください。 -- 左の方は、Geany で step9.js を開き、idの値を 'jp.kagawa.takamatsu.e-topia.tempSensor.{自分の座席番号}' に変えてください。 -- そのまま、Chromium で step9.htmlを開きましょう -- 右の方は、Geanyでstep7.jsを開き、上のidに合わせます。 -- 右の方は、Chromiumで step7.htmlを開き、温度センサを温めます。 -- ファンは回りましたか? --- ## Step10 GPSセンサーの利用 ### 配線図 GPSセンサーの配線は、 <a href="https://denor.jp/raspberry-pi%e3%81%ab%e3%80%8c%e3%81%bf%e3%81%a1%e3%81%b3%e3%81%8d%e3%80%8d%e5%af%be%e5%bf%9cgps%e3%83%a2%e3%82%b8%e3%83%a5%e3%83%bc%e3%83%ab%e3%82%92%e6%8e%a5%e7%b6%9a">こちら</a> を参考にしてください。 GPS信号を受信できていれば点滅する <iframe width="560" height="315" src="https://www.youtube.com/embed/xWc4jAz4mEQ" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe> --- ## Step10 GPSセンサーの利用 ### プログラム #### GPSセンサープログラムの本体(step10.js という名前で保存) ```javascript= // シリアルポートへの接続モジュール var SerialPort = require('serialport'); var Readline = SerialPort.parsers.Readline; var parser = new Readline('\r\n'); var port = new SerialPort('/dev/serial0', { baudRate: 9600, parser: parser }); // GPSデータの取得 var GPS = require('gps'); var gps = new GPS; // 最新のGPSデータを保持するための変数 var lat = null; var lon = null; // シリアルポートを監視して信号を処理 port.on('data', function(data) { gps.updatePartial(data); }); // GPSデータを抽出 gps.on('data', function(data) { if(typeof data.lat !== "undefined" && typeof data.lon !== "undefined"){ lat = data.lat; lon = data.lon; } }); // 定期的にデータ処理を実行する setInterval(function(){ console.log(lat+ ","+ lon); }, 5000); ``` --- ## Step10 GPSセンサーの利用 ### プログラムの実行 - 左上のラズベリーアイコン>設定>Raspberry pi の設定をクリック -「インターフェイス」タブをクリックし、以下を設定してください。 - Serial Port の「有効」にチェックする - Serial Console の「無効」にチェックする - 再起動する - LXterminalを開き、以下を実行してください。 - `npm install serialport` - `npm install gps` - `sudo nodejs /home/pi/Desktop/web-iot/step10.js` --- ## Step11 FIWAREへの登録(GPSロガーを作る) ### 配線図 GPSセンサーの配線は、 <a href="https://denor.jp/raspberry-pi%e3%81%ab%e3%80%8c%e3%81%bf%e3%81%a1%e3%81%b3%e3%81%8d%e3%80%8d%e5%af%be%e5%bf%9cgps%e3%83%a2%e3%82%b8%e3%83%a5%e3%83%bc%e3%83%ab%e3%82%92%e6%8e%a5%e7%b6%9a">こちら</a> を参考にしてください。 GPS信号を受信できていれば点滅する <iframe width="560" height="315" src="https://www.youtube.com/embed/xWc4jAz4mEQ" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe> --- ## Step11 FIWAREへの登録(GPSロガーを作る) ### プログラム #### GPSセンサープログラムの本体(step11.js という名前で保存) ```javascript= // 最新のGPSデータを保持するための変数 var lat = null; var lon = null; // FIWAREモジュールを読み込む var fiware = require("./fiware-api/config.js"); var orion = fiware.orion; var ngsi = fiware.ngsi; // シリアルポートとの通信を開始する openPort(); function openPort(){ console.log("シリアルポートと通信を開始します。"); try { Serialport = requireUncached("serialport"); GPS = requireUncached("gps"); Readline = Serialport.parsers.Readline; parser = new Readline('\r\n'); port = new Serialport('/dev/serial0', { baudRate: 9600, parser: parser }); gps = new GPS; port.on('data', function(data) { try{ gps.updatePartial(data); } catch(e){ console.log("ERROR parsing serial data\n"); lat = null; lon = null; resetPort(); } }); gps.on('data', function(data) { console.log("gpsデータが更新されました。"); if(typeof data.lat !== "undefined" && typeof data.lon !== "undefined"){ lat = data.lat; lon = data.lon; } }); } catch (ex){ console.log("ERROR opening port\n" + ex); resetPort(); } } // シリアルポートに再接続する function resetPort(){ console.log("シリアルポートに再接続します。"); if (port.isOpen) { port.close(); } setTimeout(openPort, 10000); } // シリアルポートに再接続するためにモジュールをリセットする function requireUncached(module){ console.log(module + "を再読み込みします。"); delete require.cache[require.resolve(module)]; return require(module); } // 定期的にデータ処理を実行する setInterval(function(){ console.log(lat+ ","+ lon); // GPSロガーをデータとして表現する var gpsLogger = { id: "jp.kagawa.takamatsu.e-topia.gpsLogger.0001", type: "GpsLogger", location: {type: "geo:point", value: lat + "," + lon, metadata: {}}, name: { type: "Text", value: "gpsLogger001", metadata: {} }, }; // ルールに従い送信データを整形する var ngsiContext = { "entities":[ gpsLogger ], "actionType" : "APPEND" }; // Orionにデータを送る orion.batchUpdate( ngsiContext , function (data, status) { console.log("STATUS : " + status + "\n"); }); }, 5000); ``` --- ## Step11 FIWAREへの登録(GPSロガーを作る) ### プログラムの実行 - LXterminalを開き、以下を実行してください。 - `npm install jsdom` - `npm install jquery` - `sudo nodejs /home/pi/Desktop/web-iot/step11.js` ### プログラムの動作確認 http://komelabo.sakura.ne.jp/webxiot2019/gps-loggers.html ![](https://i.imgur.com/cj1TUzx.png) --- ## Step12 FIWAREへの登録(移動温度センサーを作る) ### 配線図 #### GPSセンサーの配線 <a href="https://denor.jp/raspberry-pi%e3%81%ab%e3%80%8c%e3%81%bf%e3%81%a1%e3%81%b3%e3%81%8d%e3%80%8d%e5%af%be%e5%bf%9cgps%e3%83%a2%e3%82%b8%e3%83%a5%e3%83%bc%e3%83%ab%e3%82%92%e6%8e%a5%e7%b6%9a">こちら</a> を参考にしてください。 #### 温度センサーの配線 Step3と基本同じですが、対象GNDをGPSセンサが占有しているので、 別のGNDに差してください。 ![](https://i.imgur.com/hjpB5vI.png) --- ## Step12 FIWAREへの登録(移動温度センサーを作る) ### プログラム #### 移動温度センサープログラムの本体(step12.js という名前で保存) ```javascript= // 最新のGPSデータ、温度データを保持するための変数 var lat = null; var lon = null; var adt7420 = null; var tmp = null; // FIWAREモジュールを読み込む var fiware = require("./fiware-api/config.js"); var orion = fiware.orion; var ngsi = fiware.ngsi; const {ADT7420} = require('i2c-adt7420'); const config = { pollingInterval: 5000, i2cBusNumber: 1 }; ADT7420.open({ i2cBusNumber: config.i2cBusNumber }) .then((instance) => { adt7420 = instance; return adt7420.configure({ resolution: 16, lowPowerMode: (config.pollingInterval >= 1000) }); }) .then(() => { console.log('Configured ADT7420'); }) .then(() => { }) .catch((err) => { console.error(err); process.exit(3); }); // シリアルポートとの通信を開始する openPort(); function openPort(){ console.log("シリアルポートと通信を開始します。"); try { Serialport = requireUncached("serialport"); GPS = requireUncached("gps"); Readline = Serialport.parsers.Readline; parser = new Readline('\r\n'); port = new Serialport('/dev/serial0', { baudRate: 9600, parser: parser }); gps = new GPS; port.on('data', function(data) { try{ gps.updatePartial(data); } catch(e){ console.log("ERROR parsing serial data\n"); lat = null; lon = null; resetPort(); } }); gps.on('data', function(data) { console.log("gpsデータが更新されました。"); if(typeof data.lat !== "undefined" && typeof data.lon !== "undefined"){ lat = data.lat; lon = data.lon; } }); } catch (ex){ console.log("ERROR opening port\n" + ex); resetPort(); } } // シリアルポートに再接続する function resetPort(){ console.log("シリアルポートに再接続します。"); if (port.isOpen) { port.close(); } setTimeout(openPort, 10000); } // シリアルポートに再接続するためにモジュールをリセットする function requireUncached(module){ console.log(module + "を再読み込みします。"); delete require.cache[require.resolve(module)]; return require(module); } // 定期的にデータ処理を実行する setInterval(function(){ console.log(lat+ ","+ lon); adt7420.readTemperature() .then((result) => { tmp = result; // GPSロガーをデータとして表現する var tempSensor = { id: "jp.kagawa.takamatsu.e-topia.tempSensor.0001", type: "TempSensor", location: {type: "geo:point", value: lat + "," + lon, metadata: {}}, name: { type: "Text", value: "tempSensor001", metadata: {} }, status: { type: "Number", value: tmp.celsius, metadata: {} }, }; // ルールに従い送信データを整形する var ngsiContext = { "entities":[ tempSensor ], "actionType" : "APPEND" }; // Orionにデータを送る orion.batchUpdate( ngsiContext , function (data, status) { console.log("STATUS : " + status + "\n"); }); }); }, 5000); ``` --- ## Step12 FIWAREへの登録(移動温度センサーを作る) ### プログラムの実行 - LXterminalを開き、以下を実行してください。 - `npm install i2c-adt7420` - `sudo nodejs /home/pi/Desktop/web-iot/step12.js` ### プログラムの動作確認 http://komelabo.sakura.ne.jp/webxiot2019/temp-sensors.html ![](https://i.imgur.com/tnworWP.png) --- ## Step12 FIWAREへの登録(移動温度センサーを作る) ### フィールドワーク #### インターネット接続の確保 - Android端末を貸与します。 - 設定アプリを開き、「ネットワークとインターネット」→「アクセスポイントとテザリング」とクリック - アクセスポイントの名称を確認、アクセスポイントがONになっているか確認 - Raspberry PiのWi-Fi設定で上記のアクセスポイントを選択、アクセスパスワードは「kometani」 <img src="https://i.imgur.com/vW2v5VP.jpg" width="100"> #### 電源の確保 - モバイルバッテリーを差した状態で駆動する - 電源コード - モバイルバッテリー - Raspberry Pi と間にかまして駆動させておくと脱着が容易 - フィールドワークに出るときは、モバイルバッテリー+Raspberry Piを持ち歩く --- ## Step12 FIWAREへの登録(移動温度センサーを作る) ### フィールドワーク #### プログラムの動作 - 配線はstep12と同じにしてください。 - LXTerminalのウィンドウないしタブを2つ準備 - それぞれで step11.js、step12.js を動作させたままにする #### モニタリングの準備 - 手持ちのスマートフォンで以下を開いておく - http://komelabo.sakura.ne.jp/webxiot2019/gps-loggers.html - http://komelabo.sakura.ne.jp/webxiot2019/temp-sensors.html #### 上の準備ができたら、屋外に出て測位できるか、データをモニタリングできるかを確認してみましょう