PocketDuinoに接続したセンサーデータをAWS Mobile SDKでAmazon Mobile Analyticsにデータを入れてみた


## はじめに
センサーの情報をクラウドに送信するのにスマホやタブレットは最適。このスマホとタブレットと接続して利用できるAruduino Pro mini互換のモジュールがPocketDuinoです。
[Indiegogo]("https://www.indiegogo.com/projects/pocketduino-innovation-from-your-pocket")でキャンペーンをだされていたので、ファンドしました！
Aruduinoの拡張性、開発容易性を持ちつつ、Androidの開発容易性も持っているので、大変強力です。
スペックは、以下のとおりです。

| 項目 | 内容 |
|:-----------|:------------|
|Microcontroller|ATmega328|
|Digital I/O Pins|14|
|Analog Input Pins|8|
|Flash Memory|16 KB|
|SRAM|1 KB|
|EEPROM|512 bytes|
![PIN配置](http://www.physicaloid.com/wiki/lib/exe/fetch.php?w=500&tok=a9e1bf&media=hardware:pocketduino:pocketduinopin.png "PIN配置")

詳細は[こちら]("http://www.physicaloid.com/product/pocketduino/")をご覧ください。

## PocketDuinoを動かしてみる
PocketDuinoでは、Tutorialプロジェクトが提供されているので、まずは、[この]("http://www.physicaloid.com/wiki/doku.php?id=hardware:pocketduino:tutorial")手順にそって動作確認してみました。もちろん、半田付けの作業もしました。

![pic.JPG](https://qiita-image-store.s3.amazonaws.com/0/60724/53dbf0bd-b8c0-fd71-1fe1-162c69927798.jpeg "pic.JPG")


手順がかなり詳しく書かれているので特にひっかるところはなかったのですが、今回の作業に合わせてAndroidの開発環境をEclipseからAndroid Studioにしたので、Android Studioの環境整備の方に手間取りました。
PocketDuinoとの通信を、Android用のUSBシリアル通信ドライバであるPhysicaloid Libraryを利用するので、適切にライブラリをインポートする必要があります。

この時のNexus7の画面キャプチャを採るのを忘れてしまったのですが、先のサイトにある以下の画面の通り動作することが確認できました。

![画面](http://www.physicaloid.com/wiki/lib/exe/fetch.php?w=300&tok=de48d2&media=hardware:pocketduino:start_read.png "画面")
(*) PocketDuinoチュートリアルより

## 温度センサを付けてみる
[以前の投稿]("http://qiita.com/ToshiakiEnami/items/c3b5b87a148a2fcf5ee4")で使用した温度センサをそのままつなげてみます。ソフトウェアは若干修正してみました。

![pic1.JPG](https://qiita-image-store.s3.amazonaws.com/0/60724/78cbccf5-e5ea-9130-9517-01d0af11e4eb.jpeg "pic1.JPG")



```C:Pocketduino.c

#include <OneWire.h>
#include <LiquidCrystal.h>

OneWire  ds(9);  // on pin 9

void setup(void) {
  Serial.begin(9600);
}

void loop(void) {
  byte i;
  byte present = 0;
  byte type_s;
  byte data[12];
  byte addr[8];
  float celsius;

  if ( !ds.search(addr)) {
    ds.reset_search();
    delay(1000);
    return;
  }

  if (OneWire::crc8(addr, 7) != addr[7]) {
      return;
  }
  switch (addr[0]) {
    case 0x10:
      type_s = 1;
      break;
    case 0x28:
      type_s = 0;
      break;
    case 0x22:
      type_s = 0;
      break;
    default:
      return;
  }

  ds.reset();
  ds.select(addr);
  ds.write(0x44,1);
  delay(1000);
  present = ds.reset();
  ds.select(addr);   
  ds.write(0xBE);
  for ( i = 0; i < 9; i++) {
    data[i] = ds.read();
  }
 unsigned int raw = (data[1] << 8) | data[0];
  if (type_s) {
    raw = raw << 3;
    if (data[7] == 0x10) {
      raw = (raw & 0xFFF0) + 12 - data[6];
    }
  } else {
    byte cfg = (data[4] & 0x60);
    if (cfg == 0x00) raw = raw << 3;
    else if (cfg == 0x20) raw = raw << 2;
    else if (cfg == 0x40) raw = raw << 1;
  }
  celsius = (float)raw / 16.0;
  Serial.print("s");
  Serial.print(celsius);
  Serial.print("\r");
}

```

## 温度情報をAmazon Mobile Analyticsに登録
ちょうど、Amazon Mobile AnalyticsにS3にExportする機能がリリースされたこともあり、温度情報をMobile AnalyticsのCustom Eventとして登録することにしました。
Amazon Mobile Analyticsは、モバイルアプリの使用状況を収集して可視化してくれるサービスで、DAUやMAUといった基本的なアプリの利用分析だけでなく独自イベント（ボタンのクリック数など）を収集して分析もできます。
今回は、この独自イベント（カスタムイベントと呼びます）を使います。
Amazon Mobile Analyticsについては[こちら]("http://aws.amazon.com/jp/mobileanalytics/")をご覧ください。
AndroidのProjectは以下の様な感じです。
ベースはPocketDuinoのTutorialプロジェクトを使いましたので、差分について記述いたします。
![AndroidStadio2.png](https://qiita-image-store.s3.amazonaws.com/0/60724/8ec250bb-30fd-a5d5-927e-eeb7e78101db.png "AndroidStadio2.png")

# 追加したライブラリ
チュートリアルで追加したライブラリ（d2xx.jar, physicaloidlibrary.jar)以外にMobile Analyticsにデータを送信するために、core、cognitoとMobileAnalyticsのライブラリを追加しました。
Mobile Analyticsに利用するにもAWSの認証が必要になります。その認証をCognitoを使っております。

# サンプルソース

```Java:AmazonClientManager.java

public class AmazonClientManager {
    private static CognitoCachingCredentialsProvider provider = null;
    private static MobileAnalyticsManager analytics = null;

    public static final String AWS_ACCOUNT_ID = "";
    public static final String COGNITO_POOL_ID = "";
    public static final String COGNITO_ROLE_AUTH = "";
    public static final String COGNTIO_ROLE_UNAUTH = "";
    private static final String TAG = "AmazonClientManager";
    private static Context context;

    public AmazonClientManager(Context context) {
        this.context = context;
    }

    public static void init()
    {
        provider = new CognitoCachingCredentialsProvider(context,
                AWS_ACCOUNT_ID, COGNITO_POOL_ID, COGNTIO_ROLE_UNAUTH,
                COGNITO_ROLE_AUTH, Regions.US_EAST_1);
        try {
            AnalyticsConfig options = new AnalyticsConfig();
            options.withAllowsWANDelivery(true);
            options.withAllowsEventCollection(true);
            analytics = MobileAnalyticsManager.getOrCreateInstance(context, "", Regions.US_EAST_1, provider,options);
        } catch(InitializationException ex) {
            Log.e(TAG, "Failed to initialize Amazon Mobile Analytics", ex);
        }
    }
    public static MobileAnalyticsManager getAnalytics() {
        if (analytics == null) {
            init();
        }
        return analytics;
    }
}

```

```Java:AnalyticsManager.java

public class AnalyticsManager {
    private static final String TAG = "MobileAnalyticsManager";

    public static void send(String text) {

        Log.i(TAG,"MobileAnalytics API called");
        try{
            MobileAnalyticsManager analytics = MainActivity.clientManager.getAnalytics();

            Date date = new Date();
            SimpleDateFormat f = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");

            AnalyticsEvent requestEvent = analytics.getEventClient().createEvent("temp")
                    .withAttribute("time", f.format(date))
                    .withAttribute("temp", text);
            analytics.getEventClient().recordEvent(requestEvent);
            analytics.getEventClient().submitEvents();

        } catch (Exception e){
            Log.e(TAG, "Exception: "+Log.getStackTraceString(e));
        }
    }
}


```

MainActivityでは、画面に温度を表示するタイミングでMobileAnalyticsにデータを送信するようにしました。
頻度が高いとAndroidデバイスに負荷がかかるのであまりいいコードではないと思います。

```Java:MainActivity.java
/* 割愛 */

mPhysicaloid.addReadListener(new ReadLisener() {

                    @Override
                    public void onRead(int size) { 
                        byte[] buf = new byte[size];
                        mPhysicaloid.read(buf, size);
                        try {
                            mReadStr = new String(buf, "UTF-8");
                        } catch (UnsupportedEncodingException e) {
                            return;
                        }

                        Integer num = decodePacket(buf);
                        mReadStr = String.valueOf(num);
                        mHandler.post(new Runnable() { 
                            @Override
                            public void run() {
                                mTvRead.setText(mReadStr);
                                new MobileAnalyticsManagerTask().execute(mReadStr);
                            }
                        });
                    }
                });

/* 割愛 */
    private class MobileAnalyticsManagerTask extends
            AsyncTask<String,Void,Void> {

        @Override
        protected Void doInBackground(String... params) {
            // TODO Auto-generated method stub
            try{
                AnalyticsManager.send(params[0]);

            } catch (Exception e){
                Log.e(TAG, "Exception: " + Log.getStackTraceString(e));
            }

            return null;
        }
    }

```

アプリを起動するとセンサーからデータを取得し、Mobile Analyticsのカスタムイベントに送信されます。
コンソール上では、以下のように見えます。

![Screen3.png](https://qiita-image-store.s3.amazonaws.com/0/60724/7a6ab868-75ce-bb78-3399-7ffe198eda60.png "Screen3.png")

![Screen4.png](https://qiita-image-store.s3.amazonaws.com/0/60724/9bc801ed-d901-ad6c-cc76-da3213731286.png "Screen4.png")



Mobile AnalyticsのS3へのエクスポート機能はマネジメントコンソールからAuto Exportウィザードを使って設定します。

![Screen1.png](https://qiita-image-store.s3.amazonaws.com/0/60724/5929361f-0abf-c9ff-0a93-7434a2c36a40.png "Screen1.png")

S3のバケットとIAMを指定すると自動的にエクスポートされてます。

![Screen2.png](https://qiita-image-store.s3.amazonaws.com/0/60724/33a392f4-408b-71d7-2a2d-1f8d5d86aeb7.png "Screen2.png")


## まとめ
Aruduinoの拡張性と様々なものが作れるAndroidの組み合わせはかなり強力だと思います。
AWS Mobile SDKも充実しているので、デバイスとAWSマネージドサービスを使った2Tierアーキテクチャも容易に構築できます。PocketDuinoは、Androidデバイスに直挿しをして電源いらずで利用できる手軽さはスバラシイです。



## 免責
こちらは個人の意見で、所属する企業や団体は関係ありません。