Check! ESP-WROOM-02 から Azure Event Hubs にデータを送り、Power BI で可視化する（3） ～ データ送信編


こんばんは、 @dz_ こと大平かづみです。

Prologue - はじめに
====
[Check! ESP-WROOM-02 から Azure Event Hubs にデータを送り、Power BI で可視化する（2） ～ クラウド準備編]("Check! ESP-WROOM-02 から Azure Event Hubs にデータを送り、Power BI で可視化する（2） ～ クラウド準備編") の続きです。

いよいよ、手元の Things から Internet にのせてクラウドへ届けます！

大まかな流れ
====

1. Azure Stream Analytics のジョブを開始する
2. ESP-WROOM-02 を配線する
3. Azure Event Hubs API に必要な接続情報を取得する
4. スケッチを準備する
5. データ送信！

手順
====

Azure Stream Analytics を開始する
----
まず、イベントを受け付けられるように、 [Stream Analytics](https://azure.microsoft.com/ja-jp/services/stream-analytics/ "Stream Analytics - リアルタイム データ分析 | Microsoft Azure") のジョブを開始します。クラシックポータルの Stream Analytics の画面を開き、「開始」をクリックして下さい。「出力の開始」のタイミングの選択はそのまま続行で構いません。

![20160307_azure-iot_001.png](https://qiita-image-store.s3.amazonaws.com/0/3812/f574a34b-13da-ccbf-4604-ef416fd72635.png)

ESP-WROOM-02 を配線する
----
使いたいセンサーを ESP-WROOM-02 に接続します。私は安価な光センサー(CdS) を使いました。

なお、今回は `TOUT` を入力端子として使いましたが、アナログ入力を正確に取得したい場合は ADコンバーターで変換するとよいそうです！以下は `TOUT` から直接読み込むようになっていますので、あくまで参考程度とされてください。

![20160307_azure-iot_002.png](https://qiita-image-store.s3.amazonaws.com/0/3812/5bb63701-23de-a0cd-c681-90855090881a.png)

Azure Event Hubs API に必要な接続情報を集める
----
[Azure Event Hubs](https://azure.microsoft.com/ja-jp/services/event-hubs/ "Event Hubs - クラウド ビッグ データのソリューション | Microsoft Azure") の API を使うには、以下の情報が必要です。

| 必要な情報 | 入手方法 |
|-----------|----------|
| 名前空間名 | 作成した Service Bus のページ |
| イベントハブ名 | 作成したイベントハブのページ |
| イベントハブの共有アクセスポリシー名 | 作成したイベントハブの「構成」ページ |
| イベントハブの共有アクセスキー | 作成したイベントハブの「構成」ページ（プライマリを使用） |

![20160307_azure-iot_009.png](https://qiita-image-store.s3.amazonaws.com/0/3812/e77aebb9-1581-3bc0-c04a-c71cc56d8af2.png)

スケッチを準備する
----
スケッチは、[こちら](https://github.com/dzeyelid/esp-arduino/tree/master/samples/esp_azure_event_hub "esp-arduino/samples/esp_azure_event_hub at master · dzeyelid/esp-arduino") に私が使ったものを置きました。ちょっと雑ですが、最低限の処理ですので難しくはないかと思います。

構成
　├ config.h
　└ esp_azure_event_hub.ino

いくつかポイントをピックアップして説明します。

### SASトークンについて

SAS （Shared Access Signature: 共有アクセス署名）のトークンは、当初 ESP-WROOM-02 (Arduino) で作成する方法がわからなかったので、別途 Node.js で生成ツールを作成しました（笑） [Azure Event Hubs Tool](azure-event-hub-tool.mybluemix.net/ "Azure Event Hubs Tool") で公開していますので、適宜お使いくださいませ。なお、ソースコードも[こちら](https://github.com/dzeyelid/azure-event-hub-tool "dzeyelid/azure-event-hub-tool")で公開しています。

![20160307_azure-iot_005.png](https://qiita-image-store.s3.amazonaws.com/0/3812/6c216f57-e1b4-5612-741d-a72a49c681a9.png)

ちょっとわかりにくいかもしれませんが、以下の情報を設定して「Generate Signature」をクリックしてください。下方の「Signature token」のテキストエリアにSASトークンが出力されます。これを後述のSASトークンとして指定してください。

![20160307_azure-iot_003.png](https://qiita-image-store.s3.amazonaws.com/0/3812/07ff2b18-b127-0569-9ad2-2be10374783a.png)

SASには有効期限を設定する必要があります。上記では `60` 分で設定されています。変更したい場合は、「Token TTL min」を変更してください。

なお、こちらの記事「[Proof of Concept – NodeMCU, Arduino and Azure Event Hub](https://www.hackster.io/stepanb/proof-of-concept-nodemcu-arduino-and-azure-event-hub-a33043 "Proof of Concept – NodeMCU, Arduino and Azure Event Hub - Hackster.io")」を参考にすると、Arduino でSASトークンを作成できそうなので、いつか試したいです。

### 接続情報について
今回、接続情報は `config.h` にまとめました。

まず、WiFi に接続するための SSID とパスワードを指定します。

それから、上記で確認した Event Hubs への接続情報を指定します。イベントハブのエンドポイントは、 `名前空間名.servicebus.windows.net` となります。

SASトークンは、上記で生成したものを設定します。

```cpp:config.h
// Wifi 接続情報
const char* ssid = "YOUR-SSID";               // SSID
const char* password = "YOUR-SSID-PASSWORD";  // SSIDに対するパスワード

// Azure Event Hubs REST API 接続情報
const char* host = "YOUR-EVENTHUB-ENDPOINT.servicebus.windows.net";  // イベントハブのエンドポイント
const char* eventHubName = "YOUR-EVENTHUB-NAME";                     // イベントハブ名

// Set SAS token that can be created at https://azure-event-hub-tool.mybluemix.net/
const char* sas = "YOUR-SAS-TOKEN";                                  // SASトークン
```

![20160307_azure-iot_006.png](https://qiita-image-store.s3.amazonaws.com/0/3812/3f0b463f-aa8b-11c2-94d0-b09aaa69bfee.png)

### ESP-WROOM-02 で WiFi を使う
`ESP8266WiFi.h` を読み込んで、以下のようにWiFiのセットアップをします。`ssid`, `password` は前述のとおりです。

```cpp:esp_azure_event_hub.ino
#include <ESP8266WiFi.h>

void setup() {
  // ... <略> ...
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("");
  Serial.println("WiFi connected");
  // ... <略> ...
}
```

### HTTPS で接続
HTTPS で接続する場合は、 `WiFiClientSecure.h` を読み込んで、以下のように書きします。今回の場合の `host` は前述のエンドポイントです。

```cpp:esp_azure_event_hub.ino
#include <WiFiClientSecure.h>

// Use WiFiClientSecure class to create TLS connection
WiFiClientSecure client;

const int httpsPort = 443;

void sendData(String payload) {
  String data = String("POST ") + url + " HTTP/1.1\r\n" +
              "Host: " + String(host) + "\r\n" +
              // ... <略> ...
              "\r\n" +
              payload + "\r\n";
  client.print(data);

  while (client.connected()) {
    String line = client.readStringUntil('\n');
    if (line == "\r") {
      Serial.println("headers received");
      break;
    }
  }
  String line = client.readStringUntil('\n');
  // ... <略> ...
}

void setup() {
  // ... <略> ...
  if (!client.connect(host, httpsPort)) {
    Serial.println("connection failed");
    return;
  }
  // ... <略> ...
}

void loop() {
  // ... <略> ...
  sendData(payload);
  // ... <略> ...
}
```

### Azure Event Hubs の API をたたく

イベントハブにイベントを送信するには、以下のヘッダーに接続情報を設定して送信します。事前に、 [Postman](http://www.getpostman.com/ ”Postman | Supercharge your API workflow”) などのAPIツールで動作を試してみるとわかりやすいです。

| 設定項目 | 内容 |
|---------|------|
| Authorization | SASトークンを設定する |
| Content-Type | "application/atom+xml;type=entry;charset=utf-8" |
| Content-Length |送信するデータのバイト数 |

また、送信するデータは、JSON形式にします。

ソースコードでは以下が該当します。

``` cpp:esp_azure_event_hub.ino
void sendData(String payload) {
  // ... <略> ...
  String data = String("POST ") + url + " HTTP/1.1\r\n" +
              "Host: " + String(host) + "\r\n" +
              "Authorization: " + String(sas) + "\r\n" +
              "Content-Type: " + String(contentType) + "\r\n" + 
              "Content-Length: " + payload.length() + "\r\n" +
              "\r\n" +
              payload + "\r\n";
  client.print(data);
  // ... <略> ...
}

void loop() {
  int sensorValue = analogRead(A0);
  String payload = "{lightResistance:" + String(sensorValue) + "}";
  sendData(payload);
  // ... <略> ...
}
```

ESP-WROOM-02 における TOUT からの入力
----
ESP-WROOM-02 の `TOUT` からの入力は、`analogRead(A0)` で取得できます。

```cpp:esp_azure_event_hub.ino
void loop() {
  // ... <略> ...
  int sensorValue = analogRead(A0);
  // ... <略> ...
```

データ送信！
----

ここまで準備できたら、いよいよ ESP-WROOM-02 に書き込んで実行してみましょう！

...

‹‹\(´ω\` ๑ )/››‹‹\( 　 ๑´)/›› ‹‹\( ๑´ω\`)/››

...

しばらくして、[PowerBI](powerbi.microsoft.com/ "Microsoft PowerBI") のデータセットに指定したデータセットが作成されれば、データ送信成功です！

![20160307_azure-iot_007.png](https://qiita-image-store.s3.amazonaws.com/0/3812/305a28cb-fba8-1fbb-6214-66e6cc0b5080.png)

ヾ(o´∀`o)ﾉ

（記事が長すぎて、送信できたときの感動が… ここまで辿り着いた本人には実感できるはずです！！）

Epilogue - おわりに
====
さて、データをためられるところまで来たら、次はデータ分析！

なんですが、長くなってしまったので、PowerBI でのグラフ生成については次回に回します…！

備考
====
参考にした情報を記載します。

- [Communicating with Microsoft Azure EventHub using Arduino](https://iotguys.wordpress.com/2014/12/25/communicating-with-microsoft-azure-eventhub-using-arduino/ 'Communicating with Microsoft Azure EventHub using Arduino – Experimenting with "IoT"')
- [Sending data to Azure Event Hubs from Node.JS using the REST API](http://hypernephelist.com/2014/09/16/sending-data-to-azure-event-hubs-from-nodejs.html "Sending data to Azure Event Hubs from Node.JS using the REST API · hypernephelist")
- [光センサーでArduinoへの入力を試してみる！](http://deviceplus.jp/hobby/entry_005/ "光センサーでArduinoへの入力を試してみる！ | Device Plus - デバプラ")