Azure IoT Edge カスタムモジュールの作成（RaspberryPi & Python）

Azure IoT Edge の[インストール](https://qiita.com/linyixian/items/f0da0df8f5f9cb034988)、[設定](https://qiita.com/linyixian/items/39a15c8a85db2f43f090)に続いてカスタムモジュールの作成を行います。

一番最初なのでLチカします。（T先生の[FPGA+IoT EdgeでLチカ](https://qiita.com/takasehideki/items/a9f33823abce97efd3c8)よりもテクノロジの無駄遣いのような気もしますね）
ただ、Lチカするだけでも罠があったりします。
あとで詳しい説明はしますけど、IoT Edgeがコンテナで動作していることが問題になります。

[公式ドキュメント](https://docs.microsoft.com/ja-jp/azure/iot-edge/tutorial-python-module?view=iotedge-2018-06)も参照してください。

##準備

・IoTHub
・RaspberryPi（ARM32v7以上の機種）IoT Edgeをインストール済み
・コンテナレジストリ
・Docker
・VS Code
・VS Code用Python拡張機能
・VS Code用Azure IoT Tools
・Python（3.7)

RaspberryPiにはLEDと抵抗を接続します。
![led.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/62606/756ff873-8dd2-a656-c568-2a9c1321676c.png)


##プロジェクトの作成

１．VSCodeを起動します。F1キーを押してコマンドパレットを開きます。

２．Azure: Sign in コマンドでAzureにサインインしておきます。

３．コマンドパレットでAzure IoT Edge:New IoT Edge solution コマンドを入力して実行します。
![led01.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/62606/e220c434-988e-0797-08b1-973426510ce9.png)

４．ソリューションファイルを保存するフォルダーを選択します。
![led02.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/62606/1d5571d1-c505-fbd5-2cc0-22c5eaa693a1.png)

５．ソリューション名を入力します。
![led03.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/62606/4baca9d4-e7b0-3a0a-2b36-a167e6c47591.png)

６．Pythonモジュールを選択します。
![led04.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/62606/63ff7afe-76f4-8166-35a4-b0a60b8b5d9a.png)

７．モジュール名を入力します。
![led05.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/62606/036539cd-7ab4-8127-8f60-3d02c6165b0d.png)

８．リポジトリ情報を入力します。 [registry name].azurecr.io/モジュール名 になります。
![led07.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/62606/926042a0-6be2-c4f3-19ef-e791bea18b97.png)

９．プロジェクト内の.envファイルを開いてユーザー名、パスワードが設定されているのを確認します。設定されいない時はコンテナレジストリのアクセスキーからユーザー名とパスワードをコピーします。
![led09.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/62606/fbdc60d3-29e3-a4bb-27eb-abc5a85ec802.png)
![contener05.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/62606/e57c0b3f-27e7-0d51-422b-9a70453138a8.png)

１０．画面下部のターゲットプラットフォームをクリックしてプラットフォームを「ARM32v7」に変更します。
![led08.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/62606/3669459e-d620-55c1-c83e-c8bb0d86e3dd.png)


１１．画面下部の使用言語がPython3.7になっているのを確認します。違う場合にはコマンドパレットで選択しなおします。
![led10.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/62606/00f2b3fe-413b-e6a5-5c67-1a49e66bf574.png)

１２．main.pyを開き次の内容に変更します。

```python:main.py
import time
import RPi.GPIO as gpio

gpio.setmode(gpio.BCM)

gpio.setup(26,gpio.OUT)


try:
    while True:

        gpio.output(26,1)

        time.sleep(.5)

        gpio.output(26,0)

        time.sleep(.5)

except KeyboardInterrupt:
    gpio.cleanup()
```

１３．Dockerfile.arm32v7を開き次のように変更します。

```Dockerfile.arm32v7
FROM arm32v7/python:3.7-slim-buster

WORKDIR /app

RUN apt update && apt install -y \
    build-essential

COPY requirements.txt ./
RUN pip install -r requirements.txt

RUN pip install RPi.GPIO

COPY . .

CMD [ "python3", "-u", "./main.py" ]
```

１４．deployment.template.jsonを開き、67行目以降を変更します。この設定がキモになります。
通常コンテナ内からデバイスのハードウェアへのアクセスはできません。コンテナからアクセスするためにはprivilegedオプションを使うことで可能になりますが、Dockerのようにコマンドラインで指定することはできません。そこでdeployment.template.json内でオプションを追加することでアクセスすることができるようになります。デバイスのGPIO以外にBluetoothやネットワークにアクセスする必要がある場合にはこのようなオプションの追加が必要になります。（しかし、この情報が公式にでてないのはどうしてなのかな。見落としている？）

```deployment.template.json

～省略～

"createOptions": {
  "NetworkingConfig": {
    "EndpointsConfig": {
      "host": {}
    }
  },
  "HostCOnfig": {
    "NetworkMode": "host",
    "Privileged": true
  }
}

～省略～
```

![led13.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/62606/386e3340-8b90-45e4-f9d1-6174936b71af.png)


１５．deployment.template.jsonを右クリックして「Build and Push IoT Edge Solution」をクリックします。
　　　問題がなければコンテナレジストリにビルドしたソリューションファイルが登録されます。
![led14.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/62606/379aa20e-df9b-8e7e-9123-66b605dd89f9.png)


１６．Auzre IoT HubセクションからDevicesを展開し、デプロイしたいデバイスを右クリックし「１つのIoT Edgeに配置」をクリックします。
![led15.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/62606/1f601ab9-f650-5c3e-73f7-e797bc978b24.png)

１７．configフォルダを開き「deployment.arm32v7.json」を選択します。
![led16.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/62606/1e599c38-52cc-9acb-2518-a11cda899e1b.png)
![led17.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/62606/abe7be02-5b1e-ccbe-3fac-4600fad93619.png)
![led18.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/62606/409617d8-64a8-6c16-309b-2915d8241508.png)

１８．問題がなければしばらくしてLEDが点滅を始めます。

１９．試しにmain.pyの14,18行目のtime.sleepの中の数値を変更してみてください。

２０．module.json内の7行目の「version」の数値を大きくして保存します。

２１．再び手順１５から進めると変更した内容がデバイスに反映されるはずです。


IoT Edgeを利用してリモートデプロイをすることができました。

いかがでしたでしょうか。