Linguaggio dell'espressione di mappatura

È possibile utilizzare il linguaggio di espressione della mappatura per manipolare e combinare i dati, e per formattare i risultati di eventuali query che si potrebbero eseguire sui dati elaborati.

Il linguaggio dell'espressione di associazione è un sottoinsieme di JSONata e può essere utilizzato quando si definiscono le associazioni o si creano le regole.

JSONata è una query lightweight e linguaggio di trasformazione per i dati JSON. È inoltre disponibile uno strumento JSONata Exerciser che fornisce un modo rapido e conveniente per provare JSONata.

Le seguenti informazioni mostrano gli operatori chiave e le funzioni attualmente supportate, insieme ad alcuni esempi di come potreste utilizzarli.

Linguaggio di espressione e regole di notifica

Il linguaggio delle espressioni di associazione è stato esteso per l'utilizzo con la funzione delle regole di notifica di gestione dati mediante l'introduzione delle variabili $state e $instance definite per l'utilizzo nelle espressioni.

  • La variabile $state viene utilizzata per fare riferimento alle proprietà sullo stato del dispositivo in un'espressione, ad esempio $state.temperature.
  • La variabile $instance viene utilizzata per fare riferimento agli attributi e ai metadati sull'istanza del dispositivo in un'espressione, ad esempio $instance.metadata.tempThresholdMax.

Si potrebbe voler utilizzare queste variabili in modo da non aver bisogno di valori hard - code nelle espressioni delle condizioni della regola di notifica e può impostare un valore di soglia diverso per ogni istanza del dispositivo.

Operatori JSONata

Tutti Gli Operatori JSONata sono supportati, salvo quanto elencato:

  • Utilizzare Parenthesis ( ) per il raggruppamento delle espressioni e per alterare la precedenza dell'operatore.
  • Utilizzare le virgolette singole o doppie per circondare stringhe e nomi di proprietà, ad esempio $event.object.'ab'.
  • Utilizzare i back - ticks per surround nomi di proprietà che contengono caratteri speciali, inclusi gli spazi, ad esempio:
    {"x y":22}.`x y`
  • Usa indietro - ticks per surround nomi di proprietà che iniziano con un numero, ad esempio
    `7emperature`

Funzioni JSONata

Estensione della lingua di espressione della mappatura

La lingua di espressione della mappatura è stata estesa per l'utilizzo con la funzione di gestione dei dati attraverso l'introduzione di variabili $event, $state e $istanza. JSON è legato a queste variabili prima che l'espressione venga valutata. La seguente tabella fornisce una panoramica di queste variabili, definite per l'utilizzo nelle espressioni:

Variabile Esempio di input JSON Esempio come espressione Uso a ...
$event {"t": 34.5} $event.t Selezionare una proprietà di un evento in entrata da utilizzare in un'espressione.
$state {"temperature": 34.5,"humidity": 78 } $state.temperature Selezionare una proprietà sullo stato del dispositivo da utilizzare in un'espressione.
$instance {"deviceId": "tSensor","typeId": "humiditySensor","metadata": {"temp_adjustment": 50}} $instance.metadata.temp_adjustment Selezionare l'attributo di tipo di dispositivo o di dispositivo da utilizzare in un'espressione.

Il seguente esempio utilizza il seguente oggetto come input per un evento:

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

L'oggetto viene convertito in una matrice utilizzando la seguente espressione:

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

L'espressione determina la generazione della seguente emissione:

 [
    35,
    72,
    1024
  ]

È possibile invertire questo esempio e convertire un array dall'input in un oggetto. Il seguente esempio utilizza il seguente array come input per un evento:

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

L'array viene convertito in un oggetto utilizzando la seguente espressione:

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

L'espressione determina la generazione della seguente emissione:

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

È anche possibile definire un'espressione che combina l'uso di queste variabili. Nell'esempio seguente, una proprietà temp_adjustment viene definita nei metadati del dispositivo e viene utilizzata per calibrare la lettura dell'evento. La proprietà è definita in una sola mappatura ma può essere applicata a molti dispositivi.

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

L'operatore di dot "." viene utilizzato per l'accesso all'oggetto con una chiave letterale, ad esempio $event.object.hh. La prima espressione, che nell'esempio è $event.t, è vincolata a una proprietà specifica, nell'evento ($event) o nello stato ($state) o nei metadati ($instance). La seconda espressione, che nell'esempio è $instance.metadata.temp_adjustment, contiene le informazioni a cui si potrebbe voler accedere.

Guida linguistica

  • Sono supportate tutte le query semplici .
  • Le query predicato sono supportate, tranne che per i caratteri jolly.
  • Le espressioni tra parentesi sono supportate, ad eccezione dei blocchi di codice.
  • Sono supportate le seguenti Espressioni condizionali :
    • Logica condizionale
    • Le variabili
      Variabili sono supportate attraverso l'utilizzo delle variabili $instance, $statee $event come parte della lingua di mappatura estesa che è specifica questa funzione di gestione dei dati.
      Nota: Le variabili $ e $$ utilizzate in JSONata non sono attualmente supportate.
    • Richiamo delle funzioni più predefinite.
      Nota: Non è possibile definire le proprie funzioni.

Costruzione dell'output

È possibile specificare come vengono presentati i dati elaborati nell'output utilizzando i costruttori di array o i costruttori di oggetti.

Costruttori di array supportati

Gli array possono essere creati racchiudendo un elenco separato da virgole di valori letterali o espressioni in una coppia di parentesi. Le virgette sono utilizzate per separare le espressioni multiple all'interno della generazione di sequenza di inlcuding dell'array, ad esempio [1, 3-1] = [1,2], [1..3] -> [1,2,3] e [1..3, 7..9] -> [1,2,3,7,8,9].

Costruttori di oggetti supportati

È possibile costruire oggetti JSON nella propria emissione utilizzando una coppia di parentesi {} che contengono valori chiave o coppie separate da virgole, con ogni tasto e valore separati da un colon, ad esempio {key1 : value1, key2:value2} o {"hello" : "world"}. La chiave oggetto deve essere una stringa.

Esempio: utilizzare gli array per elaborare e segnalare i dati di temperatura

Le seguenti sezioni si basano sull'esempio in Introduzione alla gestione dei dati utilizzando le API REST per mostrare come puoi utilizzare gli array per mantenere una finestra scorrevole di letture della temperatura e calcolare la somma o la media corrente della lettura contenuta in tale finestra.

Una finestra scorrevole memorizza i dati in ordine di arrivo. Piuttosto che tenere tutti i dati mai inseriti, le finestre scorrevoli possono essere configurate per sfrattare i dati in modo incrementale. Quando una finestra scorrevole si riempie, qualsiasi futuro inserimento determina l'eviction della voce dati più antica in quella finestra.

Il seguente esempio mostra una finestra scorrevole configurata con una politica di sfratto basata su conteggio di dimensioni 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) -> ...

Il seguente esempio mostra come la configurazione del file di schema dell'interfaccia logica mostrata al passo 7 della Guida passo a passo 1, può essere modificata aggiungendo un array denominato tempReadings. L'array viene utilizzato per mantenere una finestra degli ultimi 5 valori inviati dai dispositivi per gli ultimi 5 eventi. Se non ci sono valori memorizzati in tempReadings, la schiera è impostata a 0 e la successiva lettura ricevuta viene accodata alla schiera che cresce fino a 5 letture ricevute. Dopo 5 letture vengono ricevute, una nuova lettura determina la rimozione della lettura più antica dalla finestra.

Nota: è necessario impostare tempReadings come "required", e come matrice per impostazione predefinita.
{
  "$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 seguente sezione mostra un esempio di come è possibile configurare la risorsa delle mappature per calcolare la lettura della temperatura media, e la somma di tutte le letture di temperatura in base alle letture contenute all'interno della finestra scorrevole corrente:

[
   {
       "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: L'array $state.tempReadings viene ricalcolato prima di essere utilizzato nelle funzioni $medio e $sum. Il ricalcolo della matrice è richiesto per garantire che la matrice contenga i valori correnti quando viene valutata l'espressione tempAverage o tempSum , perché l'ordine delle espressioni di mappatura non può essere controllato.

Il seguente esempio mostra la temperatura media e la temperatura sommata in base a una finestra scorrevole di 5 letture di temperatura:

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

Gestione dei mismatch tra espressione di mappatura e dati di input

Un aggiornamento di stato potrebbe non riuscire quando una delle espressioni di mappatura contiene un riferimento ai dati di input non specificati nell'evento pubblicato.

Ad esempio, è possibile configurare le seguenti espressioni:

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

dove t è una proprietà opzionale per l'evento.

Se un evento che contiene solo dati di umidità viene ricevuto, ad esempio, {"humidity":22}, allora l'espressione temperature = $event.t non riesce a valutare, perché la proprietà t opzionale non viene specificata nell'evento del dispositivo pubblicato.

L'aggiornamento dello stato fallisce. La proprietà dello stato di umidità non viene aggiornata e viene pubblicato un messaggio di errore sull'argomento di errore MQTT per il dispositivo:

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

Per evitare errori di aggiornamento dello stato a causa di dati opzionali non specificati, è possibile utilizzare la funzione $esiste in combinazione con un condizionale ternario per specificare un valore predefinito per le proprietà opzionali. Il seguente esempio definisce un valore predefinito di 0 per la proprietà t :

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

Definendo un valore predefinito per la proprietà opzionale in questo modo, l'espressione valuta correttamente, anche quando la proprietà t non viene specificata nell'evento del dispositivo pubblicato.

Pertanto, se l'evento {"humidity":22} viene ricevuto, l'aggiornamento dello stato si completa correttamente e lo stato del dispositivo è impostato su {"humidity":22, "temperature":0}.