Check! SORACOM Funnel を使って Azure ML まで連携する 〜 アーキテクチャ編

こんばんは、オークファンの @dz_ こと大平かづみです。

Prologue - はじめに
====
本記事は、SORAOCM さんの [Software Design 誌 巻頭特集記念リレーブログ](https://blog.soracom.jp/relay-blog/2016-04/ "Software Design 誌 巻頭特集記念リレーブログ - SORACOM Blog") の 5月13日分として投稿いたします。

今回は、[SORACOM](https://soracom.jp/ "IoT プラットフォーム 株式会社ソラコム") を使って [Microsoft Azure](https://azure.microsoft.com/ja-jp/ "Microsoft Azure: クラウド コンピューティング プラットフォームとサービス") にデータを送り、最終的に Azure Machine Learning (Azure ML) でセンサーデータを機械学習に繋げられるアーキテクチャを検討してみました！

大分ボリュームが出てしまったので、今回は、アーキテクチャのご紹介と、 SORACOM Funnel を利用して、 Azure ML が使えるようデータを蓄積する方法をご紹介いたします。

全体像
====
![20160513_azureml_003.png](https://qiita-image-store.s3.amazonaws.com/0/3812/efd91721-42f1-a7f9-4789-ef89b5bc73f0.png)

使っているもの
----
### SORACOM 関連

| 役割 | サービス・プロダクト |
|------|-----------------|
| データ通信 | [SORACOM Air](https://soracom.jp/services/air/ "SORACOM Air とは") |
| Azure への仲介 | [SORACOM Funnel](https://soracom.jp/services/funnel/ "SORACOM Funnel とは") |

### クラウド関連
| 役割 | サービス・プロダクト |
|------|-----------------|
| プラットフォーム | Microsoft Azure |
| データの受け口 | [Azure Event Hubs](https://azure.microsoft.com/ja-jp/services/event-hubs/ "Event Hubs - クラウド ビッグ データのソリューション - Microsoft Azure") |
| データの転送 | [Azure Stream Analytics](https://azure.microsoft.com/ja-jp/services/stream-analytics/ "Stream Analytics - リアルタイム データ分析 - Microsoft Azure") |
| データの蓄積 | [Azure Table Storage](https://azure.microsoft.com/ja-jp/services/storage/ "Azure Storage - セキュリティで保護されたクラウド ストレージ - Microsoft Azure") |

### デバイス関連
| 役割 | サービス・プロダクト |
|------|-----------------|
| ゲートウェイ | [Raspberry Pi 2 Model B](https://www.raspberrypi.org/products/raspberry-pi-2-model-b/ "Raspberry Pi 2 Model B") |
| センサー | [SensorTag](http://www.tij.co.jp/sensortag "Simplelink センサタグ - TI") |
| SIMアダプタ | [FS01BU](http://amzn.to/1ZLcOr0 "Amazon.co.jp： 3G USB ドングル (FS01BU): パソコン・周辺機器")

概要解説
====
まずは全体の概要をご紹介します。既知のことが多いので、さらっと書きます。

SORACOM Funnel → Auzre のつまづきポイントについては、後述の「[要SORACOMチェックポイント詳説](http://qiita.com/dz_/items/ef090cd4f0fb2cce459b#%E8%A6%81soracom%E3%83%81%E3%82%A7%E3%83%83%E3%82%AF%E3%83%9D%E3%82%A4%E3%83%B3%E3%83%88%E8%A9%B3%E8%AA%AC)」をご参照くださいませ！

SensorTag から Bluetooth 経由でデータを取得する
----
SensorTag は、10種のセンサーを持つデバイスで、Bluetooth などを介してデータを取得・書込みすることができます。

私の場合は、復習もかねて、 Python で実装を試みました。その準備編（サンプルコードへのリンク含む）は以下にまとめましたので、ご参考になれば幸いです。

- [Check! Raspbery Pi で Bluetooth 経由のセンサーデータを取得する 〜 準備編](http://qiita.com/dz_/items/4e858e4d50db19b57491 "Check! Raspbery Pi で Bluetooth 経由のセンサーデータを取得する 〜 準備編 - Qiita")

SORACOM Air の使い方
----
SORACOM Air と FS01BU の使い方はすでにたくさんの方が情報を上げてくださっています。

私はコチラの記事を参考にしました。

- [USBドングルと絡めてSORACOM Air（データ通信のみ）をRaspberry Piにつなげたメモ](http://www.1ft-seabass.jp/memo/2015/11/16/soracom-air-raspberry-pi-firststep/ "USBドングルと絡めてSORACOM Air（データ通信のみ）をRaspberry Piにつなげたメモ – 1ft-seabass.jp.MEMO")

また、余談ですが WiFi と併用して FS01BU を利用する場合は、ネットワークのルーティングを調整しなければならない場合があるようです。以下にまとめましたので、ご参考になれば幸いです。

- [Check! SORACOM Air の接続はオンラインなのに、エンドポイントに送信できない場合の対処（WiFiとの競合）](http://qiita.com/dz_/items/6c67e1815cadb15cc0b6 "Check! SORACOM Air の接続はオンラインなのに、エンドポイントに送信できない場合の対処（WiFiとの競合） - Qiita")


SORACOM Funnel から Azure Event Hubs へ
----
基本的には、下記の SORACOM 開発者サイトを参考にすれば、SORACOM Funnel を介して Event Hubs へ JSON データを送信することができます。

- [SORACOM Funnel の Event Hubs アダプターを使用してデータを送信する](https://dev.soracom.io/jp/start/funnel_eventhubs/ "SORACOM Funnel の Event Hubs アダプターを使用してデータを送信する | Getting Started | SORACOM Developers")

Azure Event Hubs から Azure Table Storage へ
----
Azure Event Hubs から Azure Table Storage へデータを転送するには、 Azure Stream Analytics を用います。

また、Azure Stream Analytics は、出力するデータを整形することができます。配列からの抽出や、データ型の変換などができます。公式ドキュメントで [一般的なクエリ例](https://azure.microsoft.com/ja-jp/documentation/articles/stream-analytics-stream-analytics-query-patterns/ "Stream Analytics の一般的使用状況パターンのクエリ例 | Microsoft Azure") が紹介されていますので、ご参考になるかと思います。

Azure Table Storage にデータを蓄積する理由
----
Azure ML で使える入力ソースはいくつかありますが、比較的安価で扱いやすいものとして Azure Table Storage を採用しました。

なお、Azure Table Storage は、 Azure Storage Explorer (Windows 向け)や Microsoft Azure Storage Explorer (Win, Mac, Linux から利用可能) などを利用して読み書きが可能です。

- [Microsoft Azure Storage Explorer」の設定方法 | nrjlog](http://zuvuyalink.net/nrjlog/archives/2668 "Microsoft Azure Storage Explorer」の設定方法 | nrjlog")

Azure ML への入力
----
Azure ML の利用の仕方は割愛しますが、入力方法についてご紹介します。

Azure ML で Azure Table Storage からデータを取得するには、 `Import Data` モジュールを利用します。

左ペインから `Import Data` モジュールをドラッグ&ドロップし、右の「Properties」で Azure Table Storage の設定を行います。

![20160513_azureml_002.png](https://qiita-image-store.s3.amazonaws.com/0/3812/4c4a65b0-2834-a389-b508-f638a34efbcb.png)

| 設定項目 | 設定値 |
|----------|-------|
| `Data source` | `Azure Table` |
| `Authentication type` | `Storage Account` |
| `Account name` | [出力先のストレージアカウント名] |
| `Account key` | [出力先のストレージアカウントのキー] |
| `Table name` | [出力先のテーブルストレージ名] |
| `Rows to scan for property names` | `ScanAll` (任意） |

要SORACOMチェックポイント詳説
====
SORACOM Funnel x Azure 連携で私がつまづいたポイントについて、もう少し詳しくご紹介します。

SORACOM Funnel を介したデータは Azure Event Hubs にどう届くのか？
----
作業していて、これが一番悩みました。なぜかというと、自分が送信したデータ構造を想定してクエリを書いても、どうも取得できないのです。

いろいろ確認してみると、どうやらSORACOM Funnel を経由する段階でいくつかの情報が付与され、自分が設定したデータは `payloads` に内包されていることがわかりました。

実際には、Event Hubs には、このようなデータが届きます。

| key | value |
|-----|-------|
| `payloads` | **自分が設定した JSON データ** を内包する |
| `credentialsId` | SORACOM 「セキュリティ」>「認証情報ストア」>「認証情報ID」 |
| `imsi` | SORACOM Air (SIM) の IMSI |
| `sourceProtocol` | 送信形式 |

ですので、Event Hubs に届いたデータを利用する際は、 `payloads` からデータを取れば良いことがわかりました。

*※ ちなみに、これは一度 Stream Analytics 経由で Power BI に出力してデータ構造を確認しました。上記のほかにも、 `destination`, `operatorId`, `PartionId`,  `timestamp` が出力されていたのですが、SORACOM のものなのか、それ以外のものなのかわからないため追って確認します。*

SORACOM Funnel からのデータを出力するには？
----
上記のように、SORACOM Funnel から受け取ったデータは `payloads` に含まれてることが分かったのですが、配列の形になっているので、そのままでは Stream Analytics から Azure Storage に出力することができません。

そこで、Stream Analytics のクエリを利用して、配列を展開してから出力することができます。

```json:送信したデータの例
{"deviceId":"Sensor1","data":{"temp":"20"}}
```

```:StreamAnalyticsのクエリ
SELECT
    e.payloads.deviceId AS deviceId,
    CAST(e.payloads.data.temp AS float) AS temp,
FROM
    eventhubs AS e
INTO
    tablestorage
```

この場合、入力を `e` として扱い、 `e.payloads.deviceId` や `e.payloads.data.temp` というようにデータを読み取ります。また `temp` は数値なので、 `CAST( AS float)` で浮動小数点型に変換しました。

Epilogue - おわりに
====
詳しい手順は、本記事では書ききれなかったので、追って公開していく予定です。

また、 Azure ML の詳説は、 Microsoft MVP for Data Platform の [@tottokug](https://twitter.com/tottokug "得上竜一(@tottokug)さん | Twitter") にご教示いただいて挑戦します！