シナリオ: デジタル・ツイン・アダプタを使用した測定単位の正規化

このシナリオでは、デジタル・ツイン・モデル、エンベロープとルート・マッピングを備えたデジタル・ツイン・アダプタを使用して、特定のテレメトリを共通スキーマに正規化する方法、およびサンプル・デバイス・ペイロードをポストしてフローを検証する方法について説明します。

このシナリオでは、異なるエンドポイント、2つのデジタル・ツイン・インスタンスおよび2つの異なる外部キーを使用して、1時間当たり異なる単位マイルおよび1時間当たりキロメートルで自動車テレメトリ・データをポストする方法を示します。このシナリオで参照されるJQパターンの詳細は、リファレンス: デジタル・ツイン・モデルおよびアダプタのJQ式を参照してください

デジタル・ツイン・アダプタは、エンドポイントごとにリクエストをルーティングし、ペイロードを1つのモデルにマップします。たとえば、メトリック・モデルは時速キロメートル(velocity_kph)で速度を送信し、他の標準デジタル・ツイン・インスタンスは時速マイル(speed)を送信します。

タスク

このシナリオのファイルを理解します。

次のステップで参照されるデジタル・ツイン・モデルで使用できるコード・スニペット:

  • model.jsonDTDL v3仕様に基づくデジタル・ツイン・モデルで、0から100までの値の範囲に制限を適用する検証拡張を使用するspeedテレメトリ・プロパティ(マイル/時間)。
  • envelope.json— 参照エンドポイントおよびサンプル・ペイロード・シェイプを宣言するエンベロープ構成。
  • routes.json— キロメートル/時をマイル/時に変換するルート条件およびペイロード・マッピング。
  • script.sh— この例では、次に示すすべてのOCI CLIコマンドを保存して、デジタル・ツイン・モデル、アダプタおよびインスタンスを作成し、さらにサンプル・テレメトリをPOSTしてシェル・スクリプトscript.shとして実行するためのcurlコマンドを作成できます。
  • このシナリオのステップを完了するには、OCI CLIおよび次のステップにリストされているcurlコマンドを作成して保存し、このシナリオをシェル・スクリプトとして実行します: script.sh

この例では、デジタル・ツイン・モデルのmodel.jsonコード・スニペットは、"Telemetry", "Historized", "Validated", "Velocity"要素のJSONスキーマの検証ルールを適用するカスタム拡張dtmi:com:oracle:dtdl:extension:validation;1を使用します。データがこの検証で定義された予想値と一致しない場合、データは拒否されます。

サポートされている検証プロパティ・ルールの完全なリストは、DTMI検証拡張機能リファレンスを参照してください。

model.json

{
  "@context":[
    "dtmi:dtdl:context;3",
    "dtmi:dtdl:extension:historization;1",
    "dtmi:com:oracle:dtdl:extension:validation;1",
    "dtmi:dtdl:extension:quantitativeTypes;1"
  ],
  "@id":"dtmi:com:oracle:iot:poc:testmodel;1",
  "@type":"Interface",
  "contents":[
    {
      "@type":[ "Telemetry", "Historized", "Validated", "Velocity" ],
      "displayName":"Speed",
      "name":"speed",
      "schema":"integer",
      "unit":"milePerHour",
      "minimum":0,
      "maximum":100
    }
  ]
}

envelope.json

{
  "referenceEndpoint": "telemetry/automotive/usa-standard-units",
  "referencePayload": {
    "dataFormat": "JSON",
    "data": {
      "speed": 65
    }
  }
}

次に示すこのroutes.jsonファイルには、kmを変換し、データ・ペイロードを1単位(毎時マイル)に正規化する3つの式が含まれています。
  • エンドポイントからのデータを評価する条件式:

    "condition" : "${endpoint(3) == \"metric-units\"}"

    ${ ... }構文は、APIコールendpoint(3)の3番目のエンドポイント・パラメータまたはパス要素の値を評価する式を示します。この条件は、戻り値をmetric-unitsと比較します。trueの場合、これらのルールが適用されます。

  • ペイロード・マッピング式:

    "payloadMapping" : { "$.speed": "${(.velocity_kph / 1.609) | floor}"}

    ${ ... }構文は式を示し、この式は、速度または速度を時速キロメートルから時速マイルに変換する算術計算を評価および実行します (.velocity_kph / 1.609)これにより、velocity_kphフィールドが1.609で除算され、フロア関数が適用され、最も近い整数に切り捨てられます。この値はkmからkmに変換されます。これはkm = km×1.60934です。

  • "payloadMapping": {"$.speed": "$.speed"}これは直接値マッピング式で、そのまま速度の値を渡します。
[
  {
    "description" : "Automotive data using metric units (kilometers) that's converted to miles, with a different external key in the digital twin instance",
    "condition" : "${endpoint(3) == \"metric-units\"}",
    "payloadMapping" : { 
      "$.speed": "${(.velocity_kph / 1.609) | floor}"

    },
    "referencePayload" : {
      "dataFormat" : "JSON",
      "data" : { "velocity_kph": 104 }
    }
  },
  {
    "description" : "Auto 1 and Auto 2 use USA standard units, shows speed as is.", 
    "condition" : "*",
    "payloadMapping" : { "$.speed": "$.speed" }
  }
]

ステップ1: デジタル・ツイン・モデルの作成

このoci iot digital-twin-model create CLIコマンドを使用して、model.jsonファイルを使用してデジタル・ツイン・モデルを作成します。このデジタル・ツイン・モデルは、speedを毎時マイルで標準化します。

このコマンドは、前述のmodel.jsonで定義されているように、デジタル・ツイン・モデルをこのDTMI URI dtmi:com:oracle:iot:poc:testmodel;1に登録します。

oci iot digital-twin-model create \
  --iot-domain-id <iot-domain-ocid> \
  --display-name "Test Digital Twin Model" \
  --description "Model for testing automotive telemetry routing and unit normalization" \
  --spec file://~/model.json

ステップ2: エンベロープおよびルートを使用したデジタル・ツイン・アダプタの作成

デジタル・ツイン・モデル仕様DTMIを参照し、インバウンド・エンベロープとルートを使用して着信テレメトリを正規化するアダプタを作成します。

oci iot digital-twin-adapter create \
  --iot-domain-id <iot-domain-ocid> \
  --display-name "automotive-speed-adapter" \
  --description "Routes by units" \
  --digital-twin-model-spec-uri "dtmi:com:oracle:iot:poc:testmodel;1" \
  --inbound-envelope file://~/envelope.json \
  --inbound-routes file://~/routes.json

envelope.jsonreferenceEndpointtelemetry/automotive/usa-standard-unitsです。routes.jsonファイル:

  • /telemetry/automotive/metric-unitsなど、metric-unitsと等しい3番目のパス・セグメントにリクエストをルーティングし、mphでvelocity_kphspeedに変換して、結果をフロアーします。
  • デフォルトのキャッチオール条件(*)を使用して、毎時マイルを使用する自動車のspeedを変更せずに通過します。

ステップ3: 2つのデジタル・ツイン・インスタンスの作成

ボールトシークレットを使用して認証し、両方のデジタル・ツイン・インスタンスを共有する2つのデジタル・ツイン・インスタンスは、同じデジタル・ツイン・アダプタを共有します。エンドポイントは、各デジタル・ツイン・インスタンスが一意のエンドポイントにデータをポストできるように定義されます。
  • mphのエンドポイント: https://device-host/telemetry/automotive/usa-standard-units
  • kphのエンドポイント: https://device-host/telemetry/automotive/metric-units
デジタル・ツイン・アダプタOCIDを、前のステップで作成したデジタル・ツイン・アダプタのOCIDに置き換えます。表示名と外部キーを環境の値に置き換えます。
ノート

認証を使用してデジタル・ツイン・インスタンスを作成する場合は、ボールト・シークレットまたはmTLS証明書のいずれかを使用して認証できます。セキュリティのために、デジタル・ツイン・インスタンスごとに一意のボールト・シークレットまたはmTLS証明書を作成することがベスト・プラクティスです。すべてのリソースは、他の関連するIoTリソースと同じリージョンおよびテナンシに存在する必要があります。

mTLS証明書を使用して認証する場合は、証明書の共通名を外部キーとして使用する必要があります: --external-key <common-name-from-certificate-details>シナリオ: mTLS証明書を使用するデジタル・ツイン・インスタンスの作成を参照してください。

管理者は、シークレットまたは証明書を作成するためのポリシーを追加する必要があります。前提条件ステップ3を参照してください。

米国標準単位のデジタル・ツイン・インスタンス、時速マイル(mph)は、外部キーに注意してください。

american-auto-standard-units
oci iot digital-twin-instance create \
  --iot-domain-id <IoT-domain-ocid> \
  --display-name "auto using miles per hour" \
  --external-key american-auto-standard-units \
  --digital-twin-adapter-id <same-digital-twin-adapter-ocid> \
  --auth-id <secret-ocid-or-certificate-ocid>
ヨーロッパのメトリック単位のデジタル・ツイン・インスタンス(時速キロメートル)は、外部キーに注意してください:

european-auto-metric-units

oci iot digital-twin-instance create \
  --iot-domain-id <IoT-domain-ocid> \
  --display-name "auto using kilometers per hour" \
  --external-key european-auto-metric-units \
  --digital-twin-adapter-id <same-digital-twin-adapter-ocid> \
  --auth-id <secret-ocid-or-certificate-ocid>

ステップ4: サンプルテレメトリを送信してルーティングとマッピングを検証する

テレメトリを送信するには、ステップ3、デバイス・パスワードおよびデバイス・ホスト・エンドポイントからのデジタル・ツイン・インスタンス・レスポンスからの外部キーが必要です。

デジタル・ツイン・インスタンスがボールト・シークレットを使用して認証する場合は、ベース64でエンコードされたシークレット値をデバイス・パスワードとして使用する必要があります。

  • 外部キー: 作業するデジタル・ツイン・インスタンスのexternal-keyexternal-keyに置き換えます。見積りの問題を回避するために、外部キー値に引用符を使用しないことをお薦めします。
  • デバイス・パスワード: デバイスのパスワードをプレーン・テキスト・シークレットの内容またはmTLS証明書に置き換えます。
  • デバイス・ホスト: device-hostを、IoTドメインのデバイス・ホストに置き換えます。IoTドメインのデバイス・ホスト・エンドポイントURLを取得するには、IoTドメインの詳細の取得を参照してください。

-u "external-key:device-password-secret-contents-or-certificate"

ノート

オペレーティング・システムまたはアプリケーションによっては、一部のアプリケーションまたはコード・エディタが値に不要な引用符を追加する場合があるため、エラーが発生する可能性があります。引用例については、トラブルシューティングを参照してください。
curl -i -X POST \
  -u "european-auto-metric-units:device-password-secret-or-certificate" \
  -H "Content-Type: application/json" \
  "https://device-host/telemetry/automotive/metric-units" \
  -d '{ "velocity_kph": 0 }'
curl -i -X POST \
  -u "european-auto-metric-units:device-password-secret-or-certificate" \
  -H "Content-Type: application/json" \
  "https://device-host/telemetry/automotive/metric-units" \
  -d '{ "velocity_kph": 110 }'

curl -i -X POST \
  -u "american-auto-standard-units:device-password-secret-or-certificate" \
  -H "Content-Type: application/json" \
  "https://device-host/telemetry/automotive/usa-standard-units" \
  -d '{ "speed": 0 }'

curl -i -X POST \
  -u "american-auto-standard-units:device-password-vault-secret-base-64-or-certificate-OCID" \
  -H "Content-Type: application/json" \
  "https://device-host/telemetry/automotive/usa-standard-units" \
  -d '{ "speed": 60 }'

ステップ5: 正規化動作の確認

ルート条件${endpoint(3) == "metric-units"}は、データを評価し、次のペイロード・マッピングをメトリック単位のデータ・エンドポイントに適用します。

"$.speed": "${(.velocity_kph / 1.609) | floor}"

予期した結果:

  • アダプタのマッピングは、時速キロメートル(kph)を時速マイル(mph)に変換し、整数スキーマを満たすためにフロアを適用します。

    speed_mph = floor(velocity_kph / 1.609)

  • この例では、velocity_kph = 0: speed_mph = floor(0 / 1.609) = floor(0) = 0 mph

    後階は、結果を強制的に整数に丸め、負の無限大に丸める丸めステップを示します。これは、DTDLモデルが速度テレメトリをschema: "integer"として宣言し、値が浮動小数や文字列ではなく整数である場合に必要です。

  • velocity_kph = 110speed = floor(110 / 1.609) = 68 mph
  • speedパス・スルーによる標準データ・ポスト(例: 060)

モデル検証が有効な場合、minimum: 0maximum: 100、範囲外の値は検証ルールに従って拒否されます。

ソフト型変換を使用:

  • パススルー(mph、スキーマ"integer"): {"speed": "60"}および{"speed": 60.0}は、60として格納されます。{"speed": "60.2"}は、マッピングが整数(たとえば、floor)に強制されないかぎり拒否されます。
  • メトリック・ルート(kph→mph): {"velocity_kph": 110}68、マッピングfloorが整数を発行するため{"velocity_kph": "110"}68。式エラーを回避するために、算術入力の数値を保持します。可能な場合は、"110"よりも110を優先します。
  • 丸めは明示的なままです: ソフト変換では、68.3568に自動丸められません。整数スキーマにfloorを使用するか、モデルをschema: "double"に切り替えて分数を保持します。

ベスト・プラクティス

  • デジタル・ツイン・モデルの仕様およびアダプタ用の参照JSONファイル: CLIを使用してアダプタをアップロードする際、JSONファイルを使用してデータ・マッピングを指定できます。CLIコマンドでは、file://~/name.jsonとしてファイルを参照したり、シェル環境に応じて絶対パスまたは相対パスを指定したりできます。オペレーティング・システムによっては、引用符、スラッシュまたはファイルの場所を含む構文が多少異なる場合があります。CLIの入力および出力の管理および複雑な入力のためのJSONファイルの使用を参照してください。
  • JSON構成ファイル(エンベロープ、ルート)では、camelCaseのAPIフィールド名(たとえば、referenceEndpoint)が使用されます。OCI CLIは、これらのファイルをfile://引数を介して変更せずに渡すため、CLIでcamelCase JSONを使用することが予想され、正しいです。
  • envelope.jsonreferenceEndpointは、アダプタの一般的なエンドポイントを反映する必要があります。
  • ワイルドカード・ルート条件(*)は、特定の条件の後に評価され、それに応じてルート定義を順序付けします。
  • ソフト変換スコープ: 数値のような文字列と整数倍は、モデル・タイプ(整数など)と一致する場合に受け入れられます。number()toIntegerなどのキャスト・ヘルパーは、ルート式ではサポートされません。算術およびfloorに依存するか、schema: "double"を採用して分数を保持します。

バリエーション: floorのかわりにschema="double"を使用

このバリエーションは、モデル・プロパティ・スキーマをdoubleに設定すると、アダプタ・マッピングおよび記録された値にどのように影響するかを示しています。doubleを指定すると、バリデータは、範囲制約を満たす数値整数または小数値を、自動丸めなしで受け入れます。floorを使用して、小数精度(raw)または整数への強制を保持することを選択できます。値が定義された範囲内に残っているかぎり、両方とも検証に合格します。

schema=double検証の動作

  • タイプ受入れ: 小数部(60、68.35など)の有無にかかわらず、JSON番号を受け入れます。"68"のような文字列は無効なままです。
  • 範囲: たとえば、最小値および最大値(この例では0–100が強制されます)。
  • 自動丸めなし: IoTプラットフォームは値を丸めません。データを表示するように構成されたシステムに応じて、APEXまたはSQLを使用してデジタル・ツイン・アダプタ・マッピングまたはダウンストリームで丸めを制御します。

このバリエーションで使用されるファイル:

  • model_double.jsonschema: "double"を使用したDTDLモデル。
    {
      "@context": [
        "dtmi:dtdl:context;3",
        "dtmi:dtdl:extension:historization;1",
        "dtmi:com:oracle:dtdl:extension:validation;1",
        "dtmi:dtdl:extension:quantitativeTypes;1"
      ],
      "@id": "dtmi:com:oracle:iot:poc:testmodeldouble;1",
      "@type": "Interface",
      "contents": [
        {
          "@type": [
            "Telemetry",
            "Historized",
            "Validated",
            "Velocity"
          ],
          "displayName": "Speed",
          "name": "speed",
          "schema": "double",
          "unit": "milePerHour",
          "minimum": 0,
          "maximum": 100
        }
      ]
    }
  • routes_double_raw.json— マッピングは小数精度"$.speed": "${.velocity_kph / 1.609}"を保持します。
    [
      {
        "description": "Double model: European metric units to miles per hour (mph); preserving fractional precision (no floor).",
        "condition": "${endpoint(3) == \"metric-units\"}",
        "payloadMapping": {
          "$.speed": "${.velocity_kph / 1.609}"
        },
        "referencePayload": {
          "dataFormat": "JSON",
          "data": { "velocity_kph": 110 }
        }
      },
      {
        "description": "Double model: USA standard units passthrough.",
        "condition": "*",
        "payloadMapping": { "$.speed": "$.speed" }
      }
    ]
  • routes_double_floor.json— マッピングは、doubleとして格納された"$.speed": "${(.velocity_kph / 1.609) | floor}"という整数mphに強制変換されます。
    [
      {
        "description": "Double model: European metric units to miles per hour (mph); floor to whole number (stored as double).",
        "condition": "${endpoint(3) == \"metric-units\"}",
        "payloadMapping": {
          "$.speed": "${(.velocity_kph / 1.609) | floor}"
        },
        "referencePayload": {
          "dataFormat": "JSON",
          "data": { "velocity_kph": 110 }
        }
      },
      {
        "description": "Double model: USA standard units passthrough.",
        "condition": "*",
        "payloadMapping": { "$.speed": "$.speed" }
      }
    ]
    

ステップA:doubleを使用してデジタルツインモデルを作成する

oci iot digital-twin-model create \
  --iot-domain-id iot-domain-ocid \
  --display-name "TestModelSpeedDouble" \
  --spec file://model_double.json

ステップB: doubleモデルに関連付けられた2つのアダプタの作成

raw値を使用して小数精度を保持します。

oci iot digital-twin-adapter create \
  --iot-domain-id iot-domain-ocid \
  --display-name "auto-adapter-double-raw" \
  --digital-twin-model-id double-model-ocid \
  --inbound-envelope file://envelope.json \
  --inbound-routes file://routes_double_raw.json

Floorはmphとして整数を使用します。これはdoubleです。

oci iot digital-twin-adapter create \
  --iot-domain-id iot-domain-ocid \
  --display-name "auto-adapter-double-floor" \
  --digital-twin-model-id double-model-ocid \
  --inbound-envelope file://envelope.json \
  --inbound-routes file://routes_double_floor.json

ステップC: 各アダプタのデジタル・ツイン・インスタンスの作成

oci iot digital-twin-instance create \
  --iot-domain-id iot-domain-ocid \
  --display-name "american-auto-raw" \
  --external-key american-auto-raw \
  --digital-twin-adapter-id adapter-double-raw-ocid \
  --auth-id vault-secret-ocid

oci iot digital-twin-instance create \
  --iot-domain-id iot-domain-ocid \
  --display-name "european-auto-raw" \
  --external-key european-auto-raw \
  --digital-twin-adapter-id adapter-double-raw-ocid \
  --auth-id vault-secret-ocid
oci iot digital-twin-instance create \
  --iot-domain-id iot-domain-ocid \
  --display-name "american-auto-dfloor" \
  --external-key american-auto-dfloor \
  --digital-twin-adapter-id adapter-double-floor-ocid \
  --auth-id vault-secret-ocid

oci iot digital-twin-instance create \
  --iot-domain-id iot-domain-ocid \
  --display-name "european-auto-dfloor" \
  --external-key european-auto-dfloor \
  --digital-twin-adapter-id adapter-double-floor-ocid \
  --auth-id vault-secret-ocid

ステップD: サンプルテレメトリを投稿し、結果を比較する

デジタル・ツイン・インスタンスの外部キーおよびデバイス・パスワードを使用して、データを送信します:
 -u "external-key:device-password" \
  • デジタル・ツインがボールト・シークレットを使用して認証する場合は、base64-secretをデバイス・パスワードとして使用します。
  • デジタル・ツイン・インスタンスでmLTS動作保証を使用する場合は、certificate-ocidをデバイス・パスワードとして使用します。

RAW値(doubleno floor):

curl -i -X POST \
  -u "american-auto-raw:device-password" \
  -H "Content-Type: application/json" \
  "https://device-host/telemetry/automotive/usa-standard-units" \
  -d '{ "speed": 60 }'

curl -i -X POST \
  -u "european-auto-raw:device-password" \
  -H "Content-Type: application/json" \
  "https://device-host/telemetry/automotive/metric-units" \
  -d '{ "velocity_kph": 110 }'

予想される結果: 2番目のポストは約68.35… mph(小数)を生成し、schema=doubleは範囲内の小数を受け入れるため、受け入れられます

フロア(ダブル、フロアあり):

curl -i -X POST \
  -u "american-auto-dfloor:device-password" \
  -H "Content-Type: application/json" \
  "https://device-host/telemetry/automotive/usa-standard-units" \
  -d '{ "speed": 60 }'

curl -i -X POST \
  -u "european-auto-dfloor:device-password" \
  -H "Content-Type: application/json" \
  "https://device-host/telemetry/automotive/metric-units" \
  -d '{ "velocity_kph": 110 }'

予想される結果: 2番目のポストは、68を整数で生成し、受け入れられます。値は、整数であっても、たとえば68.0のようにdoubleとして格納されます。

ユーザー名引用符とダウンストリームへの影響に関するノート

  • 外部キーが認証ユーザー名と等しい: デジタル・ツイン・インスタンスが外部キー値("\"american-auto-standard-units\""など)の引用符を使用して作成された場合、curlリクエストのBasic認証ユーザー名に引用符が含まれているか、不一致が発生し、401 Unauthorizedエラーが発生します。見積りの問題を回避するには、このシナリオの例のように、外部キー値に引用符を使用しないことをお薦めします。
  • APEXでのダウンストリームまたはSQLの使用: schema=doubleでは、小数mph値が保持されます。レポートに整数が必要な場合は、SQLでFLOORおよびROUND (SELECT FLOOR(speed) FROM …など)を適用します。schema=integerでは、floorを使用して整数型入力を満たすなど、マッピングが整数値を出力することを確認します。
  • 式のサポート: inbound-routeは算術とfloorを受け入れます。toIntegernumberなどの関数は拒否され、サポートされません。floorを使用するか、schema: "double"を採用して小数受け入れを行います。