Azure IoT Hubを久しぶりに触ってみたので個人的な備忘録 3（ファイルアップロード）

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

今回は前回の続きです。
[初回はこちら](https://qiita.com/mstakaha1113/items/ff5e86ce969caceccb8d)：メッセージングとデバイスツイン
[前回はこちら](https://qiita.com/mstakaha1113/items/02f5ffb49367c3c4bcdd)：メッセージルーティング
デバイス側をメインにやってます。

# デバイスからファイルをアップロードする
IoTと言うと、ニアリアルタイムにデバイスからの情報をクラウド上に収集するイメージがあるかと思います。
が、実際には"すべてのデバイス"から、"すべてのデータ"が送信され **続ける** 必要は無いと思います。
たとえばバッテリーの都合で送受信の機能を稼働させ続けることが得策ではないこともあるのではないでしょうか。
またアラートは即時発報したいかもしれませんが、通常稼働のログは１日１回で良いこともあるのではないでしょうか。
このようなときは、デバイス上にファイルで保存しておいてアップロードするというのも策の１つとなります。
というワケで、ファイルアップロードしたいと思います。

# IoT Hub標準機能で実装
IoT Hubが標準で保有している機能でファイルアップロードを実現します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/439826/2c964a42-de0c-2156-947a-0fb56d858a6b.png)

## IoT HubとBlobを関連付ける
こちらを参考に関連付けを実施します。
[Azure Portal を使用して IoT Hub ファイルのアップロードを構成する](https://docs.microsoft.com/ja-jp/azure/iot-hub/iot-hub-configure-file-uploadb)

## アプリの作成
ゼロベースから作成します。
今回もC#、.NETは6.0.202が入った環境でVSCodeを利用します。
フォルダ名は "device4" としました。
こちらを参考にHelloWorldから作成。
[チュートリアル: Visual Studio Code を使用して .NET コンソール アプリケーションを作成する](https://docs.microsoft.com/ja-jp/dotnet/core/tutorials/with-visual-studio-code?pivots=dotnet-6-0)

こちらを参考にファイルアップロードを作成します。
https://github.com/Azure-Samples/azure-iot-samples-csharp/tree/main/iot-hub/Samples/device/FileUploadSample

パッケージを入れます
> dotnet add package Microsoft.Azure.Devices.Client
dotnet add package Azure.Storage.Blobs

完成したコードはこちらを参照ください。
このままでは使い物にはなりませんが、理解するに必要最小限にはなっているかと思います。
https://github.com/matakaha/iotsample2022/blob/main/device4/Program.cs

実行すると、ローカルにファイルが作成されます。(今回はdevice4afa29a9b-9083-4d73-b532-a7102944245c.txtでした)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/439826/098324f9-4142-5c52-4ef9-dec3a577091d.png)
同じファイルが、Blob Storage上にも確認できると思います。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/439826/7bfebddd-75ce-22f7-b6e8-4ac95344e4f0.png)

## IoT Hub標準ファイルアップロードあれこれ
ファイルアップロードの主な制限事項
- X.509認証では利用できない(プレビュー)
- 1度にアクティブにできる同時ファイル アップロードは各デバイスで 10 件(Complete命令出さないままだと制限かかる)
- 一定時間内にアップロードできる数に限りがある

特に最後のアップロードファイル数の制限はIoT Hubのユニット単位での縛りとなります。
ざっくり言えばデバイスの数ではなくIoT Hubの数で縛りが入りますので、**意外とテスト中に気づかない可能性があります** のでご注意ください。
[参照 - IoT Hub のクォータと調整](https://docs.microsoft.com/ja-jp/azure/iot-hub/iot-hub-devguide-quotas-throttling#operation-throttles)

IoT Hubが払い出すSASURIですが、基本的にはBlob Storageから標準で取得できるSASURIと同じです。
（Blob Storageの↓ここで設定するのとほぼ同じ）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/439826/71c80f43-de4f-1b16-67ac-b5738fe5aff3.png)
余談ですが、例えばIoT Hubで生成してもらったSASURIをコピーしてBlobへのファイルアップロードを単独実行しても普通に動作します。


## 制限事項を超えてファイルアップロードを実現したい場合
上記制限事項を超えてファイルアップロードを実現したい場合、IoT Hubが簡易的に提供してくれている機能を自前で実装する必要があります。
たとえばこのような感じで実装します。
1. デバイスからd2cメッセージでSASURIを要求、例えばプロパティに"messageType:SASURI"みたいなのをつける。
1. メッセージルーティングでSASURI要求をEvent Hubsへルーティング
1. Event HubsからFunctionsを発火
1. FunctionsがBlob StorageのSASURIを作成し、IoT Hubの該当デバイスへのdesired propertiesにSASURIを載せる
1. IoT Hubがデバイスツイン機能でデバイスにSASURIを通知する
1. デバイスツインのdesired propertiesでSASURIを取得したら、デバイスはファイルをアップロードする
1. アップロードイベント起因の処理を作成する場合は、BlobのEventGrid等で代用

これだけのことを中でやってくれてると思うと、標準機能のファイルアップロードなかなか素敵だと思いました。

# さいごに
今日はここまで。
次回があれば、サービス側(クラウドの中)を作成したいと思います。