Azure IoT HubをNode.jsで始めてみる


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

公式のドキュメントにある[Node を使用してシミュレーション対象デバイスを IoT Hub に接続する](https://docs.microsoft.com/ja-jp/azure/iot-hub/iot-hub-node-node-getstarted)を参考に進めてみます。 サンプルは少し古いコードだったのでES2015ライクな書き方に直しています。

> Async/Awaitも使ったのでなるべく最新のNode.js v8系で試してください。 (筆者は v8.1.2 / macOS Sierra)

ポータル(Web管理画面)側の説明は省略します。

![](https://i.gyazo.com/2dc2dad58e42004f67c797174672f210.gif)

こんな感じで、アプリケーション間でデータの送受信

* CreateDeviceIdentity.js: デバイス ID と関連付けられているセキュリティ キーを作成し、シミュレーション対象デバイス アプリを接続します。
* ReadDeviceToCloudMessages.js: シミュレーション対象デバイス アプリから送信されたテレメトリを表示します。
* SimulatedDevice.js: 以前に作成したデバイス ID で IoT ハブに接続し、MQTT プロトコルを使用して 1 秒ごとにテレメトリ メッセージを送信します。

## 準備

* 必要なパッケージをインストール

```bash
$ npm init -y
$ npm i --save azure-iothub azure-event-hubs azure-iot-device-mqtt azure-iot-device
```

* `接続文字列`を確認する

![](https://docs.microsoft.com/ja-jp/azure/includes/media/iot-hub-get-started-create-hub/create-iot-hub5.png)

## デバイスキーを取得

`接続文字列`を適宜書き換えます。

```CreateDeviceIdentity.js
'use strict';

const iothub = require('azure-iothub');
const connectionString = '接続文字列';
const registry = iothub.Registry.fromConnectionString(connectionString);
const device = new iothub.Device(null);
device.deviceId = 'myFirstNodeDevice';

const printDeviceInfo = (err, deviceInfo, res) => {
    if (deviceInfo) {
        console.log(`Device ID: ${deviceInfo.deviceId}`);
        console.log(`Device key: ${deviceInfo.authentication.symmetricKey.primaryKey}`);
    }
}

registry.create(device, (err, deviceInfo, res) => {
    if (err) {
        registry.get(device.deviceId, printDeviceInfo);
    }
    if (deviceInfo) {
        printDeviceInfo(err, deviceInfo, res)
    }
});
```

実行すると生成されるDevice keyの値を後で利用します。

```bash
$ node CreateDeviceIdentity.js
Device ID: myFirstNodeDevice
Device key: xxxxxxxxxxxxxxxxxxxxxxxxxxxx
```

## レシーバーの登録

データの受信側を作ります。

```ReadDeviceToCloudMessages.js
'use strict';

const EventHubClient = require('azure-event-hubs').Client;
const connectionString = '接続文字列';
let client = EventHubClient.fromConnectionString(connectionString);

const printError = (err) => {console.log(err.message)};
const printMessage = (message) => {console.log(`Message received: ${JSON.stringify(message.body)}`)};

//レシーバの登録
const main = async () => {
    let partitionIds = await client.open().then(client.getPartitionIds.bind(client));
    for(let partitionId of partitionIds){
        const receiver = await client.createReceiver('$Default', partitionId, { 'startAfterTime' : Date.now()})
        console.log(`Created partition receiver: ${partitionId}`);
        receiver.on('errorReceived', printError);
        receiver.on('message', printMessage);
    }
}

main().catch(err=> {
    console.error(err);
    console.error("エラーでたっぽい");
});
```

## デバイス側を作成します。

データの送信側です。

以下の二つの値を使います。

* アプリ名: Azure IoT HubをWeb管理画面で作成する際の名称
* Device Key: 先ほど作成したもの

```SimulatedDevice.js
'use strict';

const clientFromConnectionString = require('azure-iot-device-mqtt').clientFromConnectionString;
const Message = require('azure-iot-device').Message;
const connectionString = 'HostName=<アプリ名>.azure-devices.net;DeviceId=myFirstNodeDevice;SharedAccessKey=<Device Key>';

const client = clientFromConnectionString(connectionString);

const printResultFor = (op) => {
    return (err, res) => {
        if (err) console.log(`${op} error: ${err.toString()}`);
        if (res) console.log(`${op} status: ${res.constructor.name}`);
    };
}

const connectCallback = (err) => {
    if (err) {
        console.log('Could not connect: ' + err);
        return;
    }
    console.log('Client connected');    
    // Create a message and send it to the IoT Hub every second
    setInterval(() => {
        const temperature = 20 + (Math.random() * 15);
        const humidity = 60 + (Math.random() * 20);            
        const data = JSON.stringify({
            deviceId: 'myFirstNodeDevice',
            temperature: temperature,
            humidity: humidity
        });
        const message = new Message(data);
        message.properties.add('temperatureAlert', (temperature > 30) ? 'true' : 'false');
        console.log(`Sending message: ${message.getData()}`);
        client.sendEvent(message, printResultFor('send'));
    }, 1000);
};

client.open(connectCallback);
```

## 実行

`ReadDeviceToCloudMessages.js`と`SimulatedDevice.js`を実行しましょう。

```
$ node ReadDeviceToCloudMessages.js
```

これで受信側が起動します。別窓などで送信側を実行しましょう。

```
$ node SimulatedDevice.js
```

これでデータ連携ができました。

![](https://i.gyazo.com/2dc2dad58e42004f67c797174672f210.gif)

## 所感

思ったより簡単に試せました印象。
最初のチュートリアルをまるっとやっただけなのでもっと試そ