はじめに
これは、最近AzureのIoT Hubを触ってなかったので、触ってみる個人的な備忘録です。
何回かに分けてツラツラ触ってみたいと思います。
忙しくなったら途中で終わるかもです。
前回まではデバイス側の基本的な実装をおこなったので、今回はサービス側(クラウド側)をやります。
初回はこちら:メッセージングとデバイスツイン
2回はこちら:メッセージルーティング
3回はこちら:ファイルアップロード
サービス側で実施できる主なこと
IoT Hubのサービス側では、主に以下ができます
- メッセージのやりとり
- プロパティのやりとり(デバイスツイン)
- ダイレクトメソッド
- デバイスの管理
他にも、フェールオーバーやモニタリングなどもありますが、言い出すとネットワークとかセキュリティとかキリがないですが、AzureのPaaSでできそうなことはフンワリできます。
Device Updateなるものも出てきていますので、機会があればやってみようと思います。
今回はメッセージのやりとりを対象とします。
メッセージのやりとりでサービス側からできること
メッセージのやりとりでIoT Hubが主導的に実施するのは主に以下の2つです
c2dメッセージをゼロベースから作成
c2dメッセージをゼロベースから作成します。
今回もC#、.NETは6.0.202、VSCodeで作成します。
とりあえずこちらに沿ってハローワールドだけ作成。
チュートリアル: Visual Studio Code を使用して .NET コンソール アプリケーションを作成する
フォルダ名は "service1" としました。
サービスクライアントを利用するため、Program.csの1行目に以下を追加します。
using Microsoft.Azure.Devices;
また、ターミナル(Ctrl+@)よりパッケージを追加します。
dotnet add package Microsoft.Azure.Devices.
あとはこちらを参考にサンプルを作成します。
デバイスに IoT Hub でクラウドからメッセージを送信する (.NET)
参考ドキュメントには配信後の動作状況の確認なども含まれていますが、全部省略しています。
起動したら固定文字列を送ってプログラムは終了します。
こちらで以前作成したdevice1を動かすと、メッセージを受信できます。
完成したコードはこちらを参照ください。
このままでは使い物にはなりませんが、理解するに必要最小限にはなっているかと思います。
https://github.com/matakaha/iotsample2022/blob/main/service1/Program.cs
余談ですが、ここで利用する接続文字列は、今までデバイスで利用していたものとは別ですのでご注意くださいませ。
IoT Hub→共有アクセスポリシー→service→接続文字列をご利用ください。
もう1つ余談ですが、今回は配信後の動作状況を省略しました。
ここも実施する場合は、参考ドキュメント通りにサービス側を作成します。
そのうえで、デバイス側を改修してみてください。
改修ポイントは2点
- 通信プロトコルをMQTTからAMQPに変更する(TransportType.MqttをTransportType.Amqp)
- メッセージ受信完了通知で受信拒否する(CompleteAsyncをRejectAsyncやAbandonAsync)
これで拒否したステータスがサービス側で取得できます。また、ここらへんがMQTTとAMQPの動作上の差異となってきます。
メッセージエンリッチメント
メッセージエンリッチメントは設定するだけで動作します。
IoT Hubで受信したメッセージに情報を追加することができます。
作業そのものはチュートリアルとおり実施しました。
チュートリアル: Azure IoT Hub のメッセージ エンリッチメントを使用する
チュートリアルの概要
事前準備
- IoT Hubの作成(ContosoTestHubMsgEn~~)
- Blob Storageの作成(contosostorage~~)
- Blobのコンテナを2つ作成(originalコンテナとenrichedコンテナ)
- デバイスIDの作成(Contoso-Test-Device)
- メッセージルーティングで利用するルーティングエンドポイントを2つ作成(ContosoStorageEndpointOriginalとContosoStorageEndpointEnriched)
- ルート(ルーティングの条件はlevel="storage")を2つ作成(ContosoStorageRouteOriginalとContosoStorageRouteEnriched)
- ContosoStorageEndpointEnrichedルートにはエンリッチメントを3つ設定(myIotHub:\$iothubname, DeviceLocation:$twin.tags.location, customerID:6ce345b8-1e4a-411e-9398-d34587459a3a)
動作
- デバイスからd2cメッセージが送信される。メッセージにはプロパティ"level"が付与されており、ランダムに"storage"という値が入る(ルーティング条件:level="storage"に合致する)
- メッセージルーティングでContosoStorageRouteOriginalとContosoStorageRouteEnrichedで条件を確認、ルーティング条件:level="storage"と合致するメッセージであった場合は、各々のエンドポイントへメッセージをルーティングする
- ContosoStorageRouteEnrichedにルーティングされたメッセージはメッセージエンリッチメントが適用される
- ContosoStorageEndpointOriginalへ向かったメッセージはBlobのoriginalコンテナのjsonに書き込まれる
- ContosoStorageEndpointEnrichedへ向かったエンリッチメントが適用されたメッセージはBlobのenrichedコンテナのjsonに書き込まれる
そもそも何ができるのか
チュートリアルを確認するとわかりますが、メッセージなどに情報を追加して後続の処理に投げ込むことができます。
例えば、デバイスツインのReported propertiesでバッテリー残量を投げているデバイスがあるとします。メッセージとともに、このバッテリー残量もチェックしたい場合、通常であればメッセージ処理時にデバイスIDを取得し、デバイスIDを使ってIoT HubにあるReported propertiesのバッテリー残量を問い合わせるAPIを1回投げなければなりません。もしくはデバイスがメッセージにもバッテリー残量を付与して送信しなければなりません。
メッセージエンリッチメントを使ってメッセージにバッテリー残量を付与すれば、デバイスの負荷を増やすことなく、またAPI1回投げ込む手間をかけることなく、バッテリー残量を取得することができます。
さいごに
今回はサービス側のメッセージあれこれを実施してみました。
個人的な学びとしては、メッセージルーティングで同じ条件で2つのルートを作成すると両方にメッセージがコピーされるんだということを学びました。
言われてみればそうなるとわかるけど、そんなこと考えてもみませんでしたので、学びになりました。
これを使うべきか、コンシューマーグループを使うのか、また似て非なる機能があるのだと発見です。
久しぶりにIoT Hubしてみました。
ひととおりやってみて、以前よりドキュメントが充実してきたなぁという印象です。
次回はx.509のデバイス認証か、IoT Edgeでもやろうかと思います。