Azure IoT Centralに接続するデバイスコード

## はじめに
- 現状、以下のエラーが発生しており正しく動作していません（2019.1.31現在）。
- 作業途中までの備忘として記載しています。

```
TypeError: transportCtor is not a constructor
    at Function.Client.fromConnectionString (/path/to/dir/node_modules/azure-iot-device/lib/device_client.js:194:27)
    at Object.<anonymous> (/path/to/dir/index.js:6:21)
    at Module._compile (module.js:621:14)
```
## 接続文字列の生成

```bash
npm i -g dps-keygen
dps-keygen <device key> <device id> <scope_id>
```

device key, device id, scope_idは、IoT Central側でデバイスを作成して確認する。
参考：[GitHub \- Azure/dps\-keygen: Helper tool to deal with the device keys](https://github.com/Azure/dps-keygen)

## デバイス側のコード
- npm パッケージのインストール

```bash
npm init
npm install azure-iot-device azure-iot-device-mqtt --save
```

- 以下のコードの{your connection string here}の部分を生成された接続文字列で置き換え

```javascript:index.js
const Client = require('azure-iot-device').Client;
const Message = require('azure-iot-device').Message;

var connectionString = '{your connection string here}';
var targetTemperature = 0;
var client = Client.fromConnectionString(connectionString);

// Send device telemetry.
function sendTelemetry() {
  var temperature = targetTemperature + (Math.random() * 15);
  
  var data = JSON.stringify({ temperature: temperature });
  var message = new Message(data);
  client.sendEvent(message, (err, res) => console.log(`Sent message: ${message.getData()}` +
    (err ? `; error: ${err.toString()}` : '') +
    (res ? `; status: ${res.constructor.name}` : '')));
}

// Send device properties
function sendDeviceProperties(twin) {
  var properties = {
    firmwareVersion: "9.75",
    serialNumber: "10001"
  };
  twin.properties.reported.update(properties, (errorMessage) => 
    console.log(` * Sent device properties ` + (errorMessage ? `Error: ${errorMessage.toString()}` : `(success)`)));
}

// Add any settings your device supports
// mapped to a function that is called when the setting is changed.
var settings = {
  'setTemperature': (newValue, callback) => {
    // Simulate the temperature setting taking two steps.
    setTimeout(() => {
      targetTemperature = targetTemperature + (newValue - targetTemperature) / 2;
      callback(targetTemperature, 'pending');
      setTimeout(() => {
        targetTemperature = newValue;
        callback(targetTemperature, 'completed');
      }, 5000);
    }, 5000);
  }
};

// Handle settings changes that come from Azure IoT Central via the device twin.
function handleSettings(twin) {
  twin.on('properties.desired', function (desiredChange) {
    for (let setting in desiredChange) {
      if (settings[setting]) {
        console.log(`Received setting: ${setting}: ${desiredChange[setting].value}`);
        settings[setting](desiredChange[setting].value, (newValue, status, message) => {
          var patch = {
            [setting]: {
              value: newValue,
              status: status,
              desiredVersion: desiredChange.$version,
              message: message
            }
          }
          twin.properties.reported.update(patch, (err) => console.log(`Sent setting update for ${setting}; ` +
            (err ? `error: ${err.toString()}` : `status: success`)));
        });
      }
    }
  });
}

// Respond to the echo command
function onCommandEcho(request, response) {
  // Display console info
  console.log(' * Echo command received');
  // Respond
  response.send(10, 'Success', function (errorMessage) {});
}

// Handle device connection to Azure IoT Central.
var connectCallback = (err) => {
  if (err) {
    console.log(`Device could not connect to Azure IoT Central: ${err.toString()}`);
  } else {
    console.log('Device successfully connected to Azure IoT Central');
    // Send telemetry measurements to Azure IoT Central every 1 second.
    setInterval(sendTelemetry, 1000);
    // Setup device command callbacks
    client.onDeviceMethod('echo', onCommandEcho);
    // Get device twin from Azure IoT Central.
    client.getTwin((err, twin) => {
      if (err) {
        console.log(`Error getting device twin: ${err.toString()}`);
      } else {
        // Send device properties once on device start up
        sendDeviceProperties(twin);
        // Apply device settings and handle changes to device settings.
        handleSettings(twin);
      }
    });
  }
};

client.open(connectCallback);
```

## 参考
- [Azure IoT Central アプリケーションに実デバイスを追加する \| Microsoft Docs](https://docs.microsoft.com/ja-jp/azure/iot-central/tutorial-add-device)