Lenguaje de expresión de correlación

Puede utilizar el lenguaje de expresión de correspondencia para manipular y combinar datos y para dar formato a los resultados de cualquier consulta que pueda ejecutar en los datos procesados.

El lenguaje de expresión de correlación es un subconjunto de JSONata y se puede utilizar al definir correlaciones o crear reglas.

JSONata es un lenguaje de transformaciones y una consulta ligera para datos JSON. También está disponible una herramienta JSONata Exerciser , que proporciona una forma rápida y cómoda de probar JSONata.

La siguiente información muestra las funciones y operadores clave que se soportan actualmente, junto con algunos ejemplos de cómo puede utilizarlos.

Lenguaje de expresión y reglas de notificación

El lenguaje de expresiones de mapeo se ha ampliado para su uso con la gestión de datos. Uso de reglas de notificación y acciones mediante la introducción de $state variables $instance y que se definen para su uso en expresiones.

  • La variable $state se utiliza para hacer referencia a las propiedades del estado del dispositivo en una expresión, por ejemplo, $state.temperature.
  • La variable $instance se utiliza para hacer referencia a atributos y metadatos en la instancia de dispositivo en una expresión, por ejemplo, $instance.metadata.tempThresholdMax.

Es posible que desee utilizar estas variables para que no sea necesario codificar valores en las expresiones de condición de notificación de reglas, y puede establecer un valor de umbral distinto para cada instancia de dispositivo..

Operadores de JSONata

Se admiten todos los operadores JSONata, excepto los que se indican en la lista:

  • Utilice paréntesis ( ) para agrupar expresiones y para modificar la prioridad de operadores.
  • Utilice comillas simples o dobles para series y nombres de propiedad, por ejemplo $event.object.'ab'.
  • Utilice comillas invertidas para rodear nombres de propiedad que contienen caracteres especiales, incluidos espacios, por ejemplo:
    {"x y":22}.`x y`
  • Utilice comillas invertidas para rodear nombres de propiedad que comienzan con un número, por ejemplo
    `7emperature`

Funciones de JSONata

Ampliación del lenguaje de expresión de correspondencia

El lenguaje de expresión de correlación se ha ampliado para utilizarlo con la característica de gestión de datos a través de la introducción de las variables $event, $state e $instance. El JSON se limita a estas variables antes de evaluar la expresión. La siguiente tabla proporciona una visión general de estas variables, definidas para utilizarlas en expresiones:

Variable JSON de ejemplo de entrada Ejemplo como expresión Se utiliza para...
$event {"t": 34.5} $event.t Seleccionar una propiedad de un suceso de entrada para utilizar en una expresión.
$state {"temperature": 34.5,"humidity": 78 } $state.temperature Seleccionar una propiedad en el estado de dispositivo para utilizar en una expresión.
$instance {"deviceId": "tSensor","typeId": "humiditySensor","metadata": {"temp_adjustment": 50}} $instance.metadata.temp_adjustment Seleccionar dispositivo o atributo de tipo de dispositivo para utilizar en una expresión.

En el ejemplo siguiente se utiliza el objeto siguiente como entrada a un suceso:

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

El objeto se convierte en una matriz utilizando la expresión siguiente:

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

La expresión da como resultado la generación de la salida siguiente:

 [
    35,
    72,
    1024
  ]

Puede invertir este ejemplo y convertir una matriz de la entrada en un objeto. En el ejemplo siguiente se utiliza la matriz siguiente como entrada a un suceso:

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

La matriz se convierte en un objeto utilizando la expresión siguiente:

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

La expresión da como resultado la generación de la salida siguiente:

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

También puede definir una expresión que combine el uso de estas variables. En el ejemplo siguiente, se define una propiedad temp_adjustment en los metadatos del dispositivo y se utiliza para calibrar la lectura de sucesos. La propiedad se define en una correlación pero se puede asignar a muchos dispositivos.

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

El operador punto "." se utiliza para el acceso a objetos con una clave literal, por ejemplo $event.object.hh. La primera expresión, que en el ejemplo es $event.t, está restringida a una propiedad específica, ya sea en el suceso ($event) o el estado ($state) o los metadatos ($instance). La segunda expresión, que en el ejemplo es $instance.metadata.temp_adjustment, contiene la información a la que desea acceder.

Guía lingüística

  • Se da soporte a todas las Consultas simples .
  • Las consultas de predicado están soportadas, excepto para los comodines.
  • Las expresiones entre paréntesis están soportadas, excepto para bloques de código.
  • Se da soporte a las Expresiones condicionales siguientes:
    • Lógica condicional
    • Variables
      Las variables están soportadas mediante el uso de las variables $instance, $statey $event como parte del lenguaje de correlación ampliado que es específico de esta característica de gestión de datos.
      Nota: Las variables $ y $$ que se utilizan en JSONata no están soportadas actualmente.
    • Invocación de la mayoría de funciones predefinidas.
      Nota: No puede definir sus propias funciones.

Construcción de la salida

Puede especificar cómo se presentan los datos procesados en la salida utilizando constructores de matrices o constructores de objetos.

Constructores de matrices soportados

Las matrices se pueden construir delimitando una lista separada por comas de literales o expresiones en un par de corchetes. Las comas se utilizan para separar varias expresiones dentro de la generación de secuencia inlcuding del constructor de matrices, por ejemplo, [1, 3-1] = [1,2], [1..3] -> [1,2,3] y [1..3, 7..9] -> [1,2,3,7,8,9].

Constructores de objetos soportados

Puede construir objetos JSON en la salida utilizando un par de llaves {} que contienen valores de clave o pares separados por comas, con cada clave y valor separados por dos puntos, por ejemplo, {key1 : value1, key2:value2} o {"hello" : "world"}. La clave de objeto debe ser una serie.

Ejemplo: Utilización de matrices para procesar y notificar datos de temperatura

Las secciones siguientes se basan en el ejemplo de Iniciación a la gestión de datos utilizando las API REST para mostrar cómo puede utilizar matrices para mantener una ventana deslizante de lecturas de temperatura y calcular la suma o el promedio actual de la lectura contenida en esa ventana.

Una ventana deslizante almacena datos en orden de llegada. En lugar de mantener todos los datos siempre insertados, las ventanas deslizantes pueden configurarse para expulsar datos de forma incremental. Cuando una ventana deslizante se llena, cualquier futura inserción da como resultado el desalojo del elemento de datos más antiguo de la ventana.

El siguiente ejemplo muestra una ventana deslizante configurada con una política de desalojo basada en recuento de un tamaño de 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) -> ...

El ejemplo siguiente muestra cómo se puede modificar la configuración del archivo de esquema de interfaz lógica que se muestra en el paso 7 de la Guía paso a paso 1, añadiendo una matriz denominada tempReadings. La matriz se utiliza para mantener una ventana de los 5 últimos valores que envían los dispositivos para los 5 últimos sucesos. Si no hay valores almacenados en tempReadings, la matriz se establece en 0 y la siguiente lectura recibida se añade a la matriz que crece hasta que se reciben 5 lecturas. Cuando se reciban 5 lecturas, una nueva lectura provocará la eliminación del resultado más antiguo de la ventana.

Nota: Debe establecer tempReadings como "required"y como matriz de forma predeterminada.
{
  "$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"
}

La siguiente sección muestra un ejemplo de cómo puede configurar el recurso de correlación para calcular la lectura de temperatura promedio y la suma de todas las temperaturas basándose en las lecturas contenidas en la ventana deslizante actual:

[
   {
       "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"
   }
]
Nota: La matriz $state.tempReadings se vuelve a calcular antes de que se utilice en las funciones $average y $sum. El recálculo de la matriz es necesario para asegurarse de que la matriz contiene los valores actuales cuando se evalúa la expresión tempAverage o tempSum , porque el orden de las expresiones de correlación no se puede controlar.

El siguiente ejemplo muestra la temperatura promedio y la suma de temperaturas basadas en las 5 lecturas de temperatura de la ventana deslizante:

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

Manejo de discrepancias entre la expresión de correlación y los datos de entrada

Una actualización de estado puede fallar cuando una de las expresiones de correlación contiene una referencia a datos de entrada que no se han especificado en el suceso publicado.

Por ejemplo, puede configurar las expresiones siguientes:

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

donde t es una propiedad opcional para el suceso.

Si se recibe un suceso que contiene sólo datos de humedad, por ejemplo, {"humidity":22}, la expresión temperature = $event.t no se puede evaluar, porque la propiedad t opcional no se especifica en el suceso de dispositivo publicado.

La actualización de estado falla. La propiedad de estado de humedad no se actualiza, y se publica un mensaje de error en el tema de error de MQTT para el dispositivo:

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

Para evitar anomalías de actualización de estado debido a datos opcionales no especificados, puede utilizar la función $exists en combinación con un condicional ternario para especificar un valor predeterminado para las propiedades opcionales. El ejemplo siguiente define un valor predeterminado de 0 para la propiedad t :

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

Al definir un valor predeterminado para la propiedad opcional de esta forma, la expresión se evalúa correctamente, incluso cuando la propiedad t no se especifica en el suceso de dispositivo publicado.

Por lo tanto, si se recibe el suceso {"humidity":22} , la actualización de estado se completa correctamente y el estado del dispositivo se establece en {"humidity":22, "temperature":0}.