Azure IoT Hubを久しぶりに触ってみたので個人的な備忘録 2（メッセージルーティング）

# はじめに
これは、最近AzureのIoT Hubを触ってなかったので、触ってみる個人的な備忘録です。
何回かに分けてツラツラ触ってみたいと思います。
忙しくなったら途中で終わるかもです。

今回は前回の続きです。
[前回はこちら](https://qiita.com/mstakaha1113/items/ff5e86ce969caceccb8d)
デバイス側をメインにやってます。

# メッセージにプロパティを付与する
前回、デバイスツインをやりました。これはデバイスそのもののプロパティのやりとりでした。
デバイスそのもののプロパティをやりとりすることで、結果的にクラウド上にデバイスの複製を作る（デバイスツイン）という機能でした。
ここでは、メッセージそのものに属性を付与します。
デバイスからメッセージを送信する際、そもそもメッセージの内容や処理方法、仕向けが異なる場合があります。
たとえば普段はセンサーの温度や湿度を送信するためにメッセージを利用しているとします。
でも時々、デバッグ用のメッセージなど普段利用しない、また顧客向けサービス上は不要な情報を送信したい場合があります。
このようなときは、メッセージそのものに"デバッグ用"みたいな属性を付与します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/439826/4ae1a524-350c-ef3c-ba7d-5a10c4111f73.png)
前回d2cメッセージ作成の際に参考にした
https://github.com/Azure-Samples/azure-iot-samples-csharp/blob/main/iot-hub/Quickstarts/SimulatedDevice/Program.cs
こちらにも実は記載がありました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/439826/3507fcdf-5676-5010-6dcc-f350ed60a583.png)
こちらです。
30℃よりも高くなったら温度アラートをTrueにするといったサンプルだと思います。
これをヒントに作成します。

## ゼロベースから作成
今回もC#で作ってみます。
.NETは6.0.202が入った環境です。VSCodeで作成します。

もう１度ゼロベースから作成します。
とはいえ、面倒なので今回もdevice1をコピペしてdevice3として作成していきます。
先ほど同様にdevice3フォルダを作成して

> dotnet new console --framework net6.0

して、中にdevice1で作成したコードをコピペしました。

> dotnet add package Microsoft.Azure.Devices.Client

もお忘れなく。
ここで扱うサンプルではカウントしか送付していませんので、カウントが3の倍数になったときはメッセージ種別を"保守(maintenance)"として送ります。
コードはこちら、最小限に絞ってます。今回は1行追加しただけです。
https://github.com/matakaha/iotsample2022/blob/main/device3/Program.cs

## プロパティによってメッセージを振り分ける
IoT Hubには、"メッセージルーティング"という機能があります。
詳細は本家のドキュメントを参照ください。
本家：[IoT Hub メッセージ ルーティングを使用して device-to-cloud メッセージを別のエンドポイントに送信する](https://docs.microsoft.com/ja-jp/azure/iot-hub/iot-hub-devguide-messages-d2c)
とりあえず覚えておくべき情報を記載します。
メッセージルーティングは、IoT Hubが取得したメッセージやデバイスツインイベントを、他のAzureサービスにルーティングする機能です。
例えば取得したメッセージを全部Blob Storageに保管したり、条件に応じてEvent Hubsに流し込んだりします。
どの条件にも合致しなかった情報は、フォールバックルートというところに流れてきます。
今までAzureCLIで見ていたテレメトリーメッセージは、ここに飛んできた情報です。
（なぜならメッセージルーティングを使用していなかったから、情報収集の最後の砦となるフォールバックルートに飛んでいたから。）
ここでは、これをします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/439826/382075c0-5f6f-7bfb-ba4d-f545303d6eed.png)
- デバイスからc2dメッセージが送信される
- メッセージプロパティで"messageType : maintenance"が付与されているデータをBlob Storageへ送る
- その他メッセージはCLIセッションでモニターする

## 該当データをBlobに保存する(事前準備)
こちらの情報を見ながら設定します。
[チュートリアル:Azure CLI と Azure portal を使用して IoT Hub のメッセージ ルーティングを構成する - ストレージ アカウントへのルーティング](https://docs.microsoft.com/ja-jp/azure/iot-hub/tutorial-routing#route-to-a-storage-account)
まずはルーティング先のBlob Storageおよび中にコンテナ(実際のデータが入る箱)を作成します。
ここではIoT HubからBlob Storageの作成を実施しますが、先にBlob Storageを作成しておいて設定することもできます。

IoT Hubの左側のメニューから"メッセージルーティング"を選択、右側の画面内"ルート"が選択された状態で、"＋追加"ボタンを押下します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/439826/75c0ea98-d0f5-d208-027f-88cde8c36aaa.png)
適当な名前を入れて、"＋エンドポイントの追加"→"ストレージ"の順に押下します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/439826/a7b5ca25-9638-36da-9e97-c9e2a0f73a64.png)
また適当な名前を入れて、"コンテナーを選択します"を押下します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/439826/3ae7d384-4d16-5c34-8cf9-e61afa92e124.png)
"＋ストレージアカウント"を押下、適当な名前を入れ、その他設定を行い"OK"ボタンを押下します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/439826/a4fd4977-f3bb-fe9e-c554-ed836597a5db.png)
Storageの種類は今後を見越して"汎用v2"を、場所はIoT Hubと同じリージョンをお勧めします。
パフォーマンスとレプリケーションは今回はお試しなのでデフォルトのままとしました。
本番前に要件確認やパフォーマンステストを実施して、ここら辺は決めると良いかと思います。（が、個人的には本当に本番でここにセンシティブなデータをバンバン飛ばすことなんてあるか？ほかのルーティング先がよくない？と思います。）

作成中は待ちましょう。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/439826/84367727-bb0f-acca-95b2-f6656920255b.png)
できたら作成したBlobを選択し、"＋コンテナー"を押下します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/439826/bf9ca308-31ac-9dec-4995-58f3d8e38d8d.png)
適当な名前を入れてコンテナーを作成します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/439826/427ed0ef-c28b-9721-58a0-1e72561f355f.png)
作成したコンテナーを選び、"選択"ボタンを押下します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/439826/78ab2ad0-60d9-d72d-aaee-7dbbe7c38f90.png)
元の"ストレージ エンドポイントの追加"画面まで戻ってきます。
とりあえず人間が見やすい状態にしたいので、"エンコード"を"JSON"にして、"作成"ボタンを押下します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/439826/e1efcd57-ff61-155d-d1a7-bb2736e9f1f7.png)
## 該当データをBlobに保存する(ルーティング作成)
詳細は本家のドキュメントを参照ください。
本家：[IoT Hub メッセージ ルーティングのクエリ構文](https://docs.microsoft.com/ja-jp/azure/iot-hub/iot-hub-devguide-routing-query-syntax)
いまから扱うのは"アプリケーションプロパティ"です。ルーティング条件を指定するクエリを記載します。
"ルーティングクエリ"に以下を指定します。
> messageType = "maintenance"

入力したら"保存"ボタンを押下します。

## 動作確認
まず、通常のメッセージを受け取るモニターを起動します。
ドキュメントを参考に以下のコマンドをAzureポータルのCloud Shell(CLIセッション)に入れます。
参照：[クイック スタート:デバイスから IoT ハブに利用統計情報を送信して Azure CLI で監視する](https://docs.microsoft.com/ja-jp/azure/iot-hub/quickstart-send-telemetry-cli)
> az iot hub monitor-events --output table --hub-name {YourIoTHubName}

起動を確認したら、先ほど作成したデバイスアプリ(device3)を動かします。

CloudShell上にデータが流れてくると思いますが、3の倍数の時(正確には3で割ってあまりがゼロの時)だけデータがモニターに表示されません。
ルーティングにヒットしたデータは、フォールバックルートには流入しないことがわかります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/439826/0e1e8601-a4ff-d4a2-e60f-c754b1c327e0.png)
ではルーティングされたデータを確認します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/439826/c288bb1c-6df1-6a52-ce73-e351a5059035.png)

ポータルで先ほど作成したBlob Storageの中を確認すると、ファイルができていることがわかります。
ファイルを選択して"編集"で中を確認すると、ファイルにデータが書き込まれていることがわかります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/439826/86f29bb3-40ef-7caa-4374-a1eff96a1845.png)
ルーティングされたデータは、こちらに書き込まれました。

# まとめ
今日は、c2dメッセージにプロパティを付与してみました。
また、プロパティを使って、IoT Hubでメッセージルーティングを実施してみました。
これを使って、たとえばデバッグログはBlobへ、アラートはEventHubsに投げ込んでその先でメールやTeamsに通知、残った通常のメッセージは通常のルート(フォールバックルート)を通過してデータベースへ登録、といった動きが実現できます。
IoT Hubの背後に構えるプログラムの中で、このような振り分け処理を作成しても良いですが、この機能を活用すればプログラムを分割しやすくなります。

# 以上
本日はここまでです。
次回はファイルアップロードをしたいと思います。