チュートリアル: Azure Digital Twins プレビューを使用して建物をプロビジョニングし、作業条件を監視する

重要

Azure Digital Twins サービスの新しいバージョンがリリースされました。 新しいサービスの拡張された機能に照らして、元の Azure Digital Twins サービス (このドキュメント セットで説明) は廃止されました。

新しいサービスのドキュメントを表示するには、アクティブな Azure Digital Twins のドキュメントを参照してください

このチュートリアルでは、Azure Digital Twins プレビューを使用して、望ましい温度条件と快適度を基準に空間を監視する方法について説明します。 サンプルの建物を構成した後、このチュートリアルの手順を使用して建物をプロビジョニングし、センサー データに対してカスタム関数を実行できます。

このチュートリアルでは、以下の内容を学習します。

  • 監視する条件を定義する。
  • ユーザー定義関数 (UDF) を作成する。
  • センサー データをシミュレートする。
  • ユーザー定義関数の結果を取得する。

前提条件

このチュートリアルでは、Azure Digital Twins の設定が完了していることを前提としています。 次に進む前に、以下が準備されていることを確認します。

ヒント

新しいインスタンスをプロビジョニングする場合は、一意の Digital Twins インスタンス名を使用します。

監視する条件を定義する

デバイスまたはセンサーのデータについて監視する特定の条件のセット ("マッチャー" と呼ばれます) を定義できます。 その後、"ユーザー定義関数" と呼ばれる関数を定義できます。 ユーザー定義関数では、マッチャーによって指定された条件が発生したときに、空間およびデバイスから受け取ったデータに対してカスタム ロジックが実行されます。 詳細については、「データ処理とユーザー定義関数」を参照してください。

Visual Studio Code で、occupancy-quickstart サンプル プロジェクトの src\actions\provisionSample.yaml ファイルを開きます。 型 matchers で始まるセクションに注目してください。 この型の各エントリによって、指定された名前のマッチャーが作成されます。 このマッチャーによって、型 dataTypeValue のセンサーが監視されます。 これが Focus Room A1 という名前の空間とどのように関係しているかに注目してください。ここには、いくつかのセンサーがある devices ノードが含まれています。 これらのセンサーの 1 つを追跡するマッチャーをプロビジョニングするには、その dataTypeValue がセンサーの dataType と一致している必要があります。

既存のマッチャーの下に次のマッチャーを追加します。 キーの位置が揃っていて、空白がタブで置き換えられていないことを確認してください。 これらの行は、コメントアウトされた行として provisionSample.yaml ファイル内にもあります。 各行の先頭にある # 文字を削除するだけでコメント解除することができます。

      - name: Matcher Temperature
        dataTypeValue: Temperature

このマッチャーでは、最初のチュートリアルで追加した SAMPLE_SENSOR_TEMPERATURE センサーが追跡されます。

ユーザー定義関数を作成する

ユーザー定義関数を使用すると、センサー データの処理をカスタマイズできます。 これらは、マッチャーによって記述された特定の条件が発生したときに Azure Digital Twins インスタンス内で実行できるカスタム JavaScript コードです。 マッチャーとユーザー定義関数は、監視したいセンサーごとに作成できます。 詳細については、「データ処理とユーザー定義関数」を参照してください。

サンプルの provisionSample.yaml ファイルで、型 userdefinedfunctions で始まるセクションを見つけます。 このセクションによって、指定された名前のユーザー定義関数がプロビジョニングされます。 この UDF は、matcherNames の下のマッチャーの一覧を対象にして動作します。 独自の JavaScript ファイルをスクリプトとして UDF に提供する方法に注目してください。

さらに、roleassignments という名前のセクションに注目してください。 これによって、ユーザー定義関数にスペース管理者ロールが割り当てられます。 このロールでは、すべてのプロビジョニング済み空間から届いたイベントへのアクセスが許可されます。

  1. provisionSample.yaml ファイルのノードに次の行を追加またはコメント解除して、温度マッチャーをmatcherNames含むように UDF を構成します。

            - Matcher Temperature
    
  2. エディターで src\actions\userDefinedFunctions\availability.js ファイルを開きます。 これは、provisionSample.yamlscript 要素で参照されているファイルです。 このファイル内のユーザー定義関数では、室内でモーションが検出されず、二酸化炭素レベルが 1,000 ppm 未満の条件が検索されます。

    温度とその他の条件を監視するように JavaScript ファイルを変更します。 室内でモーションが検出されず、二酸化炭素レベルが 1,000 ppm 未満、温度が華氏 78 度未満の条件を検索するために、次のコード行を追加します。

    Note

    このセクションでは、ユーザー定義関数の 1 つの記述方法を詳しく学習できるように、ファイル src\actions\userDefinedFunctions\availability.js を変更しています。 ただし、セットアップ内の src\actions\userDefinedFunctions\availabilityForTutorial.js ファイルを直接使用してもかまいません。 このファイルには、このチュートリアルに必要なすべての変更が含まれています。 代わりにこのファイルを使用する場合は、src\actions\provisionSample.yaml 内の script キーに適切なファイル名を使用するようにしてください。

    a. ファイルの先頭で、コメント // Add your sensor type here の下に温度用の次の行を追加します。

        var temperatureType = "Temperature";
        var temperatureThreshold = 78;
    

    b. var motionSensor を定義するステートメントの後ろにあるコメント // Add your sensor variable here の下に、次の行を追加します。

       var temperatureSensor = otherSensors.find(function(element) {
           return element.DataType === temperatureType;
       });
    

    c. var carbonDioxideValue を定義するステートメントの後ろにあるコメント // Add your sensor latest value here の下に、次の行を追加します。

        var temperatureValue = getFloatValue(temperatureSensor.Value().Value);
    

    d. コメント // Modify this line to monitor your sensor value の下にある次のコード行を削除します。

       if(carbonDioxideValue === null || motionValue === null) {
           sendNotification(telemetry.SensorId, "Sensor", "Error: Carbon dioxide or motion are null, returning");
           return;
       }
    

    それらを次の行に置き換えます。

        if(carbonDioxideValue === null || motionValue === null || temperatureValue === null){
            sendNotification(telemetry.SensorId, "Sensor", "Error: Carbon dioxide, motion, or temperature are null, returning");
            return;
        }
    

    e. コメント // Modify these lines as per your sensor の下にある次のコード行を削除します。

        var availableFresh = "Room is available and air is fresh";
        var noAvailableOrFresh = "Room is not available or air quality is poor";
    

    それらを次の行に置き換えます。

        var alert = "Room with fresh air and comfortable temperature is available.";
        var noAlert = "Either room is occupied, or working conditions are not right.";
    

    f. コメント // Modify this code block for your sensor の後ろにある次の if-else コード ブロックを削除します。

        // If carbonDioxide less than threshold and no presence in the room => log, notify and set parent space computed value
        if(carbonDioxideValue < carbonDioxideThreshold && !presence) {
            log(`${availableFresh}. Carbon Dioxide: ${carbonDioxideValue}. Presence: ${presence}.`);
            setSpaceValue(parentSpace.Id, spaceAvailFresh, availableFresh);
        }
        else {
            log(`${noAvailableOrFresh}. Carbon Dioxide: ${carbonDioxideValue}. Presence: ${presence}.`);
            setSpaceValue(parentSpace.Id, spaceAvailFresh, noAvailableOrFresh);
    
            // Set up custom notification for poor air quality
            parentSpace.Notify(JSON.stringify(noAvailableOrFresh));
        }
    

    これを次の if-else ブロックに置き換えます。

        // If sensor values are within range and room is available
        if(carbonDioxideValue < carbonDioxideThreshold && temperatureValue < temperatureThreshold && !presence) {
            log(`${alert}. Carbon Dioxide: ${carbonDioxideValue}. Temperature: ${temperatureValue}. Presence: ${presence}.`);
    
            // log, notify and set parent space computed value
            setSpaceValue(parentSpace.Id, spaceAvailFresh, alert);
    
            // Set up notification for this alert
            parentSpace.Notify(JSON.stringify(alert));
        }
        else {
            log(`${noAlert}. Carbon Dioxide: ${carbonDioxideValue}. Temperature: ${temperatureValue}. Presence: ${presence}.`);
    
            // log, notify and set parent space computed value
            setSpaceValue(parentSpace.Id, spaceAvailFresh, noAlert);
        }
    

    変更後の UDF では、部屋が使用可能で、二酸化炭素と温度が許容限度内にある状態が検索されます。 この条件が満たされると、parentSpace.Notify(JSON.stringify(alert)); ステートメントによって通知が生成されます。 条件が満たされているかどうかに関係なく、監視されている空間の値が対応するメッセージと共に設定されます。

    g. ファイルを保存します。

  3. コマンド ウィンドウを開き、occupancy-quickstart\src フォルダーに移動します。 次のコマンドを実行して、空間インテリジェンス グラフおよびユーザー定義関数をプロビジョニングします。

    dotnet run ProvisionSample
    

    重要

    Digital Twins Management API への不正アクセスを防ぐために、occupancy-quickstart アプリケーションでは Azure アカウントの資格情報を使用してサインインする必要があります。 資格情報は一時的に保存されるため、実行するたびにサインインする必要はありません。 このプログラムを初めて実行したときと、その後保存された資格情報が期限切れになったときは、アプリケーションによってサインイン ページが表示され、そのページに入力するセッション固有のコードが与えられます。 プロンプトに従って、Azure アカウントを使用してサインインします。

  4. アカウントが認証された後、アプリケーションによって、provisionSample.yaml の構成どおりにサンプル空間グラフの作成が開始されます。 プロビジョニングが完了するまで待機します。 これには数分かかります。 その後、コマンド ウィンドウのメッセージを見て、空間グラフがどのように作成されているかを確認します。 アプリケーションによってルート ノードまたは Venue に IoT ハブがどのように作成されているかに注目します。

  5. コマンド ウィンドウの出力から、Devices セクションの ConnectionString の値をクリップボードにコピーします。 この値は、次のセクションでデバイス接続をシミュレートするために必要です。

    サンプルをプロビジョニングする

ヒント

プロビジョニングの途中で "The I/O operation has been aborted because of either a thread exit or an application request (スレッドの終了またはアプリケーション要求のため I/O 操作が中止されました)" のようなエラー メッセージが表示された場合は、コマンドをもう一度実行してみてください。 これは、ネットワークの問題が原因で HTTP クライアントがタイムアウトしたときに発生する可能性があります。

センサー データをシミュレートする

このセクションでは、サンプル内の device-connectivity という名前のプロジェクトを使用します。 モーション、温度、二酸化炭素を検出するためのセンサー データをシミュレートします。 このプロジェクトでは、センサーのランダムな値が生成され、デバイス接続文字列を使用してそれらが IoT ハブに送信されます。

  1. 別のコマンド ウィンドウで、Azure Digital Twins サンプルに移動し、device-connectivity フォルダーに移動します。

  2. 次のコマンドを実行して、プロジェクトの依存関係が正しいことを確認します。

    dotnet restore
    
  3. エディターで appsettings.json ファイルを開き、次の値を編集します。

    a. DeviceConnectionString: 前のセクションの出力ウィンドウに含まれている ConnectionString の値を割り当てます。 シミュレーターが IoT ハブに正常に接続できるように、引用符で囲まれたこの文字列を完全にコピーしてください。

    b. センサーアレイ内の HardwareId: Azure Digital Twins インスタンスにプロビジョニングされたセンサーからのイベントをシミュレートするため、このファイル内のセンサーのハードウェア ID と名前は provisionSample.yaml ファイルのノードと一致sensorsする必要があります。

    温度センサーの新しいエントリを追加します。 appsettings.jsonSensors ノードは次のようになります。

    "Sensors": [{
      "DataType": "Motion",
      "HardwareId": "SAMPLE_SENSOR_MOTION"
    },{
      "DataType": "CarbonDioxide",
      "HardwareId": "SAMPLE_SENSOR_CARBONDIOXIDE"
    },{
      "DataType": "Temperature",
      "HardwareId": "SAMPLE_SENSOR_TEMPERATURE"
    }]
    
  4. 次のコマンドを実行して、温度、モーション、二酸化炭素に関するデバイス イベントのシミュレーションを開始します。

    dotnet run
    

    注意

    シミュレーション サンプルは Digital Twins インスタンスと直接通信しないため、認証を行う必要はありません。

ユーザー定義関数の結果を取得する

ユーザー定義関数は、インスタンスがデバイスとセンサーのデータを受信するたびに実行されます。 このセクションでは、Azure Digital Twins インスタンスに対するクエリを実行して、ユーザー定義関数の結果を取得します。 部屋が使用可能な場合、空気が新鮮であり温度が適切であることが、ほぼリアルタイムで通知されます。

  1. サンプルのプロビジョニングに使用したコマンド ウィンドウを開くか、新しいコマンド ウィンドウを開き、再度サンプルの occupancy-quickstart\src フォルダーに移動します。

  2. 次のコマンドを実行します。メッセージが表示されたら、サインインします。

    dotnet run GetAvailableAndFreshSpaces
    

出力ウィンドウに、どのようにユーザー定義関数が実行され、デバイス シミュレーションからのイベントがインターセプトされているかが表示されます。

UDF の出力

監視されている条件が満たされると、前述のとおりに、ユーザー定義関数によって空間の値が関連メッセージと共に設定されます。 メッセージは、GetAvailableAndFreshSpaces 関数によってコンソールに出力されます。

リソースをクリーンアップする

この時点で Azure Digital Twins の探索を中止する場合は、このチュートリアルで作成されたリソースを削除してかまいません。

  1. Azure portal の左側のメニューにある [すべてのリソース] をクリックし、目的の Digital Twins リソース グループを選択して [削除] を選択します。

    ヒント

    ご自分の Digital Twins インスタンスの削除で問題が発生していた場合は、サービス更新が修正と共にロールアウトされています。 ご自分のインスタンスの削除を再試行してください。

  2. 必要に応じて、作業マシン上のサンプル アプリケーションを削除します。

次のステップ

これで、空間をプロビジョニングし、カスタム通知をトリガーするフレームワークを作成できたので、次のいずれかのチュートリアルに進むことができます。