シナリオ: オブジェクト・ストレージからのバッチ・データの取込み

OCI Object Storageから順次CSVオブジェクトをダウンロードし、Node-REDの各バッチ・レコードを変換してOCI IoTに取り込みます。

このシナリオを使用して、オブジェクト・ストレージから順次CSVオブジェクトをダウンロードし、オフラインまたは履歴の読取りをOCI IoTにリプレイして、デジタル・ツイン履歴を完全な状態に保ちます。Node-REDフローはInject -> Prepare Filename -> Object Storage Download -> Increment Index -> CSV -> Transform -> MQTT-OUTです。

ノート

このシナリオでは、各CSVファイルはフローがオンデマンドでダウンロードおよび処理する個別のオブジェクトであるため、オブジェクト・ストレージを使用します。フローで、マウントされたファイル・システム・パスを介して使用可能な共有ファイルが必要な場合は、File Storageを使用します。ファイル・ストレージまたはオブジェクト・ストレージの選択を参照してください。

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

前提条件

バッチCSVオブジェクトのオブジェクト・ストレージ・バケットを作成します。オブジェクト・ストレージ・ネームスペースおよびバケット名を記録します。フロー・ランタイム動的グループを作成し、オブジェクト・ストレージ・ノードで使用されるリソース・プリンシパル構成に、バケットからオブジェクトをダウンロードするために必要なオブジェクト・ストレージ読取りポリシーがあることを確認します。

フロー・ランタイムは、オブジェクト・ストレージおよびOCI IoTデバイス・ホストに到達できる必要があります。

ステップ1: IoTフロー・ランタイムの作成

  1. OCI Consoleで、ナビゲーション・メニューを開きます。「開発者サービス」に移動し、「Internet of Things」を選択します。操作するIoTドメインを選択し、「フロー・ランタイム」、「フロー・ランタイムの作成」の順に選択します。
  2. 次の値を使用します。
    フィールド値
    表示名FR Guide - Batch Ingest
    摘要オブジェクト・ストレージからバッチCSVファイルを読み取り、テレメトリをOCI IoTに取り込みます。
    スケールMEDIUM
  3. ランタイムを作成し、アクティブになるまで待機します。

ステップ2: バッチCSVオブジェクトのアップロード

  1. iot-data-1.csvという名前のオブジェクトをオブジェクト・ストレージ・バケットにアップロードします。

    カウンタ1で始まるiot-data-<counter>.csvの形式で順次名前を使用します。

  2. 次の内容を追加します。
    deviceType,externalId,time,cpuUtil,memUtil,diskUtil,firmware,temperature,humidity,pressure,mode
    gateway,fr-guide-gw-01,1773768299143534,33,28,22,Oracle Linux 9.1,,,,
    hvacs,fr-guide-hvac-01,1773768299144534,,,,,70.5,44.2,101.1,cool
    hvacs,fr-guide-hvac-02,1773768299145534,,,,,78.3,52.0,100.7,heat

インポートまたは手動構成パスの選択

このバッチ取込みシナリオは、次の2つの方法で完了できます。どちらの方法でも、オブジェクト・ストレージからCSVオブジェクトをダウンロードし、バッチ・データをOCI IoTに取込む方法を示しています。
  1. オプション1: ステップ3を完了して、このシナリオの例のJSONフロー・ファイルを管理対象Node-REDエディタにインポートし、インポートされたフローを変更してリソースを使用し、その構成を確認します。
  2. オプション2: ステップ4に進み、管理対象Node-REDエディタでフローを直接構築および構成します。
ノート

このシナリオを手動ですでに作成している場合は、JSONをインポートする必要はありません。インポートしたコピーと手動で作成したコピーの両方をデプロイしないでください。重複した読取りを取り込むことができます。

ステップ3: このシナリオのJSONフロー・ファイルのインポート

OCIコンソールから開いた管理対象ノード-REDエディタには、この例に必要なOCIノードが含まれます。

インポートにより、オブジェクト・ストレージからバッチ・データを取り込むというフロー・タブとその構成ノードが作成されます。前述のステップおよび共通設定で必要なバケット、アクセス・ポリシーまたはデジタル・ツイン・リソースは作成されません。MQTT資格証明は、エクスポートされたJSONに含まれません。

  1. ingesting-batch-data-from-object-storage-flow.jsonをコンピュータにダウンロードします。

    ブラウザにJSONが表示されている場合は、その保存オプションを使用して、.json拡張子でファイルを保存します。

  2. OCIコンソールで、IoTドメインを選択し、「フロー・ランタイム」を選択して、ステップ1で作成したランタイムを開き、「フロー・ランタイム・エディタを開く」を選択します。
  3. エディタのメイン・メニューで、「インポート」を選択し、ダウンロードしたJSONファイルを選択して、新しいフローにインポートするオプションを選択し、「インポート」を選択します。
  4. 次の表を使用して、インポートされたノード構成の4つのプレースホルダ値を置き換えます。

    ノードをダブルクリックして、そのエディタを開きます。ノードで共有される構成の場合は、その構成フィールドの横にある「編集」ボタンを選択します。山カッコを含むプレースホルダ全体を値に置き換えます。たとえば、<bucket-name>を実際のバケット名(iot-batch-dataなど)に置き換えます。値を引用符なしで入力します。各構成を保存し、「完了」を選択してノード・エディタを閉じます。

    プレースホルダ置換する場所入力する値
    <region>オブジェクト・ストレージ・ノードを開き、そのOCI構成を編集して、リージョンを設定します。バケットのOCIリージョン識別子(us-ashburn-1など)。表示名ではなく、バケットを作成したリージョンを使用します。リソース・プリンシパル認証を選択したままにします。
    <object-storage-namespace>オブジェクト・ストレージ・ノード: ネームスペース。OCIコンソールでバケットの詳細からオブジェクト・ストレージ・ネームスペースをコピーします。これは、テナンシの表示名やOCIDではなく、前提条件に記録されるネームスペースです。
    <bucket-name>オブジェクト・ストレージ・ノード: バケット。iot-data-1.csvを含むバケットの正確な名前をステップ2からコピーします。その大/小文字を保持し、バケットOCIDまたはURLを入力しないでください。
    <device-host>MQTT-OUTノードを開き、そのサーバー構成を編集して、「サーバー」を置き換えます。IoTドメインの詳細からデバイス・ホストをコピーします。Getting an IoT Domain's Detailsを参照してください。URLスキーム、ポートまたはパスを使用せずにホスト名のみを入力します。ポートは、8883として個別に構成されます。
  5. MQTTサーバー構成で、ゲートウェイ資格証明を入力し、接続設定を確認します。

    共通設定値を使用した場合は、「セキュリティ」タブで、ゲートウェイ外部キーを「ユーザー名」としてfr-guide-gw-01と入力します。Vaultに格納されている実際のゲートウェイ・デバイス・パスワードを、シークレットOCIDまたはOCIコンソール・パスワードではなく、パスワードとして入力します。これらの値は、ゲートウェイ・デジタル・ツイン・インスタンスの作成から取得されます。

    「クライアントID」で、このデバイス・ホストに接続されているクライアント間で一意の値(fr-guide-batch-01など)を選択します。別のコピーをデプロイする場合は、別の値を使用します。MQTT-OUT構成ステップでTLSおよびその他の設定を確認し、Content Typeをapplication/jsonに設定してMQTT 5.0を保持します。

  6. デプロイする前に、次のリンクを使用して、インポートされたノードをシナリオ手順と照合して確認します。

    ノードはすでに接続されています。既存の設定およびコードを確認します。重複ノードを追加する必要はありません。

    インポートされたノードシナリオ指示
    注入時間間隔および手動トリガーを確認します。
    ビルドファイル名次の順次オブジェクト名がどのように構築されるかを確認します。
    オブジェクト・ストレージリソース・プリンシパル・アクセスとテキスト/UTF-8のダウンロード設定を確認します。
    インデックス増分ダウンロード後に file counterの更新を確認します。
    CSVcolumnsおよび1行につき1つのメッセージの出力を確認します。
    csvからIoTゲートウェイおよびHVACのトピックとペイロード・マッピングを確認します。
    MQTT-OUTdevice-host connectionおよび認証を確認します。
    Catch、OS Node error catchおよびMQTT Inputエラー・レポートおよびMQTT-OUTに送信されたメッセージを確認します。

ステップ4: ノード-REDフローの確認および構成

例をインポートした場合は、次のステップを使用して既存のノードをレビューおよび調整します。フローを手動で構築する場合は、ノードを追加および接続してから構成してください。

  1. 「IoTドメイン」リスト・ページで、フロー・ランタイムを含むドメインを選択し、「フロー・ランタイム」を選択します。フロー・ランタイム名およびオープン・フロー・ランタイム・エディタを選択します。
  2. フローを手動で構築する場合は、次のノードを順番に追加して接続します。

    Inject -> Prepare Filename Function -> Object Storage -> Increment Index Function -> CSV -> Transform Function -> MQTT-OUT

    サンプル・プレースホルダを独自のリソース値に置換する手順は、ステップ3: このシナリオのJSONフロー・ファイルのインポートを参照してください。

  3. 1時間ごとに繰り返すようにインジェクト・ノードを構成します。

    インポートされたフローでは、すでに時間間隔が使用されており、起動時に1回注入されません。最初のテストでは、repeatオプションをnoneに設定し、ノードを手動でトリガーします。検証後に時間間隔をリストアします。

  4. filename-preparation Functionノードを1つの出力に設定し、次のコードを使用します。
    let index = flow.get("iotFileIndex") || 1;
    
    let objectName = `iot-data-${index}.csv`;
    
    msg.fileIndex = index;
    msg.objectName = objectName;
    msg.payload = objectName;
    
    return msg;
  5. オブジェクトをダウンロードするようにオブジェクト・ストレージ・ノードを構成します:
    フィールド値
    OCI構成リソース・プリンシパル構成を作成または選択します。
    工程ダウンロード
    ネームスペース<object-storage-namespace>
    バケット<bucket-name>
    オブジェクト名空白のまま。前述の「関数」ノードは、順次オブジェクト名を指定します。
    ファイル・パス空白のまま。
    出力のダウンロードテキスト
    エンコーディング UTF-8
  6. 索引増分ファンクション・ノードを1つの出力に設定し、次のコードを使用します。
    const current = msg.fileIndex || flow.get("iotFileIndex") || 1;
    
    flow.set("iotFileIndex", current + 1);
    
    msg.processedObjectName = msg.objectName;
    return msg;
  7. CSVノードを構成します。
    フィールド値
    カラムdeviceType,externalId,time,cpuUtil,memUtil,diskUtil,firmware,temperature,humidity,pressure,mode
    1行目のデータに列名が含まれる有効
    出力行ごとに1つのメッセージ
  8. 変換関数ノードを1つの出力に設定し、次のコードを使用します。
    const row = msg.payload || {};
    
    const deviceType = String(row.deviceType || "").trim();
    const externalId = String(row.externalId || "").trim();
    
    if (!deviceType || !externalId) {
      node.warn("Skipping CSV row with missing deviceType or externalId");
      return null;
    }
    
    const timeValue = Number(row.time || Date.now() * 1000);
    
    if (deviceType === "gateway") {
      msg.topic = "data";
      msg.payload = {
        time: timeValue,
        cpuUtil: Number(row.cpuUtil || 0),
        memUtil: Number(row.memUtil || 0),
        diskUtil: Number(row.diskUtil || 0),
        firmware: row.firmware || "unknown"
      };
    } else if (deviceType === "hvacs") {
      msg.topic = "hvacs/" + externalId;
      msg.payload = {
        time: timeValue,
        temperature: Number(row.temperature || 0),
        humidity: Number(row.humidity || 0),
        pressure: Number(row.pressure || 0),
        mode: row.mode || "unknown"
      };
    } else {
      node.warn("Unsupported CSV deviceType: " + deviceType);
      return null;
    }
    
    msg.payload = JSON.stringify(msg.payload);
    return msg;
  9. OCI IoTデバイス・ホストに公開するようにMQTT-OUTを構成します。
    ノート

    MQTT v5を使用する場合は、Content Type application/jsonを使用する必要があります
    フィールド値
    サーバー<device-host>
    ポート8883
    TLSの使用有効
    トピック空白のまま。「ファンクション」ノードはmsg.topicを設定します。
    QoS1
    ユーザ名fr-guide-gw-01
    パスワードVaultに格納されているゲートウェイデバイスのパスワード。
    コンテンツ・タイプ(MQTT v5を使用している場合) application/json
  10. フローの検証中にキャッチ・ノードとデバッグ・ノードを確認します。

    インポートされたCatchノードは、オブジェクト・ストレージ・ノードにスコープ指定され、OSノード・エラー・キャッチのデバッグ・ノードにエラーを送信します。「MQTT入力」デバッグ・ノードには、MQTT-OUTに送信された変換出力が表示されます。OCI IoTがメッセージを受信したかどうかは確認されません。手動で構築する場合は、これらの接続を追加して、「デバッグ」サイドバーでエラーおよび変換されたメッセージを検査します。

エクスポートされた完全フローJSONファイルの操作

  • ダウンロード可能なシナリオをインポートするには、ステップ3: このシナリオのJSONフロー・ファイルのインポートを使用します。エクスポートされた別のフロー・ドキュメントの場合は、次のエディタ・ステップを使用します。CLIおよびAPIメソッドは、ランタイムの完全なフロー・ドキュメントを置き換えます。

    1. フロー・ランタイム・エディタを開きます。エディタの検索に関するヘルプが必要な場合は、IoTフロー・ランタイムの詳細の取得を参照してください。
    2. ノード-REDエディタで、メイン・メニューを開き、「インポート」を選択します。詳細は、Node-REDのインポートのドキュメントを参照してください。
    3. エクスポートしたフロー・ドキュメントを貼り付けるか、そのファイルを選択して、「インポート」を選択します。
    4. インポートされたノードと接続を確認し、「デプロイ」を選択します。
  • 完全なフロー・ドキュメントを置換するには、oci iot flow-runtime update-flowsコマンドを使用します。

    oci iot flow-runtime update-flows \
      --iot-flow-runtime-id <flow-runtime-ocid> \
      --flows-document file://<path-to-flows-json>
    ノート

    このコマンドは、完全なフロー・ドキュメントを置き換えます。バックアップが必要な場合は、最初に現在のドキュメントを取得して保存します。

    詳細は、IoTフロー・ランタイムのフローの更新を参照してください。

  • 完全なフロー・ドキュメントを置き換えるには、UpdateIotFlowRuntimeFlows操作を実行します。

    PUT /20250531/iotFlowRuntimes/{iotFlowRuntimeId}/flows
    <complete-Node-RED-flows-document>

    エクスポートされた完全なNode-REDフロー・ドキュメントをリクエスト本文として渡します。同期操作ではフロー・ドキュメントが返され、作業リクエストは作成されません。

    ノート

    この操作により、完全なフロー・ドキュメントが置換されます。バックアップが必要な場合は、最初に現在のドキュメントを取得して保存します。

ステップ5: フローのデプロイと実行

  1. リソースのプレースホルダが交換され、ゲートウェイ資格証明が入力され、ノードに構成エラーが表示されていないことを確認します。「デプロイ」を選択します
  2. iot-data-1.csv、iot-data-2.csv、iot-data-3.csvなどの順次名を使用して、構成済バケットにCSVオブジェクトをアップロードします。
  3. 最初のテストでは、Injectノードを手動でトリガーします。Object Storageノードが次のオブジェクトをダウンロードしていることを確認します。

    新しいフローは iot-data-1.csvで始まります。成功した各ダウンロードは、フロー・コンテキストでiotFileIndexに進みます。後続のトリガーは、テストを繰り返すときも含めて、次のファイル名を使用します。

  4. オブジェクトがダウンロードされた後にのみカウンタが増加することを確認します。次のオブジェクトが使用できない場合は、先に進めないでください。

ステップ6: バッチ・データ収集の検証

  1. オブジェクト・ストレージ・ノードが予期したCSVオブジェクトをダウンロードし、CSVノードが行ごとに1つのメッセージを発行したことを確認します。
  2. ゲートウェイ行がトピックdataを生成し、HVAC行がhvacs/fr-guide-hvac-01およびhvacs/fr-guide-hvac-02を生成したことを確認します。
  3. 共通コンソール検証を使用して、3つのデジタル・ツイン・インスタンスすべてについて、RAWデータまたは取込みデータ、スナップショット値、正規化値または履歴値を確認します。
  4. 検証後、インジェクト・ノードの時間間隔をリストアし、「デプロイ」を選択します。

    スケジュールされた各実行の前に、次の順次CSVオブジェクトを使用可能にしておきます。2つのデバッグ・ノードは、検証後に有効化/無効化ボタンを使用して無効化できます。また、後でトラブルシューティングを行うために、キャッチ・ノードとその接続は維持されます。

トラブルシューティング

  • オブジェクト・ストレージ・ネームスペース、バケット名、シーケンシャル・オブジェクト名およびリソース・プリンシパル構成を確認します。
  • オブジェクト・ストレージ・ノードで、「出力のダウンロード」 = 「テキスト」および「エンコーディング」 = UTF-8が使用されていることを確認します。CSVノードはテキストを直接受信します。
  • 「デバッグ」サイドバーの「OSノード・エラー・キャッチ」でオブジェクト・ストレージのエラーを確認し、「MQTT入力」でメッセージを変換します。検証後に無効化した場合は、デバッグ・ノードを再度有効にします。
  • 次のポーリングの前にiot-data-<counter>.csvが存在することを確認します。カウンタは、ダウンロードが成功した後にのみ進みます。
  • CSVデリミタおよび1行目の列名がサンプルと一致することを確認します。
  • 各行に、サポートされているdeviceType、一致する外部キーおよび数値のソース・タイムスタンプが含まれていることを確認します。
  • MQTTデバイス・ホスト接続、ゲートウェイ資格証明、アダプタ・マッピングおよびターゲット・デジタル・ツイン・ライフサイクルの状態を確認します。

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

FAQ

CSVオブジェクト名でカウンタを使用するのはなぜですか。
フローは、iot-data-1.csvやiot-data-2.csvなどの予測可能な順序を処理します。カウンタは、正常にダウンロードされた後にのみ進行するため、オブジェクトは順番に処理されます。
Object Storageノードがリソース・プリンシパルを使用するのはなぜですか。
フロー・ランタイムは、フローにユーザー資格証明を格納せずに、承認済バケットにアクセスできます。動的グループおよびポリシーは、必要な読取りアクセス権を付与する必要があります。
次の順次オブジェクトが存在しない場合はどうなりますか。
ダウンロードに失敗し、カウンタは変更されません。フローを再度トリガーする前に、予期されるオブジェクトをアップロードするか、ネームスペース、バケット、接頭辞およびカウンタを修正してください。
Object Storageノードがオブジェクトをテキストとしてダウンロードする理由
CSVノードにはテキスト入力が必要です。UTF-8エンコーディングでダウンロード出力をテキストに設定すると、その入力が直接提供されます。index-increment関数はカウンタを先に進め、処理されたオブジェクト名を記録するだけです。
最初のCSVオブジェクトからテストを再開するにはどうすればよいですか。
インジェクト・ノードの繰返し間隔を無効にしてから、flow.set("iotFileIndex", 1); return msg;を含む同じフロー・タブに一時関数ノードを追加します。手動でトリガーされた別のインジェクト・ノードをそのファンクション・ノードにのみ接続します。カウンタをリセットするために1回デプロイおよびトリガーしてから、両方の一時ノードを削除し、再度デプロイします。シナリオのInjectノードをトリガーして、iot-data-1.csvを再度処理します。これにより、すでに取り込まれた検針がリプレイされます。テストを繰り返す場合にのみ使用してください。