5
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

Azure IoT実践(Azure IoT Edge for Linux on Windows)

Last updated at Posted at 2022-10-14

概要

Azure IoT実践編としてRaspberry Piに温湿度センサーを付け、Azure IoT Hubへ温度と湿度を送信、PowerBIで可視化する構成で作ってみます。
デバイスからAzure IoT Hubへ直接情報を送ってもいいのですが、実際のところではAzure IoT Edgeを経由することが多い?と思うので、自宅のWindows PCをAzure IoT Edgeとして利用しAzure IoT Hubへ情報を流しています(データの加工などは行っていません)。

※Azure IoT Edgeでは、デバイスからの情報の不要部分の削除や集約などを行うことができ、必要なデータだけを送ることで帯域幅コスト削減などが期待できる。
※Raspberry Piに温湿度センサーを付ける、情報を読み取る方法は解説しませんのでそこは他のサイトを参照ください。

構成図と説明

①Raspberry Piから温度・湿度の値をWindows PC(Azure IoT Edge for Linux on WIndows)へ流す
②Windows PCからAzure IoT Hubへそのまま情報を受け渡す(3秒間隔)
③Azure IoT Hubで情報を受信
④Stream AnalyticsでAzure IoT Hubからデータを読み込み、ADLS(Azure Data Lake Storage Gen2)へファイルを出力
⑤DatabricksでADLSのファイルを読み込んで分単位の温度・湿度平均を算出
⑥PowerBIレポートで分毎の温度・湿度変化をグラフ化
構成図.png

環境

  • デバイス:Raspberry Pi 4 Model B Rev 1.2(Raspbian 10)
  • IoT Edge(Windows PC):Windows10 Pro(21H1)
  • IoT Hub:Edgeエージェント Ver1.4、Edgeハブ Ver1.4

構築手順

1.Azureサービスの作成

1.1 Azure IoT Hub

①Azure PortalからIoT Hubを検索
IoT Hub.png
②以下の設定で作成(記載以外はデフォルト)

  • リソースグループ:任意
  • IoT Hub名:任意
  • リージョン:Japan East
  • 価格とスケールティア:F1:Free レベル

1.2 Azure Stream Analytics

①Azure PortalからStream Analytics ジョブを検索
Stream Analytics.png
②以下の設定で作成(記載以外はデフォルト)

  • リソースグループ:Azure IoT Hubを作成したリソースグループ
  • 名前:任意
  • リージョン:Japan East
  • ストリーミングユニット:1

1.3 Azure Data Lake Storage Gen2(ADLS)

①Azure Portalからストレージ アカウントを検索
ADLS.png
②以下の設定で作成(記載以外はデフォルト)

  • リソースグループ:Azure IoT Hubを作成したリソースグループ
  • ストレージ アカウント名:任意
  • リージョン:Japan East
  • 冗長性:ローカル冗長ストレージ(LRS)
  • 階層型名前空間を有効にする:チェック

③デバイスからのメッセージ出力用のコンテナを作成しておく
ADLS2.png

1.4 Azure Databricks

①Azure PortalからAzure Databricksを検索
Databricks.png
②以下の設定で作成(記載以外はデフォルト)

  • リソースグループ:Azure IoT Hubを作成したリソースグループ
  • ワークスペース名:任意
  • リージョン:Japan East
  • 価格レベル:試用版

③クラスタ作成(お金があまりかからないように低スペックで作成)
Databricks2.png

2.Azure IoT Hub設定

①IoT Edge デバイスの追加
 デバイス IDは任意のものを指定し、その他はデフォルト設定
IoT Hub_1.png
IoT Hub_2.png
 プライマリ接続文字列は後で使うので保管しておいてください。
IoT Hub_5.png
 IoT Edgeに届いたメッセージをIoT Hubに転送するよう設定する
IoT Hub_7.png
 ↓
IoT Hub_8.png
 ↓ 名前:allMessagesToHub、値:FROM /messages/* INTO $upstream を設定
IoT Hub_9.png

②デバイスの追加
 デバイス IDは任意、親デバイスに①で作成したIoT Edgeを指定し、その他はデフォルト設定
IoT Hub_3.png
IoT Hub_4.png
 こちらも同様にプライマリ接続文字列は後で使うので保管しておく。
IoT Hub_6.png

3.Raspberry Pi設定①

①以下のコマンドでRaspberry PiにAzure IoT SDKをインストール

Bash
pip3 install azure-iot-device
pip3 install azure-iot-hub

②Gitリポジトリもクローン

Bash
git clone https://github.com/Azure/azure-iot-sdk-python.git

4.Windows PC設定

4.1 Azure IoT Edge for Linux on Windowsをインストール

参考サイト:対称キーを使用して IoT Edge for Linux on Windows デバイスを作成してプロビジョニングする

①PowerShellスクリプト実行ポリシー設定

PowerShellプロンプト
Set-ExecutionPolicy -ExecutionPolicy AllSigned -Force

②IoT Edge for Linux on Windows をダウンロード

PowerShellプロンプト
$msiPath = $([io.Path]::Combine($env:TEMP, 'AzureIoTEdge.msi'))
$ProgressPreference = 'SilentlyContinue'
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
Invoke-WebRequest "https://aka.ms/AzEFLOWMSI-CR-X64" -OutFile $msiPath

③IoT Edge for Linux on Windows をインストール

PowerShellプロンプト
Start-Process -Wait msiexec -ArgumentList "/i","$([io.Path]::Combine($env:TEMP, 'AzureIoTEdge.msi'))","/qn"

④IoT Edge for Linux on Windows のデプロイ
 ライセンス条項はYで同意。Optional diagnostic dataはRを入力。
 「Deployment successful」が表示されれば成功。

PowerShellプロンプト
Deploy-Eflow
IoT Edge_1.png

⑤デバイスをプロビジョニング
 PASTE_DEVICE_CONNECTION_STRING_HEREには2-①で保管していたプライマリ接続文字列を設定

PowerShellプロンプト
Provision-EflowVm -provisioningType ManualConnectionString -devConnString "PASTE_DEVICE_CONNECTION_STRING_HERE"

⑥IoT Edge仮想マシンにログインしモジュールの状態を確認

PowerShellプロンプト
Connect-EflowVm
Bash
sudo iotedge list

 edgeAgent、edgeHubともにrunningになっていればOK(edgeHubが出てこなければしばらく待って再度確認)。
IoT Edge_2.png
 IoT HubのIoT Edgeデバイスもrunningになる。
IoT Edge_3.png

4.2 証明書の作成

4.1でとりあえずIoT HubとIoT Edgeが繋がりましたが、デバイスからIoT Edgeに繋げるのに証明書が必要になるためデモ用証明書(30日間のみ使用可能)を作成します。
参考サイト:IoT Edge デバイスの機能をテストするためのデモ用の証明書を作成する

①OpenSSL のインストール
 参考サイト参照

②証明書作成スクリプト実行のための準備

PowerShellプロンプト
git clone https://github.com/Azure/iotedge.git

mkdir wrkdir
cd .\wrkdir\
cp ..\iotedge\tools\CACertificates\*.cnf .
cp ..\iotedge\tools\CACertificates\ca-certs.ps1 .

Set-ExecutionPolicy -ExecutionPolicy Unrestricted -Scope CurrentUser

. .\ca-certs.ps1

③ルート CA 証明書の作成

PowerShellプロンプト
New-CACertsCertChain rsa

④エッジ CA 証明書の作成
 ※ CA cert nameは任意ではあるが、IoT HubのデバイスIDと同じにしない方がよいらしい。
   今回は「iotEdgeMyPCCACert」にした。

PowerShellプロンプト
New-CACertsEdgeDevice "<CA cert name>"

4.3 証明書をIoT Edge仮想マシンに配置

参考サイト:透過的なゲートウェイとして機能するように IoT Edge デバイスを構成する

①IoT Edge仮想マシンに証明書配置用ディレクトリを作成

PowerShellプロンプト
Connect-EflowVm
Bash
cd ~
mkdir certs
cd certs
mkdir certs
mkdir private
exit

②証明書をIoT Edge仮想マシンにコピー
 pathは4.2-②で作成したwrkdirのパス。CA cert nameは4.2-④で決めた名前。

PowerShellプロンプト
# Copy the IoT Edge device CA certificates
Copy-EflowVMFile -fromFile <path>\certs\iot-edge-device-ca-<CA cert name>-full-chain.cert.pem -toFile /home/iotedge-user/certs/certs/iot-edge-device-ca-<CA cert name>-full-chain.cert.pem -pushFile
Copy-EflowVMFile -fromFile <path>\private\iot-edge-device-ca-<CA cert name>.key.pem -toFile /home/iotedge-user/certs/private/iot-edge-device-ca-<CA cert name>.key.pem -pushFile

# Copy the root CA certificate
Copy-EflowVMFile -fromFile <path>\certs\azure-iot-test-only.root.ca.cert.pem -toFile /home/iotedge-user/certs/certs/azure-iot-test-only.root.ca.cert.pem -pushFile

③証明書へのアクセス権付与
 参考サイトの設定だとうまくいかなかったので、以下のようにした。

PowerShellプロンプト
Invoke-EflowVmCommand "sudo chmod 755 -R /home/iotedge-user/"

④IoT Edgeの構成ファイルに証明書を設定する
 既存の構成ファイルの内容はEdge用になっていない場合があるためリネームして使われないようにし、Edge用テンプレートを構成ファイルにする。

PowerShellプロンプト
Connect-EflowVm
Bash
#構成ファイルの場所に移動
cd /etc/aziot

#既存の構成ファイルをリネーム
sudo mv config.toml config.toml.bk

#Edge用テンプレートを構成ファイルにする
sudo cp config.toml.edge.template config.toml

 構成ファイルを開いて、以下のように編集する。

Bash
sudo vim config.toml

 ・provisioning部分のコメントを外し、connection_stringを2-①で保管していたプライマリ接続文字列を設定
IoT Edge_4.png

 ・trust_bundle_cert部分のコメントを外し、ルートCA証明書のパスを設定
IoT Edge_5.png

 ・edge_ca部分のコメントを外し、デバイスCA証明書とデバイスCA秘密キーのパスを設定
IoT Edge_6.png

 構成ファイルの変更を適用。

Bash
sudo iotedge config apply

 モジュールの状態がrunningになっていることをsudo iotedge listコマンドで確認。
 runningになっていない場合はsudo iotedge checkコマンドを実行しエラー内容を確認。
IoT Edge_2.png

4.4 IoT Edge仮想マシンのポート開放

 今回はMQTTプロトコルで通信するため8883ポートだけ開放。

PowerShellプロンプト
# Open MQTT port
Invoke-EflowVmCommand "sudo iptables -A INPUT -p tcp --dport 8883 -j ACCEPT"

# Save the iptables rules
Invoke-EflowVmCommand "sudo iptables-save | sudo tee /etc/systemd/scripts/ip4save"

4.5 Windows PCのポート開放とポート転送設定

 FWの受信設定で8883ポートを許可
IoT Edge_7.png

 デバイスからIoT Edge仮想マシンに通信するにはWindows PCを経由する必要があるため、デバイス⇒Windows PC⇒IoT Edge仮想マシンという流れになる。
 Windows PCはデバイスからのアクセスをIoT Edge仮想マシンに流す必要があるためその設定を入れる。

PowerShellプロンプト
netsh interface portproxy add v4tov4 listenport=8883 listenaddr=<Windows PCIPアドレス> connectport=8883 connectaddress=<IoT Edge仮想マシンのIPアドレス>

 IoT Edge仮想マシンのIPアドレスは以下のコマンドで確認できる。

PowerShellプロンプト
Get-EflowVmAddr

5.Raspberry Pi設定②

①IoT Edge仮想マシンに配置したルート CA 証明書をデバイス側にも配置
Raspberry_1_1.png

②IoT Edgeとの通信プログラム作成
 3-②でクローン下azure-iot-sdk-python内のサンプルプログラムを少し書き換えて作ります。
Raspberry_2.png

simple_send_message.sh(プログラム実行用のシェル)
#! /bin/bash

echo "Run simple_send_message.py"

#引数:接続文字列
export IOTHUB_DEVICE_CONNECTION_STRING="<2-②で保管したプライマリ接続文字列>;GatewayHostName=<IoT Edge仮想マシン名>"

#引数:ルートCA証明書パス
export IOTHUB_CA_CERTIFICATE_PATH="/home/pi/Desktop/Azure IoT/azure-iot-test-only.root.ca.cert.pem.iotEdgeMyPC"

python3 simple_send_message.py

read -p "Press [Enter] key to resume."
simple_send_message.py(プログラム本体)
import osimport time
import asyncio
import Adafruit_DHT as DHT
from azure.iot.device.aio import IoTHubDeviceClient

async def main():
    # IoT Edge -> Hub Connection Ver
    conn_str = os.getenv("IOTHUB_DEVICE_CONNECTION_STRING")
    ca_path_str = os.getenv("IOTHUB_CA_CERTIFICATE_PATH")
    certfile = open(ca_path_str)
    root_ca_cert = certfile.read()
    
    #MQTT(port:8883)
    device_client = IoTHubDeviceClient.create_from_connection_string(connection_string=conn_str, server_verification_cert=root_ca_cert)
    
    # Connect the device client.
    await device_client.connect()

    while True:
      # Send a single message
      print("Sending message...")
      SENSOR_TYPE = DHT.DHT22
      DHT_GPIO = 4
      h,t = DHT.read_retry(SENSOR_TYPE, DHT_GPIO)
      send_message = "{\"temprature\":" + "{0:0.1f}".format(t) + ", \"humidity\":" + "{0:0.1f}".format(h) + "}"
      print(send_message)
      await device_client.send_message(send_message)
      print("Message successfully sent!")

      time.sleep(3)

    # Finally, shut down the client
    await device_client.shutdown()

if __name__ == "__main__":    asyncio.run(main())

 simple_send_message.shの<IoT Edge仮想マシン名>Get-EflowVmNameコマンドで取得できます。

PowerShellプロンプト
Get-EflowVmName

 simple_send_message.pyの7~11行目では引数を取得して、証明書を読み込んでいます。

simple_send_message.pyの7~11行目
    # IoT Edge -> Hub Connection Ver
    conn_str = os.getenv("IOTHUB_DEVICE_CONNECTION_STRING")
    ca_path_str = os.getenv("IOTHUB_CA_CERTIFICATE_PATH")
    certfile = open(ca_path_str)
    root_ca_cert = certfile.read()

 simple_send_message.pyの13~17行目ではIoT Edge仮想マシンに接続しています。

simple_send_message.pyの13~17行目
    #MQTT(port:8883)
    device_client = IoTHubDeviceClient.create_from_connection_string(connection_string=conn_str, server_verification_cert=root_ca_cert)
    
    # Connect the device client.
    await device_client.connect()

 simple_send_message.pyの19~30行目は、3秒おきに温湿度センサーの情報を取得し、温度と湿度をIoT Edge仮想マシンに送り続ける内容になっています。
 h,t = DHT.read_retry(SENSOR_TYPE, DHT_GPIO):温湿度センサーから温度、湿度を取得
 send_message = "{\"temprature\":" + "{0:0.1f}".format(t) + ", \"humidity\":" + "{0:0.1f}".format(h) + "}":JSON形式のメッセージを作成
 await device_client.send_message(send_message):IoT Edge仮想マシンにメッセージを送信

simple_send_message.pyの19~30行目
    while True:
      # Send a single message
      print("Sending message...")
      SENSOR_TYPE = DHT.DHT22
      DHT_GPIO = 4
      h,t = DHT.read_retry(SENSOR_TYPE, DHT_GPIO)
      send_message = "{\"temprature\":" + "{0:0.1f}".format(t) + ", \"humidity\":" + "{0:0.1f}".format(h) + "}"
      print(send_message)
      await device_client.send_message(send_message)
      print("Message successfully sent!")

      time.sleep(3)

③Host設定
 ②で設定したIoT Edge仮想マシン名の名前解決ができないのでとりあえずHostsに記載
 IPはWindows PCに投げるのでWindows PCのものにする。

Bash
sudo vim /etc/hosts
Raspberry_3.png

④simple_send_message.shの実行
 simple_send_message.shを実行し正常に送信できていることを確認。
Raspberry_4.png

6.Azure IoT Explorer

送信はできているとしてIoT Hubまでメッセージがに届いているかをAzure IoT Explorerで確認してみる。
①インストール
 参考サイト参照:Azure IoT エクスプローラーをインストールして使用する

②IoT Hubを登録
 IoT Hubの共有アクセスポリシーの接続文字列を使うのでコピーしておく
IoT Explorer_1.png
 IoT ExplorerのConnection_stringに接続文字列を貼り付けてSave
IoT Explorer_2.png

③メッセージ監視
 ②で登録したIoT Hubを選択
IoT Explorer_3.png
 デバイスを選択
IoT Explorer_4.png
 TelemetryでStartをクリックし、下の欄にメッセージ内容が表示されればデバイス⇒IoT Edge⇒IoT Hubへと正常にメッセージが流れてきたことを確認できる。
 ※simple_send_message.shを実行し、メッセージ送信中の状態であること
IoT Explorer_5.png

7.Azure Stream Analytics設定

①入力の設定
Stream Analytics_1.png
Stream Analytics_2.png
 以下を設定(記載以外はデフォルト)

  • 入力のエイリアス:任意
  • サブスクリプションからIoT Hubを選択する:チェック
  • サブスクリプション:自身のサブスクリプション
  • IoT Hub:1.1で作成したIoT Hub
  • コンシューマーグループ:$Default
  • 共有アクセスポリシー名:iothubowner

②出力の設定
Stream Analytics_3.png
Stream Analytics_4.png
 以下を設定(記載以外はデフォルト)

  • 出力のエイリアス:任意
  • サブスクリプションからBlob StorageまたはADLS Gen2を選択する:チェック
  • サブスクリプション:自身のサブスクリプション
  • ストレージアカウント:1.3で作成したADLS
  • コンテナー:既存のものを使用にチェックし、1.3で作成したコンテナを選択

③クエリの設定
 入力のエイリアス名出力のエイリアス名には①②で決めた名前を設定
Stream Analytics_5.png
 クエリのテストを実行すると結果が表示されればOK(simple_send_message.shは実行中であること)
Stream Analytics_6.png

④ジョブを開始
Stream Analytics_7.png

8.Azure Data Lake Storage Gen2(ADLS)確認

jsonファイルが作成されていればOK
ADLS.png

9.Azure Databricksコード実行

 DatabricksにADLSのiotコンテナーをマウントしておき以下のようなコードで、JSON読み込み⇒3秒おきのデータを分単位の平均値に変換したiot_avgテーブルを作成
 マウント方法は参考サイトなどを参考
Databricks.png
 

10.PowerBIレポート作成

 Databricksにアクセスしてiot_avgテーブルを読み込んでグラフ化
PowerBI_1.png
PowerBI_2.png
PowerBI_3.png
 ↑サーバホスト名HTTPパスにはDatabricksのクラスタのServer HostnameHTTP Pathを設定
PowerBI_4.png
 サインインして接続
PowerBI_5.png
 iot_avgテーブルを読み込んで任意のグラフを作成
PowerBI_6.png

最後まで読んでいただきありがとうございました。
Azure IoT Edge for Linux on Windowsを経由させるというだけで結構四苦八苦したので備忘も兼ねて残しておきます。

5
3
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
5
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?