10
2

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 x IoT]Azure IoTHub とAzure Functionsを連携しよう

Last updated at Posted at 2022-02-23

はじめに

こちらの記事でデバイスからAzure IoTHubへデータを送信する方法は紹介しました。
今回は、Azure IoTHubで受け取ったデータをAzure Functionsに連携する方法を紹介します.

本記事のゴール
image.png

準備

以下の準備はAzurePortalから関数を作成する場合は不要です。

ローカル環境でAzure Functionsの雛形作成、デプロイのためにはAzure Functions Core Toolsと呼ばれるCLIツールがAzure CLIとは別に必要です。

以下を参考にインストールしてください。

Work with Azure Functions Core Tools

Macの場合は以下です

brew tap azure/functions
brew install azure-functions-core-tools@4

Azure Functionsを作成する

ポータルから作成する(今回は割愛)

本記事では、コマンドを使って作成する方法をメインで書くのでこちらは割愛させていただきます。

以下の記事がとても丁寧でわかりやすいです

Azure IoT Hubで受け取ったデータを利用する方法(Azure function) - Qiita

コマンドで作成する

実は、複雑なことはしなくてもAzure側でIoTHub連携用のテンプレートが用意されおり、以下のコマンド1発で連携に必要なFunctionの雛形を作成できます

func new --name IoTHubTriggeredFunc --template "IoT Hub (Event Hub)"

コマンドを実行するとプロンプトが立ち上がり、runtime,languageを聞かれます。

今回はそれぞれ 3. node 2.typescriptを選択しました

image.png

成功すると以下のようなディレクトリ構成で雛形が作成されます

.
├── IoTHubTriggeredFunc
│   ├── function.json
│   └── index.ts
├── host.json
├── local.settings.json
├── package.json
└── tsconfig.json

index.tsの中身

import { AzureFunction, Context } from "@azure/functions"

const IoTHubTrigger: AzureFunction = async function (context: Context, IoTHubMessages: any[]): Promise<void> {
    context.log(`Eventhub trigger function called for message array: ${IoTHubMessages}`);
    
    IoTHubMessages.forEach(message => {
        context.log(`Processed message: ${message}`);
    });
};

export default IoTHubTrigger;

余談ですが、他にも様々なテンプレートがあり以下のコマンドで確認できます

func templates list

TypeScriptの部分だけ一部抜粋するとこんな感じです

TypeScript Templates:
  Azure Blob Storage trigger
  Azure Cosmos DB trigger
  Durable Functions activity
  Durable Functions entity
  Durable Functions Entity HTTP starter
  Durable Functions HTTP starter
  Durable Functions orchestrator
  Azure Event Grid trigger
  Azure Event Hub trigger
  HTTP trigger
  IoT Hub (Event Hub)←今回使うのはこれ

関数をデプロイする

  1. デプロイ対象になる関数アプリをAzurePortal上で作成する
  2. function.jsonを修正
    ここにIoTHubとの連携に関わる情報を設定します。

まず今回はバッチではなく、1メッセージずつ受信するためにcardinalityをoneにします。(参考)
ここをmanyにしておくとメッセージをバッチで受け取れるので、例えばDBに直接データを入れたい場合にバルクインサートができたり、パフォーマンス改善につながります。

次にeventHubNameの部分にMyEventHubを設定し、connection部分にmyEventHubReadConnectionAppSettingを入力します。
これらは実は任意の文字列でよく、後ほどAzurePortalから環境変数として値を設定します。

修正前

```json
{
  "bindings": [
    {
      "type": "eventHubTrigger",
      "name": "IoTHubMessages",
      "direction": "in",
      "eventHubName": "samples-workitems",
      "connection": "",
      "cardinality": "many",
      "consumerGroup": "$Default"
    }
  ],
  "scriptFile": "../dist/IoTHubTriggeredFunc/index.js"
}
```

修正後

```json
{
  "bindings": [
    {
      "type": "eventHubTrigger",
      "name": "IoTHubMessages",
      "direction": "in",
      "eventHubName": "MyEventHub",  ←変更
      "connection": "myEventHubReadConnectionAppSetting",  ←変更
      "cardinality": "one", ←変更
      "consumerGroup": "$Default"
    }
  ],
  "scriptFile": "../dist/IoTHubTriggeredFunc/index.js"
}
```
  1. index.tsを修正
    修正前はFunctionの引数がIoTHubMessages: any[]となっていますが、今回はステップ2で1メッセージずつ受信するようにしたので以下のように引数の型を修正します。もちろん、送られてくるデータの型がわかっていればanyではなくきちんと定義するのが望ましいです。

    import { AzureFunction, Context } from "@azure/functions"
    
    const IoTHubTrigger: AzureFunction = async function (context: Context, IoTHubMessage: any): Promise<void> {
        context.log(`Eventhub trigger function called for message array: ${IoTHubMessage}`);
    
    };
    
    export default IoTHubTrigger;
    
  2. 以下のコマンドでデプロイ

    # まずアプリケーションをビルドする
    npm run build
    
    # 指定した関数アプリにデプロイする
    func azure functionapp publish $FUNCTION_APP_NAME
    

以下のような表示がされれば成功です。

image.png

IoTHubとFunctionの連携設定をする

仕上げに先程functions.jsonに設定したMyEventHubmyEventHubReadConnectionAppSettingをAzurePortal上で環境変数として設定します。

  1. AzurePortalでデプロイした関数アプリのページに行き,Configuration(構成)を開きます

    image.png

  2. New application settingを選択し、環境変数を設定していきます

    image.png

    MyEventHubmyEventHubReadConnectionAppSettingに設定するIoTHubの名前とEvent Hub-compatible endpointはそれぞれIoTHubから確認できます

  • IoTHubの名前
    image.png

  • Event Hub-compatible endpoint
    image.png

  1. 保存ボタンを押して環境変数を保存する.
    意外と気づきづらいのでしっかり保存してください。
    image.png

もしAzurePortal上で警告が出た時

  • EventHub拡張機能のバージョンが古いと怒られたとき
    image.png

    警告全文

    Microsoft.Azure.WebJobs.Script: One or more loaded extensions do not meet the minimum requirements. For more information see https://aka.ms/func-min-extension-versions.
    ExtensionStartupType EventHubsWebJobsStartup from assembly 'Microsoft.Azure.WebJobs.EventHubs, Version=4.1.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35' does not meet the required minimum version of 4.3.0.0. Update your NuGet package reference for Microsoft.Azure.WebJobs.Extensions.EventHubs to 4.3.0 or later.
    

    次のコマンドでバージョンアップしてください

    func extensions install --package Microsoft.Azure.WebJobs.Extensions.EventHubs --version 5.0.0
    
  • Event Hub-compatible endpointeventHubNameが載っているのに二重で指定してくるな!と怒ってきたとき
    eventHubNameを空文字にしてデプロイし直してください。

メッセージを送ってみる

この記事に従って以下のスクリプトでメッセージを送ってみます

IOTHUB_NAME=xxxx
DEVICE_NAME=xxxx
SAS=xxxx
mosquitto_pub -d -q 1 \
  -V mqttv311 \
  -p 8883 \
  -h "$IOTHUB_NAME.azure-devices.net" \
  -i $DEVICE_NAME \
  -u "$IOTHUB_NAME.azure-devices.net/$DEVICE_NAME/api-version=2016-11-14" \
  -P $SAS \
  -t "devices/$DEVICE_NAME/messages/events/$.ct=application%2Fjson&$.ce=utf-8" \
  -m '{"value":"Hello,world with MQTT"}'

関数アプリのApp Insightsログでメッセージが確認できたら成功です!

image.png

終わりに

これでデバイス→IoTHub→Azure Functionsまでを繋ぐことが出来ました!

次はAzureFunctionsとその他のAzureリソースを連携する方法を紹介する記事も執筆予定です、お楽しみに!

10
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
10
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?