WioLTE & GPSで位置情報のトラッキングをする

私が小学校くらいの頃、雑誌の裏表紙にあった「電子工作キット」が欲しかったけど、買ってもらえなかったことを覚えています。多分、親も誕生日におねだりすれば買ってくれただろうに、そのときはファミコンのソフトをおねだりして買ってもらって大喜びしていました。なぜ「電子工作キット」をリクエストしなかったのか。自分の電子工作への思いはその程度だったのかと今頃になり思い知らされます。ロボコンを観るのは大好きだったのですけどね。誕生日プレゼント＝テレビゲームのソフトという価値観からブレることのない少年時代でした。

それから20年以上の時が経ちました。今ではインターネットや東急ハンズなどで電子工作キットが安価に買えていい時代ですね。電子工作と聞くと、はんだ付けや回路設計など、電気電子の基礎知識が必要で敷居が高いイメージがあります。もちろん、そういうものを少しずつ学んでいきながら楽しむのが醍醐味なんだろうと思いますが、とりあえずサクッと動かしてみたいということもあります。 [WioLTE](https://soracom.jp/products/module/wio_lte/) はそんなニーズを叶えてくれます。

ちょっと前の話になってしまうのですが、今年の4月に WioLTE を使った GPS トラッカーを作ったので、今回はその作り方を公開します。

# 完成したもの

![image_from_its.jpg](https://qiita-image-store.s3.amazonaws.com/0/18113/0cd11c43-7d85-cadb-017e-572c2929b55e.jpeg)
iPhoneXの力で自分の工作技術をごまかしていくスタイル

# 構成

![Screen Shot 2018-12-15 at 16.38.55.png](https://qiita-image-store.s3.amazonaws.com/0/18113/b337532a-e3a9-2724-00f1-6d0e88d4af2d.png)

UDPでSORACOM Harvestにデータを送信しています。
SORACOM Harvest は SORACOM Air を利用しているデバイスからのデータを簡単に保存・蓄積できるサービスです。詳しくは [SORACOM Harvest のサービス紹介ページ](https://soracom.jp/services/harvest/)をどうぞ。

# 用意するもの

- WioLTE
- GPS センサー
- SORACOM アカウント
- SORACOM Air SIM (ナノ)

私は [Grove IoT スターターキット for SORACOM(Wio LTE JP Version)](https://soracom.jp/products/kit/grovestarter_kit_lte/) を利用しています。最近、グローバルカバレッジのチップ型SIMを搭載した Wio 3G SORACOM Edition を同梱した[Grove IoT スターターキット for SORACOM(Wio 3G SORACOM Edition)](https://soracom.jp/products/kit/grovestarter_kit_3g_soracom_edition/)
 という商品もあります。

ただ、2018/12/15 現在、どちらも品切れとなっております。
今、手元にある人しか試せない記事になってしまい申し訳ないですが、次回入荷を待ちましょう。私の手元にあるのは、発売当初に自分で購入したものです。

- Arduino IDE

WioLTE のスケッチを書くためには、事前作業が必要です。
その手順は[こちら](https://qiita.com/matsujirushi/items/bd3b277bbf002898a9ff)によくまとまっています。セットアップ以外にも素晴らしい記事がたくさんありますので必見ですね。~~もうこれでいいんじゃないかな~~

### あったほうがよい

- モバイルバッテリー

簡単に手に入るもので作りたいという気持ちと、出力が大きいほうが安定するだろうという判断で、5V/2.1A で 5000mAh のモバイルバッテリーを使っています。小型化を目指すならば、ここは工夫のしどころだと思います。

- お好みのケースと、WioLTE やセンサー類を固定するための部材

WioLTE や GPS センサーは小さいのですが、モバイルバッテリーが大きいので 100円ショップでタッパーを買ってきて収納しています。バックパックに入れて自転車で移動したかったのである程度衝撃を和らげられるようにスポンジを緩衝材として敷いています。

![material.jpg](https://qiita-image-store.s3.amazonaws.com/0/18113/c5a783a3-01b0-5664-3ce7-5d64d4f2ab04.jpeg)

また、WioLTEの固定には耐久性には難がありますが簡単に加工できる、僕らの味方ダンボールを採用して、キリで穴を開けてネジ、スペーサー、ワッシャーで固定しています。
3D プリンタがご自宅にある場合は自作するのもいいですね。

![spacer.jpg](https://qiita-image-store.s3.amazonaws.com/0/18113/4d4df84d-691c-f562-421f-e8dd0ec3b632.jpeg)

このあたりは東急ハンズで買いました。

## SORACOM Air SIM を登録する

スターターキットを購入した場合は、SIMを登録する必要があります。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/18113/a5d2f43c-1892-e1e2-7845-a943454acc5a.png)

![image.png](https://qiita-image-store.s3.amazonaws.com/0/18113/c685a563-5307-419e-0dda-7a6dc193dd38.png)

登録時にグループを作成できます。このタイミングで作っておくと、この後のタイミングでグループを改めて作成したり、グループを変更する手間が省けます。

## クーポンを登録する（オプション）

スターターキットに同梱されているSIMの通信料に適用できるクーポンも、
このタイミングで登録しておくと忘れなくてよいでしょう。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/18113/f16bcf2a-d858-63d6-ce4b-7481f04198a0.png)

## SORACOM ユーザーコンソールでSIMグループを作成し、Harvest を ON にする

SIMグループとは、SORACOM Air SIMにSORACOM Harvest の設定を有効するために必要になるものです。ユーザーコンソールで、SIMグループの画面に進み、SIMグループを作成します。先程の登録時にグループを作った人は、作ったグループを選択して SORACOM Harvest を有効にしてください。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/18113/5dba792c-2c24-f90a-0307-ce7675c38274.png)

グループの SORACOM Harvest のパネルを選び、スイッチをONにして保存します。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/18113/7abc6a8c-f00d-720f-d2a4-78c59f979422.png)

SORACOM Harvest は1日5円の追加料金がかかりますが、アカウントあたりSIM1枚分の無料利用枠があるので他にHarvestを有効にしていなければ無料で利用できます。

## SIMをSIMグループに所属させる

SIM登録時にSIMグループを作成した人はこのステップは不要です。
SIM一覧で、先程登録したSIMにチェックを入れて、「操作」＞「所属グループ変更」をクリックしてSIMをSIMグループに入れてください。

## WioLTE を組み立てる

SIMカードを挿すときに気をつけないといけないことがあります。このスロット、SIMカードのスロットとマイクロSDカードのスロットが2層構造になっているんです。間違えて挿すとSIMが傷ついて最悪壊れてしまうので気をつけましょう（1敗）。
基板に近いほうがSIMスロットです。

GPS センサーは UART を使うので、WioLTEの UART プローブソケットに挿す必要があります。基板をよーくみると小さく書いてあります。

## WioLTE にスケッチを書き込む

こちらが自分で用意したスケッチです。キレイなコードではありませんが、数時間の高速道路ドライブではちゃんと位置情報を上げ続けてくれていたので、ちょっと遊ぶ分には問題ないかとおもいます。参考程度にしてください。

```cpp:osanpo.ino
#include <TinyGPS++.h>
#include <WioLTEforArduino.h>
#include <stdio.h>

#define INTERVAL        (60000)
#define RECEIVE_TIMEOUT (10000)

TinyGPSPlus gps;
WioLTE Wio;

void setup()
{
  delay(200);

  SerialUSB.println("");
  SerialUSB.println("--- START ---------------------------------------------------");
  
  SerialUSB.println("### I/O Initialize.");
  GpsBegin(&Serial);
  Wio.Init();
  
  SerialUSB.println("### Power supply ON.");
  Wio.PowerSupplyLTE(true);
  Wio.PowerSupplyGrove(true);
  delay(500);

  SerialUSB.println("### Turn on or reset.");
  if (!Wio.TurnOnOrReset()) {
    SerialUSB.println("### ERROR! ###");
    return;
  }

  SerialUSB.println("### Connecting to \"soracom.io\".");
  if (!Wio.Activate("soracom.io", "sora", "sora")) {
    SerialUSB.println("### ERROR! ###");
    return;
  }

  SerialUSB.println("### Setup completed.");
}

int dataArrived = 0;
void loop()
{
  const char* data;
  int connectId;

  data = GpsRead();
  if (data != NULL) {
    SerialUSB.println("### GPS updated ###");
    SerialUSB.println(data);
    SerialUSB.println(dataArrived++);
    # 毎回データを上げていると頻度が高すぎるので、適当に捨てる
    if (dataArrived >= 20) {
      dataArrived = 0;            
      connectId = Wio.SocketOpen("harvest.soracom.io", 8514, WIOLTE_UDP);
      if (connectId < 0) {
        SerialUSB.println("### ERROR! ###");
        goto err;
      }
      SerialUSB.println("### Send.");
      SerialUSB.println(data);
      SerialUSB.print("Send:");
      SerialUSB.println("");
      if (!Wio.SocketSend(connectId, data)) {
        SerialUSB.println("### ERROR! ###");
        goto err_close;
      }

      SerialUSB.println("### Receive.");
      int length;
      char returnData[100];
      length = Wio.SocketReceive(connectId, returnData, sizeof (returnData), RECEIVE_TIMEOUT);
      if (length < 0) {
        SerialUSB.println("### ERROR! ###");
        goto err_close;
      }
      if (length == 0) {
        SerialUSB.println("### RECEIVE TIMEOUT! ###");
        goto err_close;
      }
      SerialUSB.print("Receive:");
      SerialUSB.print(returnData);
      SerialUSB.println("");
      Wio.SocketClose(connectId);
    }
  }
  return;
  
err_close:
  SerialUSB.println("### Close.");
  if (!Wio.SocketClose(connectId)) {
    SerialUSB.println("### ERROR! ###");
    goto err;
  }

err:
  delay(INTERVAL);
}

////////////////////////////////////////////////////////////////////////////////////////
//

#define GPS_OVERFLOW_STRING "OVERFLOW"

HardwareSerial* GpsSerial;
char GpsData[100];
char GpsDataLength;
char data[100];
char incoming;

void GpsBegin(HardwareSerial* serial)
{
  GpsSerial = serial;
  GpsSerial->begin(9600);
  GpsDataLength = 0;
}

const char* GpsRead()
{
  while (GpsSerial->available()) {
    incoming = GpsSerial->read();
    // SerialUSB.print(incoming);
    gps.encode(incoming);
    if (incoming == '\r') continue;
    if (incoming == '\n') {
      GpsData[GpsDataLength] = '\0';
      GpsDataLength = 0;
      if (gps.location.isUpdated()) {
        sprintf(data, "{\"lat\":%.4f,\"lng\":%.4f}", gps.location.lat(), gps.location.lng());
        return data;
      } else {
        // return GpsData;
      }
    }
    
    if (GpsDataLength > sizeof (GpsData) - 1) { // Overflow
      GpsDataLength = 0;
      return GPS_OVERFLOW_STRING;
    }
    GpsData[GpsDataLength++] = incoming;
  }

  return NULL;
}

////////////////////////////////////////////////////////////////////////////////////////
```

## 実際に接続して、外に出る！

SORACOM Harvest の画面でデータが確認できれば成功です！

![image.png](https://qiita-image-store.s3.amazonaws.com/0/18113/cc4b12df-fb5e-8600-6593-b40b805dca38.png)


## かかった費用

|　品目           | 費用|
|:----------|---------:|
| Grove IoT スターターキット for SORACOM (Wio LTE JP Version) | 18,166円 |
| タッパー、ボール紙などの部材 | 約500円 |
| SORACOM 利用料（通信料はクーポンで相殺） | 1日10円 |
| 合計 | 約19,000円|

## おまけ

SORACOM Harvest はデータ保存期間の上限が40日間なのですが、最近それを2年に延長するオプションがリリースされました。（ [Harvestデータ保持期間に731日延長オプションが追加されました！](https://blog.soracom.jp/blog/2018/11/22/harvest-data-extension-option/)
）
さらに、SORACOM Harvest に保存したデータは先日のSORACOM Discovery 2018 でリリースされた SORACOM Lagoon というダッシュボードサービスでも簡単に利用できます。そのときの[講演資料もアップされています](https://www.slideshare.net/SORACOM/soracom-conference-discovery-2018-b3-iot-iot)。

SORACOM Lagoon の機能が拡充されていくことによって、もっと便利になっていくはずです！

## さいごに

この記事は「SORACOM アドベントカレンダー」の15日目として書きました。

私は電子工作初心者です。
もしおかしなところがあればコメント、DM等でご指摘いただければありがたいです。

12月も後半に入りました。年末年始のやりたいことリストにひとつ、IoT でなにか遊んでみるというのを入れてみてはいかがでしょうか。私は最近買った Amazon Echo spot と、積んである obniz で遊びたいな〜と思っています。それではみなさま、良いお年をお迎えください。

P.S. 年末年始のやりたいことリストが膨らんだ結果まともに消化しきれないのに、食べたものはきっちり成果として残っていく現象に名前をつけたい。