【Azure】IoT HubとCosmos DBをStream Analyticsでつないでみた

#1.はじめに
本記事では，Microsoft Azureで提供するIoT サービスを利用してデバイスの情報をデータベースに保存する手順を備忘録として記載している。
※2019/09/01時点での情報に基づいた記事となる。

#2.アーキテクチャ
本記事では、下記図のように、IoT HubとCosmos DBをStream Analyticsでつなぐ簡単な構成となっている。
今回は、デバイスを用意していないので、プログラムで実装した温度・湿度情報を送信する仮想的なデバイスを利用してクラウドに保存する。
![IoTsolution.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/355769/d1773dfe-7ffb-c1c5-4fc9-6f0567129119.png)
【リソース選択理由】
①IoT Hub：IoT Hub はデバイスからデータを受信，デバイスの管理およびデバイスへの情報の送信ができることため，今回はIoT Hubを選択する
②Cosmos DB：色々なDBがあるが、今回はとりあえずCosmos DBをつかってみる
③Stream Analytics：二つのリソースをつなぐ機能があったので、Stream Analyticsを選択

#3.IoT Hubの作成と設定
本章では、主に[こちら](https://docs.microsoft.com/ja-jp/azure/iot-hub/quickstart-send-telemetry-python)のチュートリアルを参照しながら、IoT Hubを作成した。
※Pythonを使ったことがあるので、Pythonを選択。（他の言語も利用可）

##IoT Hub作成
Azure Portalにログインし、IoT Hubを作成した。
【IoT Hub作成①】
![IoTHub-1_fix.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/355769/ab4837f5-5f01-b3b1-0460-905b5f131500.png)
【IoT Hub作成②】
![IoTHub-2.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/355769/79203044-5e9c-f3aa-d3e9-95b69b922ed6.png)
###各種設定項目([こちら](https://docs.microsoft.com/ja-jp/azure/iot-hub/quickstart-send-telemetry-python#create-an-iot-hub)参照)
①IoT Hub のスケールティアの選択
サイズ・価格については[こちら](https://azure.microsoft.com/ja-jp/pricing/details/iot-hub/)
※1メッセージ= 4KBの情報
②ユニット数
トラフィックは、ハブ単位ではなく、ユニット単位で測定されます。レベル1または2のIoT Hubインスタンスには、最大で 200 個のユニットを関連付けることができます。レベル3のIoT Hubインスタンスは、最大で 10 個のユニットを持つことができます。[リンク](https://docs.microsoft.com/ja-jp/azure/iot-hub/iot-hub-scaling#message-throughput)
③Device to cloud パーティション
IoT Hubの中のEvent Hubパーティション数
※パーティションとは，Hubがデータを格納できるキューの数
【補足リンク】
[ソリューションに適した IoT Hub のレベルを選択する](https://docs.microsoft.com/ja-jp/azure/iot-hub/iot-hub-scaling)

##IoT Hubの設定
###デバイスの登録
デバイスとクラウドを接続するために、作成したIoT Hubの 「IoTデバイス＞新規作成」 でIoT Hubと接続するデバイスを登録する。（1デバイスずつ登録する）
【デバイス登録①】
![IoTHub-device1.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/355769/e5defa92-4d20-39f4-8a1c-f2620a3736d9.png)
【デバイス登録②】
![IoTHub-device2.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/355769/b63e31b7-9bf0-dc15-fbe0-0818961044b1.png)
※プライマリ接続文字列を後ほどデバイスをクラウドと接続するために利用する

##IoT Hubにテストデータを送信してみる
###IoT Hub が受信したデータをモニタリングするためのDevice Explorerの準備
下記のようにDevice ExplorerとIoT Hubを接続する。
1.接続文字列（主キー）を'IoT Hub Connection String'に入力
　※作成したIoT Hubの共有アクセスポリシーより取得
2.'Update'をクリック
![DeviceExplorer-1_fix.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/355769/0f0a4f92-5691-6971-0d83-730df47407e9.png)

###デバイスからIoT Hub にデータを送信
今回チュートリアルにあるサンプルコード（[こちら](https://github.com/Azure-Samples/azure-iot-samples-python/archive/master.zip)）を利用して仮想的なデバイスからIoT Hubにデータを送信してみた。
※プログラムは"azure-iot-samples-python-master\azure-iot-samples-python-master\iot-hub\Quickstarts\simulated-device\SimulatedDevice.py"を利用する。

サンプルコードの{Your IoT Hub device connection string}を作成したIoT Hubの接続文字列を貼り付ける。（IoT Hubからみてデバイスとの接続のため、デバイス登録した時に取得したプライマリー接続文字列を利用する）

```python:SimulatedDevice.py
# az iot hub device-identity show-connection-string --hub-name {YourIoTHubName} --device-id MyNodeDevice --output table
CONNECTION_STRING = "{Your IoT hub device connection string}"
```
Device ExplorerのDataタブの「Monitor」をクリックし、モニタリングを開始。
サンプルコードを実行すると、下記のように結果が出た。
【実行画面】
![IoTHub-send1_fix.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/355769/0ec0cf17-be22-274a-3184-e5868dab40a5.png)
【Device Explorer(IoT Hub側)】
![IoTHub-send2_fix.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/355769/8ce3e1c6-9c68-bb65-a3b4-e43d4720d9e2.png)
実行画面のデータとDevice Explorerで表示されているデータが一致するため、デバイスから送った情報が正しくIoT Hubに送信されていることが確認できた。

#4.Cosmos DBの作成
###Cosmos DB のリソース作成
IoT Hub で受信したデータを保存するためのデータベースを作成する。
![CosmosDB-1_fix.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/355769/7f230b88-5f3a-05fb-25ed-854b19036399.png)
※マルチリージョン書き込み：他リージョンへレプリケーションを行った際に他リージョンからも書き込みが可能なようにする設定。無効にすると，上記例では東日本リージョンのリソースからしか書き込みできない。

価格について：[こちら](https://azure.microsoft.com/ja-jp/pricing/details/cosmos-db/)

###Cosmos DB のデータベースとコンテナ作成
受け取ったデータを保存するためのコンテナを作成する
Partition key の設定は，送信されるデータの一番最初のキーを設定し、今回は"temperature"とする
ここが送信されるデータの先頭のキーと一致しない場合はエラーが発生する
【Cosmos DBコンテナ作成画面】
![CosmosDB-2.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/355769/6d6a23a1-ef04-0a2d-f2c4-4571b25ff7eb.png)
【作成後のデータエクスプローラーの画面】
![CosmosDB-3.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/355769/c11ccd98-18fb-be80-bad8-50b9a4ca9f14.png)


#5.Azure Stream Analyticsの作成と設定
ここでは、IoT Hubで受け取ったデータをCosmos DBに保存するためのリソース、Stream Analyticsを作成・設定する
##Stream Analyticsの作成
Azure Portalより、Stream Analyticsを作成する。
【Stream Analytics作成画面】
![stream-1_fix.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/355769/915f9a35-2364-955b-65dc-65f45e4bbb85.png)
ストリーミングユニットごとに課金が1時間単位で発生するので注意（後から変更可）
課金は[こちら](https://azure.microsoft.com/ja-jp/pricing/details/stream-analytics/)を確認

##Stream Analyticsの設定
Stream Analyticsへの入力と出力のリソースと入出力間で適用するクエリをそれぞれ設定する。
###入力
入力＞ストリーム追加＞IoT Hubより設定
![stream-2_fix.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/355769/3b5eb0d9-dd54-8bdd-863d-bba8b5e9b52b.png)
※コンシューマグループとは，IoT Hubでのデータの出口のグループのことを指す
###出力
出力＞ストリーム追加より設定
![stream-3_fix.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/355769/4015efab-47ed-527d-614c-eb8bc4a59c31.png)
※コンテナ名パターンはデータを保存するCosmos DBのコンテナ名を指す
###クエリの設定
今回は、デフォルトのクエリのまま、受信した情報をそのまま出力するようにクエリを記載。下記のように入力と出力の名前を書き換える。
【クエリ設定画面】
![stream-4.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/355769/81b70c71-0f08-b8c1-3a1e-c6df92f14028.png)

全ての設定が終了したら、開始ボタンを押す
【注意】Stream Analyticsは入力と出力の設定が終わった後に開始をしないと，エラーが発生します。開始後に入力・出力リソースの設定変更を実施すると、エラーが発生します。

#6.デバイスからデータを送信し、Cosmos DBに保存されていることを確認
IoT Hubにデータを送信した時と同じプログラム(SimulatedDevice.py)を実行して、IoT HubおよびCosmos DBでデータが受信しているかを確認した。
【実行画面】
![solutiontest-1_fix.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/355769/0ee34891-2f49-342f-534f-1820112a1774.png)
【Device Explorer(IoT Hub側)】
![solutiontest-3_fix.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/355769/4d18b218-1b1a-e799-87e0-104455a654a2.png)
【Cosmos DB】
![solutiontest-2.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/355769/dcf72b1d-3175-4cca-2a27-dc9107501078.png)

上記の3つの結果より、temperatureの値が全ての結果で一致しているため、Cosmos DBにデータが保存されてことを確認できる。

#参考情報
https://docs.microsoft.com/ja-jp/azure/iot-hub/quickstart-send-telemetry-python