本記事のゴール
本記事ではIoTHubで受信したメッセージをRDBに保存できるようにします.
AzureFunctionからAzureDatabaseへのアクセスについてはVnet統合という機能を使います。
本記事の内容は筆者の次の3つの記事を組み合わせた内容になります。
IotHubは使わないけど、部分的に参考にしたいという方は以下を参考にしてください。
- [Azure x IoT]Azure IoTHubにメッセージを送ろう
- [Azure x IoT]Azure IoTHub とAzure Functionsを連携しよう
- [Azure] Azure FunctionsからVnet内のRDBを操作する
準備するもの
- AzureIoTHub
- Azure Functions(Function PremiumかApp Service のStandardプラン以上)
- Azure Database For MySQL
- 踏み台仮想マシン
- vnet
- Vnet統合に使うFunction用のsubnet
1. Azure IoTHubを作成する
AzurePortalでAzure IoTHubサービスを作成します。
プランはF1(無料)で大丈夫です。
2. Azure Database For MySQLと踏み台サーバーを用意する
-
以下のチュートリアルを参考にDBと踏み台サーバーの作成を行う
Azure portal でプライベート アクセスを使用して Azure Database for MySQL フレキシブル サーバーに接続する
-
テスト用のデータベース、テーブルを作成
CREATE DATABASE test_database; CREATE TABLE test_table ( id INTEGER AUTO_INCREMENT PRIMARY KEY, message VARCHAR(255), created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP );
ざっくりとした解説にとどめましたが、筆者の以下記事にもう少しだけ詳しく書いてあるのでよかったら参考にしてください
[Azure] Azure FunctionsからVnet内のRDBを操作する - Qiita
3. Function用のSunetを用意する
vnetはDB作成時に既に作成されているはずなので、そこにFunction用のsubnetを作成します。
先程DBに紐付けたvnetのページにいき、サイドメニューの”サブネット”を選択し、サブネットの追加を行います。名前は適当なもので構いません。サブネットアドレス範囲は自動で入力されるので名前さえ入力できればあとは保存して終了です!
4. FunctionAppを作成する
-
AzurePortal上でFunctionAppを作成する
Vnet統合が使えるのはAppServiceプランのStandard
以上だけなのでそこだけ注意してください。
参考:https://docs.microsoft.com/ja-jp/azure/app-service/overview-vnet-integration -
Azure Functions Core Tools
のfuncコマンドで関数を作成.func new --name IoTHubTriggeredFunction --template "IoT Hub (Event Hub)"
-
functions.jsonを編集
{ "type": "eventHubTrigger", "name": "IoTHubMessages", "direction": "in", "eventHubName": "MyEventHub", ←テンプレートから変更 "connection": "myEventHubReadConnectionAppSetting", ←テンプレートから変更 "cardinality": "one", ←テンプレートから変更 "consumerGroup": "$Default" }
-
index.tsを編集
import { AzureFunction, Context } from "@azure/functions" import {createConnection} from 'mysql2/promise' const IoTHubTrigger: AzureFunction = async function (context: Context, IoTHubMessage: any): Promise<void> { // ①接続情報オブジェクトを作成し、コネクションを確立する const config = { host: process.env['DB_HOST'], user: process.env['DB_USER_NAME'], password: process.env['DB_PASSWORD'], database: process.env['DB_DATABASE_NAME'], port: 3306, ssl : { rejectUnauthorized: false } }; const conn = await createConnection(config); //②DBへinsert try { const [rows,fields] = await conn.query(`insert into test_table (message) values ('${IoTHubMessage.value}')`) .catch(e=>{throw Error(e)}); context.log(fields) } catch(e) { context.log(e) } finally { conn.end();//接続を切る } }; export default IoTHubTrigger;
-
デプロイ
ここまででコードは完成したのでデプロイします。デプロイ前にビルドするのを忘れずに
npm run build func azure functionapp publish ${FunctionAppの名前}
-
AzurePortalで環境変数を設定する
作成した関数アプリのサイドメニューから「構成」を選びます。
そこで”新しいアプリケーション設定”をクリックして以下を作成します。
- DB_HOST
- DB_USER_NAME
- DB_PASSWORD
- MyEventHub
- myEventHubReadConnectionAppSetting
MyEventHub
とmyEventHubReadConnectionAppSetting
に設定するIoTHubの名前とEvent Hub-compatible endpointはそれぞれIoTHubから確認できます
5. 動作確認
-
IotHubに対してメッセージを送信します
必要な環境変数を設定して以下を実行します。
curl -i -X POST \ -H "Content-Type:application/json" \ -H "Authorization:$SAS" \ -d '{"value":"hello,world via iothub"}' \ "https://$IOTHUB_NAME.azure-devices.net/devices/$DEVICE_NAME/messages/events?api-version=2018-06-30"
SASは次のコマンドで取得できます
az iot hub generate-sas-token -n $IOTHUB_NAME --du $EXPIRATION_SECONDS
詳しくは筆者のこちらの投稿をご覧ください
-
VMからDBにログインしてレコードが挿入されているか確認する
以下のようにIoTHubに送ったメッセージの内容がinsertされていれば成功です!
おわりに
いかがだったでしょうか。これでIoTデバイスから得られたセンシングデータをDBに格納することができるようになりました。あとはこのデータをアプリケーションに合わせて加工して、必要ならフロントエンドも足して、簡単なIoTシステムの完成です!