Node.jsでAzure IoT Hubにテレメトリを送信するサンプルコードを動かすメモ

## はじめに

[デバイスから IoT ハブに利用統計情報を送信してバックエンド アプリケーションで読み取る](https://docs.microsoft.com/ja-jp/azure/iot-hub/quickstart-send-telemetry-node)を参考にサンプルコードを動かしてみます。
[![Image from Gyazo](https://i.gyazo.com/2423a85698f478493dd983f957020b80.gif)](https://gyazo.com/2423a85698f478493dd983f957020b80)
接続文字列は Azure CLI を使わずに、コンソールから取得します。

Azure IoT については[こちら](https://docs.microsoft.com/ja-jp/azure/iot-hub/about-iot-hub)を参照。

## 準備

- Node.js をインストールする（今回は`v14.1.0`を使用）
- [サンプルコード](https://github.com/Azure-Samples/azure-iot-samples-node/releases/tag/234607)をダウンロードする
- [手順](https://docs.microsoft.com/ja-jp/azure/iot-hub/quickstart-send-telemetry-node#create-an-iot-hub)を参考に、Iot Hub をデプロイする（スケールは`S1`を選択）。

## IoTデバイスを登録する

`Azure IoT Hubコンソール > サイドバー > IoTデバイス > 新規`からデバイスを追加する。

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

追加できたら、追加したデバイスを選択して`プライマリ接続文字列`をコピーしておく。

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

## データを送信する

ダウンロードしたサンプルコードから、`SimulatedDevice.js`を開き、17 行目あたりの`connectionString`に先程コピーした`プライマリ接続文字列`を貼り付ける。

コードはこんな感じになる。

```javascript
var connectionString = '{Your device connection string here}'; // ←ここに`プライマリ接続文字列`を貼り付ける。

var Mqtt = require('azure-iot-device-mqtt').Mqtt;
var DeviceClient = require('azure-iot-device').Client
var Message = require('azure-iot-device').Message;

var client = DeviceClient.fromConnectionString(connectionString, Mqtt);

setInterval(function(){
  // 送信するデータを生成する。（本当はセンサーで測定した値を入れるがシミュレーションのため乱数を使用）
  var temperature = 20 + (Math.random() * 15);
  var message = new Message(JSON.stringify({
    temperature: temperature,
    humidity: 60 + (Math.random() * 20)
  }));

  message.properties.add('temperatureAlert', (temperature > 30) ? 'true' : 'false');

  console.log('Sending message: ' + message.getData());

  // イベントを送信する
  client.sendEvent(message, function (err) {
    if (err) {
      console.error('send error: ' + err.toString());
    } else {
      console.log('message sent');
    }
  });
}, 1000);
```

以下のコマンドをターミナルで実行する。

```
$ node SimulatedDevice.js
```

データが送信されている。

[![Image from Gyazo](https://i.gyazo.com/704649ca914c6fb0fae082906579d5d8.gif)](https://gyazo.com/704649ca914c6fb0fae082906579d5d8)

## 送信したデータを受信する

ダウンロードしたサンプルコードから、`ReadDeviceToCloudMessages.js`を開き、38 行目あたりの`connectionString`に`Azure IoT Hubコンソール > サイドバー > 組み込みのエンドポイント > イベントハブ五感エンドポイント`の値を貼り付ける。
(26 行目あたりに`eventHubsCompatibleEndpoint`などの変数が用意されていますが、無視します。)

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

コードはこんな感じになる。

```javascript:ReadDeviceToCloudMessages.js
const connectionString = 'Endpoint=**********************;SharedAccessKeyName=*****************;EntityPath=********************';

var printError = function (err) {
  console.log(err.message);
};

var printMessages = function (messages) {
  for (const message of messages) {
    console.log("Telemetry received: ");
    console.log(JSON.stringify(message.body));
    console.log("Properties (set by device): ");
    console.log(JSON.stringify(message.properties));
    console.log("System properties (set by IoT Hub): ");
    console.log(JSON.stringify(message.systemProperties));
    console.log("");
  }
};

async function main() {
  console.log("IoT Hub Quickstarts - Read device to cloud messages.");

  const clientOptions = {
    // webSocketOptions: {
    //   webSocket: WebSocket,
    //   webSocketConstructorOptions: {}
    // }
  };

  const consumerClient = new EventHubConsumerClient("$Default", connectionString, clientOptions);

  // イベントハブのストリームからデータを取得する
  consumerClient.subscribe({
    processEvents: printMessages,
    processError: printError,
  });
}

main().catch((error) => {
  console.error("Error running sample:", error);
});
```

これを実行します。

```bash
$ node ReadDeviceToCloudMessages.js
```

実行すると以下のように表示され、受信待ち状態になります。

```
IoT Hub Quickstarts - Read device to cloud messages.
```

この状態で、`SimulatedDevice.js`を実行すると、以下のように受信できます。
[![Image from Gyazo](https://i.gyazo.com/2423a85698f478493dd983f957020b80.gif)](https://gyazo.com/2423a85698f478493dd983f957020b80)

## まとめ

公式の[デバイスから IoT ハブに利用統計情報を送信してバックエンド アプリケーションで読み取る](https://docs.microsoft.com/ja-jp/azure/iot-hub/quickstart-send-telemetry-node)を動かしました。
また、Azure CLI を使わずにコンソールから接続文字列を取得しました。

Azure IoT Hub の`S1`スケールは**月に2~3000円ほどかかる**ので、試し終わったら忘れずに止めておきましょう。

次回は、M5 系のデバイスからデータを送信してみます。