Condividi tramite


Informazioni di riferimento sulle espressioni per i flussi di dati

Questo riferimento si applica sia ai flussi di dati che ai grafici del flusso di dati. Entrambi usano lo stesso linguaggio delle espressioni per le trasformazioni di mapping, filtro e arricchimento. I grafici del flusso di dati supportano anche trasformazioni di rami e finestre (accumulo), indicate se applicabile.

Variabili posizionale

La matrice di inputs ogni regola determina le variabili disponibili in expression. Il primo input diventa $1, il secondo diventa $2e così via.

Ingressi dati Expression Result
Position, Office $1 + ", " + $2 Concatena Posizione e Office con una virgola
temperature cToF($1) Converte Celsius in Fahrenheit
temperature, humidity $1 * $2 < 100000 Controlla una soglia rispetto a due campi

Se viene specificato un solo input e non viene specificata alcuna espressione, il valore in corrispondenza dell'input viene copiato direttamente nell'output.

Operatori

Le espressioni supportano gli operatori seguenti, elencati dalla precedenza più alta alla più bassa:

Precedenza Operatori Descrizione
1 ! NOT logico (unario)
2 ^ Elevamento a potenza
3 *, /, % Moltiplicazione, divisione, modulo
4 +, - Addizione/concatenazione di stringhe, sottrazione
5 <, >, <=>= Confronto
6 ==, != Uguaglianza, disuguaglianza
7 && E logico
8 \|\| oppure logico

L'operatore + concatena le stringhe quando almeno un operando è una stringa. Usare le parentesi per eseguire l'override della precedenza predefinita.

Esempi:

Expression Descrizione
$1 * 2 ^ 3 Exponentiation first: $1 * 8
($1 * 2) ^ 3 Override tra parentesi: moltiplicare per primo
-$1 * 2 Negazione prima, quindi moltiplica
$1 > 100 && $2 > 200 Concatenare le condizioni con AND logico

Funzioni predefinite

Funzioni di conversione unità

Queste funzioni accettano un singolo valore numerico e restituiscono un valore float.

Funzione Conversione Formula
cToF(value) Da Celsius a Fahrenheit F = (C × 9/5) + 32
fToC(value) Da Fahrenheit a Celsius C = (F - 32) × 5/9
psiToBar(value) Da PSI a bar bar = PSI × 0.0689476
barToPsi(value) Da bar a PSI PSI = bar / 0,0689476
inToCm(value) Pollici a centimetri cm = in × 2,54
cmToIn(value) Centimetri a pollici in = cm / 2,54
ftToM(value) Piedi a metri m = ft × 0,3048
mToFt(value) Metri a piedi ft = m / 0,3048
lbToKg(value) Sterline a chilogrammi kg = lb × 0,453592
kgToLb(value) Chilogrammi a chili lb = kg / 0,453592
galToL(value) Galloni statunitensi a litri L = gal × 3.78541
lToGal(value) Litri a galloni statunitensi gal = L / 3.78541

Funzioni di ridimensionamento e arrotondamento

Funzione Descrizione
scale(value, srcLo, srcHi, dstLo, dstHi) Scala value in modo lineare dall'intervallo di origine all'intervallo di destinazione. Tutti e cinque gli argomenti devono essere numerici.
round_n(value, decimals) Arrotonda un oggetto float al numero specificato di posizioni decimali (da 0 a 15).

Funzioni matematiche

Queste funzioni provengono dalla libreria matematica predefinita.

Funzione Descrizione
floor(value) Intero più grande minore o uguale a un numero
round(value) Numero intero più vicino, arrotondamento a metà strada da 0,0
ceil(value) Intero più piccolo maggiore o uguale a un numero
math::abs(value) Valore assoluto
math::sqrt(value) Radice quadrata (restituisce NaN per numeri negativi)
math::cbrt(value) Radice cubo
math::ln(value) Logaritmo naturale
math::log2(value) Logaritmo di base 2
math::log10(value) Logaritmo di base 10
math::log(value, base) Logaritmo con base arbitraria
math::exp(value) e elevato alla potenza del valore
math::exp2(value) 2 elevato alla potenza del valore
math::pow(base, exp) Alza la base alla potenza di exp
math::cos(value) Coseno (radianti)
math::sin(value) Seno (radianti)
math::tan(value) Tangente (radianti)
math::acos(value) Arccosine (restituisce radianti)
math::asin(value) Arcsine (restituisce radianti)
math::atan(value) Arctangent (restituisce radianti)
math::atan2(y, x) Arcotangente a quattro quadranti (restituisce radianti)
math::hypot(a, b) Lunghezza dell'ipotenusa dai lati a e b

Funzioni stringa

Funzione Descrizione
len(string) Lunghezza del carattere di una stringa o numero di elementi di una tupla
str::to_lowercase(string) Converte in minuscolo
str::to_uppercase(string) Converte in maiuscolo
str::trim(string) Rimuove gli spazi vuoti iniziali e finali
str::from(value) Converte un valore nella relativa rappresentazione di stringa
str::substring(string, start, end) Estrae una sottostringa per indice di caratteri
str::regex_matches(string, pattern) Restituisce true se la stringa corrisponde al modello regex. Disponibile solo nei grafici del flusso di dati.
str::regex_replace(string, pattern, replacement) Sostituisce tutte le corrispondenze regex con la stringa di sostituzione. Disponibile solo nei grafici del flusso di dati.

Funzioni condizionali e di raccolta

Funzione Descrizione
if(condition, trueVal, falseVal) Restituisce trueVal quando la condizione è true; in caso contrario, falseVal
min(values) Minimo di uno o più valori numerici o di una matrice
max(values) Massimo di uno o più valori numerici o di una matrice
contains(tuple, value) Restituisce true se la tupla contiene il valore
contains_any(tuple, candidates) Restituisce true se la tupla contiene qualsiasi valore della tupla candidati
typeof(value) Restituisce il tipo come stringa: "string", "float", "int", "boolean", "tuple"o "empty"

Funzioni di aggregazione (solo trasformazioni di finestra)

Queste funzioni sono disponibili solo nelle regole di accumulo all'interno delle trasformazioni di finestra. Ognuno accetta una singola variabile posizionale.

Funzione Restituzioni Comportamento della finestra vuota
average($n) Media dei valori numerici Error
sum($n) Somma dei valori numerici 0.0
min($n) Valore numerico minimo Error
max($n) Valore numerico massimo Error
count($n) Numero di messaggi in cui esiste il campo 0
first($n) Primo valore nella finestra Error
last($n) Ultimo valore nella finestra Error

Per informazioni dettagliate sull'uso delle funzioni di aggregazione, vedere Aggregare i dati nel tempo.

Logica condizionale

Usare la funzione per diramare la if logica all'interno di un'espressione:

Expression Descrizione
if($1 > 100, "high", "normal") Restituisce "alto" quando la temperatura supera 100
if($2 == (), $1, $1 * $2) Torna a $1 quando manca $2
if($1 > 5, true, false) Restituisce un valore booleano basato su una soglia

Usare () (il valore vuoto) nei confronti per rilevare i campi mancanti.

Suggerimento

Se è necessario solo un fallback statico per un campo mancante, la ?? <default> sintassi è più semplice. Vedere Valori predefiniti. Riservare if per i casi in cui è necessario scegliere tra i valori calcolati.

Campi dei metadati

Leggere e scrivere nei metadati dei messaggi usando il $metadata. prefisso nei inputs campi o output di una regola. I riferimenti ai metadati vengono inseriti nel percorso del campo, non nell'espressione stessa.

Proprietà dei metadati

  • Argomento: funziona sia per MQTT che per Kafka. Contiene la stringa in cui è stato pubblicato il messaggio. Esempio: $metadata.topic.
  • Proprietà utente: in MQTT, si riferisce alle coppie chiave/valore in formato libero che un messaggio MQTT può contenere. Ad esempio, se il messaggio MQTT è stato pubblicato con una proprietà utente con la chiave "priority" e il valore "high", il $metadata.user_property.priority riferimento contiene il valore "high". Le chiavi delle proprietà utente possono essere stringhe arbitrarie e possono richiedere l'uso di caratteri di escape: $metadata.user_property."weird key" utilizza la chiave "chiave strana" (che contiene uno spazio).
  • Proprietà di sistema: questo termine viene usato per ogni proprietà che non è una proprietà utente. Attualmente è supportata solo una singola proprietà di sistema: $metadata.system_property.content_type, che legge la proprietà del tipo di contenuto del messaggio MQTT (se impostata).
  • Intestazione: Questa è l'equivalente Kafka della proprietà utente MQTT. Kafka può usare qualsiasi valore binario per una chiave, ma i flussi di dati supportano solo chiavi stringa UTF-8. Esempio: $metadata.header.priority. Questa funzionalità è simile alle proprietà utente.
Campo Descrizione
$metadata.topic Argomento MQTT del messaggio
$metadata.user_property.<key> Proprietà utente nel messaggio, identificata dalla chiave
$metadata.system_property.content_type Proprietà di sistema del tipo di contenuto
$metadata.header.<key> Valore dell'intestazione Kafka, identificato dalla chiave

Leggere dai metadati

Per fare riferimento all'argomento di origine e a una proprietà utente in un'espressione, elencarli come input:

Inserimento Variabile
$metadata.topic $1
$metadata.user_property.device_id $2

Espressione: $1 + "/" + $2

Nell'esempio seguente, la proprietà MQTT topic è mappata nel campo origin_topic nell'output.

Inserimento Risultato
$metadata.topic origin_topic

Se la proprietà priority utente è presente nel messaggio MQTT, l'esempio seguente illustra come eseguirne il mapping a un campo di output:

Inserimento Risultato
$metadata.user_property.priority priority

Scrivere nei metadati

Per impostare una proprietà utente nel messaggio di output, usare $metadata.user_property.<key> come campo di output.

L'impostazione di un campo di metadati su un valore vuoto (()) lo rimuove. Per le proprietà utente, sono consentite chiavi duplicate.

È anche possibile eseguire il mapping delle proprietà dei metadati a un'intestazione di output o a una proprietà utente. Nell'esempio seguente, il MQTT topic è mappato al campo origin_topic nella proprietà utente dell'output.

Inserimento Risultato
$metadata.topic $metadata.user_property.origin_topic

Se il payload in ingresso contiene un priority campo, l'esempio seguente illustra come eseguirne il mapping a una proprietà utente MQTT:

Inserimento Risultato
priority $metadata.user_property.priority

Lo stesso esempio per Kafka:

Inserimento Risultato
priority $metadata.header.priority

I campi dei metadati sono supportati nelle regole di mapping, filtro e ramo. Non sono disponibili nelle regole di finestra (accumulo).

Ultimo valore noto

Usare il ? $last suffisso su un input per indicare al runtime di ricordare il valore più recente per tale campo. Se il campo non è presente nel messaggio corrente, viene invece utilizzato l'ultimo valore noto.

Inserimento Comportamento
temperature ? $last Usa l'ultima temperatura nota se il messaggio corrente non ha alcun temperature campo

La ? $last direttiva non fa distinzione tra maiuscole e minuscole e supporta spazi vuoti flessibili.

Importante

Gli ultimi valori noti vengono archiviati solo in memoria. Vengono persi quando il pod viene riavviato e non vengono condivisi tra le repliche.

L'ultimo valore noto è supportato nelle regole di mapping, filtro e ramo. Non è disponibile nelle regole di finestra (accumulo).

Valori predefiniti

Usare il ?? <default> suffisso su un input per fornire un valore di fallback quando il campo non è presente. Tipi predefiniti supportati: integer, float, boolean, string e null.

Annotazioni

La ?? <default> sintassi è disponibile solo nei grafici del flusso di dati. Non è supportata negli input del flusso builtInTransformation di dati.

Inserimento Risoluzione alternativa
temperature ?? 0 Intero 0
status ?? "unknown" Stringa "unknown"
threshold ?? 98.6 Float 98.6
enabled ?? true Valore booleano true

Combinare l'ultimo valore noto e il valore predefinito

È possibile combinare ? $last e ?? <default>. Il runtime controlla prima il messaggio corrente, quindi l'ultimo valore noto, quindi il valore predefinito. Se si usa ?? <default> senza ? $last, il runtime controlla direttamente il messaggio corrente e quindi il valore predefinito.

Inserimento Ordine di valutazione
temperature ?? 0 Valore corrente, quindi predefinito (0)
temperature ? $last ?? 0 Valore corrente, quindi ultimo noto, quindi predefinito (0)

I valori predefiniti sono supportati nelle regole di mapping, filtro e ramo. Non sono disponibili nelle regole di finestra (accumulo).

Tipi di dati

Tipo Descrizione Esempio
Intero Intero con segno a 64 bit 42, -7
Galleggiare Virgola mobile a 64 bit 3.14, -0.5
Stringa Testo UTF-8 "hello"
Bool Booleano true, false
Tupla Matrice di valori primitivi (1, 2, 3)
Vuoto Valore mancante o Null ()
JSON Oggetto JSON passato tramite (non può essere usato nelle espressioni)

Gli oggetti JSON e le matrici vengono mantenuti as-is quando i campi vengono copiati senza un'espressione, ma non possono essere usati come input per la valutazione delle espressioni.

Supporto delle funzionalità per tipo di trasformazione

Feature Mappa Filter Branch Finestra (accumulo)
Variabili posizionale
Operatori
Funzioni predefinite
Funzione di aggregazione No No No
$metadata Accesso No
$context Arricchimento No
? $last No
?? <default> ¹ No
str::regex_matches / str::regex_replace ¹ No
Caratteri jolly No No No

¹ Disponibile solo nei grafici del flusso di dati. Non supportato negli input del flusso builtInTransformation di dati.

Notazione e escape dei punti

La notazione punto viene ampiamente usata per fare riferimento a campi annidati. Un percorso di notazione punto standard è simile a Person.Address.Street.Number.

In un flusso di dati, un percorso descritto dalla notazione punto può includere stringhe e alcuni caratteri speciali senza dover eseguire l'escape, ad esempio Person.Date of Birth.

In altri casi, l'escape è necessario, ad esempio: nsu=http://opcfoundation.org/UA/Plc/Applications;s=RandomSignedInt32. Questo percorso, tra gli altri caratteri speciali, contiene punti all'interno del nome del campo. Senza escape, il nome del campo fungerebbe da separatore nella notazione del punto stesso.

Mentre un flusso di dati analizza un percorso, tratta solo due caratteri come speciali:

  • I punti (.) fungono da separatori di campo.
  • Le virgolette singole, se posizionate all'inizio o alla fine di un segmento, iniziano una sezione di escape in cui i punti non vengono considerati come separatori di campo.

Tutti gli altri caratteri vengono considerati come parte del nome del campo. Questa flessibilità è utile in formati come JSON, in cui i nomi dei campi possono essere stringhe arbitrarie.

La definizione del percorso deve inoltre rispettare le regole del formato di configurazione. Quando un carattere con un significato speciale viene incluso nel percorso, è necessario inserire le virgolette appropriate. Ad esempio, i nomi di campo che iniziano con due punti (ad :Person:.:name:esempio ) o che iniziano con un numero seguito da testo (ad 100 celsius.hotesempio ) devono essere interpretati correttamente come stringhe.

Evasione

La funzione primaria di escape in un percorso con notazione punto consiste nell'usare punti che fanno parte dei nomi dei campi anziché dei separatori. Ad esempio, il percorso Payload."Tag.10".Value è costituito da tre segmenti: Payload, Tag.10e Value. Le virgolette doppie impediscono Tag.10 al punto di fungere da separatore.

Regole di escape nella notazione con punti

  • Esegui l'escape di ciascun segmento separatamente: nel caso in cui più segmenti contengano punti, tali segmenti devono essere racchiusi tra virgolette doppie. Anche altri segmenti possono essere racchiusi tra virgolette, ma non influisce sull'interpretazione del percorso. Ad esempio: Payload."Tag.10".Measurements."Vibration.$12".Value

  • Uso corretto delle virgolette doppie: le virgolette doppie devono aprire e chiudere un segmento di testo tra virgolette. Tutte le virgolette al centro del segmento vengono considerate parte del nome del campo. Ad esempio, il percorso Payload.He said: "Hello", and waved definisce due campi: Payload e He said: "Hello", and waved. Quando un punto viene visualizzato in queste circostanze, continua a fungere da separatore. Ad esempio, il percorso Payload.He said: "No. It is done" viene suddiviso nei segmenti Payload, He said: "Noe It is done" (a partire da uno spazio).

Algoritmo di segmentazione

  • Se il primo carattere di un segmento è una virgoletta, il parser cerca la virgoletta successiva. La stringa racchiusa tra queste virgolette è considerata un singolo segmento.
  • Se il segmento non inizia con virgolette, il parser identifica i segmenti cercando il punto successivo o la fine del percorso.

Caratteri jolly

Usare un carattere jolly (*) nei percorsi di input e output per trovare una corrispondenza con più campi contemporaneamente. Ciò è utile quando l'output è simile all'input o quando è necessario applicare la stessa trasformazione in molti campi senza elencarne uno.

Copiare tutti i campi

Per passare ogni campo senza modifiche:

Inserimento Risultato
* *

Corrisponde * a ogni percorso di campo nell'input e lo inserisce nello stesso percorso nell'output. La parte del percorso corrispondente * viene chiamata segmento acquisito. Nell'output il segmento acquisito sostituisce .*

Appiattire i campi annidati

Per spostare i campi da un oggetto annidato al livello radice, inserire il prefisso nell'input e * nell'output:

Inserimento Risultato
Sensors.* *
Metadata.* *

Dato questo input:

{
  "Sensors": { "Temperature": 72.5, "Pressure": 14.7 },
  "Metadata": { "LineId": "Line-3", "Shift": "A" }
}

L'output rende flat entrambi gli oggetti:

{
  "Temperature": 72.5,
  "Pressure": 14.7,
  "LineId": "Line-3",
  "Shift": "A"
}

Ristrutturare i campi

Per spostare i campi in un nuovo elemento padre, inserire * l'input e aggiungere un prefisso nell'output:

Inserimento Risultato
* Telemetry.*

In questo modo vengono inclusi tutti i campi di primo livello all'interno di un Telemetry oggetto .

Regole di posizionamento con caratteri jolly

  • È consentito un solo valore* per input o percorso di output.
  • Deve * corrispondere a un segmento completo (non a un segmento parziale come Sensor*).
  • Può * essere visualizzato all'inizio (*.Value), al centro (Sensors.*.Reading) o alla fine (Sensors.*) di un percorso.

Caratteri jolly a più input

Quando una regola ha più input con caratteri jolly, deve * acquisire lo stesso segmento in tutti gli input. Il runtime risolve l'oggetto * dal primo input, quindi cerca i percorsi corrispondenti negli altri input.

Ad esempio, per mediare le letture massime e minime per ogni sensore:

Inserimento Risultato Expression
*.Max ($1)
*.Min ($2)
Averaged.* ($1 + $2) / 2

Dato questo input:

{
  "Temperature": { "Max": 85.3, "Min": 62.1 },
  "Pressure": { "Max": 15.2, "Min": 14.1 }
}

L'oggetto * acquisisce Temperature prima di tutto, quindi la regola cerca sia Temperature.Max che Temperature.Min. Acquisisce Pressure quindi e cerca Pressure.Max e Pressure.Min. L'output è il seguente:

{
  "Averaged": { "Temperature": 73.7, "Pressure": 14.65 }
}

Se un input non può essere risolto per un segmento acquisito(ad esempio, *.Mid.Avg quando il campo è annidato in modo diverso), tale segmento viene ignorato. Assicurarsi che i percorsi in tutti gli input riflettano la struttura effettiva dei dati.

Eseguire l'override di un carattere jolly per campi specifici

È possibile combinare una regola con caratteri jolly con regole specifiche. Le regole specifiche hanno la precedenza quando hanno una copertura inferiore (meno segmenti corrispondono a *). Questa operazione è denominata specializzazione.

Inserimento Risultato Expression
*.Max ($1)
*.Min ($2)
Averaged.* ($1 + $2) / 2
Pressure.Max ($1)
Pressure.Min ($2)
Averaged.PressureAdj ($1 + $2 + 1.0) / 2

La prima regola si applica a tutti i campi. La seconda regola esegue l'override solo per Pressure , perché Pressure.Max è più specifica di *.Max (copertura 0 e copertura 1).

Per escludere completamente un campo, usare un output vuoto:

Inserimento Risultato
Pressure.Max, Pressure.Min (vuoto)

Un output vuoto elimina il campo dal risultato. In questo modo viene eseguito l'override di qualsiasi regola con caratteri jolly che altrimenti lo includerebbe.

Più regole sugli stessi input

Se due regole hanno la stessa copertura o superiore, entrambe si applicano. In questo modo è possibile calcolare più valori derivati dagli stessi input:

Inserimento Risultato Expression
*.Max ($1)
*.Min ($2)
Stats.*.Avg ($1 + $2) / 2
*.Max ($1)
*.Min ($2)
Stats.*.Range $1 - $2

Entrambe le regole vengono eseguite per ogni segmento acquisito, producendo due campi di output per sensore.

Caratteri jolly nei set di dati di contestualizzazione

È possibile usare caratteri jolly con $context riferimenti per copiare tutti i campi da un set di dati:

Inserimento Risultato
$context(assetMeta).* Asset.*

In questo modo ogni campo del assetMeta set di dati viene copiato nella Asset sezione dell'output.

Set di dati di contestualizzazione

I set di dati di contestualizzazione consentono ai mapping di integrare dati aggiuntivi da database esterni. Usare il $context(datasetName) prefisso per fare riferimento ai campi di un set di dati. Ad esempio, $context(position).BaseSalary legge il BaseSalary campo da un set di dati denominato position.

Per informazioni dettagliate sulla configurazione dei set di dati di contestualizzazione, vedere Arricchire i dati usando i flussi di dati e Arricchire i dati esterni nei grafici del flusso di dati.