マッピング式言語

マッピング式言語を使用すると、データを操作して結合したり、処理したデータに対して実行する照会の結果をフォーマット設定したりすることができます。

マッピング式言語は JSONata のサブセットであり、マッピングの定義時またはルールの作成時に使用できます。

JSONata は、JSON データに対して照会と変換を行うための軽量の言語です。 JSONata エクササイザー ・ツールも使用可能であり、JSONata を素早く簡単に試すことができます。

以下に、現在サポートされている重要な演算子と関数、およびその使用法の例をいくつか示します。

式言語と通知ルール

式で使用するために定義されている $state 変数および $instance 変数の導入により、マッピング式言語が拡張され、データ管理 通知規則機能 で使用できるようになりました。

  • $state 変数は、式でデバイス状態のプロパティーを参照するために使用されます (例: $state.temperature)。
  • $instance 変数は、式でデバイス・インスタンスの属性およびメタデータを参照するために使用されます (例: $instance.metadata.tempThresholdMax)。

これらの変数を使用すると、通知ルール条件式で値をハードコーディングする必要がなくなり、デバイス・インスタンスごとに異なるしきい値を設定できます。

JSONata 演算子

以下を例外として、すべての JSONata 演算子がサポートされています。

  • 式のグループ化および演算子優先順位の変更には、括弧 ( ) を使用します。
  • 単一引用符または二重引用符を使用して、例えば$event.object.'ab'など、ストリングおよびプロパティー名を囲みます。
  • バックティックは、以下の例に示すように、スペースを含む特殊文字が使用されたプロパティー名を囲む場合に使用します。
    {"x y":22}.`x y`
  • バックティックは、以下の例に示すように、数値で始まるプロパティー名を囲む場合に使用します。
    `7emperature`

JSONata 関数

マッピング式言語の拡張

$event、$state、$instance の各変数の導入により、マッピング式言語が拡張され、データ管理フィーチャーで使用できるようになりました。 JSON は、式が評価される前にこれらの変数にバインドされます。 以下の表に、式で使用するために定義されたこれらの変数の概要を示します。

変数 JSON の入力例 式としての例 使用目的
$event {"t": 34.5} $event.t 式で使用するインバウンド・イベントのプロパティーを選択します。
$state {"temperature": 34.5,"humidity": 78 } $state.temperature 式で使用するデバイスの状態に関するプロパティーを選択します。
$instance {"deviceId": "tSensor","typeId": "humiditySensor","metadata": {"temp_adjustment": 50}} $instance.metadata.temp_adjustment 式で使用するデバイス属性またはデバイス・タイプ属性を選択します。

以下の例では、次のオブジェクトがイベントへの入力として使用されます。

{
    "temperature": 35,
    "humidity": 72,
    "pressure": 1024
}

オブジェクトは、以下の式を使用して配列に変換されます。

[$event.temperature, $event.humidity, $event.pressure]

この式により、以下の出力が生成されます。

 [
    35,
    72,
    1024
  ]

この例の逆を行い、配列を入力からオブジェクトに変換できます。 以下の例では、次の配列がイベントへの入力として使用されます。

{
    "readings": [
      35,
      72,
      1024
    ]
  }

配列は、以下の式を使用してオブジェクトに変換されます。

 {"temperature": $event.readings[0], "humidity": $event.readings[1], "pressure": $event.readings[2]}

この式により、以下の出力が生成されます。

{
  "temperature": 35,
  "humidity": 72,
  "pressure": 1024
}

これらの変数の使用法を結合する式を定義することもできます。 以下の例では、 temp_adjustment プロパティーがデバイス・メタデータに定義され、イベント読み取り値の調整に使用されます。 このプロパティーは、1 つのマッピングに定義されていますが、多数のデバイスに適用できます。

"propertyMappings" : {
        "tevt" : {
           "temperature" : "$event.t + $instance.metadata.temp_adjustment"
        }
     },

ドット演算子 "." リテラル・キーを使用したオブジェクト・アクセスに使用されます (例: $event.object.hh)。 最初の式 (この例では $event.t) は、イベント ($event)、状態 ($state)、またはメタデータ ($instance) のいずれかの特定のプロパティーに制約されます。 2 番目の式 (例では $instance.metadata.temp_adjustment) には、アクセスする必要がある情報が含まれています。

言語ガイド

  • すべての 単純照会 がサポートされます。
  • ワイルドカードを除き、 述部照会 がサポートされます。
  • コード・ブロックを除き、 括弧で囲んだ式 がサポートされます。
  • 以下の 条件式 がサポートされています。
    • 条件ロジック
    • 変数
      変数は、このデータ管理機能に固有の拡張マッピング言語の一部として、 $instance$state、および $event 変数を使用することによってサポートされます。
      注: JSONata で使用される $ 変数と $$ 変数は、現在サポートされていません。
    • ほとんどの事前定義関数の呼び出し。
      注: 独自の関数を定義することはできません。

出力の構成

配列コンストラクターまたはオブジェクト・コンストラクターを使用して、処理されたデータを出力にどのように表示するかを指定できます。

サポート対象の配列コンストラクター

配列は、リテラルまたは式のコンマ区切りリストを大括弧のペアで囲むことによって構成できます。 コンマは、配列コンストラクター内の複数の式を区切るために使用されます。例えば、 [1, 3-1] = [1,2][1..3] -> [1,2,3] 、および [1..3, 7..9] -> [1,2,3,7,8,9]などです。

サポート対象のオブジェクト・コンストラクター

コンマで区切られたキー値またはペアを含む中括弧 {} を使用して、出力で JSON オブジェクトを構成できます。各キーと値はコロンで区切られます (例: {key1 : value1, key2:value2} または {"hello" : "world"})。 オブジェクト・キーはストリングでなければなりません。

例: 配列を使用して温度データを処理および報告する

以下のセクションは、REST APIを使用したデータ管理入門の例に基づいて、温度計測値のスライディング・ウィンドウを維持し、そのウィンドウに含まれる計測値の現在の合計または平均を計算するために、配列を使用する方法を示しています。

スライディング・ウィンドウには、データが到着順に保管されます。 スライディング・ウィンドウは、これまでに挿入されたデータをすべて保持するのではなく、段階的にデータを削除するように構成できます。 スライディング・ウィンドウがいっぱいになった後にさらに挿入すると、そのウィンドウ内の最も古いデータ項目が削除されます。

以下に、カウント・ベースの削除ポリシー (サイズは 5) によって構成されたスライディング・ウィンドウの例を示します。

() -> (1) -> (2, 1) -> (3, 2, 1) -> (4, 3, 2, 1) -> (5, 4, 3, 2, 1) -> (6, 5, 4, 3, 2) -> (7, 6, 5, 4, 3) -> ...

以下の例は、 ステップバイステップ・ガイド 1のステップ 7 で示された論理インターフェース・スキーマ・ファイル構成を、 tempReadingsという配列を追加することによって変更する方法を示しています。 この配列は、最後の 5 つのイベントについて、デバイスから送信された最後の 5 つの値を示すウィンドウを保守するために使用します。 tempReadingsに値が保管されていない場合、配列は 0 に設定され、次に受信される読み取り値が配列に付加されます。これは、5 つの読み取り値が受信されるまで増加します。 5 つの読み取り値を受け取った後、新たに読み取り値を受け取ると、最も古い読み取り値がウィンドウから削除されます。

注: tempReadings は、 "required"として設定する必要があります。また、デフォルトでは配列として設定する必要があります。
{
  "$schema": "http://json-schema.org/draft-04/schema#",
  "definitions": {},
  "properties": {
      "temperature": {
          "description" : "latest temperature reading in degrees Celsius",
          "type" : "number",
          "minimum" : -273.15,
          "default" : 0.0
      },
      "tempAverage": {
          "type": "number"
      },
      "tempReadings": {
          "default": [],
          "items": {
              "type": "number"
          },
         "type": "array"
      },
      "tempSum": {
          "type": "number"
      }
  },
  "required": [
      "tempReadings"
  ],
  "type": "object"
}

以下のセクションでは、現在のスライディング・ウィンドウに含まれている読み取り値に基づいて温度読み取り値の平均とすべての温度の読み取り値の合計を計算するための、マッピング・リソースを構成する方法の例を示します。

[
   {
       "created": "2017-10-13T09:21:36Z",
       "createdBy": "admin",
       "logicalInterfaceId": "5846ec826522050001db0e12",
       "notificationStrategy": "on-state-change",
       "propertyMappings": {
           "tevt": {
               "tempAverage": "$average($count($state.tempReadings)<5?$append($state.tempReadings, $event.t):$append($state.tempReadings[[1..4]], $event.t))",
               "tempReadings": "$count($state.tempReadings)<5?$append($state.tempReadings, $event.t):$append($state.tempReadings[[1..4]], $event.t)",
               "tempSum": "$sum($count($state.tempReadings)<5?$append($state.tempReadings, $event.t):$append($state.tempReadings[[1..4]], $event.t))"
           }
       },
       "updated": "2017-10-13T10:05:40Z",
       "updatedBy": "a-8x7nmj-9iqt56kfil",
       "version": "active"
   }
]
注: $state.tempReadings 配列は、$average 関数および $sum 関数で使用される前に再計算されます。 マッピング式の順序は制御できないため、 tempAverage 式または tempSum 式の評価時に配列に現行値が含まれるようにするには、配列の再計算が必要です。

以下に、5 つの温度読み取り値が含まれるスライディング・ウィンドウに基づく平均温度と合計温度の例を示します。

{
    "state": {
        "tempAverage": 18557.6,
        "tempReadings": [
            17591,
            10262,
            25621,
            16676,
            22638
        ],
        "tempSum": 92788
    },
    "timestamp": "2017-10-13T11:07:20Z",
    "updated": "2017-10-13T11:05:40Z"
}

マッピング式と入力データの不一致を処理する

いずれかのマッピング式に、公開されたイベントで指定されていない入力データの参照が含まれている場合、状態の更新に失敗することがあります。

例えば、以下の式を構成するとします。

temperature = $event.t
humidity = $event.hum

ここで、 t は、イベントのオプション・プロパティーです。

湿度データのみを含むイベント ( {"humidity":22}など) を受信した場合、式 temperature = $event.t は評価に失敗します。これは、パブリッシュされたデバイス・イベントにオプションの t プロパティーが指定されていないためです。

状態の更新は失敗します。 湿度状態プロパティーは更新されず、エラー・メッセージがデバイスの MQTT エラー・トピックにパブリッシュされます。

iot-2/type/${typeId}/id/${deviceId}/err/data

オプション・データが指定されていないことが原因で状態の更新が失敗しないようにするには、$exists 関数を 3 項条件と組み合わせて使用し、オプション・プロパティーのデフォルト値を指定できます。 以下の例では、 t プロパティーのデフォルト値 0 を定義します。

"tempEvent:
    {
      "temperature": "$exists($event.t)?$event.t:0",
      "humidity": "$event.hum"
    }

この方法でオプション・プロパティーのデフォルト値を定義すると、パブリッシュされたデバイス・イベントで t プロパティーが指定されていない場合でも、式は正常に評価されます。

したがって、イベント {"humidity":22} が受信されると、状態更新は正常に完了し、デバイス状態は {"humidity":22, "temperature":0}に設定されます。