UnityからSORACOM Harvestにあるデータをゲットする方法

前回のQiitaの記事
[M5StackGRAYのジャイロセンサの値を3G拡張ボードを使ってSORACOM Harvestに送ってみた](
https://qiita.com/tatsuya1970/items/b25881ddf11ae8cd6409
)
で送ったデータを今度はUnityで取得します。

<br>
SORACOM Harvestのデータを取得方法については、[公式サイト](https://dev.soracom.io/jp/start/harvest/)に書かれてます。

```
$ curl -X GET \
  -H "X-Soracom-API-Key: ${API-KEY}" \
  -H "X-Soracom-Token: ${API-TOKEN}" \
  https://api.soracom.io/v1/subscribers/${IMSI}/data | jq .
```


普通のエンジニアの方はこれからコードに反映できると思いますが、私はcurl文だけではコード化できない素人なので、すごく悩みました。
ググっても、そのものずばりのコード例が無かったので、結構苦戦しましたが、なんとか以下のやり方で、UnityからHarvestのデータをゲットすることができました。



##SORACOMでの対応

SORACOMのAPIリファレンスページを開きます。
https://dev.soracom.io/jp/docs/api/

認証キーかアカウントのメールアドレスを入力し、認証ボタンを押します。
[![Image from Gyazo](https://i.gyazo.com/ebc0c2e77ecaae887fc219cda45cda6d.png)](https://gyazo.com/ebc0c2e77ecaae887fc219cda45cda6d)


APIキーとトークンが発行されます。
[![Image from Gyazo](https://i.gyazo.com/a8d7227e651832828fa5fcffd0dd79a2.png)](https://gyazo.com/a8d7227e651832828fa5fcffd0dd79a2)

その下は、
日本だけのSIMなら "JAPAN"
グローバルなら　"GLOBAL" を選択
[![Image from Gyazo](https://i.gyazo.com/73934a327274ad05138d13012a173367.png)](https://gyazo.com/73934a327274ad05138d13012a173367)
※デフォルトがJAPANなのでグローバルSIMの人は注意。私はグローバルSIMだったにも関わらず、そのままにしてたため、ちょっとハマりました。

<br>
下にスクロールすると、たくさんのAPIが列挙されてます。
[![Image from Gyazo](https://i.gyazo.com/aafc136d1d060d1cd644236ab162ca45.png)](https://gyazo.com/aafc136d1d060d1cd644236ab162ca45)

Harvestのデータを取得するには、先程のcurlの例法を見ると、

```
/subscribers/{imsi}/data
```

と書いてあったので、同じものを下にスクロールして探してみると、

あった！
[![Image from Gyazo](https://i.gyazo.com/f93cf2ff8905de87ac280b38ec17ff8d.png)](https://gyazo.com/f93cf2ff8905de87ac280b38ec17ff8d)

ここをクリックすると、
実際にAPIが試せる画面が現れます。

１、 必要最低限 <B>imsi</B>を入力（他の項目は任意）
　※imsiはユーザーコンソールの該当SIMの「SIM詳細」に書かれてます。
２、 <B>Tri it Out!</B> をクリックします。
[![Image from Gyazo](https://i.gyazo.com/dc11c5842cdd722cc8d5d4631ad790d9.png)](https://gyazo.com/dc11c5842cdd722cc8d5d4631ad790d9)

こんな画面が現れます。
この画面が現れないと何かが間違ってます。
[![Image from Gyazo](https://i.gyazo.com/fe2dd1a788f53f8831a0115b7bc66e1c.png)](https://gyazo.com/fe2dd1a788f53f8831a0115b7bc66e1c)

ここで注目するのが以下の赤線で囲った
curl と Request URL
あとで、Unityのプログラムで使います。
[![Image from Gyazo](https://i.gyazo.com/f27306011c2b0bcd173ceb812ca96518.png)](https://gyazo.com/f27306011c2b0bcd173ceb812ca96518)

##Unityでの対応

###動作確認バージョン
Unity 2019.2.21f1

###事前準備
UnityでHTTP(GET)通信によるJSONデータ取得するために、
Unityアセットストアから
<B>JSON Object</B>
というアセット をインポートします。

[![Image from Gyazo](https://i.gyazo.com/ed2bbfbae672e3242f348893948b8144.png)](https://gyazo.com/ed2bbfbae672e3242f348893948b8144)


###コード

```csharp:getHarvest.cs
using UnityEngine;
using System.Collections;
using UnityEngine.Networking;

public class getHarvest : MonoBehaviour
{
    private string APIKEY = "APIKEY";
    private string APITOKEN = "APITOKEN";

    void Update()
    {

      //URLは先程soracomのAPIリファレンスサイトで現れたRequestURLを記載 
      StartCoroutine(GetText("https://g.api.soracom.io/v1/subscribers/${IMSI}/data?sort=desc"));
    }


    IEnumerator GetText(string url)
    {
        using (UnityWebRequest www = UnityWebRequest.Get(url))
        {
            //soracomのAPIリファレンスにあるヘッダーの情報を設定する
            //SetRequestHeaderは何個でも書ける
            www.SetRequestHeader("Accept", "application/json");
            www.SetRequestHeader("X-Soracom-API-Key", APIKEY);
            www.SetRequestHeader("X-Soracom-Token", APITOKEN);

            yield return www.SendWebRequest();

            if (www.isNetworkError || www.isHttpError)
              {
                 Debug.Log(www.error);
             }
             else
             {
            // 結果をテキストとして表示
              Debug.Log(www.downloadHandler.text);
             }

        }
     }


}

```


<br>
###UnityのHTTP通信について参考にしたサイト

- [HTTP サーバーからテキストやバイナリデータを取得 (GET)]
(https://docs.unity3d.com/ja/2018.4/Manual/UnityWebRequest-RetrievingTextBinaryData.html)

- [UnityからOANDA APIを叩いて為替レートを取得する](https://satoshin2071.github.io/unitykaraoanda-apiwokou-ku/index.html)
※ヘッダーの設定方法を参考にしました


<br><br>

###結果
Unityのコンソール画面です。
Harvestに保存されているデータを取得できました。
[![Image from Gyazo](https://i.gyazo.com/e09c2b92b5a2e2742415606beba66b45.png)](https://gyazo.com/e09c2b92b5a2e2742415606beba66b45)

ただ、これだと、バックスラッシュがついているので、このままではデータを読めません。
前述のコードのGET Text関数にJSONを加工する処理を付け加えました。
JSON形式をいったん文字列に変換し、それからバックスラッシュを削除してからJSONに変換するという方式をとってます。
もっとキレイなやり方があると思いますが、とりあえず、動いたからヨシ！


```csharp

JSONObject json = new JSONObject(www.downloadHandler.text);
JSONObject content = json[0].GetField("content"); //配列であることに注意

//いったん文字列に変換してバックッシュラッシュを削除する
string content2 = content.str; 
string str = System.Text.RegularExpressions.Regex.Unescape(content2);

//再度JSON形式に変換
JSONObject jsonObj = new JSONObject(str);

float gyroX = jsonObj.GetField("gyroX").n;
float gyroY = jsonObj.GetField("gyroY").n;
float gyroZ = jsonObj.GetField("gyroZ").n;

Debug.Log("gyroX:" + gyroX + "\t gyroY:" + gyroY + "\t gyroZ:" + gyroZ);
```
<br>
このようにHarvestに保存してある各ジャイロデータ（gyroX,gyroY,guroZ)のデータを取得できました。
[![Image from Gyazo](https://i.gyazo.com/25bfdb5b2af971532d14ee2c55f04452.png)](https://gyazo.com/25bfdb5b2af971532d14ee2c55f04452)

<br>
これを考慮したコードが以下

##コード（完成版）
```csharp:getHarvest.cs
using UnityEngine;
using System.Collections;
using UnityEngine.Networking;

public class getHarvest : MonoBehaviour
{
    private string APIKEY = "APIKEY";
    private string APITOKEN = "APITOKEN";

    void Update()
    {

      //URLはsoracomのAPIリファレンスサイトのRequestURLを記載 
      StartCoroutine(GetText("https://g.api.soracom.io/v1/subscribers/${IMSI}/data?sort=desc"));
    }


    IEnumerator GetText(string url)
    {
        using (UnityWebRequest www = UnityWebRequest.Get(url))
        {
            //さきほどsoracomのAPIリファレンスで現れたヘッダーの情報を設定する
            //ちなみにヘッダーを複数設定する場合は以下のようにSetRequestHeaderは何個でも書ける
            www.SetRequestHeader("Accept", "application/json");
            www.SetRequestHeader("X-Soracom-API-Key", APIKEY);
            www.SetRequestHeader("X-Soracom-Token", APITOKEN);

            yield return www.SendWebRequest();

            if (www.isNetworkError || www.isHttpError)
              {
                 Debug.Log(www.error);
             }
             else
             {
            // 結果を表示
              JSONObject json = new JSONObject(www.downloadHandler.text);
              JSONObject content = json[0].GetField("content"); //配列であることに注意

            //いったん文字列に変換してバックッシュラッシュを削除する
            string content2 = content.str; 
            string str = System.Text.RegularExpressions.Regex.Unescape(content2);

            //再度JSON形式に変換
            JSONObject jsonObj = new JSONObject(str);

            float gyroX = jsonObj.GetField("gyroX").n;
            float gyroY = jsonObj.GetField("gyroY").n;
            float gyroZ = jsonObj.GetField("gyroZ").n;

            Debug.Log("gyroX:" + gyroX + "\t gyroY:" + gyroY + "\t gyroZ:" + gyroZ);

             }

        }
     }


}

```