ごった煮

色々な事を書いてます

Azure IoT HubにRaspberry Piを繋いでみた話

これはAzure Advent Calendarの15日目です。

IoT Hubで実際にデバイスを繋いでいろいろやってみたことを簡単にまとめます。

今回は、Raspberry Piを使う上で大多数の人が使うであろうRaspbianの環境でNode.jsを使ってみます。

さっそくやってみる

今回は、Node.jsを使用するので試しに動かしてみたりしたい人は、とりあえずNode.jsが入っていること前提です。

こちらの環境では、v4.2で動作を確認しています。

 

IoT Hubは、様々な言語のライブラリがすでに提供されていますが、Node.jsは特にマルチプラットフォームで同じコードが手ごろに動くので

結構いい感じでした。

とりあえず以下のコードが公式に提供されている一番シンプルなIoT Hubへの接続のコードです。

// Add reference to the Azure IoT Hub device library
var device = require('azure-iot-device');
// Define the connection string to connect to IoT Hub
var connectionString = '[IoT Device Connection String]';
// Create the client instance specifying the preferred protocol
var client = new device.Client(connectionString, new device.Https());
// Create a message and send it to IoT Hub.
var data = JSON.stringify({ 'deviceId': 'myFirstDevice', 'data': 'mydata' });
var message = new device.Message(data);
message.properties.add('myproperty', 'myvalue');
client.sendEvent(message, function(err, res){
    if (err) console.log('SendEvent error: ' + err.toString());
    if (res) console.log('SendEvent status: ' + res.statusCode + ' ' + res.statusMessage);
});
// Receive messages from IoT Hub
client.receive(function (err, res, msg) {
  console.log('receive data: ' + msg.getData());
  client.complete(msg, function(err, res){
    if (err) console.log('Complete error: ' + err.toString());
    if (res) console.log('Complete status: ' + res.statusCode + ' ' + res.statusMessage);
  });
});

最近のMSDNクリップボードにコードをコピーできていい感じですね

このコード、てっきりIoT HubのConnectionStringを[IoT Device Connection String]にコピペすればそのまま動くものかと思ってました。

冷静に考えてそんなことあり得ないってことに気が付くまで数時間悩みました。(IoT Hubの接続文字列にはデバイス情報が含まれていないので)

 

なにをすればいいのか

ポータルで提供されている接続文字列は、単純にIoT Hubに接続してデバイスの登録を行ったりIoT Hub自体の管理用的なものであって、それぞれのデバイスはそれぞれ固有の文字列が必要です。

ということは、デバイスが通信する用の専用文字列を作る必要があるわけです。めんどくさいです。

実際に運用するときは、デバイスの登録などは管理用エンドポイントなんかを用意してやりとりするといいかもしれません。

 

IoT Hubでデバイスtoクラウド通信をするのに必要な情報で一番重要なのは、デバイスIDです。

ということでデバイスIDをHubに登録します。

登録方法としては、ツールを使う方法が一番楽なので今回はそっちを使いましょう。

ちなみにGUIツールとコマンドラインツールが用意されています。

 

.NETのGUIツールとNode.jsのコマンドラインツールがあるので、今回は、統一のためにもNode.jsのツールを使用します。

IoT HubのSDKリポジトリここからコピーしてくると中にToolというフォルダが入っているのでその中のiothub-explorerというフォルダの中にツールが入っています。

 

npm install
node iothub-explorer.js <connectionString> create <device名> –connection-string

でデバイスをIoT Hubに登録できます。

バイスを確認する場合は、以下のようにします。

node iothub-explorer.js <connectionString> list

降ってくる情報は以下のような感じです。

ちなみに登録時に記述したdevice名がdeviceIdになるので、実際の運用では、乱数などでIDを生成してやるとデバイスが大量にあっても被らなくて済むかと思います。

 

deviceId: mydevice
generationId: 635835129602062155
etag: MA==
connectionState: Disconnected
status: enabled
statusReason: null
connectionStateUpdatedTime: 0001-01-01T00:00:00
statusUpdatedTime: 0001-01-01T00:00:00
lastActivityTime: 0001-01-01T00:00:00
cloudToDeviceMessageCount: 0
authentication:
SymmetricKey:
primaryKey: ??????????????????????
secondaryKey: ???????????????????

 

自前でプログラムを組んで自動でデバイス登録などを行いたい場合などは、iothub-explorerのソースを参考にすればいいかと思います。

 

バイスの情報を確認すると、接続用のキーなどが手に入るので、そのキーとエンドポイントのURLとデバイス名を使って文字列を作ります。

接続文字列のフォーマットは、以下のような形になります。

HostName=<IoT Hub名>;CredentialScope=Device;DeviceId=<deviceId>;SharedAccessKey=<Key>

これを先ほどのコードにセットしてやるとデータが送信できます。

ちなみに送信するデータはJSON形式でOKです。

 

これで基本的な送信ができました。

ポータルで確認してみましょう。

image

若干ラグがありますが、ここにメッセージ数と登録デバイス数が表示されます。

 

ちなみにIoT Suiteも入り口は、IoT Hubになっているので、リモート監視の場合は、IoT Suiteのダッシュボードでデバイスを登録した際に手に入るIDとキーを接続文字列にセットしてデータを送信すれば

それだけでデータを渡して可視化したりできます。(故障予測のほうはまだ触ってないのでまた今度)

 

また、Event Hubと同じような動きをするのでStream Analyticsに接続したりすることも可能です。

 

バイス管理の方法とか

IoT Hubの諸々を管理するには、Device Explorerといういい感じのツールがGitHubにあるのでそちらも紹介します。

IoT HubのSDKを落としてくるとToolフォルダ内に一緒に入っています。

このツールは、接続文字列などからREST用のSASキーを生成してくれたりデバイスの登録を行ったりデバイスとの疎通確認を簡単に行ったり

といったことをGUIでできるめっちゃ便利なツールです。

OSSでもあるので自分でアプリを組む場合もいろいろ参考になると思います。

 

最後に

IoT Hubでデータを送信していろいろやるというのは実際かなりハードルが低いので、回路なりデバイスを作る部分に集中できるのは非常にありがたいですね。

以前は無料枠が3000/日しかメッセージがウケられませんでしたが最近少し増強されて8000/日まで引き上げられたので、無料枠での十分使えるものになっているかと思います。

そのほかのプランも料金据え置きでメッセージ数の増強が行われたりしています。

おそらくプレビューまでにもう少し動きがあるのではないかと思われます。

 

また公式の仕様だと送信が4kbで受信が3kbなどの記述がありますが、なぜかこちらでそれより大きいデータを送信しようとしたら普通に送信できたのでそこらへんの細かい仕様が実際どうなのかよくわかっていないので

ぜひみんなでいっぱい使っていっぱい知見を貯めていきましょう。