LoginSignup
2
2

More than 5 years have passed since last update.

Armadillo-IoT G3でMicrosoft Azure IoT Edgeを動かす

Posted at

この記事の目的

独自のMicrosoft Azure IoT Edge(以下IoT Edge)のモジュールをビルドし、Armadillo-IoT G3(以下Armadillo-IoT)上で動作させます。

前提条件

  • Azureへの登録が完了し、ポータルをすぐに利用できる状態にあることをご確認ください。

  • Azure CLIを利用します。右のウェブサイトに従い、インストール及びログインを完了させてください。 Windows での Azure CLI のインストール

  • 次の記事の内容を理解する必要があります。 Azure IoT Edgeとは | Microsoft Docs

  • VSCodeの拡張機能を利用してモジュールを作成/ビルド/デプロイします。VSCodeを利用できる状態にしてください。

IoT Edgeの準備

モジュールを動作させるために、IoT Edgeを利用する準備を行います。

以下の手順に従って操作してください。

  1. 左のペインから、全てのサービスをクリックし、その中からIoT Hubを選択してください。(画面上部のフィルターと表記されたテキストボックスより検索が行えます。)

  2. 左上の「追加」をクリックします。

  3. IoT Hub Nameを設定します。英数字とハイフンが利用できますが、英数字で始まり英数字で終わる名前にする必要があります。

  4. Size and scaleへ移動し、Pricing and scale tierからF1: Free tierを選択します。

  5. 入力内容を確認し、createをクリックします。

  6. 先ほど作成したIoT Hubをクリックし、内部左のペインからIoT Edgeを選択してください。

  7. 左上のAdd an IoT Edge deviceをクリックします。

  8. 有効なDevice IDを入力し、Saveをクリックします。

  9. 作成されたIoT Edge deviceを選択し、上から4番目のConnection string (primary key)をコピーします。何らかの方法でメモすることをお勧めします。

Armadillo-IoTへのIoT Edgeの導入

モジュールをArmadillo-IoT上にデプロイする前に、Armadillo-IoTへのIoT Edgeの導入が必要です。

以下のテキストをターミナルにペーストすることで、全てのインストールが完了します。
ただし、rootでのログインが前提です。

# Install moby-engine
curl -L https://aka.ms/moby-engine-armhf-latest -o moby_engine.deb && dpkg -i ./moby_engine.deb

# Install moby-cli
curl -L https://aka.ms/moby-cli-armhf-latest -o moby_cli.deb && dpkg -i ./moby_cli.deb

# Install libiothsm-std
curl -L https://aka.ms/libiothsm-std-linux-armhf-latest -o libiothsm-std.deb && dpkg -i ./libiothsm-std.deb

# Install IoT Edge Security Daemon
curl -L https://aka.ms/iotedged-linux-armhf-latest -o iotedge.deb && dpkg -i ./iotedge.deb

apt install -f

その後、/etc/iotedge/config.yamlをエディタで開き、provisioningのセクションのコメントを解除し、先ほどコピーしたConnection string (primary key)をペーストします。

...
provisioning:
  source: "manual"
  device_connection_string: "ここにペースト"
...

その後、デーモンを再起動します。

# systemctl restart iotedge

VSCodeへのAzure IoT Edge拡張機能のインストール及び準備

VSCodeにAzure IoT Edge拡張機能をインストールすることで、モジュールを開発することができます。以下はその手順です。

  1. VSCodeを起動し、左のバーから拡張機能を選択し、「IoT Edge」でMarketplaceを検索してください。

  2. Azure IoT Edgeを選択し、インストールします。依存している拡張機能も同時にインストールされます。

  3. Ctrl+Shift+Pよりコマンドパレットを開き、Azure: Sign inをクリックしてください。(テキストボックスに一部を入力することで補完されます。)

コンテナーレジストリの準備

モジュールはAzureのコンテナーレジストリにプッシュしてからデプロイされます。

ソリューションを作成する段階でコンテナーレジストリが必要になるので、先に作成します。

  1. 「すべてのサービス」からコンテナーレジストリを選択します。

  2. 左上の「追加」をクリックします。

  3. レジストリ名を入力し、他の項目を適宜変更します。

レジストリ名は次の項で使用します。

モジュールの開発

先ほどインストールした拡張機能を用いて、モジュールを開発します。

以下の手順でソリューションを作成します。

  1. Ctrl+Shift+Pでコマンドパレットを開き、Azure IoT Edge: New IoT Edge Solutionをクリックしてください。

  2. ソリューションを作成するディレクトリを選択してください。

  3. ソリューションの名前を入力します。今回はCPUTempとします。

  4. 今回はPythonを用いてモジュールを開発するため、Python Moduleを選択します。

  5. モジュール名を入力します。ここではCPUTempとします。

  6. コンテナーレジストリのURLを入力します。ここでは、localhost:5000の部分を「(レジストリ名).azurecr.io」に置き換えます。これ以外を置き換えると正しく動作しない可能性があります。

指定されたディレクトリにソリューションが作成され、自動で開かれます。

ソリューションへのファイルの追加

ソリューションは、作成された時点ではモジュールとして即座に動作することはできません。

そこで、一部のファイルを書き換えます。

以下に、書き換えるべきファイルの名前と、その内容を表示します。


Dockerfile.arm32v7

()で囲まれた部分を置き換えてください。

FROM arm32v7/debian:stretch-slim

WORKDIR /app

RUN apt-get update && \
    apt-get install -y --no-install-recommends libboost-python1.62.0 python3-pip libpython3-dev libcurl3 && \
    rm -rf /var/lib/apt/lists/* 

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

COPY . .

RUN useradd -ms /bin/bash moduleuser
USER moduleuser

ENTRYPOINT [ "python3", "-u", "./main.py" ]

ENV IOTEDGE_AUTHSCHEME=sasToken \ 
    IOTEDGE_DEVICEID=(Azure IoT Edgeに登録したデバイスのID) \
    IOTEDGE_WORKLOADURI=unix:///var/run/iotedge/workload.sock \
    IOTEDGE_MODULEGENERATIONID=(下記の方法で取得したID) \
    IOTEDGE_GATEWAYHOSTNAME=Armadillo \
    IOTEDGE_MODULEID=CPUTemp \
    IOTEDGE_IOTHUBHOSTNAME=(Azure PortalのIoT Hubの概要から閲覧できるホスト名)

VSCodeの左下の「AZURE IOT HUB DEVICES」からデバイス名を右クリックし、「Get Device Info」を選択してください。

JSONでデバイスの情報が表示され、その先頭に近いところにgenerationIdが表示されます。これを上記のファイルの指定された場所にペーストしてください。

main.py

# 次の行のコメントは、pylintによるモジュールが存在しないことの指摘を防ぎます。
# pylint: disable=E0611
from iothub_client import IoTHubModuleClient, IoTHubClientError, IoTHubTransportProvider
from iothub_client import IoTHubMessage, IoTHubMessageDispositionResult, IoTHubError
import time
import traceback

# IoT Edgeを操作するクラスです。このファイルをインポートすることで利用できます。
class MQTTHubManager:
    def __init__(self):
        protocol = IoTHubTransportProvider.MQTT

        timeout = 10000
        self.client = IoTHubModuleClient()
        self.client.create_from_environment(protocol)

        self.client.set_option("messageTimeout", timeout)

    # メッセージ文字列を送信します。
    def sendMessage(self, queueName, messageString):
        message = IoTHubMessage(messageString)
        self.client.send_event_async(queueName, message, self.callback, 0)

    # コールバック関数です。通常、手動で呼び出すことはありません。
    def callback(self, message, result, context):
        print("result %s" % result)

def main():
    try:
        print("Starting Module...")
        hubManager = MQTTHubManager()
        tempFile = "/sys/class/thermal/thermal_zone1/temp" # CPUの温度情報ファイルです。現在の温度の1000倍の整数値が格納されています。
        print("Ready")

        while True:
            fileHandler = open(tempFile)
            tempStr = fileHandler.read()
            if tempStr is not None:
                temp = str(int(tempStr.strip()) / 1000.0)
                hubManager.sendMessage("temp", temp)
            fileHandler.close()
            time.sleep(300)
    except IoTHubError as e: # IoT Edgeからの例外に対応します。
        print("Unexpected Error: %s" % e)
        return
    except KeyboardInterrupt: # CTRL+Cの入力に対応します。
        print("OK.")
        return
    except Exception as e: # その他の例外についてはトレースバックを表示します。
        traceback.print_exc()

# このファイルがモジュールとしてインポートされていない場合にはmain()を呼びます。
if __name__ == "__main__":
    main()

../config/deployment.json

このファイルとディレクトリは最初は存在しないため、手動で作成してください。

()で囲まれた部分を置き換えてください。

{
    "modulesContent": {
        "$edgeAgent": {
            "properties.desired": {
                "schemaVersion": "1.0",
                "runtime": {
                    "type": "docker",
                    "settings": {
                        "minDockerVersion": "v1.25",
                        "loggingOptions": "",
                        "registryCredentials": {
                            "(コンテナーレジストリ名)": {
                                "username": "(コンテナーレジストリ名)",
                                "password": "(下記の方法で取得できるパスワード)",
                                "address": "(コンテナーレジストリ名).azurecr.io"
                            }
                        }
                    }
                },
                "systemModules": {
                    "edgeAgent": {
                        "type": "docker",
                        "settings": {
                            "image": "mcr.microsoft.com/azureiotedge-agent:1.0",
                            "createOptions": "{}"
                        }
                    },
                    "edgeHub": {
                        "type": "docker",
                        "status": "running",
                        "restartPolicy": "always",
                        "settings": {
                            "image": "mcr.microsoft.com/azureiotedge-hub:1.0",
                            "createOptions": "{}"
                        }
                    }
                },
                "modules": {
                    "CPUTemp": {
                        "version": "0.0.1",
                        "type": "docker",
                        "status": "running",
                        "restartPolicy": "always",
                        "settings": {
                            "image": "(コンテナーレジストリ名).azurecr.io/cputemp:0.0.1-arm32v7",
                            "createOptions": "{}"
                        }
                    }
                }
            }
        },
        "$edgeHub": {
            "properties.desired": {
                "schemaVersion": "1.0",
                "routes": {
                    "route": "FROM /* INTO $upstream"
                },
                "storeAndForwardConfiguration": {
                    "timeToLiveSecs": 7200
                }
            }
        },
        "tempSensor": {
            "properties.desired": {}
        }
    }
}

パスワードはポータルより、

コンテナーレジストリ -> (コンテナーレジストリ名) -> アクセスキー

にて取得できます。


これらのファイルを置き換えることで、モジュールのビルドの準備が完了します。

モジュールのビルドとプッシュ

モジュールのビルドはコマンドパレットより行えます。

Ctrl+Shift+Pでコマンドパレットを開き、Build and Push IoT Edge Module Imageを選択します。

ソリューション内に作成したモジュールを選択し、プラットフォームとしてarm32v7を選択します。

これにより、モジュールイメージのビルドとプッシュが完了します。

モジュールのデプロイ

その後、モジュールをデプロイします。

AZURE IOT HUB DEVICESから対象のデバイスを右クリックし、「Create Deployment for Single Device」を選択します。

そして、先ほど作成したconfig/deployment.jsonを選択します。

OUTPUTに「Deployment succeeded」と表示されればデプロイ完了です。

右下のデバイス横の更新マークを押し、CPUTempモジュールの状態がrunningであることをご確認ください。

モジュールの動作の観測

モジュールが動作しているか確認するために、PC側のAzure CLIからイベントの監視を行います。

まず、Azure CLIに拡張機能をインストールします。

$ az extension add --name azure-cli-iot-ext

そして、イベントの監視を開始します。

az iot hub monitor-events --login '接続文字列'

接続文字列は、「AZURE IOT HUB DEVICES」のデバイス名を右クリックし、「Copy Connection String」をクリックすることで取得できます。

5分ごとにCPUの温度が数値で送られてきていれば成功です。

(JSON形式で送られているデータもありますが、これはtempSensorという別のモジュールのものです。)


以上でモジュールの開発手順は終了です。お疲れさまでした。

2
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2