Soracomスターターキットで作るGPSなしの位置情報トラッカー ~その2 AWS IoT連携~

[Soracomスターターキットで作るGPSなしの位置情報トラッカー ~その1~](https://qiita.com/ymmtyuhei/items/43899ba06bd017683519)からの続きになります

ソースコードは以下になります
[ymmtyuhei/GeoLogAWS: Google Geolocation APIを使い取得した位置情報をAmbientに送信する。](https://github.com/ymmtyuhei/geologaws)

#AWS IoTのセットアップ
AWS IoTへRaspberry PIからMQTTでメッセージをPublishするまでのRaspberry PiとAWSの環境を、チュートリアルの通り構築します。

> [Raspberry Pi の接続 - AWS IoT](https://docs.aws.amazon.com/ja_jp/iot/latest/developerguide/iot-sdk-setup.html)


 - Raspberry PIからメッセージをパブリッシュしたがAWSのウェブコンソールで確認できなかったとき、
デバッグツールとしてMQTT.fxをつかってみるといいかもしれません。

>AWS IoTを始めよう -MQTTの設定(MQTT.fx編)-
https://recipe.kc-cloud.jp/archives/9629

<img width="779" alt="スクリーンショット 2018-04-18 17.05.00.png" src="https://qiita-image-store.s3.amazonaws.com/0/6968/6120ea24-1bdd-3cf7-996e-6d2a7f54fcc7.png">


 - [前回の手順で](https://qiita.com/ymmtyuhei/items/43899ba06bd017683519)Soracom AirをセットアップしたRaspberry PIに有線LANのみ接続した状態だと、
AWS IoTへのメッセージのパブリッシュができず、USBモデムを接続したときのみパブリッシュできました。


#AWS Lambdaを設定

AWS IoTのカスタムルールを作成します。特定のトピックへのメッセージをフックし、Lambdaを実行する設定をします。

>[AWS IoT チュートリアル ラムダルールの作成](https://docs.aws.amazon.com/iot/latest/developerguide/iot-lambda-rule.html)

 - トピックフィルターとして```pisora/ssids```を設定しました。
 - MQTTfxを使いながらテストデータをパブリッシュし、Lambdaが実行されることを確認します。
 - Lambdaの実行ログは ```CloudWatch>ロググループ```で確認できます。
 - RasPi側で```pisora/update```というトピックをフックして、SSIDの送信処理が実行されるようにしたので、AWS IoT側からそのトピックにメッセージを送信し、動作を確認できます。


<img width="1024" alt="スクリーンショット 2018-04-18 17.23.10.png" src="https://qiita-image-store.s3.amazonaws.com/0/6968/29c032ed-09f8-ed68-04aa-6b505022984c.png">


<img width="1013" alt="スクリーンショット 2018-04-18 17.23.22.png" src="https://qiita-image-store.s3.amazonaws.com/0/6968/1fa23f98-f60f-9ae2-27a0-fb5e955b35a1.png">

```javascript
const ambient = require('ambient-lib')
const axios = require('axios')
const geolocation_key = '***'
const ep_geolocation = 'https://www.googleapis.com/geolocation/v1/geolocate?key='+geolocation_key

//ambient.connect(チャネルId, ライトキー[, リードキー[, ユーザーキー]]);
ambient.connect(1234, "***", "***", "***");

function postAmbient(accuracy, lat, lng){
  var ambientData = {
    d5: accuracy, 
    lat: lat, 
    lng: lng
  }
  ambient.send(ambientData, function(err, res) {
      if (err) {
          console.error(err)
      }
      console.log('update to ambient success. :',res.statusCode)
  })
}

function requestPosition(ssids){
  console.log("got ssids")
  console.dir(ssids)
  axios.post(ep_geolocation, ssids)
    .then(function (response) {
      console.log("got geolocation from ssids")
      console.dir(response.data)
      postAmbient(
        response.data.accuracy,
        response.data.location.lat,
        response.data.location.lng
      )
    })
    .catch(function (error) {
      console.log(error)
    })
}

exports.handler = (event, context, callback) => {
  var eventText = JSON.stringify(event, null, 2);
  console.log("Received event:", eventText);
  requestPosition(event)
}

```

#Raspberry PiからSSIDをパブリッシュする

 - AWS IoTの鍵情報などが設定されたRaspberry Piから、定期的にSSIDを送信するスクリプトを展開します。

```javascript
const piWifi = require('pi-wifi')
const cron = require('node-cron')
const axios = require('axios')
const geolocation_key = '***'
const ep_geolocation = 'https://www.googleapis.com/geolocation/v1/geolocate?key='+geolocation_key
let awsIot = require('aws-iot-device-sdk')
let device = awsIot.device({
  keyPath: "/home/pi/deviceSDK/certs/private.pem.key",
 certPath: "/home/pi/deviceSDK/certs/certificate.pem.crt",
   caPath: "/home/pi/deviceSDK/certs/root-CA.crt",
 clientId: "PISORA",
     host: "xxx.iot.us-east-1.amazonaws.com"
})

function geolocationObject(piwifiResponse) {
    var wifiAccessPoints = []
    for (const network in piwifiResponse) {
        if (piwifiResponse.hasOwnProperty(network)) {
          const element = piwifiResponse[network]
          let wifiAccessPoint = {
              "macAddress":element.bssid,
              "signalStrength":element.signalLevel
          }
          wifiAccessPoints.push(wifiAccessPoint)
        }
    }
    let res = {
      "considerIp": "false",
      "wifiAccessPoints":wifiAccessPoints
    }
    return res
}

function scan(){
  piWifi.scan(function(err, networks) {
      if (err) {
        return console.error(err.message)
      }
      if (networks === undefined ){
        return console.error("networks undefined")
      }
      var res = geolocationObject(networks)
      console.log("found ssids :")
      console.dir(res)
      device.publish('pisora/ssids', JSON.stringify(res))
  })
}

device
  .on('connect', function() {
    console.log('connect')
    device.subscribe('pisora/update')
    scan()
    /**
     * 定期実行
     * 1分に1回実行
     */
    cron.schedule('*/1 * * * *', function(){
      scan()
    })
  })

device
  .on('message', function(topic, payload) {
    console.log('message', topic, payload.toString())
    scan()
  })

```

#永続化 (Raspberry Pi)

前回設定したpm2の自動起動の設定を削除したあと、pm2を再始動します

```
pm2 delete all
pm2 start {スクリプトのファイルパス}
pm2 save
pm2 startup
```

#Ambidataで確認

位置情報がAmbidata上にプロットされていることを確認します。
SSIDから位置情報を推測しているので、GPSの電波を受信できない、地下鉄でも位置情報をプロットできました。

<img width="1142" alt="スクリーンショット 2018-04-18 17.38.14.png" src="https://qiita-image-store.s3.amazonaws.com/0/6968/759097ea-b3ed-8e79-735e-ae554f488de8.png">


# 運用にかかった費用(参考値)

１時間ほど動かしてみたところ、以下の転送量がSoracomコンソール上で確認されました

種別 | １時間あたり転送量([その１](https://qiita.com/ymmtyuhei/items/43899ba06bd017683519)) | １時間あたり転送量(その２)
---|---|---
上り | 52.3KiB (0.05107 MiB) | 113.7KiB(0.11104 MiB)
下り | 188.2KiB (0.18379 MiB) | 69.5KiB(0.06787 MiB)

\* s1.standard 上り0.24 円/MB 下り0.8 円/MB

(なぜ上り転送量が増えたのか疑問が残る結果になりました...)

<img width="886" alt="スクリーンショット 2018-04-18 16.51.07.png" src="https://qiita-image-store.s3.amazonaws.com/0/6968/84fe8aea-a45d-7bde-c13a-57838e636a75.png">


#####1日稼働後のAWSの請求ダッシュボード

<img width="507" alt="スクリーンショット 2018-04-18 17.41.37.png" src="https://qiita-image-store.s3.amazonaws.com/0/6968/efcb03ee-d001-1a52-326e-c9973a21f653.png">



## (しばらく放置したの情報を追記)
** 条件が変わっています
*前回と条件が変わっています
送信間隔 1分→10分

バッテリは5000mAhの以下のもの
https://www.amazon.co.jp/gp/product/B01DEURI48

開始 | 終了 | 稼働時間 | 
---|---|---
21:15 | 翌06:50 | 9:35 | 


<img width="881" alt="スクリーンショット 2018-04-20 12.33.56.png" src="https://qiita-image-store.s3.amazonaws.com/0/6968/9d85705f-373c-2f02-0ca3-252d264dbf22.png">

##### 1時間あたり転送量
 - UP 37.2kb/h
 - DL 39.2kb/h

##### 上記の設定で一ヶ月稼働した場合
 - UP27.028125Mib = 6.48円
 - DL28.48125Mib = 22.4円
 - 想定される月額料金29円