シナリオ: 正規化されたIoTデータのモニター、コマンドの送信および電子メール・アラート

Node-REDで正規化されたOCI IoTデータをデキューし、ボイラー圧力がしきい値を超えた場合にリセット・コマンドを送信し、コマンド・ステータスをポーリングして、成功、失敗またはタイムアウトの電子メール・アラートを公開します。

このシナリオを使用して、OCI IoTによってすでに受信されているデータを監視し、条件が満たされたときにアクションを実行します。

フローは正規化されたデータをデキューし、ボイラー圧力が100を超えるとリセット・コマンドを送信し、IoTデータベースのコマンド・ステータスをポーリングします。最終結果は、通知ノードに進みます。非最終結果は5秒の遅延をループし、コマンドステータスを再度照会します。

このシナリオでは、IoTデータはすでにOCI IoT内にあるため、Flow Runtimeは、アプリケーションがIoTデータベースに直接アクセスする必要なく、軽量なイベント・プロセッサとして機能します。このパターンは、アラート、チケットの作成、ダウンストリーム通知およびその他の操作自動化に適応できます。

開始する前に、一般的なシナリオ設定を完了してください。

前提条件

  • OCI通知トピックとそのOCID。
  • 関連する通知およびデジタル・ツインのコマンド・インボーク・ポリシーを含むフロー・ランタイム・リソース・プリンシパル構成。

    フロー・ランタイム・リソース・プリンシパルがシナリオ・トピックにメッセージを公開できるように、通知ポリシーを追加します。

    Allow dynamic-group <flow-runtime-dynamic-group> to {ONS_TOPIC_PUBLISH} in compartment <notification-topic-compartment>

    リソース・プリンシパルがコマンドをリクエストできるように、デジタル・ツイン・コマンド・インボーク・ポリシーを追加します。

    Allow dynamic-group <flow-runtime-dynamic-group> to {IOT_DIGITAL_TWIN_INSTANCE_COMMAND_INVOKE} in compartment <iot-domain-compartment>
  • デキュー・ノードおよびSQLノードで使用可能なIoTドメイン・データベース接続。
  • 一般的なデジタル・ツイン・インスタンスの設定が完了したときに記録されるゲートウェイ外部キーおよびデバイス・パスワード。この例では、ゲートウェイの外部キーとしてfr-guide-gw-01を使用します。
  • フローによってモニターされるボイラのデジタル・ツイン・インスタンスのOCIDsおよび外部キー。
  • リセットの成功を検証するために、boilers/<external-key>/command/resetでリクエストを受信し、boilers/<external-key>/command/responseでレスポンスを返すデバイス側のコマンド・ハンドラ。

ステップ1: モニタリング・フロー・ランタイムの作成

  1. OCIコンソールでナビゲーション・メニューを開き、「開発者サービス」に移動し、「Internet of Things」で「ドメイン」を選択します。
  2. 操作するIoTドメインを選択し、「フロー・ランタイム」、「フロー・ランタイムの作成」の順に選択します。
  3. 次の値を使用します。
    フィールド値
    表示名FR Guide - Monitor and Action
    摘要NORMALIZED_DATAからIoTデータをデキューし、ボイラー圧力が100を超えるとボイラー・リセット・コマンドを送信し、コマンド結果をポーリングして、OCI通知を公開します。
    スケールMEDIUM
  4. 「作成」を選択し、フロー・ランタイムがアクティブになるまで数分待ちます。

キュー・サブスクライバの識別

フロー・ランタイム・スキーマの設定により、ドメインのNORMALIZED_DATAキューのサブスクライバが登録されます。デキュー・ノードの「サブスクライバ」フィールドで、ドメイン短縮ID、フロー・ランタイム短縮IDおよび接尾辞SUBSCRIBERから形成された名前を、単一のアンダースコアで区切って使用します。名前全体を大文字に変換します。

<DOMAIN_SHORT_ID>_<FLOW_RUNTIME_SHORT_ID>_SUBSCRIBER
ノート

サブスクライバ名全体(短縮IDとSUBSCRIBER接尾辞の両方を含む)は大文字にする必要があります。「サブスクライバ」フィールドに名前を入力する前に、短縮IDの小文字を大文字に変換します。各パーツ間にアンダースコアを1つ使用します。

キューを所有するドメインの短縮IDと、表示名や完全なOCIDsではなく、このフローを実行するフロー・ランタイムを使用します。ドメイン短縮IDは、ドメイン・データベース・スキーマ名の__IOTより前の接頭辞です。フロー・ランタイムの短縮IDは、そのエディタURLの最初の部分であるhttps://<flow-runtime-short-id>.flows.iot.<region>.oci.customer-oci.com/です。

たとえば、ドメインの短縮IDがabcd1234で、フロー・ランタイムの短縮IDがefab5678の場合は、ABCD1234_EFAB5678_SUBSCRIBERと入力します。両方のサンプルIDを独自の値に置き換えます。山カッコは入力しないでください。

接続設定のデキュー名前と目的
キュー名<domain-short-id>__IOT.NORMALIZED_DATAは、ドメイン・スキーマ内のキューを識別します。IOTの前に2つのアンダースコアがあります。
サブスクライバ<DOMAIN_SHORT_ID>_<FLOW_RUNTIME_SHORT_ID>_SUBSCRIBERは、このランタイムのキュー・サブスクライバを識別します。各パーツの間に大文字とアンダースコアを1つ使用します。
データベース・プロキシ・ユーザー<domain-short-id>_<flow-runtime-short-id>__FRは、ランタイムのデータベース・ユーザーを識別します。IDとFRの前にアンダースコアが1つあります。システム提供のIOT_FLOW_RUNTIME_PROXY_USER参照をインポートされた接続に保持します。

JSONフローをインポートしても、データベース・サブスクライバは作成されません。インジェクション・ノードはデキューをトリガーし、サブスクライバを登録しません。サブスクライバが欠落しているとデキューでレポートされた場合は、まず短いIDと大文字の両方を確認してから、スキーマ設定によってこのサブスクライバがNORMALIZED_DATAに登録されたことを確認するようランタイム管理者に依頼します。

モニタリング・フローのインポート

このインポート・パスまたは手動作成を選択します。両方のコピーをデプロイしないでください。この例では、キューからレコードを削除し、デバイスリセットコマンドおよび通知を送信できます。目的のテストデバイスおよびサブスクリプションでのみテストします。

  1. flows-monitor-send-command.jsonをダウンロードし、JSONファイルとして保存します。
  2. 既存のフローをバックアップします。ランタイム・エディタで、メニューから「インポート」を選択し、ダウンロードしたファイルを新しいフローにインポートします。まだデプロイしないでください。

    インポートには、処理ノード、ステータス・ポーリング・ループ、キャッチ/デバッグ・ノードおよび接続構成が含まれます。デジタル・ツイン、ポリシー、Notificationsのトピックまたは電子メール・サブスクリプションは作成されません。

  3. インポートされたノードで次の値を構成します。
    値または ノード構成
    <region>シナリオのOCI構成リージョンを設定します。コマンドおよび通知ノードのリソース・プリンシパル認証を保持します。
    IoTドメイン・データベース接続正規化されたデータのデキューおよび問合せコマンド・ステータスで、ランタイムのIoTドメイン接続が使用されていることを確認します。システム提供の環境参照を保持し、データベース資格証明をダウンロードに貼り付けないでください。
    <domain-short-id>デキュー・キュー名および問合せコマンド・ステータスSQLで、データベース接続と一致するドメイン・スキーマ接頭辞に置き換えます。ペイロード・タイプをJSONに設定したまま、ADTタイプを空のままにします。
    <queue-subscriber>正規化データのデキューで、このプレースホルダをドメインおよびランタイムの大文字の<DOMAIN_SHORT_ID>_<FLOW_RUNTIME_SHORT_ID>_SUBSCRIBER名に置き換えます。ネーミング・ルールおよび例は、キュー・サブスクライバの識別を参照してください。インポートではサブスクライバは作成されません。
    ボイラーOCIDs「高ボイラー圧の検出」で、<boiler-01-digital-twin-ocid>および<boiler-02-digital-twin-ocid>を2つのボイラー・デジタル・ツインOCIDsに置き換えます。外部キーを共通設定と照合します。このマップにHVAC OCIDsを入れないでください。
    <notification-topic-ocid>「ボイラ・アラート通知の公開」でトピックOCIDを設定します。ポリシーおよび電子メール・サブスクリプションの前提条件を完了します。
  4. デプロイ前にポーリング正規化データを確認します。エクスポートは、起動インジェクションなしで5秒ごとに繰り返されます。最初のテストでは、反復間隔を削除して、構成の完了後に手動でトリガーできるようにします。

    ステータスチェックの遅延は5秒、ポーリング期限は70秒のままにします。SQLのrecordIdバインドをmsg.rawCommandDataRecordIdにマップしたままにします。

  5. 電子メール・サブスクリプションとコマンド・サブスクリプションを完了します。構成済フローをデプロイし、テスト・データを生成して、ポーリング正規化データを手動でトリガーします。次のレスポンスおよび検証ステップに従います。

    検証後、連続ポーリングが必要な場合は繰返し間隔をリストアし、不要なデバッグ出力を無効にします。

ステップ2: 監視およびコマンドNode-REDフローの構成

  1. 「フロー・ランタイム」を選択して、その詳細ページを開きます。ノード-REDエディタを開くには、「フロー・ランタイム・エディタを開く」を選択するか、フロー・ランタイム・エンドポイントを表示する「エディタURL」を選択します。

    https://<flow-runtime-short-id>.flows.iot.<region>.oci.customer-oci.com/

  2. 次のノードをキャンバスに追加し、各ノードの「名前」フィールドを指定された値に設定します。
    ノード名前
    注入Poll Normalized Data
    デキューDequeue Normalized Data
    機能Detect High Boiler Pressure
    IoT送信コマンドSend Boiler Reset Command
    機能Initialize Command Status Polling
    遅延Wait Before Status Check
    SQLQuery Command Status
    機能Check Command Status
    機能Format Boiler Command Result Notification
    OCIの通知Publish Boiler Alert Notification
  3. 次の順序でノードを接続します。

    Poll Normalized Data -> Dequeue Normalized Data -> Detect High Boiler Pressure -> Send Boiler Reset Command -> Initialize Command Status Polling -> Wait Before Status Check -> Query Command Status -> Check Command Status

    コマンド・ステータスの確認の出力1をフォーマット・ボイラー・コマンド結果通知に接続し、「ボイラー・アラート通知の公開」に接続します。Check Command Statusの出力2を Wait Before Status Checkに接続します。

    他のファンクション・ノードに対して1つの出力を使用します。出力1は、最終的なコマンド結果またはポーリング・タイムアウトを処理します。出力2では、遅延によって最終でない結果がループされ、SQL問合せが再度実行されます。

  4. 「正規化されたデータのポーリング」インジェクト・ノードを次の設定で構成します:
    フィールド値
    名前Poll Normalized Data
    ペイロードタイムスタンプ
    トピック空白のまま。
    次より後に1回注入選択を解除したままにします。
    繰返し間隔
    毎回5 seconds

    最初のテストでは、繰り返し間隔を未設定のままにして、構成後にノードを手動でトリガーします。フローの検証後、5秒間隔を有効にするか、キュー・トラフィックとデータベース・ロードに一致するように調整します。

  5. 正規化されたデータのデキュー・ノードを構成します。
    フィールド値
    名前Dequeue Normalized Data
    DB接続IoTドメイン・データベース接続。
    モードトランザクション
    キュー名<domain-short-id>__IOT.NORMALIZED_DATA
    サブスクライバドメインおよびランタイムの大文字の<DOMAIN_SHORT_ID>_<FLOW_RUNTIME_SHORT_ID>_SUBSCRIBER名。「キュー・サブスクライバの識別」を参照してください。
    ペイロード・型JSON
    ADTタイプJSONペイロードの場合は空白のままにします。
    デキュー・モード削除
    Wait0
    バッチ・サイズ2
  6. ファンクション・ノードの「名前」をDetect High Boiler Pressureに、「出力」を1に設定します。boilerExternalKeyMapのデジタル・ツインOCIDsの例を置き換えます。NORMALIZED_DATAには、HVACデバイスとボイラー・デバイスの両方からの圧力イベントを含めることができます。このコードを使用してリセット・コマンドを送信するのは、イベントがマップされたボイラのデジタル・ツイン・インスタンスに属し、その圧力が100より大きい場合のみです。
    const PRESSURE_LIMIT = 100;
    
    // Include only Boiler digital twins in this map.
    // HVAC pressure records are ignored because their OCIDs are not mapped here.
    const boilerExternalKeyMap = {
      "<boiler-01-digital-twin-ocid>": "fr-guide-boiler-01",
      "<boiler-02-digital-twin-ocid>": "fr-guide-boiler-02"
    };
    
    const event = msg.payload || {};
    const twinOcid = event.digitalTwinInstanceId;
    const externalKey = boilerExternalKeyMap[twinOcid];
    
    if (event.contentPath !== "pressure" || !externalKey) {
      return null;
    }
    
    const pressure = Number(event.value);
    if (!Number.isFinite(pressure) || pressure <= PRESSURE_LIMIT) {
      return null;
    }
    
    msg.digitalTwinOcid = twinOcid;
    msg.requestEndpoint = `boilers/${externalKey}/command/reset`;
    msg.responseEndpoint = `boilers/${externalKey}/command/response`;
    
    msg.title = `Boiler High Pressure Alert - ${externalKey}`;
    msg.notificationpayload = {
      alert: "Boiler pressure is above the allowed limit",
      action: "Reset boiler command sent",
      digitalTwinOcid: twinOcid,
      externalKey: externalKey,
      pressure: pressure,
      threshold: PRESSURE_LIMIT,
      timeObserved: event.timeObserved
    };
    
    msg.payload = { reset: true };
    return msg;
  7. 「ボイラ・リセット・コマンドの送信」IoT送信コマンド・ノードを構成します:
    フィールド値
    名前Send Boiler Reset Command
    OCI構成FR - Resource Principal
    デジタル・ツインOCID空白のまま。高ボイラー圧力検出ノードは、msg.digitalTwinOcidを設定します。
    リクエスト・エンドポイント空白のまま。高ボイラー圧力検出ノードは、msg.requestEndpointを設定します。
    リクエスト・ペイロード空白のまま。高ボイラー圧力検出ノードは、msg.payloadを{"reset":true}に設定します。
    レスポンスの待機チェック・ボックスを選択します。
    レスポンス・エンドポイント空白のまま。高ボイラー圧力検出ノードは、msg.responseEndpointを設定します。
    リクエスト期間PT1M
    レスポンス期間PT1M

    ノードがコマンドを送信すると、コマンド・レコードIDがmsg.rawCommandDataRecordIdに追加されます。

  8. ファンクション・ノードの「名前」をInitialize Command Status Pollingに、「出力」を1に設定します。次のコードを使用して、70秒のポーリング期限を開始し、ポーリング・カウンタを初期化します。
    msg.pollDeadline = Date.now() + 70000;
    msg.pollCount = 0;
    return msg;

    70秒の期限は、1分間のレスポンス・ウィンドウと、最終的なデータベース更新の10秒をカバーします。

  9. 5 secondsの各メッセージを遅延するように、「ステータス・チェック前の待機」遅延ノードを構成します。
    フィールド値
    名前Wait Before Status Check
    処理各メッセージの遅延、固定遅延
    対象5 seconds

    このノードは、Initialize Command Status Pollingから初期ポーリング・メッセージを受信し、Check Command Statusの出力2から最終以外の結果を受信します。

  10. 「コマンド・ステータスの問合せ」SQLノードを構成して、コマンド・レスポンスを問い合せます。
    フィールド値
    名前Query Command Status
    DB接続IoTドメイン・データベース接続。
    SQLソースエディタ
    ソースをバインドエディタ
    バインド変数recordId
    ソースのバインドメッセージ・プロパティ
    プロパティ・パスrawCommandDataRecordId
    最大行数1

    <domain-short-id>をデバイス・ホストのドメイン短縮IDに置き換え、次の問合せを使用します。

    SELECT
           ID,
           DIGITAL_TWIN_INSTANCE_ID,
           REQUEST_ENDPOINT,
           RESPONSE_ENDPOINT,
           DELIVERY_STATUS,
           UPPER(
               JSON_VALUE(
                   RESPONSE_DATA FORMAT JSON,
                   '$.reset'
                   RETURNING VARCHAR2(30)
                   NULL ON ERROR
               )
           ) AS RESET_RESULT,
           TIME_CREATED,
           TIME_UPDATED,
           TIME_FINISHED
      FROM <domain-short-id>__IOT.RAW_COMMAND_DATA
     WHERE ID = :recordId

    列の説明については、RAW_COMMAND_DATAを参照してください。

  11. ファンクション・ノードの「名前」をCheck Command Statusに、「出力」を2に設定します。出力1をFormat Boiler Command Result Notificationに接続し、出力2をWait Before Status Checkに戻します。このコードを使用して、最終結果またはタイムアウトを出力1にルーティングし、非最終結果を出力2にルーティングします。
    const rows = Array.isArray(msg.payload) ? msg.payload : [];
    const row = rows[0];
    msg.pollCount = (msg.pollCount || 0) + 1;
    
    if (!row) {
      if (Date.now() < msg.pollDeadline) {
        return [null, msg];
      }
    
      msg.payload = [{
        DELIVERY_STATUS: "POLL_TIMEOUT",
        RESET_RESULT: null,
        TIME_FINISHED: null
      }];
      return [msg, null];
    }
    
    const status = String(row.DELIVERY_STATUS || "").toUpperCase();
    const finalStatuses = [
      "COMPLETED",
      "REJECTED",
      "REFUSED",
      "EXPIRED",
      "BAD_RESPONSE",
      "NOT_RESPONDED"
    ];
    
    if (finalStatuses.includes(status)) {
      return [msg, null];
    }
    
    if (Date.now() >= msg.pollDeadline) {
      msg.payload = [{
        ...row,
        DELIVERY_STATUS: "POLL_TIMEOUT"
      }];
      return [msg, null];
    }
    
    return [null, msg];
  12. ファンクション・ノードの「名前」をFormat Boiler Command Result Notificationに、「出力」を1に設定します。成功、失敗またはタイムアウトの電子メール本文を作成するには、次のコードを使用します。
    const row = msg.payload[0] || {};
    const alert = msg.notificationpayload || {};
    const commandStatus = String(row.DELIVERY_STATUS || "UNKNOWN").toUpperCase();
    const resetResult = String(row.RESET_RESULT || "NO_RESPONSE").toUpperCase();
    const resetSucceeded = commandStatus === "COMPLETED" && resetResult === "SUCCESS";
    
    let result;
    if (resetSucceeded) {
      msg.title = `Boiler High Pressure Alert - Reset Successful - ${alert.externalKey}`;
      result = "The device confirmed that the boiler reset completed successfully.";
    } else if (commandStatus === "POLL_TIMEOUT") {
      msg.title = `Boiler High Pressure Alert - Reset Status Timed Out - ${alert.externalKey}`;
      result = "No final command status was available before the polling deadline.";
    } else {
      msg.title = `Boiler High Pressure Alert - Reset Failed - ${alert.externalKey}`;
      result = "The device did not confirm a successful boiler reset.";
    }
    
    msg.payload = JSON.stringify({
      ...alert,
      result: result,
      commandStatus: commandStatus,
      resetResult: resetResult,
      timeFinished: row.TIME_FINISHED || null
    }, null, 2);
    
    return msg;
  13. ボイラー・アラート通知の公開OCI通知ノードを構成します:
    フィールド値
    名前Publish Boiler Alert Notification
    OCI構成FR - Resource Principal
    トピックOCID<notification-topic-ocid>
    タイトル空白のまま。Format Boilerコマンド結果通知ノードは、msg.titleを設定します。
    本文空白のまま。Format Boilerコマンド結果通知ノードは、msg.payloadを設定します。
  14. オプションで、デキューされたレコード、コマンド・レコードID、SQL結果および通知ペイロードの検証中にデバッグ・ノードを接続します。
  15. 「デプロイ」を選択します
  16. エクスポートされた完全なフロー・ドキュメントをかわりにインストールするには、次を使用します。
    oci iot flow-runtime update-flows \
      --iot-flow-runtime-id <flow-runtime-ocid> \
      --flows-document file://<path-to-flows-json>

    コンソールまたはAPIを使用してフロー・ドキュメントを更新する方法の詳細は、IoTフロー・ランタイムのフローの更新を参照してください。

ステップ3: Eメール・サブスクライブの作成

  1. OCIコンソールで、ナビゲーション・メニューを開き、「開発者サービス」に移動します。「アプリケーション統合」で、「通知」を選択し、フローで構成されている通知トピックを選択します。
  2. 「サブスクリプション」、「サブスクリプションの作成」の順に選択します。
  3. 「電子メール」プロトコルを選択し、ボイラー・アラートを受信する電子メール・アドレスを入力し、サブスクリプションを作成します。
  4. 確認の電子メールを開き、確認のリンクをクリックしてサブスクリプションを確認します。
  5. 「通知」で、サブスクリプションの状態が「保留」ではなく「アクティブ」であることを確認します。

    CLIおよびAPIの使用方法などの詳細は、通知でのトピックの作成および電子メール・サブスクリプションの作成を参照してください。

ステップ4: コマンド・リクエスト・エンドポイントのサブスクライブ

  1. MQTTXまたは別のMQTTクライアントで、ゲートウェイ資格証明を使用してOCI IoTデバイス・ホストに接続します。
    フィールド値
    ホスト<device-host>
    ポート8883
    SSL/TLS有効
    プロトコルMQTT V3.1.1またはMQTT V5
    ユーザ名fr-guide-gw-01
    パスワードゲートウェイデバイスのパスワード。
  2. 次の設定を使用して、コマンド・リクエスト・エンドポイントをサブスクライブします:
    フィールド値
    トピックboilers/fr-guide-boiler-01/command/reset
    QoS1

    フローをトリガーする前に、ゲートウェイMQTTクライアントを接続したまま、アクティブにサブスクライブします。接続されたクライアントが正確なリクエスト・エンドポイントにサブスクライブされていない場合、RAWコマンドはDELIVERY_STATUSをREFUSEDに設定してただちに終了します。

ステップ5: 高ボイラー圧力メッセージの生成

HTTPSまたはMQTTSを使用して高圧ボイラー・メッセージを送信します。前のステップのGateway MQTTクライアントを接続してサブスクライブしたままにして、resetコマンドを受信できるようにします。
  • ゲートウェイ外部キーをデバイス・ユーザー名として使用し、ゲートウェイ・デバイス・パスワードをパスワードとして使用します。<domain-short-id-from-device-host>、<region>および<gateway-device-password>を環境の値に置き換えます。

    curl -i -X POST \
      -u "fr-guide-gw-01:<gateway-device-password>" \
      -H "Content-Type: application/json" \
      "https://<domain-short-id-from-device-host>.device.iot.<region>.oci.oraclecloud.com/boilers/fr-guide-boiler-01" \
      -d '{
        "temperature": 83,
        "pressure": 102
      }'
  • 同じゲートウェイ認証MQTT接続を使用して、次の設定で高圧ボイラー・メッセージをパブリッシュします。

    フィールド値
    トピックboilers/fr-guide-boiler-01
    QoS1
    ペイロード・型JSON
    {
      "temperature": 83,
      "pressure": 102
    }

ステップ6: コマンド・レスポンスを送信する

  1. MQTTクライアントがboilers/fr-guide-boiler-01/command/resetでリセット・リクエストを受信するまで待機し、リクエスト・ペイロードに{"reset":true}が含まれていることを確認します。
  2. 次の設定を使用して、正常なデバイス・レスポンスを公開します。
    フィールド値
    トピックboilers/fr-guide-boiler-01/command/response
    QoS1
    ペイロード・型JSON
    {
      "reset": "SUCCESS"
    }

ステップ7: ポーリング・フローおよび電子メール通知の検証

  1. OCI IoTがHTTPSまたはMQTTS経由で送信された高圧ボイラー・メッセージを取り込み、モニタリング・フローがNORMALIZED_DATAから個々のイベントをデキューすることを確認します。
  2. 「高ボイラー圧力の検出」で、pressureが100より大きいマップされたボイラー・デジタル・ツイン・インスタンスに対してのみ、HVAC圧力レコードが無視され、トリガーがトリガーされることを確認します。
  3. Send Boiler Reset Commandが{"reset":true}をboilers/fr-guide-boiler-01/command/resetに送信し、msg.rawCommandDataRecordIdを返すことを確認します。
  4. 「コマンド・ステータスの初期化ポーリング」で70秒の期限が設定され、「コマンド・ステータスの問合せ」でコマンド・レコードIDを使用して5秒ごとにRAW_COMMAND_DATAを問い合せることを確認します。
  5. レスポンスが成功した場合は、問合せがDELIVERY_STATUSをCOMPLETEDとして、RESET_RESULTをSUCCESSとして返すことを確認します。「コマンド・ステータスの確認」の出力1がポーリング・ループをただちに終了することを確認します。
  6. アクティブな電子メール・サブスクリプションが、件名Boiler High Pressure Alert - Reset Successful - fr-guide-boiler-01の電子メールを受信することを確認します。
  7. 電子メールの本文が次のようになっていることを確認します。
    {
      "alert": "Boiler pressure is above the allowed limit",
      "action": "Reset boiler command sent",
      "digitalTwinOcid": "<boiler-digital-twin-ocid>",
      "externalKey": "fr-guide-boiler-01",
      "pressure": 102,
      "threshold": 100,
      "timeObserved": "<timestamp>",
      "result": "The device confirmed that the boiler reset completed successfully.",
      "commandStatus": "COMPLETED",
      "resetResult": "SUCCESS",
      "timeFinished": "<timestamp>"
    }
  8. リセットが成功したことを確認しない最終ステータスの場合、出力1がループを終了し、電子メールの件名にBoiler High Pressure Alert - Reset Failedと報告されていることを確認します。70秒以内に使用可能な最終ステータスがない場合は、フローがPOLL_TIMEOUTを出力し、電子メールの件名にBoiler High Pressure Alert - Reset Status Timed Outとレポートされていることを確認します。
  9. ボイラのデジタル・ツイン・インスタンスの「データ」タブで、最新のスナップショットにpressureと値102および予測観測時間が表示されていることを確認します。

セキュリティの考慮事項

フロー・ランタイム・リソース・プリンシパルを使用して、承認済通知トピックにのみ公開し、承認済デジタル・ツイン・インスタンスでのみコマンドを起動します。通知およびコマンド・ペイロードを受信者に必要な操作フィールドに制限し、IoTドメインのデータベース接続、キュー・サブスクライバおよびコマンド・レスポンス・データを保護します。

トラブルシューティング

  • キュー名、サブスクライバ、JSONペイロード・タイプ、待機値、2のバッチ・サイズおよびIoTドメイン・データベース接続を確認します。
  • デバッグ・ノードを使用して、正規化されたレコードがdigitalTwinInstanceId、contentPath、valueおよびtimeObservedを公開することを確認します。
  • boilerExternalKeyMapに、正確なボイラー・デジタル・ツインOCIDsおよび一致するデジタル・ツイン・インスタンスの外部キーのみが含まれていることを確認します。HVAC圧力レコードは、OCIDsがマップされていないため無視されます。外部キーを検索するには、デジタル・ツインのインスタンス詳細の取得を参照するか、外部キーを変更するには、デジタル・ツイン・インスタンスの更新を参照してください。
  • IoT送信コマンド・ノードがリソース・プリンシパル構成を使用し、msg.digitalTwinOcid、msg.requestEndpointおよびmsg.responseEndpointを受信し、「レスポンスの待機」が選択されていることを確認します。
  • フローがコマンドを送信する前に、ゲートウェイMQTTクライアントが接続されたまま、正確なリクエスト・エンドポイントにサブスクライブしていることを確認します。アクティブなサブスクライバがない場合、コマンドはDELIVERY_STATUSをREFUSEDに設定してただちに終了します。
  • デバイス側のコマンド・ハンドラがリクエスト・エンドポイントをリスニングし、レスポンス期間が期限切れになる前にその結果をレスポンス・エンドポイントにパブリッシュすることを確認します。
  • 「コマンド・ステータスの初期化ポーリング」で、最初の遅延の前にmsg.pollDeadlineおよびmsg.pollCountが設定されていることを確認します。
  • SQLノードが行を返さない場合は、IoT送信コマンド・ノードの後にmsg.rawCommandDataRecordIdが存在し、recordIdバインド変数にマップされていることを確認します。期限が切れる前に、Check Command Statusの出力2から行がない状態が続く必要があります。
  • 「コマンド・ステータスの確認」の出力1が「フォーマット・ボイラー・コマンド結果通知」に接続され、出力2が「ステータス・チェックの前に待機」に接続されていることを確認します。
  • リセットが失敗と報告された場合は、RAW_COMMAND_DATAのDELIVERY_STATUS、RESET_RESULTおよびTIME_FINISHEDを調べます。最終的なステータスは、COMPLETED、REJECTED、REFUSED、EXPIRED、BAD_RESPONSEおよびNOT_RESPONDEDです。
  • フローでPOLL_TIMEOUTがレポートされた場合は、遅延ノードが5秒を使用し、コマンドが70秒の期限より前に最終ステータスに達していないことを確認します。
  • 「通知」トピックのOCID、リソース・プリンシパル構成、メッセージの公開権限およびアクティブな電子メール・サブスクリプションを確認します。

詳細は、「IoTフロー・ランタイムのトラブルシューティング」および「フロー・ランタイムFAQ」を参照してください。

FAQ

電子メール・サブスクリプションがアクティブである必要があるのはなぜですか。
OCI通知では、状態が「保留中」の間はアラートが電子メール・サブスクリプションに配信されません。フローをテストする前に、確認リンクに従ってください。
フローが5秒ごとにコマンド・ステータスを問い合せるのはなぜですか。
短い遅延により、フローは完全な応答ウィンドウを待たずに、最終的なコマンドステータスを検出できます。最終以外の結果は、遅延ノードにループして戻され、再度問い合せられます。
なぜ投票期限は70秒?
コマンド・レスポンス期間はPT1Mです。この追加10秒により、フローがPOLL_TIMEOUTをレポートする前に、OCI IoTで最終的なデータベース更新を適用できます。
このフローはどのキュー・レコードを評価しますか。
フローは、<domain-short-id>__IOT.NORMALIZED_DATAからJSONレコードをデキューします。pressureイベントは、デジタル・ツインOCIDがboilerExternalKeyMapに存在する場合にのみ評価されるため、HVAC圧力レコードおよびマップされていないボイラー・レコードは無視されます。
通知によってリセットが成功したのはいつですか。
リセットが成功するのは、DELIVERY_STATUSがCOMPLETEDで、レスポンスJSONにreset: SUCCESSが含まれている場合のみです。その他の最終結果ではリセット失敗通知が使用され、期限内に最終結果がない場合にはタイムアウト通知が使用されます。
コマンドがREFUSEDで終了したのはなぜですか。
フローがコマンドを送信したときに、ゲートウェイMQTTクライアントが接続されておらず、正確なコマンド・リクエスト・エンドポイントにアクティブにサブスクライブされていました。フローをトリガーする前に、boilers/fr-guide-boiler-01/command/resetをサブスクライブします。
Live-ingestionシナリオを使用してテスト・データを生成できますか。
いいえ、提供されているライブ・インジェクション・フローではなく、ゲートウェイおよびHVACレコードのみを受け入れ、ボイラのトピックを無視します。このシナリオのHTTPSまたはMQTTSテスト・ステップに従って、IoTデバイスホスト・トピックboilers/fr-guide-boiler-01に直接公開します。