前回の記事では、Azure IoT Hub で受信したデータをデータベース CosmosDB へ自動的に保存しました。
取得したデータをデータベースへ保存しておくだけでなく、クラウド上で処理を行うことが出来ると応用範囲がぐっと広がります。
ユーザが作成したプログラムを Azure のクラウド上で実行する方法には、いくつか種類があります。
(Azure Functions, Batch, Logic Apps など)
この記事では、Azure Functions サービスを使ってクラウド上で処理を行う方法を環境構築から紹介し、IoT Hub でデータが受信されるたびに処理を走らせるところまで解説します。
関数作成用ローカル環境の準備
ローカルなパソコン上で Azure Functions 用の関数の作成を行うための準備を行います。
この記事では、多機能かつフリーな開発ツールである Visual Studio Code を用いる方法を紹介します。
Visual Studio Code の環境作成
Visual Studio Code のインストール
以下のサイトを参考に、お使いのパソコンへ Visual Studio Code をインストールしてください。
[リンク] Visual Studio Code – Code Editing. Redefined
拡張機能 Azure Functions for Visual Studio Code のインストール
Azure Functions for Visual Studio Code は、開発した関数をローカルなパソコン上でテスト実行したり、作成した関数を Visual Studio Code の GUI 上から Azure へアップロード (デプロイ) したりできる便利なツールです。
拡張機能 C# for Visual Studio Code のインストール
C# for Visual Studio Code は Visual Studio Code でソースコードの編集を支援してくれる便利なツールです。
必須の機能ではありませんが、今回の記事では C# によるサンプルコードを紹介するので、インストールしておくことをお勧めします。
Azure Functions Core Tools のインストール
以下のサイトを参考に、Azure Functions Core Tools をインストールしてください。
[リンク] Core Tools を使用してローカルで Azure Functions を開発する | Microsoft Learn
.NET Core SDK のインストール
今回は C# で Azure Functions を開発するため、 .NET Core SDK をインストールします。
以下のサイトから、開発用 パソコンの OS に対応するバージョンをダウンロードし、インストールしてください。
[リンク] .NET のダウンロード
なお、上記のWEBページ上で「すべての Microsoft .NET バージョン」というリンクをクリックすると、下記のように最新版以外もダウンロードすることが出来ます。
当記事のサンプルでは .NET 6.0 向けのコードを紹介しているので、.NET 6.0 をダウンロードしてインストールしてください。他のバージョンとも共存できるので、最新である .NET 8.0 等もインストールして大丈夫です。
開発環境の動作確認:簡単なHTTPトリガー関数の作成とローカル実行
簡単なHTTPトリガー関数を作成
開発環境のテスト用に、HTTP トリガーを使ったシンプルな関数を自動生成してみます。
以下の手順でコードを生成してください。
もし自動生成された sln ファイルの名前に”generated” とついていたら、ファイル名からその部分を取り払ってください。
ローカルでの動作確認
F5 キーを押すことで、作成した関数をローカル環境で試すことが出来ます。
ターミナルに表示された URL をブラウザで開いてください。
うまく動作していれば、以下のようにブラウザにメッセージが表示されます。
さらに、URL へ 「?name=あいうえお」と追加してみましょう。
C# のコードの内容通り、メッセージが変わります。
以上で、開発環境が正しく導入されたことを確認することができました。
Visual Studio Code の ターミナル上で Ctrl + x を押せば実行を中断することができます。
クラウド上での関数の実行方法
次に、先ほどのサンプル関数をクラウド上へ配置 (デプロイ) し、クラウド上で実行する手順を説明します。
Azure に「関数アプリ」リソースを作成
関数をクラウド上に配置するには、まず配置先となる「関数アプリ」リソースが必要です。
Azure ポータルへログインし、下記の手順で
関数のデプロイ
まず、Visual Studio Code で Azure へサインインします。
すると、Webブラウザが自動的に開かれるので、ブラウザ上で Azure へのログイン操作を行ってください。
ブラウザを閉じたら再び Visual Studio Code で操作を続けます。
クラウド上の関数を実行
このサンプル関数は HTTP トリガなので、URL へアクセスすれば動作させることが出来ます。
クラウド上の関数へアクセスするための URL は、Azure ポータルの関数アプリのページから以下の様に取得することが出来ます。
取得したURLへパソコンの Web ブラウザからアクセスしてください。以下の様に、ローカル実行時と同様の結果を得ることができます。
ログ出力の確認
自動生成された C# のコードには、以下の様にログへ情報を出力している部分があります。
log.LogInformation("C# HTTP trigger function processed a request.");
この様にして出力されたログは、Azure ポータルの関数アプリのページで確認することができます。
以上が、Azure Functions に自作の関数を配置して実行を確認するために最低限必要となる手順です。
CosmosDB トリガー関数
細かくは、以下のステップが必要となるので、それぞれについて紹介していきます。
・CosmosDB トリガー関数の自動生成
・データベースへの接続文字列を格納した環境変数をクラウド上に新規作成
・CosmosDB トリガー関数内から上述の環境変数を参照
CosmosDBトリガー関数を作成
CosmosDB トリガー関数の自動生成
前述の「簡単なHTTPトリガー関数を作成」と同様の手順で、CosmosDBトリガー関数の作成を開始してください。
HTTP トリガ関数の時と表示されるメニューにいくつか相違点がありますが、基本的な手順は同じです。
異なる部分だけ抜粋して以下に紹介します。
CosmosDB アカウント名、データベース名、コンテナ名が間違っているとトリガーかかからないので注意してく ださい。大文字・小文字も区別されます。
一通りの設定が済むと、自動的にコードが生成されます。
クラウド上へ新しい環境変数を追加
CosmosDB と関数を連携させるために、クラウド上にデータベースへの接続文字列を格納した環境変数が必要なので、以下の手順で追加してください。
- データベースへ接続するためのプライマリ接続文字列を Azure ポータル上で取得する。
- Visual Studio Code を操作してクラウド上に新しい環境変数 CosmosDbConnectionString を作成し、値として上述のプライマリ接続文字列を与える。
- Azure ポータル上の環境変数設定を、ローカル環境にも反映
データベースへ接続するためのプライマリ接続文字列を Azure ポータル上で取得
クラウド上へ新しい環境変数を追加
この操作はローカル PC 上の Visual Studio Code で行いますが、あくまでもクラウド環境に対する設定操作を Visual Studio Code を介して行っているだけです。
そのため、ローカル開発環境上のプロジェクトには影響を与えません。
Azure ポータル上の環境変数設定を、ローカル環境にも反映
この操作は、関数を動作させることとは関係が無いため省いても構いません。ただ今後コードを拡張したり管理したりする際に、クラウド上の環境変数についての情報がローカルにも存在した方が良いため行っておきます。
関数内から新しい環境変数を参照
ソースコード内の Connection 変数の値を、クラウド上の環境変数を参照するよう修正してください。
簡易動作確認
まずはこの段階で動作確認をしてみましょう。
デプロイ
前述した「関数のデプロイ」と同じように、CosmosDB トリガー関数をデプロイ (クラウドへ配置)してください。
ログ画面準備
動作確認のために、まずログ画面を表示しておきます。
データベースへダミーデータを書き込み
次に、ブラウザの新しいタブ、もしくは新しいウインドウで Azure ポータルの CosmosDB の画面を開いてください。
以下のように手動で新しいレコードを追加すると、CosmosDB トリガー関数がトリガーされます。
結果確認
関数がトリガーされると、先ほど開いておいたログ画面にメッセージが表示されます。
CosmosDB データの読み出し
では、前回の記事「Azure連携(3):IoT Hub受信データをCosmos DBへ自動保存」の方法でデバイスから IoT Hub へ送って CosmosDB へ記録した json データを関数内で読み出す仕組みを実装してみましょう。
・jsonライブラリをプロジェクトへ追加
・CosmosDB のデータを json
json 用ライブラリをプロジェクトへ追加
jsonデータのパースを行うために、Newtonsoft.Json ライブラリをプロジェクトへ追加します。
ライブラリの追加には Visual Studio Code の拡張機能 Nuget Package Manager を使用します。
拡張機能 Nuget Package Manager のインストール
まだ Visual Studio Code に拡張機能 Nuget Package Manager を入れていなければ、インストールしてください。
Newtonsoft.Json ライブラリをプロジェクトへ追加
拡張機能 Nuget Package Managerを使って、Newtonsoft.Json ライブラリをプロジェクトへ追加してください。
DBデータへアクセスするコードを追加
CosmosDB トリガー関数に、DBデータへアクセスするためのコードを追加します。
追加する場所は、下記の3箇所です。
追加箇所①:json 用ライブラリの using 宣言
using Newtonsoft.Json を追加してください。
変更前
using System;
using System.Collections.Generic;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Host;
using Microsoft.Extensions.Logging;
変更後
using System;
using System.Collections.Generic;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Host;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
追加箇所②:電文データ部分へアクセスするためのプロパティ追加
「Azure連携(3):IoT Hub受信データをCosmos DBへ自動保存」で CosmosDB へ記録されたデータは以下の様な構造になっており、IoT Hub で受信した電文部分は “Body” という要素に格納されていることがわかっています。
この “Body” 部分へアクセスするために、プロパティを追加します。
変更前
// Customize the model with your own desired properties
public class ToDoItem
{
public string id { get; set; }
public string Description { get; set; }
}
変更後
// Customize the model with your own desired properties
public class ToDoItem
{
public string id { get; set; }
public string Description { get; set; }
public dynamic Body { get; set; }
}
追加箇所③:json 文字列からの要素値の読み出し
“Body” の値を関数側で要素毎に読み出し、読み出した値をログへ出力するコードを追加します。
変更前
if (input != null && input.Count > 0)
{
log.LogInformation("Documents modified " + input.Count);
log.LogInformation("First document Id " + input[0].id);
}
変更後
if (input != null && input.Count > 0)
{
log.LogInformation("Documents modified " + input.Count);
log.LogInformation("First document Id " + input[0].id);
// IoT Hub で受信され CosmosDB に登録された電文を json の要素毎にアクセスできるようにします。
string json_str_Body = input[0].Body.ToString();
dynamic data_Body = JsonConvert.DeserializeObject<dynamic>(json_str_Body);
string device_name = data_Body.DEVICE_NAME;
int count = data_Body.COUNT;
double temp_val = double.Parse(data_Body.TEMPERATURE.ToString());
double temp_thr_h = double.Parse(data_Body.TEMP_WARN_H.ToString());
double temp_thr_l = double.Parse(data_Body.TEMP_WARN_L.ToString());
double hum_val = double.Parse(data_Body.HUMIDITY.ToString() );
double hum_thr_h = double.Parse(data_Body.HUM_WARN_H.ToString() );
double hum_thr_l = double.Parse(data_Body.HUM_WARN_L.ToString() );
double pwr_val = double.Parse(data_Body.POWER.ToString() );
double pwr_thr_h = double.Parse(data_Body.PWR_WARN_H.ToString() );
double pwr_thr_l = double.Parse(data_Body.PWR_WARN_L.ToString() );
double voltage = double.Parse(data_Body.VOLTAGE.ToString() );
double current_ma = double.Parse(data_Body.CURRENT.ToString() );
string timestamp = data_Body.TIMESTAMP.ToString();
log.LogInformation($"device_name : {device_name}");
log.LogInformation($"count : {count}");
log.LogInformation($"temp_val : {temp_val:F2} [Cel. deg.], temp_thr_h : {temp_thr_h:F2}, temp_thr_l : {temp_thr_l:F2}");
log.LogInformation($"hum_val : {hum_val:F2} [%], hum_thr_h : {hum_thr_h:F2}, hum_thr_l : {hum_thr_l:F2}");
log.LogInformation($"pwr_val : {pwr_val:F2} [W], pwr_thr_h : {pwr_thr_h:F2}, pwr_thr_l : {pwr_thr_l:F2}");
log.LogInformation($"voltage : {voltage:F2} [V], current_ma : {current_ma:F2} [mA]");
log.LogInformation($"timestamp : {timestamp} [JST]");
}
このコードは、
- json_str_Body = input[0].Body.ToString(); で Body の内容を文字列として取得しています。
- data_Body = JsonConvert.DeserializeObject<dynamic>(json_str_Body) で文字列から json の構造を持ったオブジェクトへ変換しています。
- xxxx = data_Body.yyyy の部分は、json の要素一つ一つから値を読み出しています。
- log.LogInformation($…… の部分は、読み出した値を読みやすい表現にして log へ出力しています。
修正後の全体イメージは以下の通りです。
最終動作確認
最終的な動作確認をしてみましょう。
デプロイ
前述した「関数のデプロイ」と同じように、CosmosDB トリガー関数をデプロイ (クラウドへ配置)してください。
ログ画面準備
前述した「ログ画面準備」とおなじように、ログ画面を表示しておいてください。
デバイスから Azure IoT Hub へデータを送信
前々回の記事「Azure連携(2):デバイスからIoT HubへのMQTT送信(Python)」で作成した Python コードを実行して下さい。
結果確認
IoT Hub へ json 形式のデータが送信されると、メッセージルーティングによってCosmosDB に新しいレコードが追加されるたびに CosmosDB トリガー関数がトリガーされ、先ほど開いておいたログ画面にメッセージが表示されます。
以上で、IoT Hub でデータが受信されるたびにクラウド上で処理を走らせることが出来るようになりました。