GPSマルチユニット SORACOM Editionで遊ぶ

#この記事でやったこと
* GPSマルチユニットSORACOM Editionの初期導入、動作確認
* データをSORACOM Funk経由でAWS Lambdaに送り、GoogleSpreadSheetに保存
* GPSマルチユニットはGPSロガーの代わりになるか？の考察

# GPSマルチユニット SORACOM Edition
SORACOMさんから今年発売されたGPSマルチユニットが気になっていました。
発売開始の記事を見た時もこんな反応をしています。
<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">これは凄いものが出ちゃったんじゃない？？ :<br>4 つのセンサーと省電力通信 LTE-M 内蔵「GPS マルチユニット SORACOM Edition」発売開始！ – SORACOM エンジニアブログ <a href="https://t.co/e8O6h9sXyQ">https://t.co/e8O6h9sXyQ</a> <a href="https://twitter.com/hashtag/soracom?src=hash&amp;ref_src=twsrc%5Etfw">#soracom</a></p>&mdash; mokatsumo (@mokatsumo) <a href="https://twitter.com/mokatsumo/status/1227603377795686401?ref_src=twsrc%5Etfw">February 12, 2020</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
GPSマルチユニットは温度、湿度、加速度、位置情報(GPS/GLONASS/みちびき)の4つのセンサーを備え、そのデータをLTEで送信できるデバイスです。

私、GPSのログを取ったり気温・湿度を記録するのが好きで、旅行なんかに行くときによく次の写真のようなものを持ち歩いたりしているんですね。

![A81E60CE-A8AC-4CE1-89D4-1DF16291B31D.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/641828/a716f3ab-5396-c2b4-0d04-2313b0a9222a.jpeg)
GPS ロガー M-241と、オムロンの環境センサー(ウェザーニュース版)です。

GPS マルチユニットがあれば、これらの機能をまとめて代わりにできるんじゃないかと思ったりしてました。もちろん全く同じできることができるわけじゃないですが、その辺の検証込みで遊んでみたいな、と。

そんなときに、SORACOMさんのキャンペーンでGPSマルチユニットが期間限定の割引価格で販売されていました。SORACOMユーザーコンソールのMenu内、発注ボタンからサクッと注文できました。
(記事執筆時、割引は終了しています。)

# 初期設定
まだ緊急事態宣言下でしたが、2営業日目には到着しました。ありがとうございます。
![169A570F-7C18-423A-8DCF-B8790A9F9B9E.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/641828/6b787cd4-8dba-27a6-9564-708c200c9445.jpeg)
500円玉はサイズ比較用です。名刺より一回り横幅が小さいくらいで、思ってたよりコンパクトです。これでバッテリー内蔵ですからね。
他にmicroSIMが1枚と、microUSBケーブルが1本ついてきます。
↓この記事を参考に、初期設定を進めていきます。必要なことは全て書いてあります。
[GPS マルチユニット SORACOM Edition と SORACOM Harvest Data で簡単に可視化する](https://dev.soracom.io/jp/start/gps_multiunit_location/)

### 届いたら最初にすること
これ大事でした。「受け取り確認」を最初にしないと、設定画面にSIMが現れません。
ユーザーコンソール「発注」画面から 「受け取り確認」ボタンを押しておきます。

![0438A2EA-0A8B-47C6-BECB-903F32A06C98.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/641828/965b93ad-4e23-75e1-6305-c50d6f3da2db.jpeg)

側面のカバーを開けて赤いトレイを引き出し、SIMを入れます。
赤いトレイはバネ式ではないので押し込んでも出てきません。爪などで引っ掛けて引き出し、SIMをトレイの形に合うようにのせて押し込みます。端子側を上にします。

細かい設定は上記リンク先記事の通りにすればいいので、ポイントだけ記します。
SORACOMユーザーコンソールのMenu →  ガジェット管理 → GPS マルチユニットと進み、「新規デバイス設定」から先ほどセットしたSIMを選択。SIMグループの設定を行います。
ここで先ほどの「受け取り確認」をしておかないとSIMが表示されません。

デバイス設定より、「位置情報」「温度」「湿度」「加速度」をチェック。
送信先は「SORACOM Harvest Data (Lagoon)」をONにします。

データを送信するタイミングを「定期送信 - 手動モード 詳細設定」から設定します。今回は1分間隔に設定してみました。
<img width="807" alt="1190A057-454D-4275-BB6D-74C13D68A02E.jpeg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/641828/4ec448be-4506-b36a-90f6-b4bb5999b022.jpeg">

GPSマルチユニットの電源をONにした状態で、ファンクションボタンを1回(1秒)押すと、サーバ上の設定が本体に反映されます。
この辺、電源を入れるのも設定の反映もファンクションボタン1回押しなので最初は混同してしまって電源を入れれば設定が反映されると思い込んでいたのですが、電源を入れておいて改めて一回押しで設定反映を行わないといけないようです。

# SORACOM Harvestで位置情報の収穫
SORACOMコンソールのMenu→ガジェット管理→GPSマルチユニット→データを確認
から、送信されたデータが確認できます。
<img width="919" alt="A646A2C4-B5CE-42F0-9C39-5F86C184D5D8.jpeg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/641828/f8246ae4-2949-088f-f6de-c4b65d5f5b16.jpeg">
折れ線グラフ上でデータにカーソルを合わせると、個別の数値がプレビューされます。tempが温度、humiが湿度、xyzは加速度、latとlonが緯度経度ですね。

赤矢印で示した位置情報ピンのアイコンをクリックすると、位置情報が地図上にプロットされます。
少し歩きながら実験をしてみました。

緊急事態宣言が解除されたとは言え、用もなく街に出るのはまだ避けたいので、ちょっとした用事のついでにあまり混んでいないところで、短時間で確認しています。

<img width="826" alt="4071D055-EC09-4FD4-8885-CD5E48048A05.jpeg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/641828/5d9af344-adcc-8095-2651-28a19a5c552a.jpeg">

送信間隔を1分にしてしばらく歩いています。緑の線が実際に歩いた経路で、後で上書きしたもの。ピンがGPSマルチユニットの位置情報プロットです。
細かく路地を曲がっていたら追いつかなそうですが、普通に歩いているくらいなら概ね補足できている感じですね。車だと逐次追っていくのはキツそうです。

# SORACOM FunkでAWS Lambdaに連携
Harvestでデータや地図を見ていくだけでも面白いんですが、データを他サービスに連携させて利用できるようにすると楽しいです。
SORACOM Funkというサービスを使うとAWS Lambdaに簡単にデータを受け渡すことができます。
LambdaからはIFTTTのWebhookを叩いて、GoogleSpreadSheetに保存してみました。
<img width="1112" alt="85E47B4C-0043-46C7-A4BD-6C5C5FB4490D.jpeg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/641828/447208bd-7bc9-b739-fc7a-122b6bff9908.jpeg">
次のようなコードを書いてみました。SORACOM LTE-M Buttonの「迎えにきてボタン」で使っていたものをチョコチョコっと変えています。そのため無駄もありますが、とり急ぎLambdaでGPSマルチユニットのデータを拾う方法を理解することを目標にしました。

```javascript:index.js
const https = require('https');
const url = require('url');

exports.handler = function(event, context, callback) {
  console.log('processing event: %j', event)

  var key = "XXXXXXXXXXXXXXXXXXXXX"     // IFTTT KEY
  var iftttEventName = "GPSMULTI01"     // IFTTTへの送信Event名

  var lat = String(event.lat)           // 経度
  var lon = String(event.lon)           // 緯度
  var batteryLevel = String(event.bat)  // 電池残量
  var rs = String(event.rs)             // アンテナピクト
  var temp = String(event.temp)         // 温度
  var humi = String(event.humi)         // 湿度
  var ac_x = String(event.x)            // 加速度X 
  var ac_y = String(event.y)            // 加速度Y
  var ac_z = String(event.z)            // 加速度Z
  var type = String(event.type)         // 0:定期送信 1:ボタン押下時の送信

  var mapUrl = "https://maps.google.co.jp/maps?q="+lat+","+lon  // google map用

  var webhookUrl = "https://maker.ifttt.com/trigger/"+iftttEventName+"/with/key/"+key
  webhookOptions = url.parse(webhookUrl)
  webhookOptions.headers = {'Content-TYpe':'application/json'}
  
  var values = []
  var data = {}

  values[1] = lat+","+lon
  values[2] = temp+","+humi+","+ac_x+","+ac_y+","+ac_z+","+batteryLevel
  values[3] = mapUrl

  var data = { 'value1': values[1], 'value2': values[2], 'value3': values[3]}
  var body = JSON.stringify(data)
  console.log("sending: "+body+ " to " + webhookUrl)
  webhookOptions.headers['Content-Length'] = Buffer.byteLength(body)
  var req  = https.request (webhookOptions, function(res){
    if (res.statusCode === 200)
    {
      console.log('webhook succeeded')
      callback(null, true)
    }
    else {
      callback("webhook failed with "+res.statusCode)
    }
    return res;
  })
  req.write(body)
  req.end()
}
```
IFTTTのkeyは自分のIFTTTアカウントで使っているWebhookのkeyに適宜置き換えます。

この中でのポイントは各データの取り出し方ですね。
GPSマルチユニットの送信データはFunk経由でevent内に格納されて飛んでくるので、下記で取り出します。

```javascript
  var lat = String(event.lat)           // 経度
  var lon = String(event.lon)           // 緯度
  var batteryLevel = String(event.bat)  // 電池残量
  var rs = String(event.rs)             // アンテナピクト
  var temp = String(event.temp)         // 温度
  var humi = String(event.humi)         // 湿度
  var ac_x = String(event.x)            // 加速度X 
  var ac_y = String(event.y)            // 加速度Y
  var ac_z = String(event.z)            // 加速度Z
  var type = String(event.type)         // 0:定期送信 1:ボタン押下時の送信
```

### アウトプット
IFTTTの設定はいろんなところに解説があるので省略しますが、Google Spread Sheetへはこのように保管されます。
<img width="853" alt="E9CD2FF4-5AE9-4CDB-AEE1-F6383810A406.jpeg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/641828/bee1e633-2bca-f9bc-3730-f2990768048d.jpeg">
C列に緯度経度、D列に温度・湿度・加速度・バッテリーレベル、E列にGoogleMap表示用URLを格納します。

とりあえずデータを受け渡すことができました。
IFTTTは３つの値しか受け渡せないので、カンマ区切りでこのように分けて無理やり送っています。本来はCSVなどにして活用したいので、それは次の課題ですね。受け取ったGoogleSpreadSheet側で処理できればと思っています。

# GPSロガーの代わりになる？
最後に、今回遊んでみた内容を踏まえて「GPSマルチユニットはGPSロガーの代わりになるのか問題」を考えてみました。

私がGPSロガーを持ち歩くとき、データ保管の間隔は15sに設定していました。自動車や列車などの早い移動でも割とよくルートを拾ってくれます。
対して今回のGPSマルチユニットの最小データ送信間隔は1分です。自動車移動などではざっくりしたルート取得になってしまいますね。

とはいえ、細かく走行ルートを取って地図上にGPSログの絵を書くとかの用途で使っているわけではありません。旅行などでこの日のこの時間にどこにいたくらいの工程記録用途であれば、間隔1分でも十分有用なデータになると思います。

GPSログの標準的形式への変換方法の検討も必要ですね。Google Spread Sheetに保管した内容から必要なデータを整形してCSVで書き出し、GPSデータフォーマットのGPXやKMLに変換すれば十分使えそうな気がしてきました。次のチャレンジとしましょう。

あと、多くのGPSロガーは高度もログに残してくれるものが多いのですが、GPSマルチユニットの送信データには緯度経度しかありません。気圧センサーなどで高度を測定しているGPSロガーもありますが、多くのロガーは衛星位置の三角測量により算出しているはずです。新たなセンサーが必要なわけではないので、アップデートなどでできるようになったら嬉しいなぁと思っています。（無理かな？）