Azure IoT EdgeランタイムをインストールしたUbuntu 18.04搭載のエッジデバイスでPythonのサンプルモジュールを作成する


# はじめに

横河電機のエッジコントローラe-RT3 Plus F3RP70-2L[^e-RT3]をAzure IoT認定デバイス[^azure]に登録する担当者として、Azure IoT Edgeについて勉強しました。
その内容を数回に分けてご紹介します。
こちらで第3回目の記事となります。
[第1回目](https://qiita.com/Yokogawa_Mita/items/f7996d539b29618d7159)、[第2回目](https://qiita.com/Yokogawa_Mita/items/d6525ebd57af03b67cf9)もぜひご覧ください！

さて、今回はAzure IoT EdgeランタイムをインストールしたUbuntu 18.04搭載のエッジデバイスでPythonのサンプルモジュールを作成してみます。
Azure IoT Edgeランタイムをエッジデバイスへインストールし、IoT Hubへ接続する手順が前回までの記事で紹介されています。

**お知らせ**
AWS IoT Greengrass認定[^aws]も取得しカタログに掲載されました！
後日にGreengrassの導入手順もご紹介したく、内容を計画中です。


# 環境

動作確認したデバイス（OS）

- e-RT3 Plus F3RP70-2L（Ubuntu 18.04 32bit）
- Raspberry Pi 4 Model B （Ubuntu Server 18.04 32bit）
   
これらのデバイスでは `armhf` アーキテクチャのパッケージが動作します。 
また、Windows 10 搭載のPCでモジュールの開発とデバイスの操作を行っています。
（前回までの記事と同様です。）



# 準備
開発環境の準備は、基本的にはMicrosoft公式のドキュメント[^doc][^doc2]に従います。

## コンテナーエンジンのインストール
1. モジュールを開発するPCにコンテナーエンジンをインストールします。
    [Install Docker Desktop on Windows](https://docs.docker.com/docker-for-windows/install/)ページのSystem Requirementsを見て、問題ないことを確認してインストールしてください。
    ※Windows HomeやWindows以外のPCの場合は、左側のメニューから該当のOSを選択して作業してください。
    今回はHyper-Vを有効化してDocker Desktopを使用します。
         
1. インストールできたらスタートメニューからDocker Desktopを起動します。
    起動中である通知が表示されます。
    今回はLinuxコンテナーを使用するため、通知に「Linux Containers Hyper-V backend is starting...」と書かれていることを確認してください。
    また、起動が終わるまでにはしばらく時間がかかります。   
    ※起動中にPCに負荷をかけると起動に失敗することがあるのでご注意ください。
    失敗した場合は再度スタートメニューから起動してください。

1. 起動したらコンテナーエンジンの準備は完了です。
    ※Proxyの設定が必要な場合の説明が[補足](#補足)セクションにあります。
    環境変数へのProxy設定やsudoers設定が必要な場合は[以前の記事の補足セクション](https://qiita.com/Yokogawa_Mita/items/f7996d539b29618d7159#%E8%A3%9C%E8%B6%B3)をご参照ください。


## Pythonのインストール
モジュールを開発するPCにPythonをインストールします。

1. [Pythonのダウンロードページ](https://www.python.org/downloads/)から、インストーラをダウンロードします。
    こちらでは使用するPythonモジュールのテンプレートに合わせてPython3.7をインストールしています。
    
3. インストーラを開き、「Install Now」をクリックしてインストールします。
    ※インストールダイアログ下部のPATHを追加するチェックボックスにチェックを入れてインストールしてください。
    
    
1. インストールが終了したらインストーラを閉じます。


## Visual Studio Codeのインストールと設定
IoT Edgeのモジュール開発にはVisual Studio Code (VS Code) が便利です。
チュートリアルでも使用されているため、モジュールを開発するPCにVS Codeをインストールします。

### インストール
1. [Visual Studio Code](https://code.visualstudio.com/)のウェブページへアクセスし、使用するPCのOSに合わせたバージョンを選択してインストーラをダウンロードします。

3. インストーラを起動し、規約を読み「同意する」を選択し次へ進みます。

1. 追加タスクの選択ダイアログでは、必要な場合は設定を変更してください。
    こちらでは特に変更せず、あらかじめ入っているチェックをそのまま適用します。

1. インストール準備完了画面で、特に問題なければインストールボタンをクリックします。
    「Visual Studio Codeセットアップウィザードの完了」と表示されたらインストール完了です。

### 日本語化の設定
インストール後は英語版のため、初めに日本語化しておきます。

1. VS Codeを起動します。    
   メニューバーの「View」ボタンから「Command Palette」を選択するか、「Ctrl + Shift + p」キーでコマンドパレットを開きます。

2. 検索窓に「Configure Display Language」を入力して検索し、選択します。
    次に言語選択が表示されるので、「Install additional language」を選択します。
    
    ![vscode_023.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/682605/288c88bb-d62e-8aa4-b7cd-f0ab612648ab.png)




1. 左側に言語パックの一覧が表示されます。
    「Japanese Language Pack for Visual Studio Code」を探してInstallボタンをクリックしてインストールしてください。

1. インストール終了後、VS Codeを再起動してください。
 

### 拡張機能の設定
1. 左側のアイコンから拡張機能をクリックし、検索窓に「Azure IoT Tools」を入力して検索します。
    検索された拡張機能の「Azure IoT Tools」のインストールをクリックすると、必要なパッケージがまとめてインストールされます。

    ![vscode_002.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/682605/e3494209-6403-29cd-e005-5eefe2a47a5f.png)


    
1. さらに、検索窓に「Python」を入力して検索します。
    検索された拡張機能の「Python」をインストールします。

    ![vscode_015.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/682605/4f1b86ae-e8c4-50d6-5289-39358f1cd5bb.png)


    
1. コマンドパレットを開きます。
   メニューバーの「表示」ボタンから選択するか、「Ctrl + Shift + p」キーで開きます。
   「Azure: Sign in」を検索し、クリックします。

    ![vscode_003-1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/682605/93a980d1-3268-a472-1e60-aab54f43b6bd.png)

 

1. Azureにサインインします。
    表示される指示に従ってサインインしてください。
    サインインできるとVS Code下部にアカウントが表示されます。

    ![vscode_004-1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/682605/4e8d7e63-67dd-9b67-6ff6-afa9d48722ab.png)


    
1. IoT Hubを選択します。
    再度コマンドパレットを開き、「Azure IoT Hub: IoT Hubを選択」を検索してクリックします。

    ![vscode_005-1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/682605/18ae3870-ed86-cf15-de72-4962802ca13e.png)


    指示に従って、サブスクリプションとエッジデバイスを接続しているIoT Hubを選択します。

    ![vscode_006-1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/682605/fabb4959-da24-3431-1a77-5f3cd43a7a0e.png)
    ![vscode_007-1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/682605/c265220b-9f30-01a0-cac9-c590aa35980a.png)



1. 左側のアイコンからエクスプローラーを選択し「AZURE IOT HUB」を展開すると、選択したIoT Hubやそこに接続されているデバイスの一覧が確認できます。

    ![vscode_008.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/682605/9226ed3e-04e1-a191-6385-7dffff878f6b.png)




## コンテナーレジストリの作成
Dockerイメージの格納にはDockerと互換性のある任意のレジストリを使用します。
チュートリアルではAzure Container Registryを使用しているため、こちらでもその手順で作成します。
※Azure Container Registryは課金が必要なサービスです。
料金の詳細は[こちら](https://azure.microsoft.com/ja-jp/pricing/details/container-registry/)を確認してください。

1. Azure Portalへサインインし、左上にある＋マークの「リソースを作成」をクリックします。
    左のリストからコンテナーを選択し、表示されたサービスから「Container Registry」を選択します。

    ![vscode_010.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/682605/8b31b0e4-80f2-f135-a4a4-e220ff25c408.png)



1. 設定を入力します。
    「情報」タブではサブスクリプション、リソースグループ、レジストリ名、場所、SKUに任意の内容を入力します。
    こちらでは、SKUは最も安いBasicに設定し、次へ進みます。

1. SKUをBasicにすると「ネットワーク」タブと「暗号化」タブの設定内容は変更できませんが、こちらのチュートリアルでは特に必要ないので次へ進みます。
    「タグ」も今回は使用しないのでそのまま次へ進みます。

1. 「確認および作成」タブで設定内容の確認をします。
    問題なければ作成ボタンをクリックします。






# モジュールの作成
IoT Edgeモジュールを作成します。
今回はMicrosoftが提供するPythonのチュートリアルモジュールを作成してみます。
基本的には公式ドキュメント[^doc2]に従いますが、こちらではARM 32bitデバイスでの手順に絞り、またAzure Portalを使用してデプロイやモジュールツインを変更する手順を説明します。

## 新しいプロジェクトを作成する
1. VS Codeでコマンドパレットを開き、「Azure IoT Edge: New IoT Edge solution」を検索して選択します。
    フォルダーの選択ダイアログが表示されるので、作成するプロジェクトを保存したい任意の場所を指定します。
    
1. 「Provide a Solution Name」の入力欄が表示されるので、任意の名前を入力します。
    こちらでは既定の `EdgeSolution` としています。
3. 「Select Module Template」の入力欄が表示されるので、「Python Module」を選択します。
4. 「Provide a Module Name」の入力欄が表示されるので、任意の名前を入力します。
    ここに入力したモジュールの名前がテンプレート内に反映され、IoT Edgeのモジュールの名称になります。
    こちらでは `PythonModule` としています。
    ※IoT Edgeのモジュールの名称は、イメージのビルド前に個別に変更することも可能です。
    
1. 「Provide Docker Image Repository ...」の入力欄が表示されます。
    デフォルトでは `localhost:5000/<Module Name>` が入力されていますが、`localhost:5000` を作成したContainer Registryのログインサーバーに変更します。
    
    **ログインサーバー取得手順**
    Azure Portalにアクセスし、作成したContainer Registryを開きます。
    左側に表示されるメニューから設定カテゴリの「アクセスキー」を探してクリックします。
    右側の画面が切り替わり、Container Registryへのアクセスに必要な情報が表示されます。
    「アクセスキー」の情報はこのあとも使用します。

    ![cr_001.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/682605/ab91e92f-065d-11c8-8c42-e2d61843aa42.png)

    
    「ログインサーバー」の内容（`<registry name>.azurecr.io`）をコピーして、VS Codeの入力欄に `<registry name>.azurecr.io/<module name>` のフォーマットで置き換えます。

    ![cr_002-1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/682605/4cb66fc3-c4db-17ea-296b-1a927c158c24.png)

    
    
1. プロジェクトのテンプレートが作成されます。
    以下の図は、作成されたプロジェクトをエクスプローラーで展開して表示したものです。

    ![vscode_012-2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/682605/81cf3ffa-6853-963c-341e-54ec75807076.png)




## レジストリ資格情報を追加する
エクスプローラーから `.env` ファイルを開きます。

```:.env

CONTAINER_REGISTRY_USERNAME_<registry name>=
CONTAINER_REGISTRY_PASSWORD_<registry name>=
```

`=` 以降にContainer Registryのユーザー名とパスワードを追加して保存します。

```:.env

CONTAINER_REGISTRY_USERNAME_<registry name>=<username>
CONTAINER_REGISTRY_PASSWORD_<registry name>=<password or password2>
```

ユーザー名とパスワードはContainer Registryの「アクセスキー」でコピーしてください。
パスワードはpassword、password2のどちらでもOKです。

![cr_004.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/682605/7243be84-066f-8daf-93ec-d3e337be958d.png)



## ターゲット アーキテクチャを選択する
VS Code下部にある現在のアーキテクチャをクリックすると、上部に「Select Azure IoT Edge Solution Default Platform」ダイアログが表示されます。
こちらでは `armhf` アーキテクチャが動作するデバイスを使用しているため、`arm32v7` を選択します。
適用されると下部の現在のアーキテクチャが `arm32v7` に変わります。

![vscode_013.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/682605/5ba3d36c-5970-778a-675a-c5ec060b678c.png)
![vscode_014.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/682605/5707a7ef-d1c3-1e30-7929-bffb7fe10861.png)



## カスタム コードでモジュールを更新する
`main.py` と `deployment.template.json` を公式ドキュメントの内容に書き換えます。
公式ドキュメントの[「カスタム コードでモジュールを更新する」](https://docs.microsoft.com/ja-jp/azure/iot-edge/tutorial-python-module#update-the-module-with-custom-code)の1.～9.の説明に従って書き換え、ファイルを保存してください。

## モジュールをビルドしてプッシュする
作成したモジュールをビルドして、イメージをContainer Registryへプッシュします。

1. VS Code上部のメニューバーの「表示」から「ターミナル」をクリックすると、画面下部にターミナルが表示されます。

    ![vscode_016-2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/682605/5354dbc2-5094-4bf7-7a0c-6b85e11e7cd6.png)




1. Container Registryにログインします。
    Container Registryのユーザー名、パスワード、ログインサーバー名を入力するので、「アクセスキー」でそれぞれ取得します。
    以下のコマンドを取得したContainer Registryの情報で置き換え、VS Codeのターミナルに入力します。
    
    ```bash
    docker login -u <username> -p <password or password2> <login server> 
    ```

    ※エラーでログインできなかった場合、Proxy設定が必要であることが考えられます。
    Proxy設定の説明が[補足](#補足)セクションにあります。

1. VS Codeのエクスプローラーで「 `deployment.template.json` 」を右クリックし「Build and Push IoT Edge Solution」を選択します。
    すると、必要なコマンドが自動的にターミナルに入力されモジュールのビルドとContainer Registryへのイメージのプッシュが行われます。
    エラーの出力が無ければ完了です。

    ![vscode_017-2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/682605/a1697c53-b150-8347-bbfe-313897dd506d.png)



1. Container Registryへイメージがプッシュされていることを確認します。
    Azure Portalへアクセスし、Container Registryを開きます。
    左側に表示されるメニューからサービスカテゴリの「リポジトリ」を探してクリックします。
    保存されているイメージの一覧が表示されるので、その中にプッシュしたイメージがあることを確認します。

    ![cr_r_001.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/682605/b22b3cdd-890e-55de-e487-d3b1c225c827.png)




# モジュールのデプロイ
Container Registryにプッシュされたイメージをエッジデバイスにデプロイします。
公式ドキュメントではVS Codeからのデプロイ手順が紹介されていますが、こちらの記事ではAzure Portalからデプロイする手順を紹介します。
※[前回の記事](https://qiita.com/Yokogawa_Mita/items/d6525ebd57af03b67cf9)の手順で紹介したSimulated Temperature Sensorモジュールのデプロイが済んでいる状態で作業を始めます。

1.  Azure Portalにアクセスし、作成したIoT Hubに移動します。
    左側のメニューからデバイスの自動管理カテゴリの「IoT Edge」をクリックし、右側に表示されるリストからモジュールをデプロイしたいデバイスIDをクリックします。
    切り替わった画面の上部の「モジュールの設定」をクリックします。

    ![iotedge_005.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/682605/9e319711-084a-a084-1f94-69fa2d8b7805.png)



1. 「Container Registry Credentials」の設定をします。
    別のウィンドウでAzure Portalを開き作成したContainer Registryに移動し、本記事の「[新しいプロジェクトを作成する](#新しいプロジェクトを作成する)」の5. の手順でアクセスキーを開きます。
    以下の組み合わせの通り、アクセスキーで得られる情報をそれぞれモジュール設定の入力欄にペーストします。
    
    | モジュールの設定項目 | 入力する情報 |
    | ---- | ---- | 
    | NAME     | レジストリ名      |
    | ADDRESS  | ログイン サーバー |
    | USERNAME | ユーザー名        |
    | PASSWORD         |password または password2                   |

     ![iothub_001.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/682605/ba3765c0-f5fe-f55f-d958-1ab864b9b935.png)




1. 「IoT Edge Modules」の設定をします。
    「＋Add」ボタンをクリックし、プルダウンメニューから「IoT Edge Module」を選択します。

    ![iothub_002.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/682605/caf9f53d-b22d-c97c-2927-991201360ef6.png)
    
1. 画面右側に表示される「Add IoT Edge Module」の設定をします。
    以下の組み合わせの通りに入力欄に入力・ペーストし、左下の「Update」ボタンをクリックします。
    
    | モジュールの設定項目 | 入力する情報 |
    | ---- | ---- | 
    | IoT Edge Module Name | 任意のモジュール名 |
    | Image URI                     |Container Registryのリポジトリから取得するImage URI（※手順はこのあと）                    |
    | Restart Policy                     | always（デフォルトのまま）                  |
    |  Desired Status                    | running（デフォルトのまま）                   |
    

    ![cr_r_003.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/682605/e29e0a67-8976-76f5-ded0-87b57bcb92ef.png)
    

    **Image URIの取得手順**
    「[モジュールをビルドしてプッシュする](#モジュールをビルドしてプッシュする)」の4. の手順でContainer Registryの保存されているリポジトリのリストを表示します。
    デプロイしたいモジュールのIDをクリックします。
    保存されているタグの一覧からデプロイしたいタグをクリックします。
       
     リポジトリの詳細情報が表示されます。
    「Docker pullコマンド」の欄にある `docker pull <registry name>.azurecr.io/<module name>:<tag>` の `docker pull` 以降の文字列をコピーします。
    以下の例では `<registry name>.azurecr.io/pythonmodule:0.0.1-arm32v7` となります。

    ![cr_r_004.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/682605/035fde23-ce73-4e95-5be9-7c1fdaea29c4.png)

  

1. 「Routes」の設定をします。
    画面上部の「Routes」タブか下部の「Next: Routes」ボタンをクリックし設定画面を切り替えます。
    表示されるNAME、VALUE入力欄に以下の通りに2行分入力してください。
    入力したら画面上部の「Review + create」タブか下部の「Next: Review + create」ボタンをクリックしてください。

    |NAME | VALUE |
    | ---- | ---- | 
    | PythonModuleToIoTHub | FROM /messages/modules/PythonModule/outputs/* INTO $upstream |
    | sensorToPythonModule | FROM /messages/modules/SimulatedTemperatureSensor/outputs/temperatureOutput INTO BrokeredEndpoint("/modules/PythonModule/inputs/input1")|

    ※VALUEに入力する項目は設定画面内の「詳細情報」リンクで参照できる[配置マニフェストの「ルートの宣言」](https://docs.microsoft.com/ja-jp/azure/iot-edge/module-composition#declare-routes)の内容に従っています。
    また、公式ドキュメント[^doc2]で紹介されているVS Codeからのデプロイで設定される内容と同じものです。

    ![iothub_004-1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/682605/9de083bb-4a3f-8f4d-1b01-0726a665c6eb.png)



1. 設定内容の確認をします。
    画面上部に「Validation passed.」と表示があり、追加した設定内容がDeploymentの中に追加されていたら画面左下の青い「Create」ボタンをクリックしてデプロイしてください。
    
    以下の画像の青い四角で囲われた内容が追加した設定内容の例です。
    モジュールをデプロイする設定、Container Registryの情報、ルートの設定などが適切な場所に配置されています。
    
    ![iothub_005-1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/682605/91e11128-be10-78e5-7e1f-8d5795968582.png)
    ![iothub_006-1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/682605/ec476222-29af-30ba-f205-c8f34fb45409.png)
    ![iothub_007-1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/682605/b1a04238-fea5-9e3f-2cff-fc772dcbc8e0.png)



1. デプロイするとデバイス設定画面に戻り、モジュールの一覧中にデプロイしたモジュールが追加されます。
    数分待ってから更新ボタンをクリックすると、モジュールがエッジデバイスにデプロイされて動作していることが確認できます。
    
    ![iothub_008-1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/682605/7c7e4f24-2d8a-3c4e-78c9-5a8cf64f2e32.png)


# モジュールの動作確認
デプロイしたモジュールによって生成されたデータを表示し、動作確認をします。
公式ドキュメント[^doc2]ではVS Codeを使用してIoT Hubに到着するメッセージを確認しますが、こちらでは**Azure IoT Explorer**を使用した確認手順を紹介します。

1. [Azure IoT Explorerのリリース情報ページ](https://github.com/Azure/azure-iot-explorer/releases)から使用するPCのOSに合わせた最新のバージョンのインストーラをダウンロードします。
    インストーラを開くと自動でインストールが始まり、終了後Azure IoT Explorerが起動します。
    ※2020/10/16現在は0.13.0が最新版なのでこちらを例に説明します。

1. Azure IoT Explorerの左側のメニューから「IoT Hubs」を選択し、画面上部の「Add connection」をクリックします。

    ![aie_002.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/682605/0d7742bf-1f51-2963-a45e-134b495d80a7.png)


1. 右側に表示される「Add connection string」設定画面に、以下の手順で取得できるIoT Hubの接続文字列を入力します。
    Azure PortalからIoT Hubにアクセスし、左側のメニューから設定カテゴリの「共有アクセスポリシー」をクリックします。
    画面が切り替わったら「iothubowner」をクリックします。
    右側に表示される「iothubowner」の情報から、「接続文字列—プライマリキー」または「接続文字列—セカンダリキー」の内容をコピーして、Azure IoT Explorerの設定画面の入力欄にペーストします。

    ![aie_001-1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/682605/2c8ad24b-ba1b-f38d-e2bf-bb9356b5f7a9.png)


1. Host name、Shared access policy name、Shared access policy keyが自動的に表示されます。
    Host name文字列の冒頭が接続したいIoT HubのIDだったら青いSaveボタンをクリックします。

    ![aie_003.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/682605/925b7562-60ae-df20-dcf4-431db7458faf.png)

    
1. 画面が切り替わり、IoT Hubに接続されているデバイスの一覧が表示されます。
    動作確認したいデバイスのIDをクリックします。
    ※もし `Failed to retrieve device list: Cannot read property 'headers' of undefined` エラーが表示された場合は、Proxy設定が必要であることが考えられます。
    また、`The port 8081 is in use. ...` エラーが表示された場合は別のPort番号を使用するように設定する必要があります。
    これらの設定の説明が[補足](#補足)セクションにあります。


1. デバイスの詳細画面の左側のメニューから「Telemetry」を選択し、「Start」をクリックするとIoT Hubに到着するメッセージを待機し始めます。

    ![aie_005.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/682605/5521fb7f-6a41-5cac-a0e6-3ef8425381a1.png)


1. メッセージが到着すると以下のようにリアルタイムで表示されていきます。

    ![aie_006-1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/682605/2cf55f3e-97bf-d23d-a65c-7bebee1e970d.png)


    ```json:Telemetry
    {
      "body": {
        "machine": {
          "temperature": 28.199417479545538,
          "pressure": 1.8201868014672131
        },
        "ambient": {
          "temperature": 20.73224486235168,
          "humidity": 25
        },
        "timeCreated": "2020-10-16T08:16:49.6184054Z"
      },
      "enqueuedTime": "2020-10-16T08:16:49.684Z",
      "properties": {
        "sequenceNumber": "13",
        "batchId": "04f0289f-0254-4eb3-85c6-f2a01ab68682",
        "$.cdid": "test_ert3_f3rp70",
        "$.cmid": "SimulatedTemperatureSensor",
        "MessageType": "Alert"
      }
    }
    ```

1. メッセージの待機を止めたい場合は「Stop」をクリックしてください。
※Simulated Temperature Sensorは500回メッセージを送信するとステータスがrunningのまま何もメッセージを送信しなくなります。
もし再度メッセージを送信させたい場合は、以下のコマンドでターミナルソフトからエッジデバイスを操作してモジュールを再起動します。

```bash:Terminal
sudo iotedge restart SimulatedTemperatureSensor
```

なお、上記コマンドの `SimulatedTemperatureSensor` の部分は他のモジュールIDに置き換えることでそのモジュールの再起動ができます。

```bash:Terminal
sudo iotedge restart <Module ID>
```


# モジュールツインを編集する
使用するサンプルモジュールは、モジュールツインを編集することでモジュールを再度ビルド、デプロイすることなく機能を編集できます。
今回はデプロイしたPythonモジュールのモジュールツインを編集して、IoT Hubへ通知するマシン温度の閾値を変更してみます。
公式ドキュメントではVS Codeを使用して編集する手順が紹介されていますが、こちらでは**Azure Portal**から編集する方法を紹介します。

1. Azure PortalからIoT Hubにアクセスし、デバイスの自動管理カテゴリのIoT Edgeを表示します。
    モジュールツインの編集をしたいモジュールがデプロイされているデバイスのIDをクリックします。

1. 表示された画面の上部の「モジュールの設定」をクリックします。
    切り替わった画面の「IoT Edge Modules」の一覧から今回デプロイしたPythonモジュールをクリックします。
    
1. 「Update IoT Edge Module」の設定画面が表示されます。
    「Module Twin Settings」タブをクリックし、記入欄に `JSON` 形式で `"TemperatureThreshold"` について記入し、左下のUpdateボタンをクリックします。
    以下の例は、VS Code使用時の説明と同様にマシン温度の閾値を40度にする場合の記入内容です。
    例えば、設定時にIoT Hubに到着しているマシン温度より5℃～10℃ほど高い値にすると変化が分かりやすいです。

    ![iothub_013.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/682605/c3b1683b-a579-b06e-204b-5f5ac50363f0.png)


    
    ```json:Module&nbsp;Twin&nbsp;Settings
    {
        "TemperatureThreshold": 40
    }
    ```

1. 1つ前の画面に戻るので、上部の「Review + Create」タブか下部の青い「Review + Create」ボタンをクリックして確認画面に移動します。
    Deploymentを確認すると先ほど変更したモジュールツインの内容が反映されています。
    変更内容の反映と上部の「Validation passed.」の表示を確認したら左下の青い「Create」ボタンをクリックして変更内容を確定します。

    ![iothub_r_001.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/682605/947209ab-d0c9-b7aa-2d52-acfc7e4acf77.png)



1. [モジュールの動作確認](#モジュールの動作確認)と同様の手順で生成されたデータを表示すると、モジュールツインの編集で変更した閾値が適用されていることが確認できます。
    
    **例：IoT Hubに到着しているメッセージのマシン温度が30℃のときにPython Moduleのモジュールツインを編集し、閾値を40℃に変更した場合**
    閾値が変更されると、Simulated Temperature Sensorが出力したデータのマシン温度が40℃を下回るうちはPython ModuleはIoT Hubにメッセージを送信しなくなります。
    Azure IoT Explorerもしばらくの間メッセージが更新されなくなります。
    マシン温度が徐々に上がっていき閾値の40℃を超えると、Python ModuleはIoT Hubにメッセージを送信するようになります。
    Azure IoT Explorerでもメッセージが更新されるようになり、その内容を確認すると確かにマシン温度が40度を超えていることが分かります。




# 補足
使用環境にProxyサーバーがある場合、こちらで紹介した手順では新たに**VS Code**と**Docker Desktop**、**Azure IoT Explorer**のProxy設定やPort設定が必要です。
VS CodeからAzure へのログインはVS Code、VS CodeのターミナルからContainer RegistryへのログインやイメージのプッシュはDockerのProxy設定をそれぞれ参照しているようです。
また、Azure IoT ExplorerではPCのProxy設定に加えて、特定のPortを使用してIoT Hubに到着したメッセージを確認するためその確認も必要になります。
こちらでは、例として私が設定した内容を紹介します。
また、使用環境によって必要な設定、不要な設定があります。

IoT Hubへ接続しているエッジデバイスへのProxy設定とsudoers設定は[こちら](https://qiita.com/Yokogawa_Mita/items/f7996d539b29618d7159#%E8%A3%9C%E8%B6%B3)、IoT EdgeランタイムへのProxy設定は[こちら](https://qiita.com/Yokogawa_Mita/items/d6525ebd57af03b67cf9#%E8%A3%9C%E8%B6%B3)をご覧ください。

## Visual Studio Code
VS CodeにProxy設定を行います。

1. メニューバーから ファイル＞ユーザー設定＞設定 を選択し、設定画面を表示します。

2. 検索窓に「proxy」と入力すると「Http: Proxy」設定が表示されるので、Proxy URLを入力してください。
    Proxy URLは例えば `http://username:password@example.com:port/` です。
    ご自身の環境によって変わりますので、詳しくは管理者の方へお問い合わせください。
    入力した設定は `C:\Users\username\AppData\Roaming\Code\User\settings.json` へ反映されます。
    
    ![vscode_018-1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/682605/4c5711c4-8ccd-74d2-0559-816ab3ba3a2b.png)


## Docker
DockerにProxy設定を行います。
設定の手順はDockerの公式ドキュメント[^dockerproxy]に従います。


1. `C:\Users\username\.docker` フォルダーの中にある `config.json` を任意のエディタで開くか、無い場合はファイルを作成してください。

1. [Dockerの公式ドキュメント](https://docs.docker.com/network/proxy/)の「Configure the Docker client」の手順に従って `config.json` にProxyの情報を入力します。
    このとき、既に `config.json` が作成されていた場合はProxy以外の設定内容が入力されていることがあります。
    そのような場合は、あらかじめ入力されている各項目と同じレベルになるように記入してください。
    私の環境で　`httpProxy` と `httpsProxy`　に設定した例は以下の通りです。
    あらかじめいくつかの項目が入力されており、`"proxies":{...}` の項目が追記した箇所です。
    
    ```JSON:C&#58;\Users\username\.docker\config.json
    {
        "HttpHeaders":
        {
            "User-Agent":"Docker-Client/19.03.13 (windows)"
        },
        "auths":
        {
            "<registry name 1>.azurecr.io":{},
            "https://index.docker.io/v1/":{},
            "<registry name 2>.azurecr.io":{}
        },
        "credStore":"desktop",
        "credsStore":"desktop",
        "proxies":
        {
            "default":     
            {
                "httpProxy":"http://username:password@example.com:port/",
                "httpsProxy":"http://username:password@example.com:port/"
            }
        },
        "stackOrchestrator":"swarm"
    }
    ```
    
1. さらに、Docker Desktopの設定にもProxy設定を行います。
    PCのツールバーのDocker Desktopのアイコンを右クリックし、Settingsを開きます。
    Resourcesを展開し、PROXIESをクリックすると表示される入力欄にProxy URLを入力してください。
    「Apply & Restart」をクリックすると設定が反映され、Docker Desktopが再起動されます。

    ![docker_019.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/682605/f7a3d969-d444-7f04-02ca-6cc526346f70.png)


## Azure IoT Explorer
Azure IoT ExplorerではProxy設定と、8081番Portが他の機能で既に使用されている場合はPort設定を追加します。


### Proxy
PCのシステム環境変数に `HTTPS_PROXY` を追加します。

1. システム環境変数の設定画面を開きます。
    * 【手順1】PCスタートメニューの検索欄に「env」と入力し、検索結果に表示される「システム環境変数の設定」を開きます。
    * 【手順2】コントロールパネルを開き、表示方法を「大きいアイコン」にします。
        「システム」をクリックし、左側のメニューから「システムの詳細設定」をクリックします。

1. 表示されるシステムのプロパティダイアログの下部にある「環境変数」をクリックします。
    新たに表示される環境変数ダイアログの「システム環境変数」の「新規」ボタンをクリックします。
    
1. 下記のように変数名と変数値を入力してOKボタンをクリックします。

    ![aie_007.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/682605/437ca86a-6c2d-f3fa-e7bf-23f48ff8fff9.png)
    

    | 項目名 | 設定内容 |
    | :------- | :--------- |
    | 変数名 | HTTPS_PROXY |
    | 変数値 | http://username:password@example.com:port/ |

1. 「システム環境変数」に `HTTPS_PROXY` が追加されていることを確認し、OKボタンをクリックしてダイアログを閉じます。

1. Azure IoT Explorerを再起動し、IoT Hubへ接続してください。
    再接続時にエラーが生じる場合は、もう一度Azure IoT Explorerを再起動してください。

### Port
PCのシステム環境変数に `AZURE_IOT_EXPLORER_PORT` を追加します。
設定の手順はAzure IoT ExplorerのFAQページ「How to solve 'Port is in use'」[^aie]の内容に従います。

1. 先に紹介した[Proxy設定](#proxy)の1.、2.と同様に環境変数の設定画面を開きます。

2. 「システム環境変数」の「新規」ボタンをクリックし、下記の例のように設定を入力してOKボタンをクリックします。
    このとき、Port番号は8081以外の使用されていない任意の数値にします。

    | 項目名 | 設定内容 |
    | :------- | :--------- |
    | 変数名 | AZURE_IOT_EXPLORER_PORT |
    | 変数値 | 8081以外の使用されていない任意のPort番号 |

3. `AZURE_IOT_EXPLORER_PORT` の設定内容が反映されているか確認し、OKボタンをクリックしてダイアログを閉じます。
    下記の画像は、Proxy設定とPort設定をどちらも行った場合の例です。

    ![aie_008-1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/682605/d2c4e29b-aac8-a7ee-c87b-766ec9254ac7.png)


1. Azure IoT Explorerを再起動し、IoT Hubへ接続してください。
    再接続時にエラーが生じる場合は、もう一度Azure IoT Explorerを再起動してください。


※私の環境ではProxy設定とPort設定のどちらも必要であった場合、IoT Hubへ接続されたデバイスの一覧は表示できましたがIoT Hubへ送信されたメッセージの確認はできませんでした。
Port設定のみが必要な環境では送信されたメッセージの確認ができています。


# 次回

Pythonモジュールのチュートリアルを、Azure Portalを使用する手順で行いました。
次回からは数回にわたって入力モジュールのデータを IoT Hub へ送り可視化していきます。

→[次回](https://qiita.com/Yokogawa_Mita/items/7214feba76ba613b3b79)

# 参考

[^e-RT3]: [リアルタイムOSコントローラ　e-RT3 Plus F3RP70-2L](https://www.yokogawa.co.jp/solutions/products-platforms/control-system/real-time-os-controller/ert3-ai-platform/)
[^azure]: [Azure Certified Device catalog](https://devicecatalog.azure.com/)
[^aws]: [AWS Partner Device Catalog](https://devices.amazonaws.com/)
[^doc]: [チュートリアル:Linux のデバイス用の IoT Edge モジュールを開発する](https://docs.microsoft.com/ja-jp/azure/iot-edge/tutorial-develop-for-linux)
[^doc2]: [チュートリアル:Linux デバイス用の Python IoT Edge モジュールを開発およびデプロイする](https://docs.microsoft.com/ja-jp/azure/iot-edge/tutorial-python-module)
[^docker]: [Control Docker with systemd](https://docs.docker.com/config/daemon/systemd/#httphttps-proxy)
[^proxy]: [プロキシ サポートの構成](https://docs.microsoft.com/ja-jp/azure/iot-edge/how-to-configure-proxy-support)
[^dockerproxy]: [Configure Docker to use a proxy server](https://docs.docker.com/network/proxy/)
[^aie]: [FAQ How to solve 'Port is in use'](https://github.com/Azure/azure-iot-explorer/wiki/FAQ#how-to-solve-port-is-in-use)