Azure IoT Hub から Azure Cosmos DB を使用してデバイス接続イベントを順序付けるOrder device connection events from Azure IoT Hub using Azure Cosmos DB

Azure Event Grid を使用すると、イベント ベースのアプリケーションを構築するのに役立ち、IoT イベントをビジネス ソリューションに簡単に統合できます。Azure Event Grid helps you build event-based applications and easily integrate IoT events in your business solutions. この記事では、最新のデバイス接続状態を追跡して Cosmos DB に保存するために使用できる設定について説明します。This article walks you through a setup which can be used to track and store the latest device connection state in Cosmos DB. ここでは、デバイス接続イベントとデバイス切断イベントで使用可能なシーケンス番号を使用し、Cosmos DB に最新の状態を保存します。We will use the sequence number available in the Device Connected and Device Disconnected events and store the latest state in Cosmos DB. Cosmos DB 内のコレクションに対して実行されるアプリケーション ロジックであるストアド プロシージャを使用します。We are going to use a stored procedure, which is an application logic that is executed against a collection in Cosmos DB.

シーケンス番号は、16 進数の文字列表現です。The sequence number is a string representation of a hexadecimal number. 文字列比較を使用して、より大きな数値を識別できます。You can use string compare to identify the larger number. 文字列を 16 進数に変換すると、数値は 256 ビットの数値になります。If you are converting the string to hex, then the number will be a 256-bit number. シーケンス番号は狭義に増加し、最新のイベントには他のイベントよりも大きな番号が与えられます。The sequence number is strictly increasing, and the latest event will have a higher number than other events. これは、デバイスの接続と切断が頻繁に発生するときに最新のイベントのみを使用してダウンストリームのアクションをトリガーする場合に便利です。それは、Azure Event Grid ではイベントの順序付けがサポートされないからです。This is useful if you have frequent device connects and disconnects, and want to ensure only the latest event is used to trigger a downstream action, as Azure Event Grid doesn’t support ordering of events.

前提条件Prerequisites

  • アクティブな Azure アカウントアカウントがない場合、Azure 試用版にサインアップして、最大 10 件の無料 Mobile Apps を入手できます。An active Azure account. アカウントがない場合は、無料アカウントを作成することができます。If you don't have one, you can create a free account.

  • アクティブな Azure Cosmos DB SQL API アカウント。An active Azure Cosmos DB SQL API account. まだ作成していない場合は、「データベース アカウントの作成」の手順を参照してください。If you haven't created one yet, see Create a database account for a walkthrough.

  • データベース内のコレクション。A collection in your database. コレクションの追加」の手順を参照してください。See Add a collection for a walkthrough. コレクションを作成するときに、パーティション キーに /id を使用します。When you create your collection, use /id for the partition key.

  • Azure の IoT Hub。An IoT Hub in Azure. まだ作成していない場合は、「IoT Hub の概要」のチュートリアルをご覧ください。If you haven't created one yet, see Get started with IoT Hub for a walkthrough.

ストアド プロシージャを作成するCreate a stored procedure

最初に、ストアド プロシージャを作成します。このストアド プロシージャで、受信イベントのシーケンス番号を比較し、デバイスごとに最新のイベントをデータベースに記録するロジックを実行するように設定します。First, create a stored procedure and set it up to run a logic that compares sequence numbers of incoming events and records the latest event per device in the database.

  1. Cosmos DB SQL API で、 [データ エクスプローラー] > [アイテム] > [新しいストアド プロシージャ] を選択します。In your Cosmos DB SQL API, select Data Explorer > Items > New Stored Procedure.

    ストアド プロシージャを作成する

  2. ストアド プロシージャ ID の LatestDeviceConnectionState を入力し、ストアド プロシージャの本文に次のコードを貼り付けます。Enter LatestDeviceConnectionState for the stored procedure ID and paste the following in the Stored Procedure body. このコードでストアド プロシージャ本文のすべての既存のコードを置き換える必要があることに注意してください。Note that this code should replace any existing code in the stored procedure body. このコードでは、デバイス ID ごとに 1 行を維持し、最も大きなシーケンス番号を識別することによってそのデバイス ID の最新の接続状態を記録します。This code maintains one row per device ID and records the latest connection state of that device ID by identifying the highest sequence number.

    // SAMPLE STORED PROCEDURE
    function UpdateDevice(deviceId, moduleId, hubName, connectionState, connectionStateUpdatedTime, sequenceNumber) {
      var collection = getContext().getCollection();
      var response = {};
    
      var docLink = getDocumentLink(deviceId, moduleId);
    
      var isAccepted = collection.readDocument(docLink, function(err, doc) {
        if (err) {
          console.log('Cannot find device ' + docLink + ' - ');
          createDocument();
        } else {
          console.log('Document Found - ');
          replaceDocument(doc);
        }
      });
    
      function replaceDocument(document) {
        console.log(
          'Old Seq :' +
            document.sequenceNumber +
            ' New Seq: ' +
            sequenceNumber +
            ' - '
        );
        if (sequenceNumber > document.sequenceNumber) {
          document.connectionState = connectionState;
          document.connectionStateUpdatedTime = connectionStateUpdatedTime;
          document.sequenceNumber = sequenceNumber;
    
          console.log('replace doc - ');
    
          isAccepted = collection.replaceDocument(docLink, document, function(
            err,
            updated
          ) {
            if (err) {
              getContext()
                .getResponse()
                .setBody(err);
            } else {
              getContext()
                .getResponse()
                .setBody(updated);
            }
          });
        } else {
          getContext()
            .getResponse()
            .setBody('Old Event - current: ' + document.sequenceNumber + ' Incoming: ' + sequenceNumber);
        }
      }
      function createDocument() {
        document = {
          id: deviceId + '-' + moduleId,
          deviceId: deviceId,
          moduleId: moduleId,
          hubName: hubName,
          connectionState: connectionState,
          connectionStateUpdatedTime: connectionStateUpdatedTime,
          sequenceNumber: sequenceNumber
        };
        console.log('Add new device - ' + collection.getAltLink());
        isAccepted = collection.createDocument(
          collection.getAltLink(),
          document,
          function(err, doc) {
            if (err) {
              getContext()
                .getResponse()
                .setBody(err);
            } else {
              getContext()
                .getResponse()
                .setBody(doc);
            }
          }
        );
      }
    
      function getDocumentLink(deviceId, moduleId) {
        return collection.getAltLink() + '/docs/' + deviceId + '-' + moduleId;
      }
    }
    
  3. ストアド プロシージャを保存します。Save the stored procedure:

    ストアド プロシージャを保存する

ロジック アプリを作成しますCreate a logic app

最初にロジック アプリを作成し、仮想マシンのリソース グループを監視する Event Grid トリガーを追加します。First, create a logic app and add an Event grid trigger that monitors the resource group for your virtual machine.

ロジック アプリ リソースを作成するCreate a logic app resource

  1. Azure portalで、 [+リソースの作成][統合][ロジック アプリ] の順に選択します。In the Azure portal, select +Create a resource, select Integration and then Logic App.

    ロジック アプリを作成する

  2. ロジック アプリにサブスクリプション内で一意の名前を指定し、IoT Hub と同じサブスクリプション、リソース グループ、場所を選びます。Give your logic app a name that's unique in your subscription, then select the same subscription, resource group, and location as your IoT hub.

    新しいロジック アプリ

  3. [作成] を選択して、ロジック アプリを作成します。Select Create to create the logic app.

    これで、ロジック アプリの Azure リソースが作成されました。You've now created an Azure resource for your logic app. Azure によってロジック アプリがデプロイされたら、すばやく開始できるように Logic Apps デザイナーによって一般的なパターンのテンプレートが表示されます。After Azure deploys your logic app, the Logic Apps Designer shows you templates for common patterns so you can get started faster.

    注意

    ロジック アプリを見つけて再度開くには、 [リソース グループ] を選択し、このハウツー記事で使用しているリソース グループを選択します。To find and open your logic app again, select Resource groups and select the resource group you are using for this how-to. 次に、新しいロジック アプリを選択します。Then select your new logic app. これにより、ロジック アプリ デザイナーが開きます。This opens the Logic App Designer.

  4. ロジック アプリ デザイナーで、一般的なトリガーが表示されるまで右にスクロールします。In the Logic App Designer, scroll to the right until you see common triggers. [テンプレート] の下で [空のロジック アプリ] を選択すると、ロジック アプリを最初から作成できます。Under Templates, choose Blank Logic App so that you can build your logic app from scratch.

トリガーを選択するSelect a trigger

トリガーは、ロジック アプリを開始する特定のイベントです。A trigger is a specific event that starts your logic app. このチュートリアルでは、ワークフローを開始するトリガーは、HTTP 経由での要求の受信です。For this tutorial, the trigger that sets off the workflow is receiving a request over HTTP.

  1. コネクタとトリガーの検索バーに、「HTTP」と入力して Enter キーを押します。In the connectors and triggers search bar, type HTTP and hit Enter.

  2. トリガーとして [要求 - HTTP 要求の受信時] を選びます。Select Request - When an HTTP request is received as the trigger.

    HTTP 要求トリガーを選ぶ

  3. [サンプルのペイロードを使用してスキーマを生成する] を選びます。Select Use sample payload to generate schema.

    サンプルのペイロードを使用してスキーマを生成する

  4. 次のサンプル JSON コードをテキスト ボックスに貼り付けて、 [完了] を選びます。Paste the following sample JSON code into the text box, then select Done:

    [{
     "id": "fbfd8ee1-cf78-74c6-dbcf-e1c58638ccbd",
     "topic":
       "/SUBSCRIPTIONS/DEMO5CDD-8DAB-4CF4-9B2F-C22E8A755472/RESOURCEGROUPS/EGTESTRG/PROVIDERS/MICROSOFT.DEVICES/IOTHUBS/MYIOTHUB",
     "subject": "devices/Demo-Device-1",
     "eventType": "Microsoft.Devices.DeviceConnected",
     "eventTime": "2018-07-03T23:20:11.6921933+00:00",
     "data": {
       "deviceConnectionStateEventInfo": {
         "sequenceNumber":
           "000000000000000001D4132452F67CE200000002000000000000000000000001"
       },
       "hubName": "MYIOTHUB",
       "deviceId": "48e44e11-1437-4907-83b1-4a8d7e89859e",
       "moduleId": ""
     },
     "dataVersion": "1",
     "metadataVersion": "1"
    }]
    

    サンプルの JSON ペイロードを貼り付ける

  5. "application/json に設定されている Content-Type ヘッダーを要求に忘れずに含めてください" というポップアップ通知を受け取る場合があります。You may receive a pop-up notification that says, Remember to include a Content-Type header set to application/json in your request. この指摘は無視しても安全なので、次のセクションに進みます。You can safely ignore this suggestion, and move on to the next section.

条件を作成するCreate a condition

ロジック アプリのワークフロー内では、条件は特定の条件を満たした後に特定のアクションを実行するのに役立ちます。In your logic app workflow, conditions help run specific actions after passing that specific condition. 条件が満たされると、目的の動作を定義することができます。Once the condition is met, a desired action can be defined. このチュートリアルでは、eventType がデバイス接続とデバイス切断のどちらであるかを調べる条件を設定します。For this tutorial, the condition is to check whether eventType is device connected or device disconnected. アクションでは、データベース内のストアド プロシージャを実行します。The action will be to execute the stored procedure in your database.

  1. [+ 新しいステップ][ビルトイン] の順に選択し、 [条件] を見つけて選択します。Select + New step then Built-in, then find and select Condition. [値の選択] をクリックすると、動的コンテンツ (選択可能なフィールド) を表示するボックスがポップアップ表示されます。Click in Choose a value and a box will pop up showing the Dynamic content -- the fields that can be selected. 次のようにフィールドに入力し、デバイス接続イベントとデバイス切断イベントのみを対象にこのアクションが実行されるようにします。Fill in the fields as shown below to only execute this for Device Connected and Device Disconnected events:

    • 値の選択: eventType -- このフィールドをクリックすると表示される動的コンテンツ内のフィールドから、この値を選択します。Choose a value: eventType -- select this from the fields in the dynamic content that appear when you click on this field.

    • [次の値に等しい] を [次の文字で終了する] に変更します。Change "is equal to" to ends with.

    • 値の選択: nectedChoose a value: nected.

      条件を入力する

  2. [true の場合] ダイアログで、 [アクションの追加] をクリックします。In the if true dialog, click on Add an action.

    true の場合のアクションを追加する

  3. Cosmos DB を検索し、 [Azure Cosmos DB - ストアド プロシージャの実行] を選択しますSearch for Cosmos DB and select Azure Cosmos DB - Execute stored procedure

    CosmosDB を検索する

  4. [接続名] に「cosmosdb-connection」と入力し、テーブルでエントリを選択して、 [作成] を選択します。Fill in cosmosdb-connection for the Connection Name and select the entry in the table, then select Create. [ストアド プロシージャの実行] パネルが表示されます。You see the Execute stored procedure panel. フィールドに次の値を入力します。Enter the values for the fields:

    データベース ID:ToDoListDatabase ID: ToDoList

    コレクション ID:項目Collection ID: Items

    Sproc ID:LatestDeviceConnectionStateSproc ID: LatestDeviceConnectionState

  5. [新しいパラメーターの追加] を選択します。Select Add new parameter. 表示されたドロップダウンで、 [パーティション キー][ストアド プロシージャのパラメーター] の横のボックスをチェックし、画面の任意の場所をクリックっします。これにより、パーティション キー値のフィールドとストアド プロシージャーのパラメーターのフィールドが追加されます。In the dropdown that appears, check the boxes next to Partition key and Parameters for the stored procedure, then click anywhere else on the screen; it adds a field for partition key value and a field for parameters for the stored procedure.

    ロジック アプリのアクションを設定する

  6. 次に示すように、パーティション キー値とパラメーターを入力します。Now enter the partition key value and parameters as shown below. 以下で示されているように、かっこと二重引用符を入力してください。Be sure to put in the brackets and double-quotes as shown. ここで使用できる有効な値を取得するために、 [動的なコンテンツの追加] をクリックしなければならない場合があります。You may have to click Add dynamic content to get the valid values you can use here.

    ロジック アプリのアクションを設定する

  7. [For Each] と表示されているウィンドウの上部の [以前の手順から出力を選択] で、 [本文] が選択されていることを確認します。At the top of the pane where it says For Each, under Select an output from previous steps, make sure it Body is selected.

    ロジック アプリ for-each の入力

  8. ロジック アプリを保存し、Save your logic app.

HTTP の URL をコピーするCopy the HTTP URL

Logic Apps デザイナーを終了する前に、ロジック アプリがトリガーをリッスンする URL をコピーします。Before you leave the Logic Apps Designer, copy the URL that your logic app is listening to for a trigger. この URL を使って、Event Grid を構成します。You use this URL to configure Event Grid.

  1. [HTTP 要求の受信時] トリガー構成ボックスをクリックして展開します。Expand the When a HTTP request is received trigger configuration box by clicking on it.

  2. [HTTP POST の URL] の横にあるコピー ボタンを選んで値をコピーします。Copy the value of HTTP POST URL by selecting the copy button next to it.

    HTTP POST の URL をコピーする

  3. 次のセクションで参照できるように、この URL を保存します。Save this URL so that you can refer to it in the next section.

IoT Hub イベント用のサブスクリプションを構成するConfigure subscription for IoT Hub events

このセクションでは、発生したらイベントを発行するように IoT Hub を構成します。In this section, you configure your IoT Hub to publish events as they occur.

  1. Azure Portal で、お使いの IoT ハブに移動します。In the Azure portal, navigate to your IoT hub.

  2. イベントを選択します。Select Events.

    Event Grid の詳細を表示する

  3. [+ イベント サブスクリプション] を選びます。Select + Event subscription.

    新しいイベント サブスクリプションを作成する

  4. [イベント サブスクリプションの詳細] を入力します。わかりやすい名前を指定し、 [イベント グリッド スキーマ] を選択します。Fill in Event Subscription Details: Provide a descriptive name and select Event Grid Schema.

  5. [イベントの種類] フィールドに入力します。Fill in the Event Types fields. ドロップダウン リストで、 [Device Connected](デバイスの接続) および [Device Disconnected](デバイスの切断) のみをメニューから選択します。In the dropdown list, select only Device Connected and Device Disconnected from the menu. 画面の他の場所をクリックしてリストを閉じ、選択内容を保存します。Click anywhere else on the screen to close the list and save your selections.

    検索するイベントの種類を設定する

  6. [エンドポイントの詳細] で、 [エンドポイントのタイプ] として [web hook] を選択し、[エンドポイントの選択] をクリックして、ロジック アプリからコピーした URL を貼り付けて選択を確認します。For Endpoint Details, select Endpoint Type as Web Hook and click on select endpoint and paste the URL that you copied from your logic app and confirm selection.

    エンドポイントの URL を選択する

  7. これで、フォームは次の例のようになります。The form should now look similar to the following example:

    サンプルのイベント サブスクリプション フォーム

    [作成] を選び、イベント サブスクリプションを保存します。Select Create to save the event subscription.

イベントを確認するObserve events

イベント サブスクリプションを設定した後は、デバイスを接続してテストします。Now that your event subscription is set up, let's test by connecting a device.

IoT Hub にデバイスを登録するRegister a device in IoT Hub

  1. IoT Hub から、 [IoT Devices](IoT デバイス) を選びます。From your IoT hub, select IoT Devices.

  2. ウィンドの上部にある [+ 追加] を選択します。Select +Add at the top of the pane.

  3. [デバイス ID] に「Demo-Device-1」と入力します。For Device ID, enter Demo-Device-1.

  4. [保存] を選択します。Select Save.

  5. 異なるデバイス ID を使用して複数のデバイスを追加できます。You can add multiple devices with different device IDs.

    ハブに追加されるデバイス

  6. デバイスを再度クリックすると、接続文字列とキーが入力されます。Click on the device again; now the connection strings and keys will be filled in. 後で使用するために [接続文字列 --- 主キー] をコピーします。Copy the Connection string -- primary key for later use.

    デバイスの接続文字列

Raspberry Pi シミュレーターを起動するStart Raspberry Pi simulator

Raspberry Pi Web シミュレーターを使用してデバイス接続をシミュレートしましょう。Let's use the Raspberry Pi web simulator to simulate device connection.

Raspberry Pi シミュレーターの起動Start Raspberry Pi simulator

Raspberry Pi Web シミュレーターでサンプル アプリケーションを実行するRun a sample application on the Raspberry Pi web simulator

この操作を実行すると、デバイス接続イベントがトリガーされます。This will trigger a device connected event.

  1. コーディング領域で、行 15 のプレースホルダーを、前のセクションの最後に保存した Azure IoT Hub デバイスの接続文字列に置き換えます。In the coding area, replace the placeholder in Line 15 with your Azure IoT Hub device connection string that you saved at the end of the previous section.

    デバイスの接続文字列を貼り付ける

  2. [Run](実行) を選択してアプリケーションを実行します。Run the application by selecting Run.

IoT Hub に送信されるセンサー データとメッセージを示す次のような出力が表示されます。You see something similar to the following output that shows the sensor data and the messages that are sent to your IoT hub.

アプリケーションの実行

[Stop](停止) をクリックしてシミュレーターを停止して、デバイス切断イベントをトリガーします。Click Stop to stop the simulator and trigger a Device Disconnected event.

サンプル アプリケーションを実行した結果、センサー データが収集され、IoT Hub に送信されました。You have now run a sample application to collect sensor data and send it to your IoT hub.

Cosmos DB でイベントを確認するObserve events in Cosmos DB

実行されたストアド プロシージャの結果は、Cosmos DB ドキュメント内で確認できます。You can see results of the executed stored procedure in your Cosmos DB document. 外観は次のようになります。Here's what it looks like. 各行にデバイスごとの最新のデバイス接続状態が含まれます。Each row contains the latest device connection state per device.

操作の結果

Azure CLI の使用Use the Azure CLI

Azure portal を使う代わりに、Azure CLI を使って IoT Hub の手順を行うことができます。Instead of using the Azure portal, you can accomplish the IoT Hub steps using the Azure CLI. 詳細については、イベント サブスクリプションの作成IoT デバイスの作成に関する Azure CLI のページを参照してください。For details, see the Azure CLI pages for creating an event subscription and creating an IoT device.

リソースのクリーンアップClean up resources

このチュートリアルでは、Azure サブスクリプションで料金が発生するリソースを使いました。This tutorial used resources that incur charges on your Azure subscription. チュートリアルを試してテストを完了したら、残しておきたくないリソースを無効にするか削除します。When you're finished trying out the tutorial and testing your results, disable or delete resources that you don't want to keep.

アプリ ロジックでの作業を失いたくない場合は、削除ではなく無効にします。If you don't want to lose the work on your logic app, disable it instead of deleting it.

  1. ロジック アプリに移動します。Navigate to your logic app.

  2. [概要] ブレードで、 [削除] または [無効] を選びます。On the Overview blade, select Delete or Disable.

    各サブスクリプションで使うことができる無料 IoT Hub は 1 つです。Each subscription can have one free IoT hub. このチュートリアル用に無料のハブを作成した場合は、課金されないように削除する必要はありません。If you created a free hub for this tutorial, then you don't need to delete it to prevent charges.

  3. IoT Hub に移動します。Navigate to your IoT hub.

  4. [概要] ブレードで [削除] を選びます。On the Overview blade, select Delete.

    IoT Hub を残しておく場合でも、作成したイベント サブスクリプションを削除できます。Even if you keep your IoT hub, you may want to delete the event subscription that you created.

  5. IoT Hub で [イベント グリッド] を選びます。In your IoT hub, select Event Grid.

  6. 削除するイベント サブスクリプションを選びます。Select the event subscription that you want to remove.

  7. [削除] を選択します。Select Delete.

Azure Cosmos DB アカウントを Azure portal から削除するには、アカウント名を右クリックし、 [アカウントの削除] をクリックします。To remove an Azure Cosmos DB account from the Azure portal, right-click the account name and click Delete account. Azure Cosmos DB アカウントを削除するための詳細な手順を参照してください。See detailed instructions for deleting an Azure Cosmos DB account.

次の手順Next steps