この記事には広告を含む場合があります。記事内で紹介する商品を購入することで、当サイトに売り上げの一部が還元されることがあります。
はじめに
今回はRaspberry Pi 4 Model B、DHT22温湿度センサー、Node-RED、Azure IoT HubそしてWeb Appsを使用してセンサーから取得した温湿度データをリアルタイムのグラフとして表示するアプリを作る方法を解説します。
データを保存して表示するというよりは、リアルタイムの数値の変化を見ることができるWebアプリケーションです。次回以降Google スプレッドシートにデータを保存するのも試してみたいと思います。
DHT22センサーとの接続方法はこちらの記事をご参照ください。


完成物
完成すると以下のようなリアルタイムで温湿度のグラフを描画するアプリを作ることができます。
このアプリはマイクロソフトのチュートリアルのコードを使用して作成しています。アプリを開いてからでないとグラフを描画できない、タイムゾーンが日本じゃないなど修正する箇所はいくつもありますが、最低限温度と湿度のリアルタイムの変化を見ることができます。

システム構成
システムの構成は次の図のようになっています。DHT22センサーから温湿度情報を取得しラズパイに送信する、そして送信されたデータをNode-REDを経由してAzure IoT Hubに送信します。IoT Hubに送信されたデータをWeb Apps上にデプロイされたアプリケーションでグラフ化して表示します。

環境 (Raspberry Pi)
ソフトウェア | バージョン |
Git | 2.20.1 |
Node.js | 14.18.1 |
npm | 6.14.15 |
Python | 3.7.3 |
Raspberry Pi OS | 10.11 |
環境 (Mac)
ソフトウェア | バージョン |
Azure CLI | 2.30.0 |
Git | 2.30.1 |
Node.js | 16.13.0 |
npm | 8.1.10 |
macOS | 10.11 Monterey 12.0.1 |
Node-REDとは
Node-REDとはフローベースのプログラミングツールです。Node.js上で構築されており、ノードと呼ばれる機能を含むパーツ同士をつなぎ合わせフロー(流れ)を作ります。今回はこれを使って、視覚的にわかりやすくシステムを構築していきます。
Node-REDのインストール方法
ターミナルで以下のコマンドを実行します。
bash <(curl -sL https://raw.githubusercontent.com/node-red/linux-installers/master/deb/update-nodejs-and-nodered)

いくつかの質問が表示されますので”y”と入力して進めましょう。

Node-REDを起動するには以下の2つの方法があります。どちらの方法でも起動できるので好みの方法で起動してください。
- node-red-startコマンドを実行する
- ラズパイのメニューから実行する
以下はNode-REDを起動するコマンドです。
node-red-start


アドレスバーに127.0.0.1:1880と入力してNode-REDにアクセスします。同じネットワーク内ならラズパイからだけでなく、お使いのPCからも(Wi-FiのIPアドレス):1880でアクセスすることができます。

Welcome画面が表示されればアクセスに成功です。かんたんなチュートリアルがあるので進めておきましょう。
DHT22センサーの情報取得
まずはDHT22センサーが正常に動いているかを確認することもかねてNode-REDでDHT22センサーからの温湿度データの取得と表示をおこないます。
まずはDHT22センサーから温湿度情報を取得します。右上のハンバーガーメニューから「パレットの管理」→「ノードを追加」をクリックし、node-red-contrib-dht-sensorを追加します。

「追加」をクリックします。

左側の共通パネルからInjectノード、Debugノードとrpi-dht22ノードをドラッグアンドドロップでフローに追加します。

ノードのポートをクリックしながらドラッグしてノード同士を接続します。左側からInjectノード、rpi-dht22、そしてDebugノードの順に接続します。

各ノードの構成は次の画像のようになっています。Injectノードの繰り返しの頻度は任意の間隔を設定してください。無料の枠で最大限データを取得するには10分に1回の間隔ぐらいが良さそうです。ちなみに取得できるテレメトリは1ヶ月で8,000メッセージまでになっています。
8,000 メッセージ / 31 日(1ヶ月)≈ 258 メッセージ / 1日 = 258 メッセージ / 24 時間 = 10.75 メッセージ / 1時間 = 10.75 メッセージ / 60 分 ≈ 1 メッセージ / 6 分
になりますので、このあたりで好きな間隔を設定してください。今回は1メッセージ / 10 分で設定しました。



この時点ではノードやフローはエディタ上にしか存在しないので サーバにデプロイする必要があります。デプロイボタンをクリックするとサーバにデプロイされます。
デプロイボタンを押したあとはInjectノードの左端をクリックしてフローを実行します。
右側のデバッグコンソールに温湿度が表示されればセンサーは正常に温湿度を取得できています。画像ではpayloadに25.30とあり、これは気温が25.30℃という意味で、humidity: “39.70” となっているところは湿度が39.70%という意味です。(乾燥注意)

以下のJSONコードを読み込むことでフローをインポートすることができます。Pin numberはご自身のものを入力してください。
[ { "id": "2a182b74.7d87c4", "type": "tab", "label": "フロー 1", "disabled": false, "info": "" }, { "id": "f0a97205.32302", "type": "rpi-dht22", "z": "2a182b74.7d87c4", "name": "", "topic": "rpi-dht22", "dht": "22", "pintype": "0", "pin": "4", "x": 380, "y": 240, "wires": [ [ "9cce35f3.4c31b8" ] ] }, { "id": "2f9efdeb.2ff4f2", "type": "inject", "z": "2a182b74.7d87c4", "name": "", "topic": "", "payload": "{\"test\":\"test\"}", "payloadType": "json", "repeat": "60", "crontab": "", "once": false, "onceDelay": 0.1, "x": 200, "y": 240, "wires": [ [ "f0a97205.32302" ] ] }, { "id": "9cce35f3.4c31b8", "type": "debug", "z": "2a182b74.7d87c4", "name": "", "active": true, "tosidebar": true, "console": false, "tostatus": false, "complete": "true", "targetType": "full", "x": 550, "y": 240, "wires": [] }
]
AzureでのWebアプリ作成
DHT22センサーの稼働を確認できたました。今からはセンサーで取得したデータをAzureに送信し、そのデータをもとにリアルタイムで温湿度のグラフを描画するWebアプリケーションを作成していきます。
Azureの登録方法などは各自検索してください。また、今回作成するWebアプリはすべて無料の範囲でできるものになっています。
手順の大まかな流れは次の通りです。
- Azureでリソースグループの作成
- AzureでIoT Hubの追加
- Node-RED経由でテレメトリ(収集したデータ)を収集・送信するための設定を行う
- 公式ドキュメントを参考にWebアプリを作成する
- Node-RED経由でテレメトリを送信する
- ローカルのWebアプリに温湿度を表示する
- WebアプリをApp Serviceにデプロイする
AzureでIoT Hubリソースを作成する
まずはリソースグループを作成します。リソースグループは、デバイスやWebアプリをなどのリソースをまとめて管理するためのグループです。
Azure Portalにアクセスしてください。https://portal.azure.com

Azureサービスの下にあるリソースの作成をクリックします。

左側のカテゴリからモノのインターネット (IoT)を選択し、”IoT Hub”の下の作成をクリックします。

サブスクリプションを選択し、任意のリソースグループの名前を入力してください(画像の場合はAgriTech)

基本の設定が終わったら「次へ:ネットワーク」をクリックします。
ネットワークタブの接続の構成でパブリックアクセスを選択します。

「次へ:管理」をクリックします。
管理タブでスケーリングベルトユニット、ロールベースのアクセス制御 (RBAC)とスケーリングを設定します。設定は以下のように行ってください。
スケーリングとユニット→F1 Free レベルを選択
Defender for IoT→オフ
ロールベースのアクセス制御→共有アクセスポリシー・RBAC
IoTハブデータ共有作成者ロールに自分を割り当てる→チェックをつける


「次へ:タグ」をクリックします。
次はタグの設定です。今回はタグの設定をしませんので、そのままで「次へ:確認および作成」をクリックします。

確認および作成タブで設定が正しく行われているかを確認し、作成ボタンを押します。

デプロイの進行が始まると右上に通知がポップアップしますので、それをクリックします。もしくは、右上のベルマークアイコンをクリックします。

デプロイが完了すると、「展開が完了しました」とポップアップが右上に表示されます。ポップアップの「リソースに移動」をクリックして、リソースに移動します。

IoT HubのTempAndHumidリソースに移動したらデバイス管理メニューの中からデバイスを選択します。
次のステップではIoT Hubに温湿度センサーを登録します。
デバイスの追加
左側のパネルのデバイス管理をクリックしたら、デバイスの追加をクリックします。

デバイスの作成では以下のように設定します。
デバイスIDを→DHT22
認証の種類→対称キー
自動生成キー→チェックする
このデバイスをIoTハブに接続する→有効化

一通り設定が終わったら保存ボタンをクリックします。
デバイスが正常に追加されるとデバイスの一覧に追加したDHT22が表示されます。

Node-REDでIoT Hubにテレメトリを送信する設定をおこなう
次はNode-REDからIoT Hubにテレメトリを送信するための設定をおこないます。IoT Hubにテレメトリを送信するにはnode-red-contrib-azure-iot-hubノードが必要です。
Node-REDを起動し、右上のハンバーガーメニューからパレットの管理をクリックします。左側のメニューからパレットを選択し、node-red-contrib-azure-iot-hubノード(以下IoT Hubノードと呼びます)を追加します。

ポップアップが出たら追加をクリックします。

左側のノード一覧からfunctionノードとIoT Hubノードをフローに追加して以下の画像のようにワイヤーで接続します。

functionノードをダブルクリックし次のコードのように設定します。デバイスIDは前のステップで設定したDHT22を、主キーはデバイスID (DHT22)をクリックした画面から確認することができます。
const data =
{ "messageId":0, "deviceId":"デバイスID", "temperature":msg.payload, "humidity":msg.humidity
}
msg.payload = { "deviceId":"デバイスID", "key":"主キー", "protocol":"amqp", "data":data
};
return msg;


IoT Hubノードをダブルクリックして以下のように設定します。
Name → Azure IoT Hub
Protocol → amqp
Hostname → IoT Hub内の


以下のJSONコードを読み込むことでフローをインポートすることができます。主キーとHostnameはご自身のものを入力してください。
[ { "id": "2a182b74.7d87c4", "type": "tab", "label": "フロー 1", "disabled": false, "info": "" }, { "id": "f0a97205.32302", "type": "rpi-dht22", "z": "2a182b74.7d87c4", "name": "", "topic": "rpi-dht22", "dht": "22", "pintype": "0", "pin": "4", "x": 380, "y": 240, "wires": [ [ "9cce35f3.4c31b8", "57de7972cbabf99b" ] ] }, { "id": "2f9efdeb.2ff4f2", "type": "inject", "z": "2a182b74.7d87c4", "name": "", "props": [ { "p": "payload" }, { "p": "topic", "vt": "str" } ], "repeat": "600", "crontab": "", "once": false, "onceDelay": 0.1, "topic": "", "payload": "{\"test\":\"test\"}", "payloadType": "json", "x": 200, "y": 240, "wires": [ [ "f0a97205.32302" ] ] }, { "id": "9cce35f3.4c31b8", "type": "debug", "z": "2a182b74.7d87c4", "name": "", "active": true, "tosidebar": true, "console": false, "tostatus": false, "complete": "true", "targetType": "full", "statusVal": "", "statusType": "auto", "x": 570, "y": 100, "wires": [] }, { "id": "57de7972cbabf99b", "type": "function", "z": "2a182b74.7d87c4", "name": "", "func": "const data =\n{\n \"messageId\":0,\n \"deviceId\":\"DHT22\",\n \"temperature\":msg.payload,\n \"humidity\":msg.humidity\n}\nmsg.payload = {\n \"deviceId\":\"DHT22\",\n \"key\":\"主キー\",\n \"protocol\":\"amqp\",\n \"data\":data\n};\nreturn msg;", "outputs": 1, "noerr": 0, "initialize": "", "finalize": "", "libs": [], "x": 580, "y": 240, "wires": [ [ "79a4c51a60f8b8fc" ] ] }, { "id": "79a4c51a60f8b8fc", "type": "azureiothub", "z": "2a182b74.7d87c4", "name": "Azure IoT Hub", "protocol": "amqp", "credentials": {}, "x": 800, "y": 240, "wires": [ [] ] }
]
デプロイボタンをクリックし、Injectノードの左側にあるボタンをクリックします。

設定が正しく行われていればIoT Hubでテレメトリの受信を確認することができます。また、Node-REDのデバッグパネルでも同様に温湿度を確認することができます。

Webアプリを作成して温湿度データを視覚化する
ここからのステップでは取得した温湿度データをリアルタイムでグラフ表示するWebアプリの作成方法の説明です。
基本的にはMicrosoftのチュートリアルに沿って説明していきますが、公式のチュートリアルは正直丁寧さにかけていてわかりづらかったり、間違っていたりと大変でしたのでそこらへんを丁寧に説明していきたいと思います。
ターミナルを開き、HomebrewでAzure CLIをインストールします。Homebrewをインストールしていない場合はインストールしてから実行してください。

以下のコマンドを実行してAzure CLIにログインします。
az login

使用するアカウントを選択します。

ログインに成功するとこのような画面が表示されます。

ターミナルに戻ってもログインできたことが確認できます。

以下のコマンドを実行してIoT Hubへコンシューマーグループを追加します。
az iot hub consumer-group create --hub-name YourIoTHubName --name YourConsumerGroupName
YourIoTHubNameをTempAndHumidに、YourConsumerGroupNameをAgriTechSensorsに設定します。IoTHubNameはIoT Hubリソースを作成したときの名前です。ConsumerGroupNameは任意のものを設定できます。今回はAgriTechSensorsと名付けました。
az iot hub consumer-group create --hub-name TempAndHumid --name AgriTechSensors

IoT Hubのサービス接続文字列を取得するには次のコマンドを実行します。
az iot hub connection-string show --hub-name YourIotHub --policy-name service
YourIotHubにはIoT Hub名のTempAndHumidを入力します。
az iot hub connection-string show --hub-name TempAndHumid --policy-name service

接続文字列は以下のようになります。
"HostName={YourIotHubName}.azure-devices.net;SharedAccessKeyName=service;SharedAccessKey={YourSharedAccessKey}"
任意のディレクトリに移動して下記のコマンドでWebアプリのコードをクローンします。
git clone https://github.com/Azure-Samples/web-apps-node-iot-hub-data-visualization.git
cd web-apps-node-iot-hub-data-visualization
クローンが完了したらクローンしたディレクトリに移動してください。

ここがドキュメントどおりにコマンドを実行して困ったステップでした。公式のチュートリアルではsetコマンドを使って環境変数を設定していたのですが、何度設定してもうまく行かないためハードコードをしたりググったりと苦労しました。
結論としては公式のチュートリアルはWindows環境での方法で説明されておりmacOS (Linux Shell) ではexportコマンドで環境変数を設定する必要がありました。
環境変数を設定するには以下のコマンドを実行します。
export IotHubConnectionString=YourIoTHubConnectionString
export EventHubConsumerGroup=YourConsumerGroupName
YourIoTHubConnectionStringにはSTEP4で取得した接続文字列を入力します。
YourConsumerGroupNameにはSTEP3で設定した”AgriTechSensors”を入力します。

以下のコマンドを実行してWebアプリを実行します。
npm install
npm start
ターミナルでアプリが起動していることを確認できたらhttp://localhost:3000
でアプリにアクセスします。正常にデータが取得できていれば温湿度データが設定時間の間隔でリアルタイムで表示されます。また、ターミナルにも取得されているデータの詳細が表示されます。

さて、これでローカルでWebアプリを起動し温湿度データを視覚化することができました。しかし、これではアプリを使用したいときに毎回起動しなくてはいけなくめんどくさいです。次のステップではこのWebアプリをApp Service上にホストし、インターネットからアクセスできるようにしていきます。
Webアプリをホストする
Azure App ServiceのWeb Appsは、Web アプリをホストするためのサービスとしてのプラットフォーム (PaaS) を提供しています。この記事では無料で使えるApp Serviceプランを使ってアプリをホストします。
Freeレベル(無料プラン)を使用してApp Serviceプランを作成するには次のコマンドを実行します。
az appservice plan create --name <app service plan name> --resource-group <your resource group name> --sku FREE
<app service plan name>にはApp Serviceの任意の名前をつけます。RealTimeTempAndHumidを入力します。
<your resource group name>にはリソースグループの名前を入力します。AgriTechを入力します。

次のコマンドを実行してWebアプリをプロビジョニングします。
az webapp create -n <your web app name> -g <your resource group name> -p <your app service plan name> --runtime "node|14-lts" --deployment-local-git
<your web app name>には任意のWebアプリの名前を入力します。Web アプリ名はグローバルに一意である必要があり、大文字と小文字の英字、数字、およびハイフンを使用できます。 使用している Node.js ランタイムのバージョンに応じて、--runtime
パラメーターにノード バージョン 10.6 以降を指定してください。
<your resource group name>にはリソースグループ名を入力します。AgriTechを入力します。
<your app service plan name>にはApp Service名を入力します。RealTimeTempAndHumidを入力します。

コマンド実行後色々と表示されます。

以下のコマンドを実行して環境変数の設定をおこないます。
az webapp config appsettings set -n <your web app name> -g <your resource group name> --settings EventHubConsumerGroup=<your consumer group> IotHubConnectionString="<your IoT hub connection string>"
<your web app name>にはWebアプリの名前を入力します。CheckTempAndHumidを入力します。
<your resource group name>にはリソースグループの名前を入力します。AgriTechを入力します。

以下のコマンドを実行してWebソケットプロトコルを有効化します。
az webapp config set -n <your web app name> -g <your resource group name> --web-sockets-enabled true
<your web app name>にはWebアプリの名前を入力します。CheckTempAndHumidを入力します。
<your resource group name>にはリソースグループの名前を入力します。AgriTechを入力します。

WebアプリがHTTPSリクエストのみを受信するようにするためには次のコマンドを実行します。
az webapp update -n <your web app name> -g <your resource group name> --https-only true
<your web app name>にはWebアプリの名前を入力します。CheckTempAndHumidを入力します。
<your resource group name>にはリソースグループの名前を入力します。AgriTechを入力します。

コードを App Serviceにデプロイするには、ユーザーレベルのデプロイ資格情報を使用します。以前に設定したことがない場合は以下のコマンドを実行して資格情報を設定してください。
az webapp deployment user set --user-name <your deployment user name>
<your deployment user name>には任意のユーザー名を入力します。コマンドを実行するとパスワードの入力も求められますのでパスワードは長さが8文字以上で、文字、数字、記号のうち2つを含む必要があります。

Git URLを取得するには以下のコマンドを実行します。
az webapp deployment source config-local-git -n <your web app name> -g <your resource group name>
<your web app name>にはWebアプリ名を入力します。CheckTempAndHumidを入力します。
<your resource group name>にはリソースグループの名前を入力します。AgriTechを入力します。

App ServiceのWebアプリのGitリポジトリを参照するリモートをクローンに追加するには以下のコマンドを実行します。
git remote add webapp <Git clone URL>
<Git clone URL>にはSTEP7で取得したURLを入力します。

App Serviceにコードをプッシュするには以下のコマンドを実行します。公式のチュートリアルとは少し違いますので注意してください。(公式のチュートリアルではmasterではなくmainになっています)
git push webapp master:master

パスワードの入力を求められたら、STEP5で作成したユーザーレベルのデプロイ資格情報を入力します。 必ず、App Serviceリモートのメインブランチにプッシュしてください。

以下のコマンドを実行してアプリが正常にApp Serviceで実行されているかを確認します。
az webapp show -n <your web app name> -g <your resource group name> --query state
<your resource group name>にはリソースグループの名前を入力します。AgriTechを入力します。

ブラウザーで https://Webアプリの名前.azurewebsites.net
にアクセスします。 Webアプリをローカルで実行したときに表示されたものと同様のWeb ページが表示されるはずです。DHT22センサーが実行中でデータを送信していれば、センサーによって送信された最新の50個の温度と湿度を示す測定値の実行中のプロットが表示されるはずです。

まとめ
Azure IoT HubとNode-REDを使えば比較的簡単にセンサーからデータを取得し、それを視覚化することができました。自分がこの記事と同じ手順でアプリを構築したときは様々なエラーに遭遇しました。エラーに遭遇するたびにググってStack Overflowを見たり、公式チュートリアルのトラブルシューティングを見たりして解決していきました。
このWebアプリは使いやすいとはまだまだ言えないです。例えば、データの表示はアクセスしたときからのものしか表示されなかったり(データベースが必要?)、表示時間がUTC(多分)になっていて把握しづらかったり、メモリの線や縦軸横軸が上下に動くなどまだまだ実用性にはかけています。解決するためにはコードを改修していく必要があります。
ともかく、DHT22センサーをAzureを組み合わせてデータを取得するイメージは掴めたと思います。この記事がお役に立てれば幸いです。