Azure IoT Edgeでダイレクトメソッドが便利だった話

# はじめに
@tishikawa-gxpです。
この記事は[グロースエクスパートナーズ Advent Calendar 2020](https://qiita.com/advent-calendar/2020/gxp)の14日目です。

今回は私が関わっている案件で使用しているAzure IoT Edgeの概要と
ダイレクトメソッド機能について記載します。

ダイレクトメソッドに関しての記載は後述しますが、
Azure IoT Edge問合せ調査時のログ採取等に重宝しましたので、
その辺りをご紹介したいと思います。

# Azure IoT Edgeについて
## Azure IoT HubとAzure IoT Edge
Azureが提供しているIoTサービスの一つとして「Azure IoT Hub（以下IoT Hub）」が存在し、
主な機能としてIoTデバイス管理・監視・メッセージ送受信機能等を備えています。
「Azure IoT Edge（以下IoT Edge）」はIoT Hubの付帯サービスという位置づけになります。
IoT Hubは有償ですが、IoT Edgeに関しては無償で使用可能です。
※IoT Edgeを使用する際はIoT HubのプランがStandardである必要があります。

* IoT HubはAzure上で動作するIoTデバイス管理サービス
* IoT EdgeはIoTデバイスの近くで動作するエッジ処理を実現するためのサービス

実際の構築イメージとしては以下のような形となります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/891004/ecc3ebac-b0cd-c7e8-8c69-7f1006fb2c47.png)

## IoT Edgeの詳細
本項ではIoT Edgeの構成図を概略で記載します。
IoT Edgeと銘打たれているサービスですが、その実体は複数のDockerコンテナの集合体となります。
コンテナ一つ一つがモジュールと呼ばれています。
標準で存在するモジュールと、開発者が定義するモジュールが存在します。

| モジュール名 | 種類 | 役割 |
|:--|:--|:--|
|Edge Agent|標準| 各モジュールの管理、IoT Hubへ各モジュール実行状態の通知。|
|Edge Hub|標準|各モジュール間の通信(メッセージルーティング)管理、<br>収集データをIoT Hubへアップロード等。|
|Custom Module|カスタム|開発者自身で実装するモジュール。<br>C言語、C#、Node.js、Python、Javaで開発可能。
![edge.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/891004/98b28bec-439f-ba5d-98e6-1fda869df23a.png)
# IoT Edge調査の際にダイレクトメソッドを使用
IoT Edgeは様々な場所で動作しうる関係上、必ずしも社内ネットワークから疎通できるとは限りません。
不具合等問い合わせで調査が必要な場合でも、IoT EdgeサーバにSSHでアクセス出来ないケースが存在します。

「これはどうしたものか」と悩んだところ、ダイレクトメソッドの存在に気づき事なきを得ました。<br>本項ではダイレクトメソッドの説明と、実際に使用したメソッド2つを紹介します。
※2つのメソッドはIoT Edgeに標準で組み込まれているものです。Edge Agentモジュールを介して実行します。
※本記事では解説しませんがダイレクトメソッドは自作メソッドに対しても適用可能です。

## ダイレクトメソッドとは
端的に言えばIoT Edgeで動作しているモジュールのメソッドを遠隔実行する機能です。直接IoT Edgeにアクセス出来なくともAzure CLIやAzure Portalから実行可能です。

「遠隔地で動作しているIoT Edgeのネットワーク情報がわからないのに何故実行できるの？」<br>と思うかもしれませんが、IoT Hubの特徴の1つとして「全ての通信はデバイス側(IoT Edge)から開始される」というものがあります。
この特徴のおかげでIoT Hub側はIoT Edgeのネットワーク情報を知らなくともIoT Edgeに働きかけることができ、ダイレクトメソッドのような機構が実現出来ています。
※IoT Edgeの設定ファイルにはIoT Hub接続文字列が設定されます。

ただ1つ注意点としては「全ての通信はデバイス側(IoT Edge)から開始される」という特徴のため、<br>ダイレクトメソッドを使用する際はIoT Edgeが必ず起動している必要があります。<br>予期せぬエラー等でIoT Edgeが停止していると、IoT Hubはダイレクトメソッド実行要求の送信先が分からないのでダイレクトメソッド実行不可となります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/891004/807803e0-0792-4b5a-6914-5cb7678b043d.png)

## ダイレクトメソッド①RestartModule
IoT Edgeモジュールの再起動を行ってくれるメソッドです。

### Azure CLIからの実行
再起動を行いたいモジュールを指定して実行するのみです。

```
az iot hub invoke-module-method --method-name 'RestartModule' -n <IoT Hub名> -d <IoT EdgeデバイスID> -m '$edgeAgent' --method-payload \
'
    {
        "schemaVersion": "1.0",
        "id": "<モジュール名>"
    }
'
```
### Azure Portalからの実行
Azure Portal上からも実行可能です。
![RestartModule.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/891004/6ba71cf0-e563-2355-a8c0-2cc86e973a45.png)
メソッド実行が成功すればHTTPステータスコード200が返却されますが、
以下IoT Hub画面上からも結果の確認が可能です。今回の場合「最後の再起動時刻(UTC)」の値が実行時の時間となっていればOKです。
![RestartModule_result.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/891004/7adf03a5-7633-8e56-37e6-e892084470a2.png)
## ダイレクトメソッド②UploadModuleLogs
IoT Edgeの各モジュールのログをAzure Blob Storageにアップロードするメソッドです。
本来だとモジュールのログ確認はIoT Edgeデバイス上で「iotedge logs」コマンドを実行して確認する必要があったのですが、本メソッドが使用可能になってからログ採取が容易になりました。
※IoT Edge Ver1.0.10（2020/10/12リリース）にて追加されました。
### Azure CLIからの実行
前述のRestartModuleメソッドに比べて指定できるパラメータが多いです。
以下は全モジュールのログ最新100行分(JSON形式)をgzip圧縮してアップロードを行う記述となっています。

```
az iot hub invoke-module-method -n <IoT Hub名> -d <IoT EdgeデバイスID> -m \$edgeAgent --mn UploadModuleLogs --mp \
'
    {
        "schemaVersion": "1.0",
        "sasUrl": "<BlobStorageのSAS付きURL>",
        "items": [
            {
                "id": ".*", 
                "filter": {
                    "tail": 100
                }
            }
        ],
        "encoding": "gzip", 
        "contentType": "json"
    }
'
```

### Azure Portalからの実行
同じくAzure Portal上からも実行可能です。
![UploadModuleLogs.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/891004/351cce23-e176-922a-d872-a7dd2f15934c.png)
メソッド実行が成功すればHTTPステータスコード200が返却されます。
ログ自体は指定したAzure Blob Storageにアップロードされているので、<br>これを取得することでIoT Edgeモジュールログの確認が可能です。
![UploadModuleLogs_result.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/891004/9b5b3b11-5903-f32a-9746-accb7b3c8c2d.png)

# まとめ
IoT Edgeとその機能であるダイレクトメソッド、
その中でも実際に使用して便利だったメソッドについて解説しました。
これ以外にも、

* デバイスツイン/モジュールツイン（各種設定の同期）
* モジュールの自動デプロイ
* オンライン復帰時のメッセージ再送機能

などIoT基盤に必要な機能が標準で用意されています。
IoT基盤を構築する際の候補の1つとして検討してみてはいかがでしょうか？


# 参考
* [Azure IoT Edge とは](https://docs.microsoft.com/ja-jp/azure/iot-edge/about-iot-edge?view=iotedge-2018-06)
* [Azure IoT Edge ランタイムとそのアーキテクチャの概要](https://docs.microsoft.com/ja-jp/azure/iot-edge/iot-edge-runtime?view=iotedge-2018-06)
* [組み込みのダイレクト メソッドを使用して edgeAgent と通信する](https://docs.microsoft.com/ja-jp/azure/iot-edge/how-to-edgeagent-direct-method?view=iotedge-2018-06)
* [Azure IoT Edge アウトバウンド/インバウンド構成を確認する](https://docs.microsoft.com/ja-jp/azure/iot-edge/production-checklist?view=iotedge-2018-06#networking)