---
# System prepended metadata

title: 'Web×IoTメイカーズチャレンジ2019-20 ハンズオン講習会２：04 IoT試作 '
tags: [Web×IoTメイカーズチャレンジ]

---

---
title: Web×IoTメイカーズチャレンジ2019-20 ハンズオン講習会２：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」に入れてください。

---

## Step６ FIWAREへの登録（プッシュスイッチ）
### 配線図
Step2と同じです。
![](https://i.imgur.com/QjPY1e2.png)

---

## Step６ 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>
```

---

## Step６ 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");
        });
    };
}
```

---

## Step６ FIWAREへの登録（プッシュスイッチ）
### 補足：データによるヒト・モノ・コトの表現の仕方

#### FIWAREで扱えるデータの構造（Key-Value形式）
- 必須属性
    - id：データ化されたヒト・モノ・コトを識別するための番号（他と衝突しないよう注意）
    - type: ヒト・モノ・コトの分類（例：ヒト=Personと表記など；国で標準化が進められている）
- オプション属性：各属性にtype, value, metadataを指定
    - location
        - type
        - value
        - metadata
    - name
        - type
        - value
        - metadata
    - status
        - type
        - value
        - metadata

---

## Step６ FIWAREへの登録（プッシュスイッチ）
### 補足：データによるヒト・モノ・コトの表現の仕方
#### FIWAREで扱えるデータの構造（Key-Value形式）

- オプション属性のtype
    - Text（文字列）
    - Number（数値）
    - ロケーションフォーマット
        - 点：　geo:location（形式：緯度,経度）
        - 線：　geo:line（形式："緯度,経度","緯度,経度","緯度,経度",・・・）
        - 長方形： geo:box（形式："緯度,経度","緯度,経度"；左上と右下を指定）
        - 多角形： geo:polygon（形式："緯度,経度","緯度,経度","緯度,経度",・・・；最初と最後が一致）
        - 複数の多角形： geo:json（複数のgeo:polygonを合わせて書く）
    - DateTime
    - Boolean（0か1か）
    - StructuredValue（配列）
    - その他

---

## Step６ 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: {} }
        };
```

---

## Step６ 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

#### 上の準備ができたら、屋外に出て測位できるか、データをモニタリングできるかを確認してみましょう
